合并“左”,但在可能的情况下覆盖“右”值

Cil*_*rek 5 python join pandas

目的

我已经查看了有关合并的pandas文档,但对在“左”合并中有效覆盖值有疑问。我可以简单地为一对值做到这一点(如看到这里),但尝试做多对,当它变得混乱。

设定

如果我采用以下数据框:

a = pd.DataFrame({
   'id': [0,1,2,3,4,5,6,7,8,9],
    'val': [100,100,100,100,100,100,100,100,100,100]
})

b = pd.DataFrame({
    'id':[0,2,7],
    'val': [500, 500, 500]
})
Run Code Online (Sandbox Code Playgroud)

我可以合并它们:

df = a.merge(b, on=['id'], how='left', suffixes=('','_y'))
Run Code Online (Sandbox Code Playgroud)

要得到

   id  val  val_y
0   0  100  500.0
1   1  100    NaN
2   2  100  500.0
3   3  100    NaN
4   4  100    NaN
5   5  100    NaN
6   6  100    NaN
7   7  100  500.0
8   8  100    NaN
9   9  100    NaN
Run Code Online (Sandbox Code Playgroud)

我想保留不存在右值的左值,但在可能的情况下用右值覆盖。

期望的结果是:

   id    val
0   0  500.0
1   1  100.0
2   2  500.0
3   3  100.0
4   4  100.0
5   5  100.0
6   6  100.0
7   7  500.0
8   8  100.0
9   9  100.0
Run Code Online (Sandbox Code Playgroud)

我的尝试

我知道我可以用几行代码来实现:

df.loc[df.val_y.notnull(), 'val'] = df[df.val_y.notnull()].val_y
df = df.drop(['val_y'], axis = 1)
Run Code Online (Sandbox Code Playgroud)

或者我可以使用这个问题逻辑

但这在我要应用此逻辑的多个列配对中变得混乱。

例如,使用ab下面:

a = pd.DataFrame({
   'id': [0,1,2,3,4,5,6,7,8,9],
    'val': [100,100,100,100,100,100,100,100,100,100],
    'val_2':[200, 200, 200, 200, 200, 200, 200, 200, 200, 200]
})
b = pd.DataFrame({
    'id':[0,2,7],
    'val': [500, 500, 500],
    'val_2': [500,500,500]
})
Run Code Online (Sandbox Code Playgroud)

有没有更快,更清洁的方法来获得我想要的结果?

cs9*_*s95 5

我会使用set_index和来做到这一点update

u = a.set_index('id')
u.update(b.set_index('id'))  # Update a's values with b's values

u.reset_index()

   id    val
0   0  500.0
1   1  100.0
2   2  500.0
3   3  100.0
4   4  100.0
5   5  100.0
6   6  100.0
7   7  500.0
8   8  100.0
9   9  100.0
Run Code Online (Sandbox Code Playgroud)

更新在索引上对齐。因此,在执行更新步骤之前,我将“ id”设置为两个DataFrame中的索引。

请注意,“ id”列必须是唯一的。


另一种选择是使用concatdrop_duplicates

pd.concat([b, a]).drop_duplicates('id').sort_values('id')

   id  val
0   0  500
1   1  100
1   2  500
3   3  100
4   4  100
5   5  100
6   6  100
2   7  500
8   8  100
9   9  100
Run Code Online (Sandbox Code Playgroud)

由于要b覆盖a,因此b必须首先执行concat