用滚动平均值或其他插值替换NaN或缺失值

时间:2014-08-11 01:45:17

标签: python pandas missing-data moving-average

我有一个带有月度数据的熊猫数据框,我想计算12个月的移动平均值。但是,(NaN)缺少1月份每个月的数据,所以我正在使用

pd.rolling_mean(data["variable"]), 12, center=True)

但它只给了我所有的NaN值。

有一种简单的方法可以忽略NaN值吗?据我所知,在实践中,这将成为11个月的移动平均线。

数据框中还有其他具有1月数据的变量,所以我不想抛弃1月份的列并做11个月的移动平均线。

2 个答案:

答案 0 :(得分:12)

有几种方法可以解决这个问题,最好的方法取决于1月数据是否与其他月份系统地不同。大多数现实世界的数据可能都是季节性的,所以让我们以北半球随机城市的平均高温(华氏温度)为例。

df=pd.DataFrame({ 'month' : [10,11,12,1,2,3],
                  'temp'  : [65,50,45,np.nan,40,43] }).set_index('month')

您可以按照建议使用滚动平均值,但问题是您将获得全年的平均温度,这忽略了1月是最冷月的事实。要纠正此问题,您可以将窗口缩小为3,这会导致1月临时值是12月和2月临时值的平均值。 (我也按@ user394430的回答中的建议使用min_periods=1。)

df['rollmean12'] = df['temp'].rolling(12,center=True,min_periods=1).mean()
df['rollmean3']  = df['temp'].rolling( 3,center=True,min_periods=1).mean()

这些都是改进,但仍然存在使用滚动方式覆盖现有值的问题。为避免这种情况,您可以使用update()方法(see documentation here)。

df['update'] = df['rollmean3']
df['update'].update( df['temp'] )  # note: this is an inplace operation

甚至有更简单的方法可以保留现有值,同时用上个月,下个月或上个月和下个月的平均值填充缺失的1月临时值。

df['ffill']   = df['temp'].ffill()         # previous month 
df['bfill']   = df['temp'].bfill()         # next month
df['interp']  = df['temp'].interpolate()   # mean of prev/next

在这种情况下,interpolate()默认为简单线性解释,但您还有其他几个插值选项。有关详细信息,请参阅documentation on pandas interpolate。或者这个statck溢出问题:  Interpolation on DataFrame in pandas

以下是包含所有结果的示例数据:

       temp  rollmean12  rollmean3  update  ffill  bfill  interp
month                                                           
10     65.0        48.6  57.500000    65.0   65.0   65.0    65.0
11     50.0        48.6  53.333333    50.0   50.0   50.0    50.0
12     45.0        48.6  47.500000    45.0   45.0   45.0    45.0
1       NaN        48.6  42.500000    42.5   45.0   40.0    42.5
2      40.0        48.6  41.500000    40.0   40.0   40.0    40.0
3      43.0        48.6  41.500000    43.0   43.0   43.0    43.0

特别要注意"更新"和" interp"在所有月份都给出相同的结果。虽然你在这里使用哪一个并不重要,但在其他情况下,这种或那种方式可能会更好。

答案 1 :(得分:10)

真正的关键是min_periods=1。此外,从版本18开始,正确的呼叫是Rolling object。因此,您的代码应该是

data["variable"].rolling(min_periods=1, center=True, window=12).mean()