如何基于同Name字段填充ID为1/6的行中Azimut列的NaN值
需求与现有问题
原始数据
Name | ID | Azimut foo | 1 | 180 foo | 6 | NaN bar | 1 | NaN bar | 6 | 200
目标
筛选出ID为1或6的行,若某行的Azimut为NaN,则用同Name下的非NaN值填充,最终得到:
Name | ID | Azimut foo | 1 | 180 foo | 6 | 180 bar | 1 | 200 bar | 6 | 200
现有代码的问题
当前代码仅能处理ID=6的NaN填充场景,反向场景(ID=1的NaN用ID=6的值填充)需重复编写逻辑,且未校验ID1与ID6的配对情况:
nan_rows = df.loc[(df['ID'] == 6) & (df['Azimut'].isna())] values = df.loc[(df['Name'].isin(nan_rows['Name'])) & (df['ID'] == 1), 'Azimut'] df.loc[(df['ID'] == 6) & (df['Azimut'].isna(), 'Azimut'] = values.values
优化方案
利用Pandas分组填充功能,可一次性处理双向填充场景,同时自动适配ID配对情况:
# 筛选出ID为1或6的行,不影响其他ID数据 target_mask = df['ID'].isin([1, 6]) # 按Name分组,用组内非NaN值填充所有NaN df.loc[target_mask, 'Azimut'] = ( df.loc[target_mask] .groupby('Name')['Azimut'] .transform(lambda x: x.fillna(x.dropna().iloc[0])) )
逻辑说明
- 先通过
isin([1,6])锁定目标ID范围,避免修改无关数据 - 按
Name分组后,transform确保填充逻辑作用于原DataFrame的对应行 x.dropna().iloc[0]取组内第一个非NaN值,若组内存在多个非NaN值,会统一用该值填充;若需要其他逻辑(如均值),可替换为x.mean()等- 自动处理ID1与ID6的双向NaN填充,无需单独编写反向逻辑
如果需要仅对存在非NaN值的组进行填充(跳过全NaN的组),可添加校验:
target_mask = df['ID'].isin([1, 6]) grouped_azimut = df.loc[target_mask].groupby('Name')['Azimut'] # 标记组内存在非NaN值的行 has_valid_value = grouped_azimut.transform(lambda x: x.notna().any()) # 仅对有效组进行填充 df.loc[target_mask & has_valid_value, 'Azimut'] = grouped_azimut.transform(lambda x: x.fillna(x.dropna().iloc[0]))
内容的提问来源于stack exchange,提问作者Sergio Del Carpio
相关产品推荐
相关产品推荐

