合并两列上的数据帧

2024-09-29 01:19:02 发布

您现在位置:Python中文网/ 问答频道 /正文

这是this question的后续

我有两个数据帧,如下所示:

print( a )

    foo   bar   let letval
9  foo1  bar1  let1      a
8  foo2  bar2  let1      b
7  foo3  bar3  let1      c
6  foo1  bar1  let2      z
5  foo2  bar2  let2      y
4  foo3  bar3  let2      x

print( b )

    foo   bar   num  numval
0  foo1  bar1  num1       1
1  foo2  bar2  num1       2
2  foo3  bar3  num1       3
3  foo1  bar1  num2       4
4  foo2  bar2  num2       5
5  foo3  bar3  num2       6

我想merge[ 'foo', 'bar' ]上的两个。你知道吗

如果我只是做c = pd.merge( a, b, on=['foo', 'bar'] ),我会得到:

prnint( c )

     foo   bar   let letval   num  numval
0   foo1  bar1  let1      a  num1       1
1   foo1  bar1  let1      a  num2       4
2   foo1  bar1  let2      z  num1       1
3   foo1  bar1  let2      z  num2       4
4   foo2  bar2  let1      b  num1       2
5   foo2  bar2  let1      b  num2       5
6   foo2  bar2  let2      y  num1       2
7   foo2  bar2  let2      y  num2       5
8   foo3  bar3  let1      c  num1       3
9   foo3  bar3  let1      c  num2       6
10  foo3  bar3  let2      x  num1       3
11  foo3  bar3  let2      x  num2       6

我想:

print( c )

    foo   bar   let letval   num   numval
0  foo1  bar1  let1      a   num1       1
1  foo2  bar2  let1      b   num1       2
2  foo3  bar3  let1      c   num1       3
3  foo1  bar1  let2      z   num2       4
4  foo2  bar2  let2      y   num2       5
5  foo3  bar3  let2      x   num2       6

最接近的是:

c = pd.merge( a, b, left_index=['foo', 'bar'], right_index=['foo', 'bar'] )

我错过了什么?你知道吗

为什么在第一个例子中得到c.shape = (12,6)?你知道吗


编辑

多亏了@piRSquared's answer,我意识到根本的问题是没有一个列的组合可以做到这一点。因此,前面提出的合并问题不能一元化地解决。也就是说,这个问题转化为一个更简单的问题:

如何在表之间建立统一的关系?

我用一个字典解决了这个问题,它映射了需要对齐的所需的输出:

map_ab = { 'num1':'let1', 'num2':'let2' }
b['let'] = b.apply( lambda x: map_ab[x['num']], axis=1 )
c = pd.merge( a, b, on=['foo', 'bar', 'let'] )
print( c )

Tags: foobarnumprintletfoo1foo2num2
2条回答

之所以会出现这种情况,是因为要合并的列不构成唯一的组合。例如,a的第一行(索引0)有foo1bar1,但第四行(索引3)也有。好吧,那很好,但是b也有同样的问题。因此,当您将bfoo1&;bar10索引的行匹配时,它会匹配两次。当您匹配foo1&;在索引为3的行中的bar1时也是如此,它匹配两次。所以这两行有四个匹配项。你知道吗

所以你得到

  • a行0与b行0匹配
  • a行0与b行3匹配
  • a行3与b行0匹配
  • a行3与b行3匹配

然后,你的例子又做了两次。3 * 4 == 12

唯一能做到这一点并且毫不含糊的方法是决定一个规则,如果有多个匹配项,那么就选择哪个匹配项。我决定按你的其他专栏之一分组,然后选第一个专栏。它仍然不符合你的预期输出,但我建议你给出一个坏的例子。你知道吗

pd.merge( a, b, on=['foo', 'bar']).groupby(['foo', 'bar', 'let'], as_index=False).first()

enter image description here

您可以使用combine_first

In[21]:a.combine_first(b)
Out[21]: 
    bar   foo   let letval   num  numval
0  bar1  foo1  let1      a  num1       1
1  bar2  foo2  let1      b  num1       2
2  bar3  foo3  let1      c  num1       3
3  bar1  foo1  let2      z  num2       4
4  bar2  foo2  let2      y  num2       5
5  bar3  foo3  let2      x  num2       6

在第一个示例中,您正在执行inner join,如果bar&;fooa,b中相等,则返回所有行。你知道吗

相关问题 更多 >