11

Python 2.6 で PyTables 2.2.1 を使用しています。可変長のネストされた配列を含むテーブルを作成したいと考えています。

私は PyTables のドキュメントを検索しました。チュートリアルの例 ( PyTables Tutorial 3.8 ) は、長さ = 1 のネストされた配列を作成する方法を示しています。しかし、この例では、可変数の行をデータ 'info2/info3/x ' および 'info2/info3/y'?

おそらくテーブル構造を理解しやすくするために、ここに私の自家製の例を示します。

"""Desired Pytable output:

DIEM    TEMPUS  Temperature             Data
5       0       100         Category1 <--||-->  Category2
                         x <--| |--> y          z <--|
                        0           0           0
                        2           1           1
                        4           1.33        2.67
                        6           1.5         4.5
                        8           1.6         6.4
5       1       99
                        2           2           0   
                        4           2           2
                        6           2           4
                        8           2           6
5       2       96
                        4           4           0
                        6           3           3
                        8           2.67        5.33


Note that nested arrays have variable length.
"""

import tables as ts

tableDef =      {'DIEM': ts.Int32Col(pos=0),
                'TEMPUS': ts.Int32Col(pos=1), 
                'Temperature' : ts.Float32Col(pos=2),
                'Data': 
                    {'Category1': 
                        {
                        'x': ts.Float32Col(), 
                        'y': ts.Float32Col()
                        }, 
                    'Category2': 
                        {
                        'z': ts.Float32Col(), 
                        }
                    }
                }

# create output file
fpath = 'TestDb.h5'
fh = ts.openFile(fpath, 'w')
# define my table
tableName = 'MyData'
fh.createTable('/', tableName, tableDef)
tablePath = '/'+tableName
table = fh.getNode(tablePath)

# get row iterator
row = table.row
for i in xrange(3):
    print '\ni=', i
    # calc some fake data
    row['DIEM'] = 5
    row['TEMPUS'] = i
    row['Temperature'] = 100-i**2

    for j in xrange(5-i):
        # Note that nested array has variable number of rows
        print 'j=', j,
        # calc some fake nested data
        val1 = 2.0*(i+j)
        val2 = val1/(j+1.0)
        val3 = val1 - val2

        ''' Magic happens here...
        How do I write 'j' rows of data to the elements of 
        Category1 and/or Category2?

        In bastardized pseudo-code, I want to do:

        row['Data/Category1/x'][j] = val1
        row['Data/Category1/y'][j] = val2
        row['Data/Category2/z'][j] = val3
        '''

    row.append()
table.flush()

fh.close()

PyTables のドキュメントには、そのような構造が不可能であるという兆候は見つかりませんでした...しかし、そのような構造が実際に不可能な場合、可変長のネストされた列に代わるものは何ですか?

  • Eアレイ? VLアレイ? もしそうなら、これらのデータ型を上記の構造に統合する方法は?
  • 他のアイデア?

どんな支援も大歓迎です!

追加情報付きの編集:PyTablesの専門家は、「そのような構造は可能ですか?」という質問にすでに対処しているようです:

PyTables メール フォーラム - 階層データセット

類似の PyTable データ構造を作成する方法を見つけた人はいますか?

再度、感謝します!

4

3 に答える 3

9

同様のタスクがあります。可変長の配列を使用して固定サイズのデータ​​をダンプすることです。

最初に、固定サイズの StringCol(64*1024) フィールドを使用して可変長データを格納しようとしました (常に < 64K です)。しかし、blosc 圧縮にもかかわらず、かなり遅く、多くのディスク領域を浪費していました。

数日間の調査の後、次の解決策で終了しました。

