【发布时间】:2020-06-02 18:34:15
【问题描述】:
我有两个数据框,df1 和 df2。 df1 具有以宽格式排列的重复观察,而 df2 以长格式排列。
import pandas as pd
df1 = pd.DataFrame({"ID":[1,2,3],"colA_1":[1,2,3],"date1":["1.1.2001", "2.1.2001","3.1.2001"],"colA_2":[4,5,6],"date2":["1.1.2002", "2.1.2002","3.1.2002"]})
df2 = pd.DataFrame({"ID":[1,1,2,2,3,3],"col1":[1,1.5,2,2.5,3,3.5],"date":["1.1.2001", "1.1.2002","2.1.2001","2.1.2002","3.1.2001","3.1.2002"], "col3":[11,12,13,14,15,16],"col4":[21,22,23,24,25,26]})
df1 看起来像:
ID colA_1 date1 colA_2 date2
0 1 1 1.1.2001 4 1.1.2002
1 2 2 2.1.2001 5 2.1.2002
2 3 3 3.1.2001 6 3.1.2002
df2 看起来像:
ID col1 date1 col3 col4
0 1 1.0 1.1.2001 11 21
1 1 1.5 1.1.2002 12 22
2 2 2.0 2.1.2001 13 23
3 2 2.5 2.1.2002 14 24
4 3 3.0 3.1.2001 15 25
5 3 3.5 3.1.2002 16 26
6 3 4.0 4.1.2002 17 27
我想从 df2 中取出一个给定的列,“col3”,然后:
(1) 如果 df2 中的“ID”和“date”列与 df1 中的“ID”和“date1”列匹配,我想将该值放在 df1 中名为“colB_1”的新列中。
(2) 否则,如果 df2 中的“ID”和“date”列与 df1 中的“ID”和“date2”列匹配,我想将该值放在 df1 中名为“colB_2”的新列中。
(3) 否则,如果 df2 中的“ID”和“date”列与(“ID”和“date1”)或(“ID”和“date2”)都不匹配,我想忽略这些行.
因此,这个输出数据帧 df3 的输出应该如下所示:
ID colA_1 date1 colA_2 date2 colB_1 colB_2
0 1 1 1.1.2001 4 1.1.2002 11 12
1 2 2 2.1.2001 5 2.1.2002 13 14
2 3 3 3.1.2001 6 3.1.2002 15 16
最好的方法是什么?
我找到了this 链接,但答案不适用于我的情况。我想要一种非常明确的方式来指定列匹配。我认为 df.mask 可能可以帮助我,但我不确定如何实现它。
例如:以下代码
df3 = df1.copy()
df3["colB_1"] = ""
df3["colB_2"] = ""
filter1 = (df1["ID"] == df2["ID"]) & (df1["date1"] == df2["date"])
filter2 = (df1["ID"] == df2["ID"]) & (df1["date2"] == df2["date"])
df3["colB_1"] = df.mask(filter1, other=df2["col3"])
df3["colB_2"] = df.mask(filter2, other=df2["col3"])
给出错误
ValueError: Can only compare identically-labeled Series objects
我问了这个问题previously,它被标记为已关闭;我的问题被标记为与this 重复。然而,这种情况并非如此。链接问题中的答案建议使用map 或df.merge。地图不适用于多种条件(在我的情况下,ID 和日期)。当 df1 和 df2 中要合并的列名之一不同(例如,“date”和“date1”)时,df.merge(匹配多个列的答案)在我的情况下不起作用。
例如下面的代码:
df3 = df1.merge(df2[["ID","date","col3"]], on=['ID','date1'], how='left')
因密钥错误而失败。
另外值得注意的是,我将处理许多不同的文件,具有许多不同的列命名方案,并且每次都需要不同的子集。这就是为什么我想要一个明确命名列和条件的答案。
对此的任何帮助将不胜感激。
【问题讨论】: