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

关于Pandas DataFrame.interpolate()函数的插值公式及自定义实现的技术问询

Pandas DataFrame.interpolate() 的插值公式与自定义方案

首先得说清楚:interpolate() 不是靠单一公式运行的函数——它的行为完全由你指定的 method 参数决定,官方文档没把所有公式列全是因为不同方法对应不同的插值逻辑,下面我把最常用的几种方法的核心公式和逻辑给你理清楚:

常见插值方法的公式/逻辑

  • Linear(线性插值,默认):这是最常用的类型,核心就是两点之间的直线插值。假设你要填充位置 x 处的NaN,左右最近的有效值是 x0(对应值 y0)和 x1(对应值 y1),公式是:

    y = y0 + (y1 - y0) * (x - x0) / (x1 - x0)
    

    注意:默认情况下,Pandas是按行/列的位置索引计算的(不是DataFrame的列名/行标签),除非你指定 method='index' 或 method='time',这时候会用实际的索引值来计算权重。

  • Nearest(最近邻插值):没有复杂公式,直接取距离当前NaN最近的有效值填充即可。

  • Quadratic/Cubic(二次/三次插值):这类属于多项式插值,会用周围多个点拟合出二次或三次曲线,再计算NaN位置的值。底层一般调用Scipy的多项式插值实现,公式就是对应的多项式方程(比如三次插值是 y = ax³ + bx² + cx + d,通过周围点求解系数)。

  • Time(时间插值):专门针对时间索引的DataFrame,本质是线性插值,但会用时间差代替位置差计算权重。比如两个时间点间隔2天,中间第1天的插值结果就是 (y1 - y0)*1/2 + y0。

自定义插值逻辑的方案

如果内置方法不符合你的需求,有几种灵活的实现方式:

1. 逐行/列自定义插值函数

用 apply() 遍历每一行或列,结合Scipy的插值工具或者自己编写逻辑。比如针对你给出的示例DataFrame,假设你想实现基于列名索引的加权线性插值(不是按位置),可以这么做:

首先导入所需库:

import pandas as pd
import numpy as np
from scipy.interpolate import interp1d

然后定义自定义插值函数:

def custom_interpolate(row):
    # 获取当前行非NaN的列索引(转为整数)和对应值
    valid_cols = row.dropna().index.astype(int)
    valid_vals = row.dropna().values
    if len(valid_cols) < 2:
        # 少于两个有效值无法插值,返回原行
        return row
    # 创建插值函数,这里用线性,你可以替换成自己的逻辑
    f = interp1d(valid_cols, valid_vals, kind='linear', fill_value='extrapolate')
    # 对所有列应用插值
    interpolated_vals = f(row.index.astype(int))
    return pd.Series(interpolated_vals, index=row.index)

最后应用到你的DataFrame:

df = pd.DataFrame([[np.nan, 10, np.nan, 20, 17, np.nan, np.nan, 14, np.nan, 10, np.nan], 
                   [5, np.nan, 0, np.nan, np.nan, np.nan, 5, np.nan, 10, np.nan, np.nan], 
                   [3, np.nan, np.nan, np.nan, np.nan, np.nan, 2, np.nan, np.nan, np.nan, np.nan], 
                   [np.nan, np.nan, np.nan, 3, 4, 5, np.nan, 7, 8, 9, np.nan]], 
                  columns=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'])

# 按行应用自定义插值
df_interpolated = df.apply(custom_interpolate, axis=1)

2. 手动填充NaN值

如果你的逻辑非常特殊(比如基于业务规则的加权、多列联动插值),可以直接遍历DataFrame的每个NaN,根据周围的值手动计算填充。比如:

for idx, row in df.iterrows():
    # 获取当前行的NaN位置
    nan_cols = row[row.isna()].index
    for col in nan_cols:
        col_int = int(col)
        # 找左边最近的非NaN值
        left_vals = row[:col].dropna()
        # 找右边最近的非NaN值
        right_vals = row[col:].dropna()
        
        if not left_vals.empty and not right_vals.empty:
            left_col = int(left_vals.index[-1])
            left_val = left_vals.iloc[-1]
            right_col = int(right_vals.index[0])
            right_val = right_vals.iloc[0]
            # 自定义加权公式:权重与列距成反比
            weight_left = 1/(col_int - left_col)
            weight_right = 1/(right_col - col_int)
            total_weight = weight_left + weight_right
            df.loc[idx, col] = (left_val * weight_right + right_val * weight_left)/total_weight
        elif not left_vals.empty:
            # 只有左边有值,填充左边最后一个值
            df.loc[idx, col] = left_vals.iloc[-1]
        elif not right_vals.empty:
            # 只有右边有值,填充右边第一个值
            df.loc[idx, col] = right_vals.iloc[0]

3. 封装复用自定义逻辑(进阶)

如果需要频繁使用自定义插值逻辑,可以把它封装成一个函数,而不是每次都写重复代码。比如:

def custom_interpolate_df(df, axis=1):
    return df.apply(custom_interpolate, axis=axis)

之后直接调用 custom_interpolate_df(df) 即可。

总结

  • 先明确你需要的插值逻辑,对应到Pandas内置的method参数,如果能匹配上直接使用即可;
  • 如果内置方法不符合需求,用apply结合自定义函数或手动填充是最灵活的方式;
  • 涉及复杂曲线拟合时,优先用Scipy的插值工具,再结合Pandas处理数据结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.01 00:14:06