假设我有两个数据帧,我想合并,但是因为行和列重叠而存在冲突。我想传递一个函数来解决冲突,而不是复制行。可以这样做吗?
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
当我真正想要的是真值来覆盖Falses(或NaN),我可以做,例如,传递“or”函数来解决这种重复冲突。这可以在熊猫中完成吗?
结果应如下所示:
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时冲突之间的一般解决方案,最好是通过传递函数。
答案 0 :(得分:3)
而不是使用concat使用merge:
>> 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=True
和right_index=True
保持行索引不变
答案 1 :(得分:3)
这应该可以满足您的需求:
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)
答案 2 :(得分:1)
当有类似的需要将列与简单的冲突解决方案合并时发现了这个问题:一列中的值覆盖另一列中的值。与 create 和传入解析函数相比,pandas 提供了一个帮助器 Series.combine_first(other)
,它选择调用者的值而不是其他者的值。