首页 > 解决方案 > Python pandas 通过其他列的条件替换更改单元格值

问题描述

我有一个数据框:

df = pd.DataFrame({'cust': {0: 'A',
  1: 'A',
  2: 'A',
  3: 'A',
  4: 'B',
  5: 'B',
  6: 'B',
  7: 'B',
  8: 'B'},
 'value': {0: 6, 1: 10, 2: 11, 3: 15, 4: 6, 5: 12, 6: 21, 7: 29, 8: 33},
 'signal': {0: 0, 1: 1, 2: 1, 3: 0, 4: 1, 5: 0, 6: 0, 7: 0, 8: 0}})


  cust  value  signal
0    A      6       0
1    A     10       1
2    A     11       1
3    A     15       0
4    B      6       1
5    B     12       0
6    B     21       0
7    B     29       0
8    B     33       0

当信号!= 0 时,我应该将“值”替换为每个客户的先前值。例如,在索引为 1 的行中,值 = 10 应替换为其先前的值,即 6。在索引为 4 的行中,我不能将值 6 替换为其先前的值,因为客户“B”没有先前的值”。在这种情况下,我应该将 value 替换为 0。

由于我有一个包含 5000 万行的数据框,如何以最高效的方式做到这一点?

标签: python-3.xpandaspandas-groupbytransformapply

解决方案


IIUC,您可以使用shift、fillna使用groupby(在cust列上)转换,然后使用 np.where 选择适当的

# find previous value from each customer group
res = df.groupby('cust')['value'].transform('shift').fillna(0)

# replace values
df['value'] = np.where(df['signal'].ne(0), res, df['value'])

print(df)

输出

  cust  value  signal
0    A    6.0       0
1    A    6.0       1
2    A   10.0       1
3    A   15.0       0
4    B    0.0       1
5    B   12.0       0
6    B   21.0       0
7    B   29.0       0
8    B   33.0       0

更新

如果您需要传播最后一个有效值,请执行以下操作:

# make invalid values na, to use ffill
df['value'] = np.where(df['signal'].ne(0), np.nan, df['value'])

# use ffill, for values at the beginning of the group fillna(0)
df['value'] = df.groupby('cust')['value'].transform('ffill').fillna(0)

print(df)

输出

  cust  value  signal
0    A    6.0       0
1    A    6.0       1
2    A    6.0       1
3    A   15.0       0
4    B    0.0       1
5    B   12.0       0
6    B   21.0       0
7    B   29.0       0
8    B   33.0       0

推荐阅读