繁体   English   中英

解决 Pandas 数据框合并与函数的冲突?

[英]Resolve Pandas data frame merge conflicts with a function?

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

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 值来覆盖 Falses(或 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 DataFrames 时在冲突之间进行仲裁的通用解决方案,最好是通过传递的函数。

而不是使用 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保持行索引不变

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

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)

当有类似的需要将列与简单的冲突解决方案合并时发现了这个问题:一列中的值覆盖另一列中的值。 与 create 和传入解析函数相比,pandas 提供了一个帮助程序Series.combine_first(other)来选择调用者的值而Series.combine_first(other)的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM