【问题标题】:How to replace only SOME column values in dataframe taking them from another on condition?如何仅替换数据框中的某些列值,根据条件从另一个列值获取它们?
【发布时间】:2019-05-22 20:11:47
【问题描述】:

我在 pandas(python) 中有两个 DataFrame

df1
UniqueKey ValueFix ValueChange
A           10        100
B           15        0
C           20        150
D           15        0
E           10        100

df2
UniqueKey ValueFix ValueChange
B           15        300
D           15        400

我想根据 df2 中的值更新 df1,但 只更新“值更改”列中的值。因为实际上我不应该更新不在 df2 中的行。我怎样才能做到这一点?我迷路了。 所以我想要的结果是:

UniqueKey ValueFix ValueChange
A            10      100
B            15      300
C            20      150
D            15      400
E            10      100

在我看来,唯一的解决方案是使用 UniqueKey-ValuChange 以某种方式将 df2 转换为字典 并且 with 循环通过 df1 中的 ValueChange 条件,例如 'If row[Value_change] in dictionary then replace with value from dictionary.

但我不知道如何使用 pandas 来做到这一点

【问题讨论】:

  • 使用df1=df1.set_index('UniqueKey')设置索引并对df2做同样的事情,然后df1.update(df2)
  • df2.set_index('UniqueKey').combine_first(df1.set_index('UniqueKey')).reset_index()
  • 但是如果我只想更新“值更改”列中的值该怎么办?
  • @Artem 我仍然认为我的方式可行。你试过了吗?
  • @anky_91 我指定了我的问题以避免混淆。我猜您的解决方案将更新 df1 中的所有行和列。我只需要更新特定值(在这种情况下 - df1 中的“值更改”列中的零)

标签: python pandas


【解决方案1】:

您可以使用 numpy where 以这种方式更新您的列:

import pandas as pd    
import numpy as np

df1 = pd.DataFrame({'UniqueKey': ['A', 'B','C','D','E'], 'ValueFix': [10,15,20,15,10], 'ValueChange': [100,0,150,0,100]})
df2 = pd.DataFrame({'UniqueKey': ['B', 'D'], 'ValueFix': [15,15], 'ValueChange': [300,400]})

merged_df = df1.merge(df2, on='UniqueKey', how='left')
df1.ValueChange = np.where(df1.UniqueKey.isin(df2.UniqueKey), merged_df.ValueChange_y, merged_df.ValueChange_x)

输出是

print(df1)
      UniqueKey  ValueFix  ValueChange
0         A        10        100.0
1         B        15        300.0
2         C        20        150.0
3         D        15        400.0
4         E        10        100.0

【讨论】:

  • 如果 UniqueKey 是索引而不是常规列,则需要使用 df1.index.get_level_values('UniqueKey') 而不是 df1.UniqueKey
  • 我重置了索引并尝试了您的第一个建议并得到 ValueError: Can only compare same-labeled Series objects。我不知道为什么,因为我的列名称相同。现在将尝试您的第二个。
  • 第二个建议我得到“ValueError:长度必须匹配才能比较”
  • 好的,我已经更正了我的答案。发生这种情况是因为 where 方法期望行号和顺序匹配。
【解决方案2】:

似乎应该这样做:

idx = df1.index.intersection(df2.index)
df1.loc[idx , 'ValueChange'] = df2[idx, 'ValueChange']

输出:

          ValueFix  ValueChange
UniqueKey                       
A                10          100
B                15          300
C                20          150
D                15          400
E                10          100

【讨论】:

  • 使用这种方法我得到两个错误: TypeError: unhashable type: 'RangeIndex' and pandas.core.indexing.IndexingError: (RangeIndex(start=0, stop=52, step=1), '价值变化')
  • 在一些修复脚本工作后,但值没有改变
  • 目前它引发 KeyError 因为来自 df1 的一些唯一键不在 df2 中
  • 我修改了答案以解决创建新行的潜在问题
  • 我很确定你没有完全按照我的回答做:df2 没有来自df1 的密钥根本不是问题,为什么会出现这个错误?你实际运行的是什么代码?
猜你喜欢
  • 2019-07-05
  • 2022-07-30
  • 2019-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多