【问题标题】:Resolve Pandas data frame merge conflicts with a function?用函数解决 Pandas 数据框合并冲突?
【发布时间】:2021-03-11 03:43:51
【问题描述】:

假设我有两个数据框,我想合并它们,但由于行和列重叠而存在冲突。我不想复制行,而是想传递一个函数来解决冲突。这个可以吗?

import numpy as np
import pandas as pd
dates1 = pd.date_range("2014-01-01", periods = 4)
dates2 = pd.date_range("2014-01-03", periods = 4)
cols1 = list("ABCD")
cols2 = list("CDEF")
df1 = pd.DataFrame(np.ones([4, 4], dtype = "bool"), index = dates1, columns = cols1)
df2 = pd.DataFrame(np.zeros([4, 4], dtype = "bool"), index = dates2, columns = cols2)

In [317]: df1
Out[317]: 
               A     B     C     D
2014-01-01  True  True  True  True
2014-01-02  True  True  True  True
2014-01-03  True  True  True  True
2014-01-04  True  True  True  True

In [318]: df2
Out[318]: 
                C      D      E      F
2014-01-03  False  False  False  False
2014-01-04  False  False  False  False
2014-01-05  False  False  False  False
2014-01-06  False  False  False  False

如您所见,两个数据框在 C 和 D 列以及 2014-01-03 和 2014-01-04 行中重叠。所以现在当我合并它们时,由于这种冲突,我得到了重复的行:

In [321]: pd.concat([df1, df2])
Out[321]: 
               A     B      C      D      E      F
2014-01-01  True  True   True   True    NaN    NaN
2014-01-02  True  True   True   True    NaN    NaN
2014-01-03  True  True   True   True    NaN    NaN
2014-01-04  True  True   True   True    NaN    NaN
2014-01-03   NaN   NaN  False  False  False  False
2014-01-04   NaN   NaN  False  False  False  False
2014-01-05   NaN   NaN  False  False  False  False
2014-01-06   NaN   NaN  False  False  False  False

当我真正想要的是 True 值来覆盖 False(或 NaN)时,我可以这样做,例如,通过传递“或”函数来解决此类重复冲突。这可以在 Pandas 中完成吗?

结果应该是这样的:

               A     B      C      D      E      F
2014-01-01  True  True   True   True    NaN    NaN
2014-01-02  True  True   True   True    NaN    NaN
2014-01-03  True  True   True   True  False  False
2014-01-04  True  True   True   True  False  False
2014-01-05   NaN   NaN  False  False  False  False
2014-01-06   NaN   NaN  False  False  False  False

即在没有重复的情况下,两个数据帧中的值通过,在任何一个帧都没有数据的情况下,返回一个NaN,但是在两个帧都有数据的情况下,True覆盖了False(即是,“或”)。

我正在寻找一种在合并 Pandas DataFrame 时在冲突之间进行套利的通用解决方案,最好是通过传递函数。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    不要使用 concat 使用合并:

    >> pd.merge(df1, df2, on=(df1.columns & df2.columns).tolist(), how='outer', left_index=True, right_index=True)
                   A     B      C      D      E      F
    2014-01-01  True  True   True   True    NaN    NaN
    2014-01-02  True  True   True   True    NaN    NaN
    2014-01-03  True  True   True   True  False  False
    2014-01-04  True  True   True   True  False  False
    2014-01-05   NaN   NaN  False  False  False  False
    2014-01-06   NaN   NaN  False  False  False  False
    

    on=(df1.columns & df2.columns).tolist() 参数为您提供重叠列的列表(在本例中为 ['C','D']

    how='outer' 将两个框架中的键合并(SQL:完全外连接)

    left_index=Trueright_index=True 保持行索引不变

    【讨论】:

    • 不幸的是这不起作用,因为它取决于参数的顺序。如果我这样做: pd.merge(df2, df1, on=(df1.columns & df2.columns).tolist(), how='outer', left_index=True, right_index=True).loc[:, list( "ABCDEF")],然后我得到 false 支配 true,这不是必需的。我们需要在冲突情况下应用“或”。我在同质 True 和 False 填充矩阵的 OP 中使用了一个简单的示例,但很可能 True 和 False 位于随机的非连续区域,所以我确实需要以某种方式评估冲突。跨度>
    【解决方案2】:

    这应该适用于您想要做的事情:

    def conflict_resolver(x):
    
        # If there is only one row, just return it as is
        if x.shape[0] == 1:
            return x
        # If all values are nan, just return the first row
        elif x.isna().all():
            return x[:1]
        else:
            # Remove na values and drop duplicates
            x = x.dropna().drop_duplicates()
    
            # If only 1 row of non-na data exists, just return it
            if x.shape[0] == 1:
                return x
            else:
    
                # Handle conflicts here:
                
                if isinstance(x, bool):
                    x.iloc[0] = x.any()
                    return x[:1]
    
    concat_df = pd.concat([df1, df2]).reset_index(drop=False).groupby(by='index').agg(conflict_resolver)
    

    【讨论】:

      【解决方案3】:

      当有类似的需要将列与简单的冲突解决方案组合时发现了此问题:一列中的值会覆盖另一列中的值。与创建和传入解析函数相比,pandas 提供了一个帮助器 Series.combine_first(other),它选择调用者的值而不是其他的值。

      【讨论】:

        猜你喜欢
        • 2014-10-26
        • 2012-03-01
        • 2015-10-15
        • 2019-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多