【问题标题】:pandas partial join on multiindex多索引上的熊猫部分连接
【发布时间】:2014-08-25 20:41:45
【问题描述】:

所以,这是我的问题:

dfa = pd.DataFrame({"a": [["a", "b", "c"][int(k/10)] for k in range(30)],
                    "b": ["a" + repr([10, 20, 30, 40, 50, 60][int(k/5)]) for k in range(30)],
                    "c": np.arange(30),
                    "d": np.random.normal(size=30)}).set_index(["a","b","c"])
dfb = pd.DataFrame({"a": [["a", "b", "c"][int(k/2)] for k in range(6)],
                    "b": ["a" + repr([10, 20, 30, 40, 50, 60][k]) for k in range(6)],
                    "m": np.random.normal(size=6)**2}).set_index(["a","b"])

基本上我有两个具有多索引的数据框,我想将dfa.d 除以dfb.m,加入("a", "b")。我不能天真地做dfa.d / dfb.mjoin,因为它说merging with more than one level overlap on a multi-index is not implemented

我发现的最直接(大​​声笑)的方法是:

dfc = dfa.reset_index().set_index(["a", "b"]).join(dfb)
dfc["r"] = dfc.d / dfc.m
dfd = dfc.reset_index().set_index(["a", "b", "c"])[["r"]]

有什么捷径吗?

【问题讨论】:

  • 我开始认为这是熊猫的一个错误。例如dfa.loc[dfb.index] 返回所有空值,但应该返回除法的值
  • 如果您在 the source code 上查找我的错误消息,这似乎是有道理的(“加入 1 但不超过 1”);我想知道为什么。

标签: python pandas


【解决方案1】:

这个问题有an open bug,当前的里程碑是0.15.1

直到出现更好的东西,a workaround 涉及以下步骤:

  • 通过unstack将不匹配的索引级别排除在列中
  • 执行乘法/除法
  • stack 列回到原来的位置。

像这样:

In [109]: dfa.unstack('c').mul(dfb.squeeze(), axis=0).stack('c')
Out[109]: 
                  d
a b   c            
a a10 0    1.535221
      1   -2.151894
      2    1.986061
      3   -1.946031
      4   -4.868800
  a20 5   -2.278917
      6   -1.535684
      7    2.289102
      8   -0.442284
      9   -0.547209
b a30 10 -12.568426
      11   7.180348
      12   1.584510
      13   3.419332
      14  -3.011810
  a40 15  -0.367091
      16   4.264955
      17   2.410733
      18   0.030926
      19   1.219653
c a50 20   0.110586
      21  -0.430263
      22   0.350308
      23   1.101523
      24  -1.371180
  a60 25  -0.003683
      26   0.069884
      27   0.206635
      28   0.356708
      29   0.111380

注意两点:

  1. dfb 必须是 Series,否则对于将 dfb 的哪些列用于乘法运算会有额外的复杂性。您可以将dfb.squeeze() 替换为dfb['m']
  2. 如果不匹配的索引不是这三个索引中的最后一个,则不会保留索引级别的顺序。在这种情况下,请执行 what @jreback suggests 并在之后重新排序索引级别:.reorder_levels(dfa.index.names)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 1970-01-01
    • 2016-10-16
    • 2019-01-19
    • 1970-01-01
    相关资源
    最近更新 更多