问题 使用均值在Pandas中合并DataFrame


我有一组DataFrames,包含数值和部分重叠的索引。如果索引出现在多个DataFrame中,我想合并它们。

import pandas as pd
import numpy as np

df1 = pd.DataFrame([1,2,3], columns=['col'], index=['a','b','c'])
df2 = pd.DataFrame([4,5,6], columns=['col'], index=['b','c','d'])

这给了我两个DataFrame:

   col            col
a    1        b     4
b    2        c     5
c    3        d     6

现在我想合并DataFrames并取每个索引的均值(如果适用,即如果它出现不止一次)。

应该是这样的:

    col
a     1
b     3
c     4
d     6

我可以通过一些高级合并/加入来做到这一点吗?


10551
2017-10-21 08:57


起源



答案:


像这样的东西:

df3 = pd.concat((df1, df2))
df3.groupby(df3.index).mean()

#    col
# a    1
# b    3
# c    4
# d    6

或其他方式,如@unutbu答案:

pd.concat((df1, df2), axis=1).mean(axis=1)

11
2017-10-21 09:04



谢谢,这很快。熊猫非常简单。 - Martin Preusse


答案:


像这样的东西:

df3 = pd.concat((df1, df2))
df3.groupby(df3.index).mean()

#    col
# a    1
# b    3
# c    4
# d    6

或其他方式,如@unutbu答案:

pd.concat((df1, df2), axis=1).mean(axis=1)

11
2017-10-21 09:04



谢谢,这很快。熊猫非常简单。 - Martin Preusse


In [22]: pd.merge(df1, df2, left_index=True, right_index=True, how='outer').mean(axis=1)
Out[23]: 
a    1
b    3
c    4
d    6
dtype: float64

关于罗马的问题,我发现 IPython的%timeit 命令一种方便的基准代码方法:

In [28]: %timeit df3 = pd.concat((df1, df2)); df3.groupby(df3.index).mean()
1000 loops, best of 3: 617 µs per loop

In [29]: %timeit pd.merge(df1, df2, left_index=True, right_index=True, how='outer').mean(axis=1)
1000 loops, best of 3: 577 µs per loop

In [39]: %timeit pd.concat((df1, df2), axis=1).mean(axis=1)
1000 loops, best of 3: 524 µs per loop

在这种情况下, pd.concat(...).mean(...) 原来有点快。但实际上我们应该测试更大的数据帧以获得更有意义的基准。

顺便说一句,如果你不想安装IPython,可以使用相同的基准测试 Python的 timeit 模。它需要更多的设置。该 docs有一些例子 显示如何做到这一点。


请注意,如果 df1 要么 df2 在其索引中有重复的条目,例如:

N = 1000
df1 = pd.DataFrame([1,2,3]*N, columns=['col'], index=['a','b','c']*N)
df2 = pd.DataFrame([4,5,6]*N, columns=['col'], index=['b','c','d']*N)

那么这三个答案给出了不同的结果:

In [56]: df3 = pd.concat((df1, df2)); df3.groupby(df3.index).mean()
Out[56]: 
   col
a    1
b    3
c    4
d    6

pd.merge 可能没有给出你想要的那种答案:

In [58]: len(pd.merge(df1, df2, left_index=True, right_index=True, how='outer').mean(axis=1))
Out[58]: 2002000

pd.concat((df1, df2), axis=1) 引发ValueError:

In [48]: pd.concat((df1, df2), axis=1)
ValueError: cannot reindex from a duplicate axis

4
2017-10-21 09:05



+1我还在学习熊猫。两种解决方案中的哪一种会更快? - Roman Pekar
好问题;)我会尝试一些更大的数据。第一个答案赢了。 - Martin Preusse
@unutbu感谢您的基准测试答案,我绝对需要更多关于Pandas和数据分析的练习,不过.. - Roman Pekar
一件小事:如果我在DataFrames中有更多列,我将如何定义我想要合并并平均'col'并对其他人执行另一个/无操作? - Martin Preusse
@MartinPreusse:您可以将任何上述方法应用于系列 df1['col'] 和 df2['col']。例如,@ Roman的答案如下所示: pd.concat((df1['col'], df2['col']), axis=1).mean(axis=1)。 - unutbu