Pandas按组从动态列表填充缺失值问题求助
解决方法:分组动态填充缺失值
核心思路
- 先维护一个CodeA+CodeB对应的动态number列表映射(用字典或单独DataFrame存储都可以,方便随时更新)
- 按
CodeA、CodeB、Hour分组后,对每个分组执行三步操作:- 提取分组内已存在的非空
number值 - 从对应映射的number列表里过滤掉已存在的值,得到可填充的候选序列
- 按列表顺序用候选序列填充分组中的缺失值
- 提取分组内已存在的非空
代码实现示例
先构造贴合场景的示例数据:
import pandas as pd import numpy as np # 原始DataFrame df = pd.DataFrame({ 'CodeA': ['A01', 'A01', 'A01', 'A01', 'A02', 'A02', 'A02'], 'CodeB': ['B01', 'B01', 'B01', 'B01', 'B02', 'B02', 'B02'], 'Hour': [1, 1, 2, 2, 1, 1, 1], 'number': [101, np.nan, np.nan, 103, np.nan, 202, np.nan] }) # 动态维护的number列表映射(key是(CodeA, CodeB),value为对应列表,可随时修改) number_list_map = { ('A01', 'B01'): [101, 102, 103, 104], ('A02', 'B02'): [201, 202, 203] }
接下来写自定义分组填充函数,通过groupby.apply执行:
def fill_missing_numbers(group): # 获取当前分组的CodeA和CodeB标识 code_a = group['CodeA'].iloc[0] code_b = group['CodeB'].iloc[0] # 取出对应动态列表 target_list = number_list_map.get((code_a, code_b), []) # 提取分组已存在的非空number,转集合快速过滤 existing_nums = set(group['number'].dropna().tolist()) # 过滤出可用填充值,严格保留原列表顺序 available_nums = [num for num in target_list if num not in existing_nums] # 定位缺失值位置,计算需要填充的数量(取可用值和缺失值的较小值) missing_mask = group['number'].isna() fill_count = min(len(available_nums), missing_mask.sum()) # 填充缺失值 group.loc[missing_mask, 'number'] = available_nums[:fill_count] return group # 按指定字段分组并应用填充逻辑 filled_df = df.groupby(['CodeA', 'CodeB', 'Hour'], group_keys=False).apply(fill_missing_numbers)
运行后得到的结果符合预期:
CodeA CodeB Hour number 0 A01 B01 1 101.0 1 A01 B01 1 102.0 2 A01 B01 2 102.0 3 A01 B01 2 103.0 4 A02 B02 1 201.0 5 A02 B02 1 202.0 6 A02 B02 1 203.0
关键细节说明
- 动态适配:
number_list_map可随时新增、修改或删除(CodeA, CodeB)对应的列表,完全满足动态变化需求 - 顺序保证:过滤后的候选序列严格遵循原列表顺序,不会打乱预设逻辑
- 边界处理:如果可用填充值数量少于缺失值数量,剩余缺失值会保留为NaN(若需其他处理,可在函数内补充循环填充或标记逻辑)
- 分组独立性:严格按三个字段分组,确保每个分组的填充逻辑互不干扰
内容的提问来源于stack exchange,提问作者soni_christus
相关产品推荐
相关产品推荐

