更新/合并和更新熊猫列的子集

时间:2019-02-13 14:52:49

标签: python python-3.x pandas

我有df1

  ColA  ColB   ID1    ColC   ID2
0    a   1.0  45.0     xyz  23.0
1    b   2.0  56.0     abc  24.0
2    c   3.0  34.0  qwerty  28.0
3    d   4.0  34.0     wer  33.0
4    e   NaN   NaN     NaN   NaN

df2

  ColA  ColB   ID1 ColC   ID2
0    i     0  45.0  NaN  23.0
1    j     0  56.0  NaN  24.0
2  NaN     0   NaN   fd  25.0
3  NaN     0   NaN  NaN  26.0
4  NaN     0  23.0    e  45.0
5  NaN     0  45.0    r   NaN
6  NaN     0  56.0  NaN  29.0

我试图仅在可以作为{= ['ColA','ColB']的列上更新df2,其中ID1ID2都在2个dfs中匹配。

预期输出:

  ColA   ColB   ID1  ColC    ID2
0    a    1.0  45.0   NaN   23.0
1    b    2.0  56.0   NaN   24.0
2  NaN      0   NaN    fd   25.0
3  NaN      0   NaN   NaN   26.0
4  NaN      0   23.0    e   45.0
5  NaN      0   45.0    r    NaN
6  NaN      0   56.0  NaN   29.0

到目前为止,我已经尝试过:

u = df1.set_index(['ID1','ID2'])
u = u.loc[u.index.dropna()]
v = df2.set_index(['ID1','ID2'])
v= v.loc[v.index.dropna()]
v.update(u)
v.reset_index()

哪个可以给我正确的更新(但是我松散了NaN的ID),更新也发生在我不想要的ColC上:

    ID1      ID2    ColA    ColB    ColC
0   45.0    23.0    a       1.0     xyz
1   56.0    24.0    b       2.0     abc
2   23.0    45.0    NaN     0.0     e
3   56.0    29.0    NaN     0.0     NaN

我也尝试过merge和Combine_first。无法根据选择列表找出执行此操作的最佳方法。

3 个答案:

答案 0 :(得分:2)

这是一种方法

df1

  ColA  ColB   ID1    ColC   ID2
0    a   1.0  45.0     xyz  23.0
1    b   2.0  56.0     abc  24.0
2    c   3.0  34.0  qwerty  28.0
3    d   4.0  34.0     wer  33.0
4    e   NaN   NaN     NaN   NaN

df2

  ColA  ColB   ID1 ColC   ID2
0    i     0  45.0  NaN  23.0
1    j     0  56.0  NaN  24.0
2  NaN     0   NaN   fd  25.0
3  NaN     0   NaN  NaN  26.0
4  NaN     0  23.0    e  45.0
5  NaN     0  45.0    r   NaN
6  NaN     0  56.0  NaN  29.0


df3 = df1.merge(df2, on=['ID1','ID2'], left_index=True)[['ColA_x','ColB_x']]
df2.loc[df3.index, 'ColA'] = df3['ColA_x']
df2.loc[df3.index, 'ColB'] = df3['ColB_x']

输出

  ColA  ColB   ID1 ColC   ID2
0    a   1.0  45.0  NaN  23.0
1    b   2.0  56.0  NaN  24.0
2  NaN   0.0   NaN   fd  25.0
3  NaN   0.0   NaN  NaN  26.0
4  NaN   0.0  23.0    e  45.0
5  NaN   0.0  45.0    r   NaN
6  NaN   0.0  56.0  NaN  29.0

答案 1 :(得分:2)

mergeright一起使用,然后combine_first

choice= ['ColA','ColB']
joined = ['ID1','ID2']
c = choice + joined

df3 = df1[c].merge(df2[c], on=joined, suffixes=('','_'), how='right')[c]
print (df3)
  ColA  ColB   ID1   ID2
0    a   1.0  45.0  23.0
1    b   2.0  56.0  24.0
2  NaN   NaN   NaN  25.0
3  NaN   NaN   NaN  26.0
4  NaN   NaN  23.0  45.0
5  NaN   NaN  45.0   NaN
6  NaN   NaN  56.0  29.0

df2[c] = df3.combine_first(df2[c])
print (df2)
  ColA  ColB   ID1 ColC   ID2
0    a   1.0  45.0  NaN  23.0
1    b   2.0  56.0  NaN  24.0
2  NaN   0.0   NaN   fd  25.0
3  NaN   0.0   NaN  NaN  26.0
4  NaN   0.0  23.0    e  45.0
5  NaN   0.0  45.0    r   NaN
6  NaN   0.0  56.0  NaN  29.0

答案 2 :(得分:1)

0.24中似乎仍然存在问题,其中NaNNaN合并为键。通过在合并之前删除那些记录来防止这种情况。我假设['ID1', 'ID2']df1的唯一键(对于两者都不为空的行):

keys = ['ID1', 'ID2']
updates = ['ColA', 'ColB']
df3 = df2.merge(df1[updates+keys].dropna(subset=keys), on=keys, how='left')

然后解决信息。如果不是df1,请获取null中的值,否则请获取df2中的值。在最新版本的python中,应该对合并输出进行排序,以便在_x列的左侧出现重复的列_y。如果没有,请对索引进行排序

#df3 =  df3.sort_index(axis=1)  # If not sorted _x left of _y
df3.groupby([x[0] for x in df3.columns.str.split('_')], axis=1).apply(lambda x: x.ffill(1).iloc[:, -1])

  ColA  ColB ColC   ID1   ID2
0    a   1.0  NaN  45.0  23.0
1    b   2.0  NaN  56.0  24.0
2  NaN   0.0   fd   NaN  25.0
3  NaN   0.0  NaN   NaN  26.0
4  NaN   0.0    e  23.0  45.0
5  NaN   0.0    r  45.0   NaN
6  NaN   0.0  NaN  56.0  29.0