我是Saddle(saddle.github.io)的作者,它提供了与pandas精神相似的功能(但在JVM上的Scala中).我正在努力确保pandas的DataFrame的HDF5序列化格式与Saddle的可互操作.我目前正在Saddle中实现字符串数组序列化.所以我的问题是pandas DataFrame如何序列化字符串.如果我在pandas中创建一个HDF5文件,如下所示:
from pandas import *
h = HDFStore('tmp.h5')
f = DataFrame({0: [1,2,3], 1: ["a", "b", "c"], 2: [1.5, 2.5, 3.5]})
h.put("f1", f)
h.close()
Run Code Online (Sandbox Code Playgroud)
并且h5dump生成的tmp.h5文件,我看到字符串块(block2_values)存储为数据类型H5T_VLEN和属性
ATTRIBUTE "CLASS" {
DATATYPE H5T_STRING {
STRSIZE 8;
STRPAD H5T_STR_NULLTERM;
CSET H5T_CSET_ASCII;
CTYPE H5T_C_S1;
}
DATASPACE SCALAR
DATA {
(0): "VLARRAY"
}
}
Run Code Online (Sandbox Code Playgroud)
这暗示了一个ASCII字符集; 但是,我看到的编码字节似乎与ASCII不对应(即"a","b","c").另外,我很好奇STRSIZE 8的来源.任何人都可以了解通过pandas - > pytables - > hdf5发生的字符串序列化的实现细节吗?(我也很满意pandas/pytables中的代码指针,我可以开始深入挖掘:)
你选择了一个表面看起来非常简单的例子,但实际上在幕后相当复杂.这最终存储3个不同的数据块(每个dtype 1个),并且每个存储和索引以及数据.
你存储的对象就是我所说的Storer格式,这意味着numpy数组一次写入,所以一旦写入它们就不会改变.请参阅此处的文档:http://pandas.pydata.org/pandas-docs/dev/io.html#hdf5-pytables
PyTables文档在这里:http://pytables.github.io/usersguide/libref/declarative_classes.html#the-atom-class-and-its-descendants
不幸的是,这些字符串以这种特定的存储格式存储为python pickle,所以我不知道你是否可以跨平台解码它们.
您可以更轻松地阅读Table使用更多基本类型存储的对象,这些对象可以轻松导出(例如,在导出到R的文档中有一节).
尝试阅读这种格式:
In [2]: df = DataFrame({0: [1,2,3], 1: ["a", "b", "c"], 2: [1.5, 2.5, 3.5]})
In [4]: h = pd.HDFStore('tmp.h5')
In [6]: h.put('df',df, table=True)
In [7]: h.close()
Run Code Online (Sandbox Code Playgroud)
使用PyTables ptdump -avd tmp.h5实用程序,产生以下结果.如果您正在阅读<PyTables 3.0.0(刚出来)或py3(我们将在0.11.1中支持).然后字符串都是以字节形式写入的utf-8编码.在(PyTables 3.0.0)之前,我认为字符串是ascii.
/ (RootGroup) ''
/._v_attrs (AttributeSet), 4 attributes:
[CLASS := 'GROUP',
PYTABLES_FORMAT_VERSION := '2.0',
TITLE := '',
VERSION := '1.0']
/df (Group) ''
/df._v_attrs (AttributeSet), 12 attributes:
[CLASS := 'GROUP',
TITLE := '',
VERSION := '1.0',
data_columns := [],
index_cols := [(0, 'index')],
levels := 1,
nan_rep := b'nan',
non_index_axes := b"(lp1\n(I1\n(lp2\ncnumpy.core.multiarray\nscalar\np3\n(cnumpy\ndtype\np4\n(S'i8'\nI0\nI1\ntRp5\n(I3\nS'<'\nNNNI-1\nI-1\nI0\ntbS'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ntRp6\nag3\n(g5\nS'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ntRp7\nag3\n(g5\nS'\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ntRp8\natp9\na.",
pandas_type := b'frame_table',
pandas_version := b'0.10.1',
table_type := b'appendable_frame',
values_cols := ['values_block_0', 'values_block_1', 'values_block_2']]
/df/table (Table(3,)) ''
description := {
"index": Int64Col(shape=(), dflt=0, pos=0),
"values_block_0": Float64Col(shape=(1,), dflt=0.0, pos=1),
"values_block_1": Int64Col(shape=(1,), dflt=0, pos=2),
"values_block_2": StringCol(itemsize=1, shape=(1,), dflt=b'', pos=3)}
byteorder := 'little'
chunkshape := (2621,)
autoindex := True
colindexes := {
"index": Index(6, medium, shuffle, zlib(1)).is_csi=False}
/df/table._v_attrs (AttributeSet), 19 attributes:
[CLASS := 'TABLE',
FIELD_0_FILL := 0,
FIELD_0_NAME := 'index',
FIELD_1_FILL := 0.0,
FIELD_1_NAME := 'values_block_0',
FIELD_2_FILL := 0,
FIELD_2_NAME := 'values_block_1',
FIELD_3_FILL := b'',
FIELD_3_NAME := 'values_block_2',
NROWS := 3,
TITLE := '',
VERSION := '2.6',
index_kind := b'integer',
values_block_0_dtype := b'float64',
values_block_0_kind := b"(lp1\ncnumpy.core.multiarray\nscalar\np2\n(cnumpy\ndtype\np3\n(S'i8'\nI0\nI1\ntRp4\n(I3\nS'<'\nNNNI-1\nI-1\nI0\ntbS'\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ntRp5\na.",
values_block_1_dtype := b'int64',
values_block_1_kind := b"(lp1\ncnumpy.core.multiarray\nscalar\np2\n(cnumpy\ndtype\np3\n(S'i8'\nI0\nI1\ntRp4\n(I3\nS'<'\nNNNI-1\nI-1\nI0\ntbS'\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ntRp5\na.",
values_block_2_dtype := b'string8',
values_block_2_kind := b"(lp1\ncnumpy.core.multiarray\nscalar\np2\n(cnumpy\ndtype\np3\n(S'i8'\nI0\nI1\ntRp4\n(I3\nS'<'\nNNNI-1\nI-1\nI0\ntbS'\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00'\ntRp5\na."]
Data dump:
[0] (0, [1.5], [1], [b'a'])
[1] (1, [2.5], [2], [b'b'])
[2] (2, [3.5], [3], [b'c'])
Run Code Online (Sandbox Code Playgroud)
可能最好离线联系我进一步讨论.