我可以更新 HDFStore 吗?

Can I update an 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' 已更新。

正确的做法是什么?

思路:先从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文件中,允许我们使用它们在 where 子句中)当你 create/append HDF5 文件时:

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

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

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)

结果:

In [347]: store.get('df')
Out[347]:
     C
0_Y  1
0_Z  2
1_Y  4
1_Z  5
0_V  0
0_W  1
0_X  2
1_V  3
1_W  4
1_X  5