我可以更新 HDFStore 吗?

Posted

技术标签:

【中文标题】我可以更新 HDFStore 吗?【英文标题】:Can I update an HDFStore? 【发布时间】:2018-01-20 08:28:19 【问题描述】:

考虑以下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】:

想法:首先从 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 文件中的 all 列,允许我们在 where 子句中使用它们)您创建/附加 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

【讨论】:

非常感谢!我在那里学到了很多。我现在有了一些想法。我会回来报告的。 @piRSquared,如果有帮助,我很高兴。是的,请就您的最终解决方案提供简短的反馈。这也将帮助那些有同样问题的人...... where="index in df.index" 语法存在问题。有关解释和解决方法,请参阅 Pandas bug#17567。

以上是关于我可以更新 HDFStore 吗?的主要内容,如果未能解决你的问题,请参考以下文章

写入 HDFStore 时删除 Dataframe 索引

如何减少 HDFStore 的大小开销?

Pandas HDFStore:省略重复项

Pandas HDFStore 从内存中卸载数据帧

使用 Pandas HDFStore 以只读模式打开文件

当字符串列内容长于已经存在的内容时,HDFStore.append(string, DataFrame) 失败