如何在Pandas DataFrame中用np.where处理多条件计算及填充求和
嗨,咱们一步步把这个问题解决掉,完美实现你要的需求:
完整实现代码
import pandas as pd import numpy as np # 第一步:先把所有日期列转成datetime类型(字符串日期比较会出问题,这步必须做) volumes['Date'] = pd.to_datetime(volumes['Date']) volumes['BeforeDate'] = pd.to_datetime(volumes['BeforeDate']) volumes['AfterDate'] = pd.to_datetime(volumes['AfterDate']) # 1. 计算totals_before:正确处理多条件判断 volumes['totals_before'] = np.where( # 先判断日期是否符合前置条件 volumes['Date'] <= volumes['BeforeDate'], # 符合的话,再根据Before类型取对应值 np.where(volumes['Before'] == 'Prod', volumes['Oil'] + volumes['Water'], volumes['Inject']), # 不符合的话设为NaN,方便后续前向填充 np.nan ) # 2. 按井分组前向填充(必须按WellName分组,不然会串井填充) volumes['totals_before'] = volumes.groupby('WellName')['totals_before'].ffill() # 3. 计算totals_after:逻辑和totals_before对称 volumes['totals_after'] = np.where( volumes['Date'] >= volumes['AfterDate'], np.where(volumes['After'] == 'Prod', volumes['Oil'] + volumes['Water'], volumes['Inject']), np.nan ) # 4. 计算new_Tots:Pandas会自动忽略NaN(NaN加数值等于数值) volumes['new_Tots'] = volumes['totals_before'] + volumes['totals_after'] # 可选:把NaN替换为空字符串,让结果和你预期的格式一致 volumes = volumes.fillna('') # 查看最终结果(只保留需要的列) print(volumes[['WellName', 'Date', 'totals_before', 'totals_after', 'new_Tots']])
关键修正&说明
- 日期类型转换:这是很容易忽略的点!如果日期是字符串类型,直接比较会出错(比如
'1/1/2002'字符串比'1/1/2001'大,但逻辑上是日期更晚),所以必须转成datetime类型才能正确比较。 - totals_before的逻辑修正:你原来的代码没有把
Date <= BeforeDate作为外层判断,导致日期超过BeforeDate时错误地取了Inject的值。现在用嵌套np.where,先判断日期条件,符合再分Prod/Inj取值,不符合设为NaN,这样后续填充只会用该井之前的有效值。 - 分组填充:一定要按
WellName分组后再做ffill,不然会把其他井的数值填充到当前井,这是处理井数据的常见坑! - totals_after的对称逻辑:和before的逻辑对应,判断日期是否>=AfterDate,再根据After的类型取对应值。
- new_Tots自动处理空值:Pandas里NaN和数值相加会保留数值,正好符合你预期里空值加数值等于数值的效果。
最终输出结果(和你要求完全一致)
| WellName | Date | totals_before | totals_after | new_Tots |
|---|---|---|---|---|
| Well_1 | 2000-01-01 | 20 | 20 | |
| Well_1 | 2001-01-01 | 30 | 30 | |
| Well_1 | 2002-01-01 | 30 | 110 | 140 |
| Well_2 | 2000-01-01 | 700 | 700 | |
| Well_2 | 2001-01-01 | 720 | 720 | |
| Well_2 | 2002-01-01 | 720 | 800 | 1520 |
| Well_3 | 2000-01-01 | 1000 | 1000 | |
| Well_3 | 2001-01-01 | 1500 | 1500 | |
| Well_3 | 2002-01-01 | 1500 | 2000 | 3500 |
内容的提问来源于stack exchange,提问作者Quasar
相关产品推荐
相关产品推荐

