假设有一个 DataFrame df1
,其中包含 INDEX
、Column1
、Column2
和另一个 df2
与 INDEX
、Column1
、Column3
。
两个 INDEX
都有相似的值,所以我想用它来合并一个表的信息到另一个表。
其他用户告诉我要执行以下操作:
df1.update(df2, join='left', overwrite=True)
如果两个索引具有相似的值,则此方法有效。结果将是 df1 现在将具有 INDEX
、Column1
(来自 df2
)和 Column2
(源自 >df1
)。 Column3
未添加到 df1
(此行为是需要的,而不是添加所有内容的“merge
”命令)。
现在,我只想在少数情况下基于 Column2 更新 df1。我认为这会起作用:
df1[df1['Column2'] == 'Cond'].update(df2, join='left', overwrite=True)
但事实并非如此;有时我会收到错误,其他命令有效,但所有 df1
值已被修改。
知道如何做到这一点吗?
PS:使用 .loc
不起作用,因为这要求您搜索的任何 INDEX 都存在,但事实并非如此。
编辑:附加示例
In [37]: df1 = pd.DataFrame([['USA',1],['USA',2],['USA',3],['FRA',1],['FRA',2]], columns = ['country', 'value'])
In [38]: df2 = pd.DataFrame([['USA',10],['FRA',20]], columns = ['country', 'value'])
In [39]: df1 = df1.set_index('country')
In [40]: df2 = df2.set_index('country')
In [41]: mask = df1['value'] >= 2
In [42]: idx = df1.index[mask]
In [43]: idx = idx.unique()
In [44]: df1
Out[44]:
value
country
USA 1
USA 2
USA 3
FRA 1
FRA 2
In [45]: df2
Out[45]:
value
country
USA 10
FRA 20
In [46]: idx
Out[46]: array(['USA', 'FRA'], dtype=object)
In [47]: df1.update(df2.loc[idx])
In [48]: df1
Out[48]:
value
country
USA 10
USA 10
USA 10
FRA 20
FRA 20
最佳答案
定义 bool 掩码
mask = (df1['Column2'] == 'Cond')
如果df1.index
与df2.index
相同,则可以使用mask
来选择
来自df2
的行——即df2.loc[mask]
。但如果它们不相同,那么
df2.loc[mask]
可能会引发错误(如果 len(df1) != len(df2)
),或者更糟糕的是,默默地选择错误的行
因为 bool 掩码未对齐 df1
和 df2
之间的索引值。
因此,在更一般的情况下,当索引不相同时,技巧是
将 bool 掩码转换为可用于限制的 Index
df2。
如果df1.index
是唯一的,则在受限的df2
上调用df1.update
:
idx = df1.index[mask]
df1.update(df2.loc[idx])
<小时/>
例如,
import pandas as pd
df1 = pd.DataFrame({'Column1':[1,2,3], 'Column2':['Cond',5,'Cond']}, index=['A','B','C'])
# Column1 Column2
# A 1 Cond
# B 2 5
# C 3 Cond
df2 = pd.DataFrame({'Column1':[10,20,30], 'Column3':[40,50,60]}, index=['D','B','C'])
# Column1 Column3
# D 10 40
# B 20 50
# C 30 60
mask = df1['Column2'] == 'Cond'
idx = df1.index[mask]
df1.update(df2.loc[idx])
print(df1)
打印
Column1 Column2
A 1 Cond
B 2 5
C 30 Cond
<小时/>
如果df1.index
不唯一,则通过向其添加mask
来使索引唯一:
df1['mask'] = df1['value'] >= 2
df2['mask'] = True
df1 = df1.set_index('mask', append=True)
df2 = df2.set_index('mask', append=True)
然后调用 df1.update(df2)
会产生所需的结果,因为 update
会对齐索引。
例如,
import pandas as pd
df1 = pd.DataFrame([['USA',1],['USA',2],['USA',3],['FRA',1],['FRA',2]],
columns = ['country', 'value'])
df2 = pd.DataFrame([['USA',10],['FRA',20]], columns = ['country', 'value'])
df1 = df1.set_index('country')
# value
# country
# USA 1
# USA 2
# USA 3
# FRA 1
# FRA 2
df2 = df2.set_index('country')
# value
# country
# USA 10
# FRA 20
df1['mask'] = df1['value'] >= 2
df2['mask'] = True
df1 = df1.set_index('mask', append=True)
# value
# country mask
# USA False 1
# True 2
# True 3
# FRA False 1
# True 2
df2 = df2.set_index('mask', append=True)
# value
# country mask
# USA True 10
# FRA True 20
df1.update(df2)
df1.index = df1.index.droplevel('mask')
print(df1)
产量
value
country
USA 1
USA 10
USA 10
FRA 1
FRA 20
关于python - 如何仅对 DataFrame 的一部分进行更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35292769/