熊猫滚动应用使用多列

新手上路,请多包涵

我正在尝试在多列上使用 pandas.DataFrame.rolling.apply() 滚动功能。 Python 版本是 3.7,pandas 是 1.0.2。

 import pandas as pd

#function to calculate
def masscenter(x):
    print(x); # for debug purposes
    return 0;

#simple DF creation routine
df = pd.DataFrame( [['02:59:47.000282', 87.60, 739],
                    ['03:00:01.042391', 87.51, 10],
                    ['03:00:01.630182', 87.51, 10],
                    ['03:00:01.635150', 88.00, 792],
                    ['03:00:01.914104', 88.00, 10]],
                   columns=['stamp', 'price','nQty'])
df['stamp'] = pd.to_datetime(df2['stamp'], format='%H:%M:%S.%f')
df.set_index('stamp', inplace=True, drop=True)

'stamp' 是单调且唯一的, 'price' 是双精度且不包含 NaN, 'nQty' 包含 Na– 是整数

所以,我需要计算滚动的“质心”,即 sum(price*nQty)/sum(nQty)

到目前为止我尝试了什么:

 df.apply(masscenter, axis = 1)

masscenter 被单行调用 5 次,输出类似于

price     87.6
nQty     739.0
Name: 1900-01-01 02:59:47.000282, dtype: float64

It is desired input to a masscenter , because I can easily access price and nQty using x[0], x[1] . However, I stuck with rolling.apply() Reading the docs DataFrame.rolling() and rolling.apply() I supposed that using 'axis' in rolling() and 'raw'apply 实现了类似的行为。天真的方法

rol = df.rolling(window=2)
rol.apply(masscenter)

逐行打印(增加行数直到窗口大小)

 stamp
1900-01-01 02:59:47.000282    87.60
1900-01-01 03:00:01.042391    87.51
dtype: float64

然后

stamp
1900-01-01 02:59:47.000282    739.0
1900-01-01 03:00:01.042391     10.0
dtype: float64

因此,列分别传递给 masscenter (预期)。

可悲的是,在文档中几乎没有任何关于 'axis' 的信息。然而,下一个变体显然是

rol = df.rolling(window=2, axis = 1)
rol.apply(masscenter)

从不调用 masscenter 并提出 ValueError in rol.apply(..)

 > Length of passed values is 1, index implies 5

我承认,由于缺少文档,我不确定 'axis' 参数及其工作原理。这是问题的第一部分: 这里发生了什么?如何正确使用“轴”?它的设计目的是什么?

当然,之前也有答案,即:

如何将函数应用于两列熊猫数据框

它适用于整个 DataFrame,而不适用于 Rolling。

如何调用-pandas-rolling-apply-with-parameters-from-multiple-column

答案建议编写我自己的 roll 函数,但对我来说,罪魁祸首与 评论 中的问题相同:如果需要使用偏移窗口大小(例如 '1T' )来获取非统一时间戳怎么办?

我不喜欢从头开始重新发明轮子的想法。此外,我想对所有内容都使用 pandas,以防止从 pandas 获得的集合与“自制卷”之间的不一致。这个问题还有另一个答案,建议单独填充数据框并计算我需要的任何东西,但这行不通:存储数据的大小将是巨大的。这里提出了相同的想法:

在具有多个参数的 pandas-dataframe 上应用滚动函数

此处发布了另一个问答

Pandas-using-rolling-on-multiple-columns

它很好并且最接近我的问题,但是同样,不可能使用偏移窗口大小( window = '1T' )。

有些答案是在 pandas 1.0 发布之前提出的,鉴于文档可能会更好,我希望现在可以同时滚动多个列。

问题的第二部分是: 是否有可能使用具有偏移窗口大小的 pandas 1.0.x 同时滚动多个列?

非常感谢你。

原文由 Suthiro 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 733
2 个回答

这个怎么样:

 def masscenter(ser):
    print(df.loc[ser.index])
    return 0

rol = df.price.rolling(window=2)
rol.apply(masscenter, raw=False)

它使用滚动逻辑从任意列中获取子集。 raw=False 选项为您提供这些子集的索引值(作为系列提供给您),然后您使用这些索引值从原始 DataFrame 中获取多列切片。

原文由 adr 发布,翻译遵循 CC BY-SA 4.0 许可协议

您可以使用 numpy_ext 模块中的 rolling_apply 函数:

 import numpy as np
import pandas as pd
from numpy_ext import rolling_apply

def masscenter(price, nQty):
    return np.sum(price * nQty) / np.sum(nQty)

df = pd.DataFrame( [['02:59:47.000282', 87.60, 739],
                    ['03:00:01.042391', 87.51, 10],
                    ['03:00:01.630182', 87.51, 10],
                    ['03:00:01.635150', 88.00, 792],
                    ['03:00:01.914104', 88.00, 10]],
                   columns=['stamp', 'price','nQty'])
df['stamp'] = pd.to_datetime(df['stamp'], format='%H:%M:%S.%f')
df.set_index('stamp', inplace=True, drop=True)

window = 2
df['y'] = rolling_apply(masscenter, window, df.price.values, df.nQty.values)
print(df)

                            price  nQty          y
stamp
1900-01-01 02:59:47.000282  87.60   739        NaN
1900-01-01 03:00:01.042391  87.51    10  87.598798
1900-01-01 03:00:01.630182  87.51    10  87.510000
1900-01-01 03:00:01.635150  88.00   792  87.993890
1900-01-01 03:00:01.914104  88.00    10  88.000000

原文由 saninstein 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题