我可以更新HDF商店吗?

时间:2017-08-11 18:26:36

标签: python pandas hdf5 hdfstore

考虑以下hdfstore和数据框dfdf2

import pandas as pd

store = pd.HDFStore('test.h5')
midx = pd.MultiIndex.from_product([range(2), list('XYZ')], names=list('AB'))
df = pd.DataFrame(dict(C=range(6)), midx)

df

     C
A B   
0 X  0
  Y  1
  Z  2
1 X  3
  Y  4
  Z  5
midx2 = pd.MultiIndex.from_product([range(2), list('VWX')], names=list('AB'))
df2 = pd.DataFrame(dict(C=range(6)), midx2)

df2

     C
A B   
0 V  0
  W  1
  X  2
1 V  3
  W  4
  X  5

我想先将df写入商店。

store.append('df', df)

store.get('df')

     C
A B   
0 X  0
  Y  1
  Z  2
1 X  3
  Y  4
  Z  5

稍后我将有另一个数据框,我想用它来更新商店。我希望用新数据帧中的索引值覆盖行,同时保留旧数据帧。

当我这样做时

store.append('df', df2)

store.get('df')

     C
A B   
0 X  0
  Y  1
  Z  2
1 X  3
  Y  4
  Z  5
0 V  0
  W  1
  X  2
1 V  3
  W  4
  X  5

这根本不是我想要的。请注意,(0, 'X')(1, 'X')会重复出现。我可以操纵组合的数据帧和覆盖,但我希望能够处理大量数据,这是不可行的。

如何更新商店以获取?

     C
A B   
0 V  0
  W  1
  X  2
  Y  1
  Z  2
1 V  3
  W  4
  X  5
  Y  4
  Z  5

您会看到'A'的每个级别,'Y'和' Z'都相同,'V''W'是新的,'X'已更新。

这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

想法:首先从HDF中删除匹配的行(具有匹配的索引值),然后将df2附加到HDFStore。

问题:我找不到将where="index in df2.index"用于多索引索引的方法。

解决方案:首先将多索引转换为普通索引:

df.index = df.index.get_level_values(0).astype(str) + '_' + df.index.get_level_values(1).astype(str)

df2.index = df2.index.get_level_values(0).astype(str) + '_' + df2.index.get_level_values(1).astype(str)

这会产生:

In [348]: df
Out[348]:
     C
0_X  0
0_Y  1
0_Z  2
1_X  3
1_Y  4
1_Z  5

In [349]: df2
Out[349]:
     C
0_V  0
0_W  1
0_X  2
1_V  3
1_W  4
1_X  5

确保您使用format='t'data_columns=True(这将为HDF5文件中的保存索引和索引所有列编制索引,允许我们在{{{ 1}}子句)当您创建/附加HDF5文件时:

where

现在我们可以先用匹配的索引从HDFStore中删除这些行:

store = pd.HDFStore('d:/temp/test1.h5')
store.append('df', df, format='t', data_columns=True)
store.close()

并附加store = pd.HDFStore('d:/temp/test1.h5') In [345]: store.remove('df', where="index in df2.index") Out[345]: 2

df2

结果:

In [346]: store.append('df', df2, format='t', data_columns=True, append=True)