(ネタバレ: 配列フィールドを個別の EArray インスタンスに格納し、1 つの配列フィールドにつき 1 つの EArray を格納します)

  1. 固定サイズのデータ​​を通常の pytables テーブルに保存します。
  2. これらのテーブルにarrFieldName_OffsetarrFieldName_Lengthの 2 つのフィールドを追加しました。

    class Particle(IsDescription):
       idnumber  = Int64Col()
       ADCcount  = UInt16Col()
       TDCcount  = UInt8Col()
       grid_i    = Int32Col()
       grid_j    = Int32Col()
       pressure  = Float32Col()
       energy    = FloatCol()
       buffer_Offset = UInt32() # note this field!
       buffer_Length = UInt32() # and this one too!
    
  3. また、配列フィールドごとに 1 つの EArray インスタンスを作成します。

    datatype = StringAtom(1)
    buffer = h5file.createEArray('/detector', 'arr', datatype, (0,), "")
    
  4. 次に、固定サイズのデータ​​に対応する行を追加します。

    row['idnumber'] = ...
    ...
    row['energy'] = ...
    row['buffer_Offset'] = buffer.nrows
    # my_buf is a string (I get it from a stream)
    row['buffer_Length'] = len(my_buf)
    table.append(row)
    
  5. タダ!バッファを配列に追加します。

    buffer.append(np.ndarray((len(my_buf),), buffer=my_buf, dtype=datatype))
    
  6. それがコツです。私の実験では、このアプローチは不規則な固定サイズの配列 (StringAtom(HUGE_NUMBER) など) を格納するよりも 2 倍から 10 倍高速であり、結果の DB は数分の 1 になります (2 倍から 5 倍)。

  7. バッファ データの取得は簡単です。そのが、DB から読み取る単一の行であるとします。

    # Open array for reading
    buffer = h5file.createEArray('/detector', 'Particle.buffer', datatype, (0,), "")
    ...
    row = ...
    ...
    bufferDataYouNeed = buffer[ row['buffer_Offset'] : row['buffer_Offset'] + row['buffer_Length']]
    
于 2012-03-26T17:01:19.817 に答える
4

これは、PyTables を使い始めた人がやりたいと思う一般的なことです。確かに、それはがやろうとした最初のことでした。2009 年の時点では、この機能はサポートされていなかったと思います。「私が常にお勧めする」ソリューションの 1 つについては、こちらを参照してください。

http://www.mail-archive.com/pytables-users@lists.sourceforge.net/msg01207.html

つまり、各 VLArray を別々の場所に配置するだけです。そうすれば、VLArray が必要なくなるかもしれません。トライアルごとに個別の VLArray を保存する場合 (または何でも)、それらの VLArray にメタデータを保持するか (名前の変更、移動などでアレイとの同期を維持することが保証されます)、またはテーブルに配置することができます (検索が容易になります)。

ただし、列アトムの単一の時点を選択してから、タイムスタンプ用に別の列を追加することもできます。これにより、メモリ内に通常の繰り返し (表形式) 構造を保持している「不規則な」配列が可能になります。例えば:

Trial Data
1     0.4, 0.5, 0.45
2     0.3, 0.4, 0.45, 0.56

になる

Trial Timepoint Data
1     1         0.4
1     2         0.5
...
2     4         0.56

上記のデータは単一の数値ですが、たとえば 4x5x3 アトムの場合もあります。

ネストされた VLArray が現在 PyTable でサポートされているかどうか、ぜひ知りたいです!

あるいは、h5py は完全な HDF5 機能セットをサポートしていると思います。そのため、ネストされたデータ レイアウトに真剣に取り組んでいるのであれば、もっとうまくいくかもしれません。ただし、多くの優れた機能を失うことになります! そして、私の経験では、素朴な神経科学者は、データ レイアウト、チャンクなどの pytables のインテリジェントな選択を取得しないため、パフォーマンスが非常に悪くなります。

于 2011-06-23T00:50:21.380 に答える
0

私もこれに遭遇し、固定配列サイズの使用を終了しました。保存しようとしていた配列は可変長だったので、正しい固定長の配列から新しいものを作成しました

私はその線に沿って何かをしました

def filled_list(src_list, targ_len):
    """takes a varible len() list and creates a new one with a fixed len()"""
    for i in range(targ_len):
        try:
            yield src_list[i]
        except IndexError:
            yield 0

src_list = [1,2,3,4,5,6,7,8,9,10,11]
new_list = [x for x in filled_list(src_list, 100)]

それは私のためにトリックをしました。

于 2012-03-16T15:39:57.587 に答える