You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于参考站点趋势填充Python DataFrame中的科考站点缺失值

基于参考站点趋势填充科考站点缺失值的解决方案

针对你提到的「参考站与科考站数值对应关系不固定」「科考站值相同时参考站仍有波动」两个核心问题,以下是几种比pandas.interpolate更适配的方案:


1. 区间比例映射法(优先推荐)

核心思路

以科考站的已知测量点为分界,将全年划分为多个独立区间,每个区间内基于参考站的变化比例,映射出科考站的缺失值。这种方法直接解决你提到的两个痛点:

  • 每个区间的映射比例独立计算,适配「同一参考值对应不同科考值」的全年变化
  • 若区间内科考站起始/结束值相同,无论参考站怎么波动,填充值都会保持一致

代码实现(Pandas)

import pandas as pd

# 假设数据集包含日期(date)、参考站数值(ref_val)、科考站数值(site_val,含缺失)
df = df.sort_values('date').reset_index(drop=True)

# 提取科考站已知数据的索引
known_indices = df[df['site_val'].notna()].index

# 遍历每个已知区间,填充缺失值
for i in range(len(known_indices) - 1):
    start_idx, end_idx = known_indices[i], known_indices[i+1]
    # 获取区间两端的参考站、科考站数值
    ref_start, ref_end = df.loc[start_idx, 'ref_val'], df.loc[end_idx, 'ref_val']
    site_start, site_end = df.loc[start_idx, 'site_val'], df.loc[end_idx, 'site_val']
    
    # 定位区间内的缺失值
    mask = (df.index > start_idx) & (df.index < end_idx)
    if ref_start != ref_end:
        # 按参考站的变化比例映射科考站数值
        df.loc[mask, 'site_val'] = site_start + (df.loc[mask, 'ref_val'] - ref_start) * (site_end - site_start) / (ref_end - ref_start)
    else:
        # 参考站区间内无变化,直接填充已知起始值
        df.loc[mask, 'site_val'] = site_start

2. 局部拟合函数法

核心思路

针对科考站的已知数据,结合对应参考站的数值,拟合一个非线性模型(如局部加权回归、样条曲线),用模型预测缺失值。适合全年参考站与科考站对应关系非线性特征明显的场景。

代码实现(Statsmodels LOWESS)

from statsmodels.nonparametric.smoothers_lowess import lowess
import pandas as pd

# 提取科考站的已知配对数据
known_data = df[df['site_val'].notna()][['ref_val', 'site_val']]
x = known_data['ref_val'].values
y = known_data['site_val'].values

# 拟合局部加权回归模型,frac参数控制平滑程度(可根据数据调整)
lowess_result = lowess(y, x, frac=0.3)
# 将拟合结果转为字典,方便快速查询
fit_map = dict(zip(lowess_result[:, 0], lowess_result[:, 1]))

# 填充缺失值:用当日参考站数值匹配拟合结果
df['site_val'] = df.apply(
    lambda row: fit_map.get(row['ref_val'], row['site_val']) if pd.isna(row['site_val']) else row['site_val'],
    axis=1
)

3. 逐点邻域加权法

核心思路

对每个缺失值,结合时间邻近性和参考值相似性,计算周边已知科考站数据的加权平均值作为填充值。适合数据点分布稀疏、局部波动较大的场景。

代码实现

import pandas as pd
import numpy as np

def weighted_fill(row, known_data):
    if not pd.isna(row['site_val']):
        return row['site_val']
    # 计算每个已知点与当前日期的时间差(天)
    known_data['time_diff'] = abs((row['date'] - known_data['date']).dt.days)
    # 计算每个已知点与当前参考值的差异
    known_data['ref_diff'] = abs(row['ref_val'] - known_data['ref_val'])
    # 生成权重:时间越近、参考值越相似,权重越高
    known_data['weight'] = 1 / (known_data['time_diff'] + 1) * 1 / (known_data['ref_diff'] + 1)
    # 加权平均得到填充值
    return np.average(known_data['site_val'], weights=known_data['weight'])

# 提取科考站已知数据
df_known = df[df['site_val'].notna()].copy()
# 批量填充缺失值
df['site_val'] = df.apply(lambda row: weighted_fill(row, df_known), axis=1)

方案选择建议

  • 若数据区间划分清晰、局部对应关系稳定:优先用区间比例映射法,逻辑简单且计算高效
  • 若全年参考站与科考站的对应关系非线性特征明显:选择局部拟合函数法
  • 若数据点稀疏、局部波动大:尝试逐点邻域加权法

内容的提问来源于stack exchange,提问作者Angus Parvis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 15:30:44