python - `pd.concat` 与 `join=='inner'` 不会产生 pandas 数据帧的交集
问题描述
我正在尝试使用 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[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==inner
似乎不起作用!我还应该指出,这ignore_index=True
对行为没有影响。在一篇关于 Real 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。
解决方案
简而言之,使用reduce(lambda left,right: pd.merge(left,right,on=cols), dfs)
, (请参阅方法 #2 - 确保包含from 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='inner'
意味着您加入的index
不是唯一的行。此外,join
只有通过 才重要axis=1
,这就是为什么实际上什么都没有发生的原因。
方法 #2 : (merge
与reduce
):
@Anky 指出这how='inner'
是默认的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
推荐阅读
- javascript - 将 JS 代码从 NodeJS HTML 文件导出到 JS 文件
- dataframe - Spark:如何根据子集条件过滤掉数据
- javascript - 是否有 Firefox 替代 Google Chrome 中可用的 debug() 函数?
- android - 如何在更新时将 React Native Android APK 替换为 Native Android APK?
- ios - 无法在 iOS 13 中转换为 mp4
- javascript - 如何使用级别嵌套的 JSON 对象在 HTML 中创建树结构
- grafana - 导入后 Grafana 仪表板空白
- python-3.x - 如果函数中的语句没有返回所需的结果
- java - Android Studio 应用程序崩溃错误:AndroidRuntime: FATAL EXCEPTION: main
- python - 如何防止keras重命名图层