计算具有非唯一日期索引的数据帧上的滚动中值

2024-06-26 01:59:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下dataframe,它有一个使用日期的非唯一索引:

                column
2019-01-07         NaN    
2019-01-08         NaN
2019-01-08        0.02
2019-01-09       31.45
2019-01-10         NaN
2019-01-10       71.87
2019-01-10       90.18
2019-01-11         NaN
2019-01-12       12.67
2019-01-12        5.68
2019-01-12       11.23
2019-01-12       21.67
2019-01-12       14.77
2019-01-12        5.18
2019-01-13       14.38
2019-01-13         NaN
2019-01-13       71.13
2019-01-13       20.02
2019-01-13      103.10
2019-01-14         NaN
2019-01-15       32.48
2019-01-16       37.37
2019-01-16       31.05
2019-01-16        7.00
2019-01-17         NaN
2019-01-17       39.65
2019-01-18       23.68
2019-01-18        0.08
2019-01-18       41.35
2019-01-19         NaN
2019-01-19       45.85
2019-01-19        3.98
2019-01-19        4.60
2019-01-19         NaN
2019-01-19         NaN
2019-01-20        3.60
2019-01-20        5.03
2019-01-20       15.70

我的目标是使用每个日期的所有值计算7天滚动中值,但忽略NaN值

结果数据框应具有唯一的日期索引,滚动中值作为该日期的列值,如下所示:

                column
2019-01-13       17.40    
2019-01-14       17.40
2019-01-15       20.85
2019-01-16       20.85
2019-01-17       20.02
2019-01-18       20.85
2019-01-19       31.05
2019-01-20       19.69

我不知道如何使用熊猫轻松实现这一点,因此如果有人能提供答案或为我指出正确的方向,我将不胜感激

编辑

为了让事情更清楚,我将解释如何计算单一日期的中位数

使用2019-01-13的日期,滚动中值将需要使用从7天到13天的所有值,不包括NaN值。这意味着第13次中位数计算中需要包含的值为0.02、31.45、71.87、90.18、12.67、5.68、11.23、21.67、14.77、5.18、14.38、71.13、20.02、103.10。13日的中位数为17.4

希望有帮助


Tags: 数据答案编辑目标dataframecolumnnan方向
2条回答

如果数据不太长,则可以进行交叉合并:

df['key'] = 1
df = df.reset_index()

(df.merge(df, on='key', suffixes=['','_'])
   .loc[lambda x: x['index'].ge(x['index_']) & 
                  x['index'].sub(x['index_']).le('7D')]
   .groupby('index')['column_'].median()
)

输出:

index
2019-01-07       NaN
2019-01-08     0.020
2019-01-09    15.735
2019-01-10    51.660
2019-01-11    51.660
2019-01-12    13.720
2019-01-13    17.395
2019-01-14    17.395
2019-01-15    20.020
2019-01-16    21.670
2019-01-17    21.670
2019-01-18    20.845
2019-01-19    20.020
2019-01-20    21.850
Name: column_, dtype: float64

rolling对象是可编辑的,它允许这样的解决方案:

# drop NAs and group by date into lists of values
df_per_date = df.dropna().groupby('date').apply(lambda g: g.value.to_list())


# compute medians across windows ('sum' concatenates multiple lists into one list)
medians = [np.median(window.agg(sum)) for window in df_per_date.rolling(5)]


# result
medians = pd.Series(index=df_per_date.index, data=medians)


medians

enter image description here


顺便说一下,我加载的数据如下:

# load the data
df = pd.read_csv(pd.io.common.StringIO("""
2019-01-07         NaN    
2019-01-08         NaN
2019-01-08        0.02
2019-01-09       31.45
2019-01-10         NaN
2019-01-10       71.87
2019-01-10       90.18
2019-01-11         NaN
2019-01-12       12.67
2019-01-12        5.68
2019-01-12       11.23
2019-01-12       21.67
2019-01-12       14.77
2019-01-12        5.18
2019-01-13       14.38
2019-01-13         NaN
2019-01-13       71.13
2019-01-13       20.02
2019-01-13      103.10
2019-01-14         NaN
2019-01-15       32.48
2019-01-16       37.37
2019-01-16       31.05
2019-01-16        7.00
2019-01-17         NaN
2019-01-17       39.65
2019-01-18       23.68
2019-01-18        0.08
2019-01-18       41.35
2019-01-19         NaN
2019-01-19       45.85
2019-01-19        3.98
2019-01-19        4.60
2019-01-19         NaN
2019-01-19         NaN
2019-01-20        3.60
2019-01-20        5.03
2019-01-20       15.70
""".strip()), sep='\s+', names=['date', 'value'], parse_dates=['date'])

相关问题 更多 >