首页 > 解决方案 > 如何编写一个返回插值的函数(熊猫数据框)?

问题描述

我有一个作为熊猫数据框导入的 xls 文件。它具有 NaN 值;如何设置用相邻值之间的插值替换 NaN 的函数?我不能使用 pd.DataFrame.interpolate 或任何现有的插值函数,因为我应该制作自己的函数。

这就是我所拥有的,但我认为这是非常错误的。抱歉,对 Python 还是很陌生 :(

import pandas as pd
file = pd.read_excel("xls file")

def interpolate(x):
  for i in range(len(x)):
    if x.iloc[i, -1].isnull():
      x.iloc[i,-1] = (((x.iloc[i-1, -1]) + (x.iloc[i+1, -1]))/2)
    else:
      x.iloc[i,-1] = x.iloc[i, -1]

interpolate(file)

例如,数据框最初看起来像这样:

0   1.04
1   0.99
2   NaN
3   1.05
4   1.05

我希望它返回:

0   1.04
1   0.99
2   1.02
3   1.05
4   1.05

为此,假设没有连续的 NaN 条目

标签: pythonpandasinterpolation

解决方案


pd.Series.interpolate此解决方案使用默认参数重新创建行为。这不是一个适合初学者的解决方案,如果您的问题是家庭作业,我很想知道您的教授期望什么。

我正在使用具有前导、尾随和连续nan值的数据框。我添加了一个带有插值的列来与我的解决方案进行比较。需要Series具有默认排序范围索引的A。

import pandas as pd
import numpy as np

np.random.seed(11)
a = np.where(np.random.rand(20) > .5, np.random.uniform(0,10, 20), np.nan)
df = pd.DataFrame({
    'x': a
})
df['x_interp'] = df.x.interpolate()
df

输出

           x  x_interp
0        NaN       NaN
1        NaN       NaN
2        NaN       NaN
3   3.187988  3.187988
4        NaN  2.661738
5        NaN  2.135487
6        NaN  1.609237
7        NaN  1.082987
8   0.556737  0.556737
9   4.797973  4.797973
10  4.016765  4.016765
11       NaN  5.597628
12  7.178492  7.178492
13  6.020641  6.020641
14       NaN  7.755832
15  9.491024  9.491024
16       NaN  9.491024
17       NaN  9.491024
18       NaN  9.491024
19       NaN  9.491024

该方法是找到具有nan和周围值的切片。然后用这些周围值之间的线性步长填充这些切片。该参数控制是否使用最后一个可用值填充ffill尾随。nan

def interp(ser, ffill=True):
    ser = ser[df.x.notna().idxmax():].copy()
    start = ser.notna() & ser.shift(-1, fill_value=0).isna()
    end = ser.notna() & ser.shift(1, fill_value=0).isna()
    
    for x,y in zip(ser.index[start],ser.index[end]):
        step = (ser.loc[y] - ser.loc[x])/(y - x)
        ser.loc[x:y] = [ser.loc[x] + i * step for i in range(y-x)] + [ser.loc[y]]

    if ffill:
        ser = ser.ffill()
        
    return ser

df['x_new_interp'] = interp(df.x, False)
df['x_new_interp_ffill'] = interp(df.x)
df

输出

           x  x_interp  x_new_interp  x_new_interp_ffill
0        NaN       NaN           NaN                 NaN
1        NaN       NaN           NaN                 NaN
2        NaN       NaN           NaN                 NaN
3   3.187988  3.187988      3.187988            3.187988
4        NaN  2.661738      2.661738            2.661738
5        NaN  2.135487      2.135487            2.135487
6        NaN  1.609237      1.609237            1.609237
7        NaN  1.082987      1.082987            1.082987
8   0.556737  0.556737      0.556737            0.556737
9   4.797973  4.797973      4.797973            4.797973
10  4.016765  4.016765      4.016765            4.016765
11       NaN  5.597628      5.597628            5.597628
12  7.178492  7.178492      7.178492            7.178492
13  6.020641  6.020641      6.020641            6.020641
14       NaN  7.755832      7.755832            7.755832
15  9.491024  9.491024      9.491024            9.491024
16       NaN  9.491024           NaN            9.491024
17       NaN  9.491024           NaN            9.491024
18       NaN  9.491024           NaN            9.491024
19       NaN  9.491024           NaN            9.491024

推荐阅读