2014-03-28 10 views
1

我將一個pandas數據框存儲爲一個包含MultiIndex的pytable。pandas pytable:如何指定一個MultiIndex的元素的min_itemsize

MultiIndex的第一個級別是與用戶ID對應的字符串。現在,大多數用戶ID都是13個字符,但其中一些是15個字符。當我追加一個包含long userID的記錄時,pytables會產生一個錯誤,因爲它需要一個13個字符的字段。

ValueError('Trying to store a string with len [15] in [user] column but\nthis column has a limit of [13]!\nConsider using min_itemsize to preset the sizes on these columns',) 

但是,我不知道如何爲MultiIndex的元素設置屬性min_itemsize。我已經嘗試{'index': 15},它不工作...

我知道我可以強制所有ID從一開始就通過追加空格爲15個字符,但如果可能,我寧願避免這種情況。

謝謝你的幫助!

回答

1

您需要指定要爲其設置min_itemsize的多索引級別的名稱。這裏有一個例子:

創建2個多索引幀

In [1]: df1 = DataFrame(np.random.randn(4,2),index=MultiIndex.from_product([['abcdefghijklm','foo'],[1,2]],names=['string','number'])) 

In [2]: df2 = DataFrame(np.random.randn(4,2),index=MultiIndex.from_product([['abcdefghijklmop','foo'],[1,2]],names=['string','number'])) 

In [3]: df1 
Out[3]: 
          0   1 
string  number      
abcdefghijklm 1  0.737976 0.840718 
       2  0.605763 1.797398 
foo   1  1.589278 0.104186 
       2  0.029387 1.417195 

[4 rows x 2 columns] 

In [4]: df2 
Out[4]: 
           0   1 
string   number      
abcdefghijklmop 1  0.539507 -1.059085 
       2  1.263722 -1.773187 
foo    1  1.625073 0.078650 
       2  -0.030827 -1.691805 

[4 rows x 2 columns] 

創建一個產品

In [9]: store = pd.HDFStore('test.h5',mode='w') 

In [10]: store.append('df1',df1) 

這裏的長度計算

In [12]: store.get_storer('df1').table 
Out[12]: 
/df1/table (Table(4,)) '' 
    description := { 
    "index": Int64Col(shape=(), dflt=0, pos=0), 
    "values_block_0": Float64Col(shape=(2,), dflt=0.0, pos=1), 
    "number": Int64Col(shape=(), dflt=0, pos=2), 
    "string": StringCol(itemsize=13, shape=(), dflt='', pos=3)} 
    byteorder := 'little' 
    chunkshape := (1456,) 
    autoindex := True 
    colindexes := { 
    "index": Index(6, medium, shuffle, zlib(1)).is_csi=False, 
    "number": Index(6, medium, shuffle, zlib(1)).is_csi=False, 
    "string": Index(6, medium, shuffle, zlib(1)).is_csi=False} 

這裏就是你現在所得到的錯誤

In [13]: store.append('df1',df2) 

ValueError: Trying to store a string with len [15] in [string] column but 
this column has a limit of [13]! 
Consider using min_itemsize to preset the sizes on these columns 

與級別名稱指定min_itemsize

In [14]: store.append('df',df1,min_itemsize={ 'string' : 15 }) 

In [15]: store.get_storer('df').table 
Out[15]: 
/df/table (Table(4,)) '' 
    description := { 
    "index": Int64Col(shape=(), dflt=0, pos=0), 
    "values_block_0": Float64Col(shape=(2,), dflt=0.0, pos=1), 
    "number": Int64Col(shape=(), dflt=0, pos=2), 
    "string": StringCol(itemsize=15, shape=(), dflt='', pos=3)} 
    byteorder := 'little' 
    chunkshape := (1394,) 
    autoindex := True 
    colindexes := { 
    "index": Index(6, medium, shuffle, zlib(1)).is_csi=False, 
    "number": Index(6, medium, shuffle, zlib(1)).is_csi=False, 
    "string": Index(6, medium, shuffle, zlib(1)).is_csi=False} 

追加

In [16]: store.append('df',df2) 

In [19]: store.df 
Out[19]: 
           0   1 
string   number      
abcdefghijklm 1  0.737976 0.840718 
       2  0.605763 1.797398 
foo    1  1.589278 0.104186 
       2  0.029387 1.417195 
abcdefghijklmop 1  0.539507 -1.059085 
       2  1.263722 -1.773187 
foo    1  1.625073 0.078650 
       2  -0.030827 -1.691805 

[8 rows x 2 columns] 

In [20]: store.close() 
+0

非常感謝您爲您詳細的例子。我曾嘗試過,但忘記用參數'names'初始化我的數據框的索引,因此只要我追加了新行,名稱就會丟失,並且'min_itemsize'選項不起作用。現在一切都是固定的。 – danieleb

+0

gr8! IIRC自0.13開始,您可以使用''level_0''等等(例如,如果您沒有設置名稱,那麼您在reset_index()時會得到的名稱)。真的有一個多指數(但因爲他們不是必需的)名稱,必須把它放進去。 – Jeff

相關問題