我试图在多列上使用pandas.DataFrame.rolling.apply()
滚动函数。Python版本为3.7,熊猫为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'
是双重的,不包含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
答案建议编写我自己的滚动函数,但对我来说,罪魁祸首与评论中的问题相同:如果需要使用偏移窗口大小(例如,'1T'
)来处理非均匀时间戳,该怎么办?
我不喜欢从头开始重新发明轮子的想法。此外,我想用熊猫的一切,以防止不一致之间的设置,从熊猫获得的‘自制卷’。对于这个问题还有另一个答案,建议单独填充dataframe并计算我需要的任何数据,但是它不会起作用:存储的数据的大小将是巨大的。这里也提出了同样的想法:
Apply-rolling-function-on-pandas-dataframe-with-multiple-arguments
在这里发布的另一个问答
这是好的,也是最接近我的问题,但同样,没有可能使用偏移窗口大小(window = '1T'
)。
一些答案是在熊猫1.0发布之前被问到的,而且考虑到文档可能会更好,我希望现在可以同时翻阅多个列。
问题的第二部分是:是否有可能同时使用带有偏移窗口大小的熊猫1.0.x滚动多个列?
非常感谢。
发布于 2020-03-29 17:27:27
这个怎么样:
def masscenter(ser):
print(df.loc[ser.index])
return 0
rol = df.price.rolling(window=2)
rol.apply(masscenter, raw=False)
它使用滚动逻辑从任意列获取子集。raw=False选项为这些子集提供了索引值(作为Series提供给您),然后使用这些索引值从原始的DataFrame中获取多列切片。
发布于 2020-03-18 16:11:32
您可以从模块中使用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
发布于 2021-04-24 16:30:49
引用来自@saninstein的优秀答案。
从: numpy_ext安装https://pypi.org/project/numpy-ext/
import numpy as np
import pandas as pd
from numpy_ext import rolling_apply as rolling_apply_ext
def box_sum(a,b):
return np.sum(a) + np.sum(b)
df = pd.DataFrame({"x": [1,2,3,4], "y": [1,2,3,4]})
window = 2
df["sum"] = rolling_apply_ext(box_sum, window , df.x.values, df.y.values)
输出:
print(df.to_string(index=False))
x y sum
1 1 NaN
2 2 6.0
3 3 10.0
4 4 14.0
备注
rolling_apply
导入为rolling_apply_ext
,这样就不可能干扰对Pandas rolling_apply
的任何现有调用(这要感谢@LudoSchmidt的评论)。另外,我放弃了使用Pandas的尝试。它是从根本上破坏的:它处理单列光栅并在应用中遇到一些小问题,但它是一台过于复杂的rube机器,当它试图让它与更多的两列或更多列一起工作时。
https://stackoverflow.com/questions/60736556
复制相似问题