我能更新HDFStore吗?

5
考虑以下的 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' 则被更新了。
正确的处理方式是什么?

你能使用普通(非多级)索引吗? - MaxU - stand with Ukraine
是的...我的真实数据有多级索引,但如果您展示单级索引的内容,我也很满意。 - piRSquared
好的,我需要一些时间来准备演示... - MaxU - stand with Ukraine
1个回答

4

思路:先从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

在创建/追加HDF5文件时,请确保使用format='t'data_columns=True(这将索引保存索引并索引HDF5文件中的所有列,使我们能够在where子句中使用它们):

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

1
非常感谢!我在那里学到了很多东西。现在我有一些想法了。我会回报的。 - piRSquared
@piRSquared,如果它有所帮助,我很高兴。是的,请就您的最终解决方案给出简短反馈。这也将帮助那些遇到相同问题的人... - MaxU - stand with Ukraine
where="index in df.index" 语法存在问题,请参见 Pandas bug#17567 获取解释和解决方法。 - Jérôme

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接