【问题标题】:The union of the intersection of rows of n dataframesn个数据帧的行交集的并集
【发布时间】:2026-01-04 03:00:01
【问题描述】:

假设我有 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,其中包含每个dataframe dfn 中出现C 列值的所有行。所以这是intersectiondataframes 在列上的一种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当且仅当,在all中可以看到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 = ...

【问题讨论】:

  • 您的预期结果是什么?我不确定我是否理解你描述的逻辑。
  • 查看我发布的预期结果的编辑。
  • 我无法理解这个问题,而且它不同意它自己的例子。值 C = 23.0 在任何 dfs 中都没有重复,但它通过了过滤器。最后在底部正确说明:当且仅当在所有数据帧中都可以看到 C 列中的值时,才在一行中过滤 不要说“重复”
  • 抱歉,我可能在您查看数据时编辑了数据。现在预期是正确的。
  • 我发布了一个不需要迭代的解决方案,或者一个 n x m 中间矩阵。

标签: pandas filter intersection concat


【解决方案1】:

直接的方法似乎是计算(n 路交点)公共 C 值(作为集合/列表),然后使用 .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) ]

【讨论】:

    【解决方案2】:

    你可以使用 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 x m 矩阵df_C 是浪费时间和内存。只需直接计算常见的 C 值(作为集合/列表),然后使用测试进行过滤df['C'].isin()
    【解决方案3】:

    为简单起见,请将您的数据框存储在一个列表中。我们将使用集合操作来尽可能加快速度。

    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,将dataframes垂直加入,然后使用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
    

    【讨论】:

    • 好的,但我需要按原始数据框的顺序排列结果。根据标准,它们堆叠在另一个之上。我想我可以自己排序....
    • @Ivan 我发布了一个更简单的解决方案,可以保留订单。
    • 感谢 COLDSPEED。这个解决方案有一些非常吸引人的地方。我认为这是在其他情况下可以遵循的模因。
    • 当然。您可能会在您对新改进的 v2.0 的回答中承认我的建议... ;-)
    • @smci 很公平,也给了你一个赞成票。干杯
    最近更新 更多