首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >熊猫滚动使用多栏

熊猫滚动使用多栏
EN

Stack Overflow用户
提问于 2020-03-18 09:21:45
回答 5查看 29K关注 0票数 28

我试图在多列上使用pandas.DataFrame.rolling.apply()滚动函数。Python版本为3.7,熊猫为1.0.2。

代码语言:javascript
运行
复制
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)

到目前为止我尝试过的是:

代码语言:javascript
运行
复制
df.apply(masscenter, axis = 1)

使用一行调用masscenter 5次,输出如下

代码语言:javascript
运行
复制
price     87.6
nQty     739.0
Name: 1900-01-01 02:59:47.000282, dtype: float64

它是masscenter所需要的输入,因为我可以使用x[0], x[1]轻松地访问pricenQty。然而,我坚持rolling.apply()阅读文档DataFrame.rolling()rolling.apply() --我认为在rolling()中使用'axis',在apply中使用'raw',可以实现类似的行为。天真的方法

代码语言:javascript
运行
复制
rol = df.rolling(window=2)
rol.apply(masscenter)

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

代码语言:javascript
运行
复制
stamp
1900-01-01 02:59:47.000282    87.60
1900-01-01 03:00:01.042391    87.51
dtype: float64

然后

代码语言:javascript
运行
复制
stamp
1900-01-01 02:59:47.000282    739.0
1900-01-01 03:00:01.042391     10.0
dtype: float64

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

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

代码语言:javascript
运行
复制
rol = df.rolling(window=2, axis = 1)
rol.apply(masscenter)

从不调用masscenter并引发ValueError in rol.apply(..)

代码语言:javascript
运行
复制
> 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滚动多个列?

非常感谢。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2020-03-29 17:27:27

这个怎么样:

代码语言:javascript
运行
复制
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中获取多列切片。

票数 24
EN

Stack Overflow用户

发布于 2020-03-18 16:11:32

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

代码语言:javascript
运行
复制
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
票数 16
EN

Stack Overflow用户

发布于 2021-04-24 16:30:49

引用来自@saninstein的优秀答案。

从: numpy_ext安装https://pypi.org/project/numpy-ext/

代码语言:javascript
运行
复制
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)

输出:

代码语言:javascript
运行
复制
print(df.to_string(index=False))
 x  y  sum
 1  1  NaN
 2  2  6.0
 3  3 10.0
 4  4 14.0

备注

  • 滚动功能是友好的时间序列。它默认为总是回顾,因此6是数组中当前值和过去值的总和。
  • 在上面的示例中,将rolling_apply导入为rolling_apply_ext,这样就不可能干扰对Pandas rolling_apply的任何现有调用(这要感谢@LudoSchmidt的评论)。

另外,我放弃了使用Pandas的尝试。它是从根本上破坏的:它处理单列光栅并在应用中遇到一些小问题,但它是一台过于复杂的rube机器,当它试图让它与更多的两列或更多列一起工作时。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60736556

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档