在pandas中将多重索引和单一索引的数据框合并

43

我有两个数据框。df1 是多级索引:

                value
first second    
a     x         0.471780
      y         0.774908
      z         0.563634
b     x         -0.353756
      y         0.368062
      z         -1.721840

而且df2:

      value
first   
a     10
b     20

我该如何合并这两个数据框,只保留其中一个多级索引,即“first”索引?所需的输出如下:

                value1      value2
first second    
a     x         0.471780    10
      y         0.774908    10
      z         0.563634    10
b     x         -0.353756   20
      y         0.368062    20
      z         -1.721840   20
3个回答

26
你可以使用get_level_values函数:
firsts = df1.index.get_level_values('first')
df1['value2'] = df2.loc[firsts].values

注意:你在这里进行的是一个 join 操作(除了 df1 是 MultiIndex),所以可能有更简洁的方式来描述这个操作...

.

举个例子(类似于您的情况):

df1 = pd.DataFrame([['a', 'x', 0.123], ['a','x', 0.234],
                    ['a', 'y', 0.451], ['b', 'x', 0.453]],
                   columns=['first', 'second', 'value1']
                   ).set_index(['first', 'second'])
df2 = pd.DataFrame([['a', 10],['b', 20]],
                   columns=['first', 'value']).set_index(['first'])

firsts = df1.index.get_level_values('first')
df1['value2'] = df2.loc[firsts].values

In [5]: df1
Out[5]: 
              value1  value2
first second                
a     x        0.123      10
      x        0.234      10
      y        0.451      10
b     x        0.453      20

3
你可以像这样 几乎 合并:df1.merge(df2, left_on=df1.index.get_level_values('first'), right_on=df2.index.get_level_values('first')) - Andy Hayden
1
这种方法在给定的例子中运行良好,但我想知道当单索引在某些情况下不同时会发生什么(例如,在一个元素中有更多元素)。 - Uncle Ben Ben
4
从版本0.23开始,可以使用“left_on ='name_of_index_level'”;也就是说,@AndyHayden的示例简化为“df1.merge(df2,left_on ='first', right_on ='first')”。 - Axel
3
@Axel,按照您的建议,我似乎正在失去另一个索引级别。但是,我正在使用“how = left”进行合并,所以为了避免这种影响,我只需存储原始索引,然后将其分配给df_merged.index = index。由于使用了 how="left",新旧索引始终具有相同的长度。 - Dr_Zaszuś

19
根据文档,自 pandas 0.14 起,你可以简单地连接单索引和多重索引的数据帧。它将匹配共同的索引名称。虽然有趣的是,'how' 参数在 'inner''outer' 中按预期工作,但在 'left''right' 中似乎被颠倒了(这可能是一个错误吗?)。
df1 = pd.DataFrame([['a', 'x', 0.471780], ['a','y', 0.774908], ['a', 'z', 0.563634],
                    ['b', 'x', -0.353756], ['b', 'y', 0.368062], ['b', 'z', -1.721840],
                    ['c', 'x', 1], ['c', 'y', 2], ['c', 'z', 3],
                   ],
                   columns=['first', 'second', 'value1']
                   ).set_index(['first', 'second'])
df2 = pd.DataFrame([['a', 10], ['b', 20]],
                   columns=['first', 'value2']).set_index(['first'])

print(df1.join(df2, how='inner'))
                value1  value2
first second                  
a     x       0.471780      10
      y       0.774908      10
      z       0.563634      10
b     x      -0.353756      20
      y       0.368062      20
      z      -1.721840      20

3
作为一种强大的重新索引的快捷方式,.ix 语法在某些情况下非常有用,但是在这种情况下,您实际上并没有进行任何行/列组合重新索引,因此可以使用更加优美(对于我来说)的重新索引方法来完成:
准备工作由 hayden 提供:
df1 = pd.DataFrame([['a', 'x', 0.123], ['a','x', 0.234],
                    ['a', 'y', 0.451], ['b', 'x', 0.453]],
                   columns=['first', 'second', 'value1']
                   ).set_index(['first', 'second'])
df2 = pd.DataFrame([['a', 10],['b', 20]],
                   columns=['first', 'value']).set_index(['first'])

那么在iPython中,它看起来是这样的:
In [4]: df1
Out[4]: 
              value1
first second        
a     x        0.123
      x        0.234
      y        0.451
b     x        0.453

In [5]: df2
Out[5]: 
       value
first       
a         10
b         20

In [7]: df2.reindex(df1.index, level=0)
Out[7]: 
              value
first second       
a     x          10
      x          10
      y          10
b     x          20

In [8]: df1['value2'] = df2.reindex(df1.index, level=0)

In [9]: df1
Out[9]: 
              value1  value2
first second                
a     x        0.123      10
      x        0.234      10
      y        0.451      10
b     x        0.453      20

在reindex方法中使用哪个级别的记忆技巧: 它表示您已经涵盖了更大索引中的级别。 因此,在这种情况下,df2已经涵盖了df1.index的0级。


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