【问题标题】:How to find out what rows are in Pandas DataFrame A only, but not in B (or vice versa), and what rows are in A, as well as in B (or vice versa)?如何找出 Pandas DataFrame A 中的哪些行,而不是 B 中的行(反之亦然),以及 A 中的行以及 B 中的行(反之亦然)?
【发布时间】:2022-02-17 04:52:54
【问题描述】:

有没有想过Pandas DataFrame A 中只有哪些行,B 中没有(反之亦然),A 和 B 中都有哪些行(反之亦然)?

虽然存在pandas.DataFrame.diff()(更像是逐个元素的减法)、pandas.Index.intersection(仅适用于索引)和pandas.DataFrame.merge()(更像是用于合并两个 DataFrame 的 SQL 连接),但它们都没有正是我们需要的……

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    因此我编写了这两个函数 df_diff()df_overlap() 就是为了做到这一点——请参阅下面的可视化演示和代码。

    关于他们的伟大之处:

    • 可以在任何列上进行比较(不仅在索引上 - 如果省略参数 on_A 和/或 on_B,则默认在索引上进行比较)
    • 可以在不同的列组合上进行比较(如 DataFrame A 中的 column_this 和 DataFrame B 中的 column_that。您也可以自己插入连接的 id 列,然后在它们上进行比较)
    • 可以正确处理重复/丢失的 ID
    • 它们主要基于集合操作——超快
    • 具有错误检查/处理(如果未找到结果或输入无效,将安全返回空 DataFrame)

    要使用这些功能,只需从下面复制它们,或访问我的GitHub repo 以获取完整的用例!

    import pandas as pd
    
    def df_diff(df_A: pd.DataFrame, df_B: pd.DataFrame, on_A: str = "", on_B: str = "") -> pd.DataFrame:
        """
        Function: Compare DataFrame "A" and "B" to find rows only in "A" but not in "B"
        Input:
            df_A: DataFrame "A" ("left table")
            df_B: DataFrame "B" ("right table")
            on_A: column name in DataFrame "A" to compare on. If not provided/valid, will default to using df_A's index
            on_B: column name in DataFrame "B" to compare on. If not provided/valid, will default to using df_B's index
        
        Output:
            DataFrame containing diff result (all rows only in df_A but not in df_B, and same columns as df_A)
            If find zero rows, will return a DataFrame of 0 row and same columns as df_A (can be checked by `df_output.empty and df_output.shape[1] != 0`)
            If input is not valid DataFrame, will return a DataFrame of 0 row and 0 column (can be checked by `df_output.empty and df_output.shape[1] == 0`)
        
        Dependency: `import pandas as pd`
        History: 2022-02-07 Developed by frank-yifei-wang@GitHub
        """
        
        if type(df_A) != pd.core.frame.DataFrame or type(df_B) != pd.core.frame.DataFrame: 
            return pd.DataFrame()
        
        if on_A != "" and on_A in df_A.columns: 
            id_col_A = df_A[on_A]
        else:
            id_col_A = df_A.index
        if on_B != "" and on_B in df_B.columns: 
            id_col_B = df_B[on_B]
        else:
            id_col_B = df_B.index
        
        id_set_A = set(id_col_A)
        id_set_B = set(id_col_B)
    
        id_set_diff = id_set_A.difference(id_set_B)
        df_output = df_A[id_col_A.isin(id_set_diff)].copy()
    
        return df_output
    
    def df_overlap(df_A: pd.DataFrame, df_B: pd.DataFrame, on_A: str = "", on_B: str = "") -> pd.DataFrame:
        """
        Function: Compare DataFrame "A" and "B" to find rows in "A" and also in "B"
        Input:
            df_A: DataFrame "A" ("left table")
            df_B: DataFrame "B" ("right table")
            on_A: column name in DataFrame "A" to compare on. If not provided/valid, will default to using df_A's index
            on_B: column name in DataFrame "B" to compare on. If not provided/valid, will default to using df_B's index
        
        Output:
            DataFrame containing overlap result (all rows in df_A and also in df_B, and same columns as df_A)
            Note: result of df_overlap(df_A, df_B) (= a slice of df_A) is different from df_overlap(df_B, df_A) (= a slice of df_B)
            If find zero rows, will return a DataFrame of 0 row and same columns as df_A (can be checked by `df_output.empty and df_output.shape[1] != 0`)
            If input is not valid DataFrame, will return a DataFrame of 0 row and 0 column (can be checked by `df_output.empty and df_output.shape[1] == 0`)
        
        Dependency: `import pandas as pd`
        History: 2022-02-07 Developed by frank-yifei-wang@GitHub
        """
        
        if type(df_A) != pd.core.frame.DataFrame or type(df_B) != pd.core.frame.DataFrame: 
            return pd.DataFrame()
        
        if on_A != "" and on_A in df_A.columns: 
            id_col_A = df_A[on_A]
        else:
            id_col_A = df_A.index
        if on_B != "" and on_B in df_B.columns: 
            id_col_B = df_B[on_B]
        else:
            id_col_B = df_B.index
        
        id_set_A = set(id_col_A)
        id_set_B = set(id_col_B)
    
        id_set_overlap = id_set_A.intersection(id_set_B)
        df_output = df_A[id_col_A.isin(id_set_overlap)].copy()
    
        return df_output
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      • 2016-07-26
      相关资源
      最近更新 更多