2011-03-20 3 views
11

PyTables 2.2.1 (Python 2.6 포함)을 사용하고 있으며 가변 길이의 중첩 배열이 포함 된 테이블을 만들고 싶습니다.PyTables에서 가변 길이의 중첩 배열을 만드는 방법은 무엇입니까?

저는 PyTables 문서를 검색했으며 튜토리얼 예제 (PyTables Tutorial 3.8)는 길이가 1 인 중첩 배열을 만드는 방법을 보여줍니다.하지만이 예제에서는 데이터 'info2/info3에 가변 개수의 행을 추가하는 방법은 무엇입니까?/x '및'info2/info3/y '? 아마도 쉽게 이해하는 테이블 구조에 대한

, 여기 내 자체 개발 한 예이다 : 나는 그런 구조가 가능하지 않은 PyTables의 문서에있는 표시를 발견하지 않았습니다

"""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() 

...하지만 경우에 이러한 구조는 실제로 불가능합니다. 가변 길이 중첩 열에 대한 대안은 무엇입니까?

  • EArray? VLArray? 그렇다면 이러한 데이터 유형을 위의 구조에 통합하는 방법은 무엇입니까?
  • 다른 아이디어가 있습니까?

모든 도움을 주시면 대단히 감사하겠습니다.

편집/추가 정보 W :

PyTables Mail Forum - Hierachical Datasets

그래서 사람이 유사한을 만드는 방법을 생각했습니다 PyTables 지도자가 이미는 "이러한 구조 가능하다"문제를 해결 한 것으로 보인다 PyTable 데이터 구조?

다시 한번 감사드립니다!

답변

4

이것은 PyTables로 시작하는 사람들이 일반적으로하는 일입니다. 확실히, 그것은 첫번째 일이었습니다 나는을 시도했습니다. 2009 년 현재이 기능이 지원되지 않았다고 생각합니다. 당신은 여기에서 볼 수있는 하나 개의 솔루션 "나는 항상 추천"한마디로

http://www.mail-archive.com/[email protected]/msg01207.html

, 다만 별도의 장소에서 각 VLArray을 넣어. 그렇게한다면 어쩌면 VLArrays가 필요하지 않을 수도 있습니다. 각 시험판에 대해 별도의 VLArrays를 저장하면 해당 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 원자.

중첩 된 VLArrays가 PyTables에서 지원된다면, 나는 확실히 알고 싶습니다!

또는 h5py가 전체 HDF5 기능 세트를 지원한다고 생각합니다. 따라서 중첩 된 데이터 레이아웃에 정말로 전념한다면 거기에 더 많은 행운이있을 수 있습니다. 당신은 멋진 기능을 많이 잃을거야! 내 경험상, 순진한 신경 과학자는 데이터 레이아웃, 청크 (chunking) 등에 대한 pytables 지능형 선택을 얻지 못하기 때문에 성능이 매우 떨어지게됩니다.

+0

감사 : 당신이 당신의 DB에서 읽어 단일 행이 있다고 가정하자! 또한 메일 목록 링크에는 Francesc의 지혜에 대한 여러 가지 흥미로운 '덩어리'가 있습니다. 결국 나는 속도와 단순함을 염려했기 때문에 패딩 된 여분의 공간으로 고정 된 배열 크기를 선택했다. – plmcw

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

의 라인을 따라 뭔가를했다 올바른 고정 된 길이

로에서 새로 만든 그래서 내가 가게에 시도 된 배열은 변수 렌의했다.

9

가변 길이의 배열로 고정 크기 데이터를 덤프하는 비슷한 작업이 있습니다.

가변 길이 데이터를 저장하기 위해 고정 크기 StringCol (64 * 1024) 필드를 사용했습니다. 항상 (< 64K)입니다. 그러나 blosc 압축에도 불구하고 다소 느리고 많은 디스크 공간을 낭비했습니다.

(스포일러 : 우리는 별도의 EArray 경우에 배열 필드, 하나 개 EArray 하나 개의 어레이 당 필드를 저장)

  1. 내가 고정 저장할 크기

    나는 다음과 같은 솔루션을 종료 조사 일 후 일반 py 테이블 테이블의 데이터arrFieldName_Offset 및 arrFieldName_Length : 제가

    datatype = StringAtom(1) 
    buffer = h5file.createEArray('/detector', 'arr', datatype, (0,), "") 
    
  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. I가 각 배열 필드 당 EArray 인스턴스를 생성

  4. 난이 표 2 개 추가 필드를 추가 고정 크기 데이터에 해당하는 행 추가 :

    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. Ta-dah! 배열에 버퍼를 추가하십시오.

    buffer.append(np.ndarray((len(my_buf),), buffer=my_buf, dtype=datatype)) 
    
  6. 그건 트릭입니다. 내 실험에서이 접근법은 비정형 고정 크기 배열 (StringAtom (HUGE_NUMBER)처럼)을 저장하는 것보다 2-10 배 빠르고 결과 DB는 몇 배나 더 작습니다 (2-5x)

  7. 버퍼 데이터를 얻는 것은 쉽습니다. 제안에 대한

    # Open array for reading 
    buffer = h5file.createEArray('/detector', 'Particle.buffer', datatype, (0,), "") 
    ... 
    row = ... 
    ... 
    bufferDataYouNeed = buffer[ row['buffer_Offset'] : row['buffer_Offset'] + row['buffer_Length']] 
    
관련 문제