Python `pd.concat`with`join==';内部';`不';t生成数据帧的交集
我正在尝试使用pd.concat从几个数据帧中提取公共行:Python `pd.concat`with`join==';内部';`不';t生成数据帧的交集,python,python-3.x,pandas,dataframe,set-intersection,Python,Python 3.x,Pandas,Dataframe,Set Intersection,我正在尝试使用pd.concat从几个数据帧中提取公共行: >>> import numpy as np >>> import pandas as pd >>> x = np.random.random(size=(5, 3)) >>> df1 = pd.DataFrame(x) >>> df2 = pd.DataFrame(x[1:3]) >>> df3 = pd.DataFrame(x
>>> import numpy as np
>>> import pandas as pd
>>> x = np.random.random(size=(5, 3))
>>> df1 = pd.DataFrame(x)
>>> df2 = pd.DataFrame(x[1:3])
>>> df3 = pd.DataFrame(x[2:4])
>>> df1
0 1 2
0 0.257662 0.453542 0.805230
1 0.060493 0.463148 0.715994
2 0.452379 0.470137 0.965709
3 0.447546 0.964252 0.163247
4 0.187212 0.973557 0.871090
>>> df2
0 1 2
0 0.060493 0.463148 0.715994
1 0.452379 0.470137 0.965709
>>> df3
0 1 2
0 0.452379 0.470137 0.965709
1 0.447546 0.964252 0.163247
如您所见,只有行0.452379 0.470137 0.965709
是所有三个数据帧的公用行。为了提取它,我尝试:
>>> pd.concat([df1, df2, df3], join='inner')
0 1 2
0 0.257662 0.453542 0.805230
1 0.060493 0.463148 0.715994
2 0.452379 0.470137 0.965709
3 0.447546 0.964252 0.163247
4 0.187212 0.973557 0.871090
0 0.060493 0.463148 0.715994
1 0.452379 0.470137 0.965709
0 0.452379 0.470137 0.965709
1 0.447546 0.964252 0.163247
因此,join==internal
似乎不起作用!我还应该指出,ignore\u index=True
对行为没有影响。在实际Python中,建议使用axis=1
。然而,我认为这是错误的:
>>> pd.concat([df1, df2, df3], join='inner', axis=1)
0 1 2 0 1 2 0 1 2
0 0.257662 0.453542 0.805230 0.060493 0.463148 0.715994 0.452379 0.470137 0.965709
1 0.060493 0.463148 0.715994 0.452379 0.470137 0.965709 0.447546 0.964252 0.163247
我现在做的有什么问题吗?另外,如果这种方法不起作用,我如何从几个数据帧中提取公共行?我正在使用熊猫版本0.25.3。试试这个
df = pd.merge(df1, df2, how='inner', on=[col1, col2, col3])
简而言之,使用
reduce(lambda left,right:pd.merge(left,right,on=cols),dfs)
,
(请参见方法2-确保包括functools import reduce中的),但请参见pd.concat
的说明(方法1):
方法#1(concat
):我认为最具活力、最稳健的pd.concat
方法(特别是我尝试过的concat
方法)是使用。与下面的第二种方法相比,此解决方案的唯一主要好处是您不必使用额外的库;但是,我认为您也可以使用merge
编写类似的代码,而无需使用其他库:
dfs = [df1, df2, df3]
cols = [*df1.columns] # enclosing with [*] is the same as tolist()
for df in dfs:
df.set_index(cols, inplace=True) # can only use inplace when looping through dfs (at least using my simpler method)
pd.concat(dfs, join='inner', axis=1).reset_index() # see below paragraph for explanation
Out[1]:
0 1 2
0 0.452379 0.470137 0.965709
请注意,join='internal'
表示您是在索引
上加入的,而不是唯一的行。另外,join
仅在通过axis=1
时才起作用,这就是为什么实际上什么都不发生
方法#2:():
@Anky指出,how='internal'
是merge
的默认值。这实际上是我贴出的第一个答案,但我对预期的产出感到困惑,于是转了一圈。请参阅下面最简单的答案:
from functools import reduce
dfs = [df1, df2, df3]
cols = [*df1.columns]
reduce(lambda left,right: pd.merge(left,right,on=cols), dfs)
Out[2]:
0 1 2
0 0.452379 0.470137 0.965709
#添加额外的标记列
df_列表=[df1、df2、df3]
对于i,枚举中的dfi(df_列表):
dfi['tag']=i+1
#合并数据帧
df=pd.concat([df1,df2,df3],ignore_index=True)
#查找重复的行
cols=df.columns[:-1].tolist()
cond=df[cols]。重复(keep=False)
obj=df[cond].groupby(cols)['tag'].agg(元组)
#滤器
条件=对象映射(len)=len(df_列表)
obj[秒]
obj
示例:
# 0 1 2
# 0.148080 0.837398 0.565498 (1, 3)
# 0.572673 0.256735 0.620923 (1, 2, 3)
# 0.822542 0.856137 0.645639 (1, 2)
# Name: tag, dtype: object
如果试图查找公用行,请执行以下操作:
temp = pd.concat([df1, df2, df3])
temp[temp.duplicated()]
不过,我相信有一个更优雅的解决方案。与@Ajay a所说的方式类似
import numpy as np
import pandas as pd
x = np.random.random(size=(5, 3))
df1 = pd.DataFrame(x)
df2 = pd.DataFrame(x[1:3])
df3 = pd.DataFrame(x[2:4])
那么
然后您可以使用pd.merge
和how='inner'
pd.merge(df2, df3, how='inner')
Out[25]:
0 1 2
0 0.972633 0.685077 0.191109
或者如果你要找的是三者的交叉点
pd.merge(pd.merge(df1,df2,how='inner'), df3, how='inner')
Out[26]:
0 1 2
0 0.972633 0.685077 0.191109
使用for循环
处理df\u列表
df_list=[df1、df2、df3]
df_交点=df1
对于df_列表[1:]中的df:
df_intersection=pd.merge(df_intersection,df,how='inner')
所需的输出是什么?@U11 Forward:一个只有公共行的数据帧。我知道这一点,但我不想要这个。为了让它工作,我必须知道我要提前合并多少帧。我想传递数据帧列表。我不能接受使用pd.merge的解决方案。我知道这很有效,但我的问题是我不知道在哪个交集上执行多少数据帧。这就是我使用pd.concat的原因,它接受数据帧列表。@也许您可以使用for循环
来完成这项工作:dfu list=[df1,df2,df3];df_交叉口=df1;对于df_列表中的df[1:]:df_intersection=pd.merge(df_intersection,df,how='inner')
@Ferris:谢谢!这实际上是一个聪明的解决方法。也许你应该写下这个作为答案。我可以试试这个,不过这个看起来很复杂。我的简单问题是“pd.concat为什么不加入class='inner'工作?”@Peace有两个原因。见我更新答案的第一段。我还向您展示了如何按照您的方式获得所需的输出。我想我已经提供了您正在寻找的两种优雅的方法。如果你想用concat来做,那么你必须有一个“公共”索引。节日快乐!感谢@anky提到默认设置的好处。我会更新我的答案并相信你:)我可能误解了预期的输出,但我不相信这是正确的。我认为预期的输出是一行:0.972633 0.685077 0.191109
pd.merge(pd.merge(df1,df2,how='inner'), df3, how='inner')
Out[26]:
0 1 2
0 0.972633 0.685077 0.191109