Ash*_*osh 2 python dataframe python-3.x pandas
我有多个pandas数据帧,为了保持简单,让我说我有三个.
>> df1=
col1 col2
id1 A B
id2 C D
id3 B A
id4 E F
>> df2=
col1 col2
id1 B A
id2 D C
id3 M N
id4 F E
>> df3=
col1 col2
id1 A B
id2 D C
id3 N M
id4 E F
Run Code Online (Sandbox Code Playgroud)
需要的结果是:
>> df=
col1 col2
id1 A B
id2 C D
id3 E F
Run Code Online (Sandbox Code Playgroud)
因为对(A,B),(C,D),(E,F)出现在所有数据帧中,尽管它可以颠倒.
使用pandas merge时,只考虑列的传递方式.为了检查我的观察,我尝试了两个数据框的以下代码:
df1['reverse_1'] = (df1.col1+df1.col2).isin(df2.col1 + df2.col2)
df1['reverse_2'] = (df1.col1+df1.col2).isin(df2.col2 + df2.col1)
Run Code Online (Sandbox Code Playgroud)
我发现结果不同:
col1 col2 reverse_1 reverse_2
a b False True
c d False True
b a True False
e f False True
Run Code Online (Sandbox Code Playgroud)
因此,如果我从reverse_1和reverse_2列收集'True'值,我可以获得两个数据帧的交叉.即使我为两个数据帧执行此操作,我也不清楚如何继续处理更多数据帧(超过两个).我对此感到困惑.有什么建议?
您可以创建DataFrames 列表并在每行的列表理解排序中删除重复项:
dfs = [df1,df2,df3]
L = [pd.DataFrame(np.sort(x.values, axis=1), columns=x.columns).drop_duplicates()
for x in dfs]
print (L)
[ col1 col2
0 A B
1 C D
3 E F, col1 col2
0 A B
1 C D
2 M N
3 E F, col1 col2
0 A B
1 C D
2 M N
3 E F]
Run Code Online (Sandbox Code Playgroud)
然后merge list of DataFrames按所有列(无参数on):
from functools import reduce
df = reduce(lambda left,right: pd.merge(left,right), L)
print (df)
col1 col2
0 A B
1 C D
2 E F
Run Code Online (Sandbox Code Playgroud)
@pygo的另一个解决方案:
创建index由frozensets,不联合起来concat与inner加盟,最后通过去除通过索引重复duplicated使用boolean indexing,并iloc为获得第2列:
df = pd.concat([x.set_index(x.apply(frozenset, axis=1)) for x in dfs], axis=1, join='inner')
df = df.iloc[~df.index.duplicated(), :2]
print (df)
col1 col2
(B, A) A B
(C, D) C D
(F, E) E F
Run Code Online (Sandbox Code Playgroud)