将 pandas 数据附加到 hdf 存储,得到 'TypeError: object of type 'int' has no len()' 错误

Posted

技术标签:

【中文标题】将 pandas 数据附加到 hdf 存储,得到 \'TypeError: object of type \'int\' has no len()\' 错误【英文标题】:Appending pandas data to hdf store, getting 'TypeError: object of type 'int' has no len()' error将 pandas 数据附加到 hdf 存储,得到 'TypeError: object of type 'int' has no len()' 错误 【发布时间】:2020-08-25 11:04:27 【问题描述】:

动机:

我有大约 3000 万行数据,一列是索引值,另一列是 512 个 int32 数字的列表。我希望一次只检索大约一千个左右,所以我想创建某种数据存储,它可以按索引查找数据,而将其余部分留在磁盘上。

现在数据被分成184个文件,可以被pandas打开。

这就是我的数据框的样子

df.head()

IndexID NumpyIds
1899317 [0, 47715, 1757, 9, 38994, 230, 12, 241, 12228...
22861131    [0, 48156, 154, 6304, 43611, 11, 9496, 8982, 1...
2163410 [0, 26039, 41156, 227, 860, 3320, 6673, 260, 1...
15760716    [0, 40883, 4086, 11, 5, 18559, 1923, 1494, 4, ...
12244098    [0, 45651, 4128, 227, 5, 10397, 995, 731, 9, 3...

有索引,然后是“NumpyIds”列,它们是大小为 512 的 numpy 数组,包含 int32 个整数。

然后我尝试了这个:

store = pd.HDFStore('/data2.h5')
store.put('index', df, format='table', append=True)

得到了这个

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-05b956667991> in <module>()
----> 1 store.put('index', df, format='table', append=True, data_columns=True)
      2 store.close

4 frames
/usr/local/lib/python3.6/dist-packages/pandas/io/pytables.py in put(self, key, value, format, index, append, complib, complevel, min_itemsize, nan_rep, data_columns, encoding, errors)
   1040             data_columns=data_columns,
   1041             encoding=encoding,
-> 1042             errors=errors,
   1043         )
   1044 

/usr/local/lib/python3.6/dist-packages/pandas/io/pytables.py in _write_to_group(self, key, value, format, axes, index, append, complib, complevel, fletcher32, min_itemsize, chunksize, expectedrows, dropna, nan_rep, data_columns, encoding, errors)
   1707             dropna=dropna,
   1708             nan_rep=nan_rep,
-> 1709             data_columns=data_columns,
   1710         )
   1711 

/usr/local/lib/python3.6/dist-packages/pandas/io/pytables.py in write(self, obj, axes, append, complib, complevel, fletcher32, min_itemsize, chunksize, expectedrows, dropna, nan_rep, data_columns)
   4141             min_itemsize=min_itemsize,
   4142             nan_rep=nan_rep,
-> 4143             data_columns=data_columns,
   4144         )
   4145 

/usr/local/lib/python3.6/dist-packages/pandas/io/pytables.py in _create_axes(self, axes, obj, validate, nan_rep, data_columns, min_itemsize)
   3811                 nan_rep=nan_rep,
   3812                 encoding=self.encoding,
-> 3813                 errors=self.errors,
   3814             )
   3815             adj_name = _maybe_adjust_name(new_name, self.version)

/usr/local/lib/python3.6/dist-packages/pandas/io/pytables.py in _maybe_convert_for_string_atom(name, block, existing_col, min_itemsize, nan_rep, encoding, errors)
   4798         # we cannot serialize this data, so report an exception on a column
   4799         # by column basis
-> 4800         for i in range(len(block.shape[0])):
   4801 
   4802             col = block.iget(i)

TypeError: object of type 'int' has no len()

我想做什么?

我有 184 个 pandas 文件,我正在尝试将它们连接成 1 个 hdf 文件,以便使用索引进行快速查找。

例如

store['index'][21]

会给我 21 的索引的 512 维向量。

编辑:

我尝试为每个数字创建一个列,所以

  df[[str(i) for i in range(512)]] = pd.DataFrame(df.NumpyIds.to_numpy(), index=df.index) 
  df.drop(columns='NumpyIds', inplace=True)
  store.put('index', df, format='table', append=True)
  store.close

这可行,尽管我觉得这可能是一种技巧,而不是理想的解决方法。但现在的问题是我似乎无法从索引中获取这些值

store.select(key='index', start=2163410)

返回

    0   1   2   3   4   5   6   7   8   9   10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  ... 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
IndexID                                                                                                                                                                                                                                                                                                                                 
0 rows × 512 columns

哪些是列名,但不是该列中的数据。此方法也需要大量 RAM。我想知道它是否一次加载所有数据,而不仅仅是指定的索引。

我正在尝试的另一种解决方法是直接在 h5py 中打开数据

df = pd.read_hdf(hdf_files[0])
df.set_index('IndexID', inplace=True)
df.to_hdf('testhdf.h5', key='df')
h = h5py.File('testhdf.h5')

但我似乎无法弄清楚如何通过索引从该商店检索数据

h['df'][2163410]

/usr/local/lib/python3.6/dist-packages/h5py/_hl/base.py in _e(self, name, lcpl)
    135         else:
    136             try:
--> 137                 name = name.encode('ascii')
    138                 coding = h5t.CSET_ASCII
    139             except UnicodeEncodeError:

AttributeError: 'int' object has no attribute 'encode'

【问题讨论】:

【参考方案1】:

据我所知,这是一个BUG。 见#34274。


我已在 #38919 中修复它。现在它会显示相应的错误消息。

【讨论】:

以上是关于将 pandas 数据附加到 hdf 存储,得到 'TypeError: object of type 'int' has no len()' 错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在 pandas 中将新类别附加到 HDF5?

如何有效地将数据附加到 C 中的 HDF5 表?

将单个组中的 pandas 数据帧迭代地附加到 h5 文件

将浮点数组写入和附加到 C++ 中 hdf5 文件中的唯一数据集

hdf5 文件到熊猫数据框

编写并将float数组附加到C ++中hdf5文件中的唯一数据集