Python:按参与者向前填充多时间点数据集的BPMEDS缺失值
问题需求
我有一个存储健康数据的Python DataFrame,每个参与者对应时间点1、2、3。其中BPMEDS列存在缺失值,多数缺失发生在最后一个时间点(可能是1、2或3),缺失值的上方是该参与者最后有有效值的行。例如RANDID为16799的参与者在period3的BPMEDS为NaN,但period2的值为0.0,我希望将该参与者最后可用的值填充到缺失行中;若仅存在period1且BPMEDS为空,则暂时忽略该情况。
尝试以下代码时出现ValueError和TypeError:
for ind in df.index: if df['PERIOD'][ind] != '1': df['BPMEDS'][ind] = df.groupby(['RANDID']).fillna(method='ffill')
数据集示例:
RANDID BPMEDS PERIOD 26 16799 0.0 1 27 16799 0.0 2 28 16799 NaN 3 29 19304 0.0 1 30 20375 0.0 1 31 20375 0.0 2 32 23727 1.0 1
解决方案
原代码问题分析
- 循环遍历索引的方式效率低下,且直接赋值
df['BPMEDS'][ind]容易触发SettingWithCopyWarning,导致赋值失效 df.groupby(['RANDID']).fillna(method='ffill')返回的是完整的分组填充后DataFrame,无法直接赋值给单个元素,这是报错的核心原因
正确实现代码
import pandas as pd # 1. 按参与者分组,对BPMEDS列做组内前向填充 df['BPMEDS'] = df.groupby('RANDID')['BPMEDS'].ffill() # 2. 还原仅period1且原BPMEDS为空的行 # 标记每个参与者的时间点数量 df['period_count'] = df.groupby('RANDID')['PERIOD'].transform('count') # 筛选需还原的行:仅1个时间点、时间点为1、原BPMEDS为空 mask = (df['period_count'] == 1) & (df['PERIOD'] == 1) & (df['BPMEDS'].isna()) df.loc[mask, 'BPMEDS'] = pd.NA # 清理临时列(可选) df = df.drop('period_count', axis=1)
代码说明
groupby('RANDID')['BPMEDS'].ffill()会在每个参与者的行内,自动用前一行的有效值填充后续的NaN,完美匹配“用最后可用值填充缺失”的需求(比如示例中16799的period3 NaN会被填充为0.0)- 第二步的筛选逻辑精准定位到“仅period1且BPMEDS为空”的行,将其还原为缺失值,满足“暂时忽略”的要求
处理后示例结果
RANDID BPMEDS PERIOD 26 16799 0.0 1 27 16799 0.0 2 28 16799 0.0 3 29 19304 0.0 1 30 20375 0.0 1 31 20375 0.0 2 32 23727 1.0 1
内容的提问来源于stack exchange,提问作者swetach
相关产品推荐
相关产品推荐

