python - 如何仅对 DataFrame 的一部分进行更新

标签 python pandas

假设有一个 DataFrame df1,其中包含 INDEXColumn1Column2 和另一个 df2 INDEXColumn1Column3

两个 INDEX 都有相似的值,所以我想用它来合并一个表的信息到另一个表。

其他用户告诉我要执行以下操作:

df1.update(df2, join='left', overwrite=True)

如果两个索引具有相似的值,则此方法有效。结果将是 df1 现在将具有 INDEXColumn1(来自 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.indexdf2.index相同,则可以使用mask来选择 来自df2的行——即df2.loc[mask]。但如果它们不相同,那么 df2.loc[mask] 可能会引发错误(如果 len(df1) != len(df2)),或者更糟糕的是,默默地选择错误的行 因为 bool 掩码未对齐 df1df2 之间的索引值。

因此,在更一般的情况下,当索引不相同时,技巧是 将 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/

相关文章:

python - 使用python随机填充MySQL数据库 'freezing'

python - 无法使用 Jupyter Lab 或 Jupyter Notebook 运行任何 ipynb 文件(FileNotFoundError : [WinError 2] The system cannot find the file specified)

python - 卡住 (.exe) 一个 traitsUI 程序,现实可行吗?

python - 如何设置时差的最小值?

python - 按重复状态划分的 Pandas 组

Python - 根据列值将数据框拆分为多个数据框并用这些值命名它们

python - 在Python中加载两个动态库实例

python - 循环 Python 的列表理解

c++ - 从下拉框中选择不同的项目时更改选项卡小部件的 currentIndex()

pandas - 执行分层时是否应该保留类别的比例?