2013-06-11 13 views
8

私は、Saddle(saddle.github.io)の著者であり、パンダと似た機能を提供しています(ただし、JVMのScalaでは)。私はpandasのDataFrameのHDF5シリアル化フォーマットがSaddleのものと相互運用可能であることを保証しようとしています。私は現在、Saddleで文字列配列のシリアル化を実装しています。だから私の質問は、パンダのDataFrameが文字列をシリアル化する方法です。私はパンダでHDF5ファイルを作成する場合は、次のように:私は見パンダの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() 

し、得られtmp.h5ファイルをh5dump、その文字列のブロック(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" 
    } 
} 

属性れますこれはASCII文字セットを暗示します。しかし、私が符号化したバイトはASCIIに対応していないようです(つまり、 "a"、 "b"、 "c")。また、STRSIZE 8がどこから来るのか不思議です。誰もがpandas - > pytables - > hdf5経由で発生する文字列のシリアル化の実装の詳細を明らかにすることができますか? (私は深く掘り下げ始めることができるpandas/pytablesのコードを書くのにも喜んでいるでしょう:)

答えて

6

表面は非常にシンプルなようですが実際はかなり背後では複雑な例があります。これにより、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漬物として保存されているので、あなたは、クロスプラットフォーム、それらをデコードすることができるかどうかはわかりません。

もっと基本的なタイプを使用して保存された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() 

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']) 

さらに詳しくお知りになりたい場合は、私に連絡してください。

+0

"これらの文字列は残念なことにこの特定の形式でPythonのピクルスとして保存されています..."これはこのままであるか、ここでmsgpackを使用する予定です。あなたが作業しているmsgpackブランチを見たので私は尋ねています。 –

+0

msgpackは、PyTablesとは関係のない独立したシリアライズフォーマットです。私が参照しているpickleは、PyTablesが可変長の文字列を保存するインラインの方法です。 – Jeff

+0

私はそれがパンダ特有であり、これがpytablesの振る舞いであることを知らなかったと思いました。もしpytablesがmsgpackを使用していれば、他の言語がデータを読み込むのが簡単になりますが、その対象はPythonです。 –

関連する問題