首页 > 解决方案 > 熊猫适用于滚动多列输出

问题描述

我正在研究将滚动窗口应用于返回多列的函数的代码。

输入:Pandas 系列
预期输出:3 列 DataFrame

def fun1(series, ):
    # Some calculations producing numbers a, b and c
    return {"a": a, "b": b, "c": c} 

res.rolling('21 D').apply(fun1)

资源内容:

time
2019-09-26 16:00:00    0.674969
2019-09-26 16:15:00    0.249569
2019-09-26 16:30:00   -0.529949
2019-09-26 16:45:00   -0.247077
2019-09-26 17:00:00    0.390827
                         ...   
2019-10-17 22:45:00    0.232998
2019-10-17 23:00:00    0.590827
2019-10-17 23:15:00    0.768991
2019-10-17 23:30:00    0.142661
2019-10-17 23:45:00   -0.555284
Length: 1830, dtype: float64

错误:

TypeError: must be real number, not dict

我试过的:

我还浏览了 SO 中的许多相关帖子,仅举几例:

但是指定的解决方案都没有解决这个问题。

有没有直接的解决方案?

标签: pythonpandasdataframerolling-computation

解决方案


这是一个使用hacky的答案rolling,生成一个 DataFrame:

import pandas as pd
import numpy as np

dr = pd.date_range('09-26-2019', '10-17-2019', freq='15T')
data = np.random.rand(len(dr))

s = pd.Series(data, index=dr)

output = pd.DataFrame(columns=['a','b','c'])

row = 0

def compute(window, df):
    global row
    a = window.max()
    b = window.min()
    c = a - b
    df.loc[row,['a','b','c']] = [a,b,c]
    row+=1    
    return 1
    
s.rolling('1D').apply(compute,kwargs={'df':output})

output.index = s.index

似乎该rolling apply函数总是期望返回一个数字,以便根据计算立即生成一个新系列。

我通过制作一个新的outputDataFrame(带有所需的输出列)并在函数中写入它来解决这个问题。我不确定是否有办法在滚动对象中获取索引,所以我改为使用global增加写入新行的计数。鉴于上述观点,您需要return一些数字。因此,虽然实际rolling操作返回一系列1,output被修改:

In[0]:
s

Out[0]:
2019-09-26 00:00:00    0.106208
2019-09-26 00:15:00    0.979709
2019-09-26 00:30:00    0.748573
2019-09-26 00:45:00    0.702593
2019-09-26 01:00:00    0.617028
  
2019-10-16 23:00:00    0.742230
2019-10-16 23:15:00    0.729797
2019-10-16 23:30:00    0.094662
2019-10-16 23:45:00    0.967469
2019-10-17 00:00:00    0.455361
Freq: 15T, Length: 2017, dtype: float64

In[1]:
output

Out[1]:
                           a         b         c
2019-09-26 00:00:00  0.106208  0.106208  0.000000
2019-09-26 00:15:00  0.979709  0.106208  0.873501
2019-09-26 00:30:00  0.979709  0.106208  0.873501
2019-09-26 00:45:00  0.979709  0.106208  0.873501
2019-09-26 01:00:00  0.979709  0.106208  0.873501
                      ...       ...       ...
2019-10-16 23:00:00  0.980544  0.022601  0.957943
2019-10-16 23:15:00  0.980544  0.022601  0.957943
2019-10-16 23:30:00  0.980544  0.022601  0.957943
2019-10-16 23:45:00  0.980544  0.022601  0.957943
2019-10-17 00:00:00  0.980544  0.022601  0.957943

[2017 rows x 3 columns]

这感觉更像是一种利用,而rolling不是预期用途,所以我很想看到一个更优雅的答案。

更新:感谢@JuanPi,您可以使用此答案获取滚动窗口索引。因此,非global答案可能如下所示:

def compute(window, df):
    a = window.max()
    b = window.min()
    c = a - b
    df.loc[window.index.max(),['a','b','c']] = [a,b,c]  
    return 1

推荐阅读