n 个数据帧的行交集的并集

The union of the intersection of rows of n dataframes

假设我有 n dataframes,在这个例子中 n = 3.

**df1**
       A  B     C
0   True  3  21.0
1   True  1  23.0
2  False  2  25.0
3  False  4  25.5
4  False  1  25.0
5  True   0  26.0

**df2**
       A  B     C
0   True  3  21.0
1   True  1  23.0
2  False  2  25.0
3  False  4  25.5
4  True   2  19.0

**df3**
       A  B     C
0   True  3  21.0
1   True  2  23.0
2  False  2  25.0
3  False  1  25.0
4  False  4  25.5
5  True   0  27.50

**dfn** ...

我想要一个 dataframe,其中包含列 C 中的值出现在每个 dataframe dfn 中的所有行。所以这是列上 dataframesintersection 的一种 union,在本例中是 C 列。因此对于上述数据帧,具有 19.0、26.0 和 27.50 的行不'进入决赛 dataframe 即:

**Expected df**
0   True  3  21.0
1   True  1  23.0
2  False  2  25.0
3  False  4  25.5
4  False  1  25.0
0   True  3  21.0
1   True  1  23.0
2  False  2  25.0
3  False  4  25.5
0   True  3  21.0
1   True  2  23.0
2  False  2  25.0
3  False  1  25.0
4  False  4  25.5

所以一行继续到 finaldataframe当且仅当,C 列中的值是见于 全部 dataframes.

可重现代码:

import pandas as pd
df1 = pd.DataFrame({'A': [True,True,False,False,False,True], 'B': [3,1,2,4,1,0],
                    'C': [21.0,23.0,25.0,25.5,25.0,26.0]})
df2 = pd.DataFrame({'A': [True,True,False,False,False], 'B': [3,1,2,4,2],
                    'C': [21.0,23.0,25.0,25.5,19.0]})
df3 = pd.DataFrame({'A': [True,True,False,False,False,True], 'B': [3,2,2,1,4,0],
                    'C': [21.0,23.0,25.0,25.0,25.5,27.5]})
dfn = ...

为简单起见,将数据帧存储在列表中。我们将利用集合操作来尽可能地加快速度。

df_list = [df1, df2, df3, ...]
common_idx = set.intersection(*[set(df['C']) for df in df_list]) 

print(common_idx)
{21.0, 23.0, 25.0, 25.5}

感谢@smci 的改进! set.intersection 将找到所有索引的交集。最后,调用pd.concat,垂直连接数据帧,然后使用query过滤上一步获得的公共索引。

pd.concat(df_list, ignore_index=True).query('C in @common_idx')

        A  B     C
0    True  3  21.0
1    True  1  23.0
2   False  2  25.0
3   False  4  25.5
4   False  1  25.0
5    True  3  21.0
6    True  1  23.0
7   False  2  25.0
8   False  4  25.5
9    True  3  21.0
10   True  2  23.0
11  False  2  25.0
12  False  1  25.0
13  False  4  25.5

您可以使用 pd.concat:

# merge column C from all DataFrames
df_C = pd.concat([df1,df2,df3],1)['C']
# concat all DataFrames
df_all = pd.concat([df1,df2,df3])
# only extract rows with its C value appears in all DataFrames C columns.
df_all.loc[df_all.apply(lambda x: df_C.eq(x.C).sum().all(), axis=1)]
Out[105]: 
       A  B     C
0   True  3  21.0
1   True  1  23.0
2  False  2  25.0
3  False  4  25.5
4  False  1  25.0
0   True  3  21.0
1   True  1  23.0
2  False  2  25.0
3  False  4  25.5
0   True  3  21.0
1   True  2  23.0
2  False  2  25.0
3  False  1  25.0
4  False  4  25.5

最直接的方法似乎是计算(n 向交集)公共 C 值(作为 set/list),然后使用 .isin:

进行过滤
common_C_values = set.intersection(set(df1['C']), set(df2['C']), set(df3['C']))
df_all = pd.concat([df1,df2,df3])
df_all = df_all[ df_all['C'].isin(common_C_values) ]