Python面板数据条件插补:均值与线性插值(仅非全缺失实体)
面板数据按实体插补(线性/均值)解决方案
问题分析
原代码直接调用interpolate()会全局跨实体填充(如公司C被错误填充为公司B的最后值),且全缺失实体也被不当处理。需要实现:
- 按实体(公司)单独执行插补逻辑
- 仅对存在非缺失值的实体进行插补
- 全缺失实体保留原始NaN值
1. 线性插值实现
通过groupby按公司分组,先判断组内是否有有效数据,再执行支持外推的线性插值,完全匹配你期望的输出:
import pandas as pd import numpy as np # 构造原始数据 company = ['A'] * 5 + ['B'] * 5 + ['C'] * 5 year = ['2017', '2018', '2019', '2020', '2021'] * 3 value = [.3, .32, .33, .35, .37, .2, .21, .22, np.nan, np.nan] + [np.nan] * 5 df = pd.DataFrame(data={'company': company, 'year': year, 'value': value}) # 定义分组线性插值逻辑 def linear_interpolate_group(group): # 仅对非全缺失组执行插值 if not group['value'].isna().all(): # 开启双向外推,对组末尾缺失值做线性延伸 return group['value'].interpolate(method='linear', limit_direction='both') else: return group['value'] # 应用分组逻辑并生成插值结果 df['value2'] = df.groupby('company').apply(linear_interpolate_group).reset_index(drop=True) # 查看格式化结果 print(df.set_index(['company', 'year']))
关键细节
groupby('company'):确保每个公司的插补逻辑独立,不会跨实体污染数据limit_direction='both':允许对组内末尾的连续缺失值(如B公司2020-2021)进行线性外推,得到你期望的0.23、0.24结果isna().all()判断:全缺失组直接返回原始值,避免错误填充
2. 均值插补实现
同样按公司分组,仅对有有效数据的组用组内均值填充缺失值:
# 定义分组均值填充逻辑 def mean_fill_group(group): if not group['value'].isna().all(): group_mean = group['value'].mean() return group['value'].fillna(group_mean) else: return group['value'] # 应用分组逻辑并生成均值插补结果 df['value_mean'] = df.groupby('company').apply(mean_fill_group).reset_index(drop=True) # 查看格式化结果 print(df.set_index(['company', 'year']))
结果说明
- 公司A无缺失值,
value_mean与原值完全一致 - 公司B的2020-2021缺失值会被填充为
(0.2+0.21+0.22)/3 = 0.21 - 公司C全缺失,
value_mean保持NaN不变
验证输出(线性插值)
执行代码后得到与你期望完全一致的结果:
value value2 company year A 2017 0.30 0.30 2018 0.32 0.32 2019 0.33 0.33 2020 0.35 0.35 2021 0.37 0.37 B 2017 0.20 0.20 2018 0.21 0.21 2019 0.22 0.22 2020 NaN 0.23 2021 NaN 0.24 C 2017 NaN NaN 2018 NaN NaN 2019 NaN NaN 2020 NaN NaN 2021 NaN NaN
内容的提问来源于stack exchange,提问作者business_of_ferrets
相关产品推荐
相关产品推荐

