将具有混合数据和类别的pandas DataFrame存储到hdf5中

Ann*_*teC 12 python pandas

我想将具有不同列的dataFrame存储到hdf5文件中(查找下面带有数据类型的摘录).

In  [1]: mydf
Out [1]:
endTime             uint32
distance           float16
signature         category
anchorName        category
stationList         object
Run Code Online (Sandbox Code Playgroud)

在转换一些列(我上面的摘录中的signature和anchorName)之前,我使用了类似下面的代码来存储它(它工作得非常好):

path = 'tmp4.hdf5'
key = 'journeys'
mydf.to_hdf(path, key, mode='w', complevel=9, complib='bzip2')
Run Code Online (Sandbox Code Playgroud)

但它不适用于类别,然后我尝试了以下:

path = 'tmp4.hdf5'
key = 'journeys'
mydf.to_hdf(path, key, mode='w', format='t', complevel=9, complib='bzip2')
Run Code Online (Sandbox Code Playgroud)

它工作正常,如果我删除列stationList,其中每个条目是一个字符串列表.但是在本专栏中,我得到以下异常:

Cannot serialize the column [stationList] because
its data contents are [mixed] object dtype
Run Code Online (Sandbox Code Playgroud)

如何改进我的代码以存储数据框?

pandas版本:0.17.1
python版本:2.7.6(由于兼容性原因无法更改)


edit1(一些示例代码):

import pandas as pd

mydf = pd.DataFrame({'endTime' : pd.Series([1443525810,1443540836,1443609470]),
                    'distance' : pd.Series([454.75,477.25,242.12]),
                    'signature' : pd.Series(['ab','cd','ab']),
                    'anchorName' : pd.Series(['tec','ing','pol']),
                    'stationList' : pd.Series([['t1','t2','t3'],['4','t2','t3'],['t3','t2','t4']])
                    })

# this works fine (no category)
mydf.to_hdf('tmp_without_cat.hdf5', 'journeys', mode='w', complevel=9, complib='bzip2')

for col in ['anchorName', 'signature']:
    mydf[col] = mydf[col].astype('category')

# this crashes now because of category data
# mydf.to_hdf('tmp_with_cat.hdf5', 'journeys', mode='w', complevel=9, complib='bzip2')

# switching to format='t'   
# this caused problems because of "mixed data" in column stationList
mydf.to_hdf('tmp_with_cat.hdf5', 'journeys', mode='w', format='t', complevel=9, complib='bzip2')

mydf.pop('stationList')

# this again works fine
mydf.to_hdf('tmp_with_cat_without_stationList.hdf5', 'journeys', mode='w', format='t', complevel=9, complib='bzip2')
Run Code Online (Sandbox Code Playgroud)

edit2:同时我尝试了不同的东西摆脱这个问题.其中之一是将列stationList的条目转换为tupels(可能因为它们不会被更改)并将其转换为类别.但它没有改变任何东西.以下是我在转换循环后添加的行(仅用于完整性):

mydf.stationList = [tuple(x) for x in mydf.stationList.values]
mydf.stationList.astype('category')
Run Code Online (Sandbox Code Playgroud)

Chr*_*don 7

你有两个问题:

  1. 您希望将分类数据存储在HDF5文件中;
  2. 您正在尝试将任意对象(即stationList)存储在HDF5文件中.

正如您所发现的那样,分类数据(目前?)仅支持HDF5的"表格"格式.

但是,存储任意对象(字符串列表等)实际上并不是HDF5格式本身所支持的.通过使用pickle序列化这些对象,然后将pickle存储为任意长度的字符串(我认为所有HDF5格式都不支持),Pandas为您解决了这个问题.但这将是缓慢而低效的,并且HDF5永远不会得到很好的支持.

在我看来,你有两个选择:

  1. 透视数据,以便按站名获得一行数据.然后,您可以将所有内容存储在表格式HDF5文件中.(这是一般的好习惯;请参阅Hadley Wickham的Tidy Data.)
  2. 如果你真的想保留这种格式,那么你也可以使用to_pickle()来保存整个数据帧.处理任何类型的对象(例如字符串列表等)都没有问题.

就个人而言,我建议使用选项1.您可以使用快速的二进制文件格式.并且数据透视表还可以使您的数据更容易进行其他操作.

  • 这个问题很标准,但解决方案很少 (4认同)