我尝试在多个列上使用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'
是double且不包含NaNs,'nQty'
是整数且也不包含NaNs。
所以,我需要计算滚动的“质心”,即。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
它是masscenter
的理想输入,因为我可以使用x[0], x[1]
轻松访问price
和nQty
。然而,我坚持使用rolling.apply()
阅读文档DataFrame.rolling()和rolling.apply(),我认为在rolling()
中使用'axis'
和在apply
中使用'raw'
可以实现类似的行为。天真的方法
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'
参数以及它是如何工作的。这是问题的第一部分:这是怎么回事?如何正确使用“轴”?它的设计目的是什么?**
当然,之前也有答案,那就是:
How-to-apply-a-function-to-two-columns-of-pandas-dataframe
它适用于整个DataFrame,而不是滚动。
How-to-invoke-pandas-rolling-apply-with-parameters-from-multiple-column
答案建议我自己写roll函数,但对我来说,罪魁祸首与评论中的问题相同:如果需要使用偏移窗口大小(例如,'1T'
)的非统一时间戳?
我不喜欢从头开始重新发明轮子的主意。另外,我想使用Pandas的一切,以防止不一致的集从Pandas和'自制辊'。这个问题还有另一个答案,需要单独填充框架并计算我需要的任何东西,但它不会起作用:存储数据的大小将是巨大的。同样的想法在这里提出:
Apply-rolling-function-on-pandas-dataframe-with-multiple-arguments
Q & A在这里发布
Pandas-using-rolling-on-multiple-columns
它很好,也最接近我的问题,但同样,没有可能使用偏移窗口大小(window = '1T'
)。
有些问题的答案是在pandas 1.0发布之前提出的,考虑到文档可以做得更好,我希望现在可以同时滚动多个列。
问题的第二部分是:是否有可能使用pandas 1.0.x和偏移窗口大小同时滚动多列?
6条答案
按热度按时间rggaifut1#
不如这样吧:
它使用滚动逻辑通过任意列获得子集。不使用任意列本身,只使用滚动索引。这依赖于默认值
raw=False
,它为这些子集提供索引值。applied函数使用这些索引值从原始数据框架中获取多列切片。yhuiod9q2#
您可以使用numpy_ext模块中的rolling_apply函数:
n3h0vuf23#
参考@saninstein的精彩回答。
安装numpy_ext从:https://pypi.org/project/numpy-ext/
输出量:
注意到
rolling_apply
导入为rolling_apply_ext
,因此它不可能干扰对Pandasrolling_apply
的任何现有调用(感谢@LudoSchmidt的评论)。顺便说一句,我放弃了使用Pandas。它从根本上被打破了:它处理单列的aggreagate和apply几乎没有问题,但是当试图让它处理更多的两列或更多列时,它是一个过于复杂的Rube-Goldberg机器。
3pmvbmvn4#
要执行滚动窗口操作并访问 Dataframe 的所有列,可以将
mehtod='table'
传递给rolling()
。范例:需要注意的是,
method='table'
需要numba引擎(pip install numba
)。示例中的@jit
部分不是必需的,但有助于提高性能。以上示例代码的结果将是:| 一|B|
| --|--|
| 楠|楠|
| 楠|楠|
| 5.0 |1.0|
| 7.0 |2.0|
| 9.0 |3.0|
| 11.0 |4.0|
4c8rllxm5#
所以我发现没有办法滚动两列,但是没有内置的pandas函数。代码如下所示。
这段代码可以工作,但相对较慢且效率较低。我认为可以使用How to invoke pandas.rolling.apply with parameters from multiple column?中的numpy.lib.stride_tricks来加速。然而,要么做大,要么回家--我结束了用C++写一个函数和它的 Package 器。
我不想把它作为答案贴出来,因为这是一个变通方案,我没有回答我的问题的任何一部分,但它太长了,不适合评论。
r55awzrz6#
这个怎么样?
结果是: