移动 Pandas 列,然后取接下来 3 个值的平均值 (post_shift)



我有一个数据帧,df看起来像这样

Open  High   Low  Close   Volume
Date                                        
2007-03-22  2.65  2.95  2.64   2.86   176389
2007-03-23  2.87  2.87  2.78   2.78    63316
2007-03-26  2.83  2.83  2.51   2.52    54051
2007-03-27  2.61  3.29  2.60   3.28   589443
2007-03-28  3.65  4.10  3.60   3.80  1114659
2007-03-29  3.91  3.91  3.33   3.57   360501
2007-03-30  3.70  3.88  3.66   3.71   185787

我正在尝试创建一个新列,该列首先将打开列移动 3 行 (df。Open.shift(-3)),然后取其自身的平均值和接下来的 2 个值。

例如,上述数据帧的Open列将移动 -3 行,如下所示:

Date
2007-03-22    2.610
2007-03-23    3.650
2007-03-26    3.910
2007-03-27    3.700
2007-03-28    3.710
2007-03-29    3.710
2007-03-30    3.500

然后,我想通过迭代获取接下来 3 个值(包括自身)的正向平均值。 因此,第一次迭代将 2.610(第一个值)+ 3.650 + 3.910(下一个值)除以 3。 然后我们取下一个值 3.650(第一个值)并执行相同的操作。创建值列。

起初我尝试了类似的东西:

df['Avg'] =df.Open.shift(-3).iloc[0:3].mean()   

但这并不能遍历 Open.shift 的所有值。

下一个循环似乎有效,但非常慢,我被告知在 Pandas 中使用循环是一种不好的做法。

for i in range(0, len(df.Open)):
df['Avg'][i] =df.Open.shift(-3).iloc[i:i+4].mean()

我试图思考使用应用程序的方法

df.Open.shift(-3).apply(loc[0:4].mean())
df.Open.shift(-3).apply(lambda x: x[0:4].mean())

但这些似乎给出了错误,例如

TypeError: 'float' object is not subscriptable

我想不出一种优雅的方式来做到这一点。

谢谢。

你可以使用熊猫rolling_mean。由于它使用向后窗口,因此它将为您提供前两行为 2.61(值本身)和 3.13(第 0 行和第 1 行的平均值)。要解决这个问题,您可以使用 shift(-2) 将值移动 2 行。

pd.rolling_mean(df, window=3, min_periods=1).shift(-2)

输出:

open
date    
2007-03-22  3.390000
2007-03-23  3.753333
2007-03-26  3.773333
2007-03-27  3.706667
2007-03-28  3.640000
2007-03-29  NaN
2007-03-30  NaN

numpy解决方案

正如承诺的那样
注意:巨大的警告<</strong>br/>这是一项高级技术,不建议任何初学者使用!!
使用它实际上可能会意外地剃掉你的贵宾犬秃顶。 小心!

as_strided

from numpy.lib.stride_tricks import as_strided
import numpy as np
import pandas as pd
# I didn't have your full data for all dates
# so I created my own array
# You should be able to just do
# o = df.Open.values
o = np.array([2.65, 2.87, 2.83, 2.61, 3.65, 3.91, 3.70, 3.71, 3.71, 3.50])
# because we shift 3 rows, I trim with 3:
# because it'll be rolling 3 period mean
# add two np.nan at the end
# this makes the strides cleaner.. sortof
# whatever, I wanted to do it
o = np.append(o[3:], [np.nan] * 2)
# strides are the size of the chunk of memory
# allocated to each array element.  there will
# be a stride for each numpy dimension.  for
# a one dimensional array, I only want the first
s = o.strides[0]
# it gets fun right here
as_strided(o, (len(o) - 2, 3), (s, s))
#          ^   ___________/    __/
#          |                      ______
# object to stride --- size of array ---  
#                      to make           memory chunk
#                                        to step forward
#                                        per dimension
[[ 2.61  3.65  3.91]
[ 3.65  3.91  3.7 ]
[ 3.91  3.7   3.71]
[ 3.7   3.71  3.71]
[ 3.71  3.71  3.5 ]
[ 3.71  3.5    nan]
[ 3.5    nan   nan]]

现在我们只是取平均值。 一起

o = np.array([2.65, 2.87, 2.83, 2.61, 3.65, 3.91, 3.70, 3.71, 3.71, 3.50])
o = np.append(o[3:], [np.nan] * 2)
s = o.strides[0]
as_strided(o, (len(o) - 2, 3), (s, s)).mean(1)
array([ 3.39      ,  3.75333333,  3.77333333,  3.70666667,  3.64      ,
nan,         nan])

你可以把它包装在一个熊猫系列中

pd.Series(
as_strided(o, (len(o) - 2, 3), (s, s)).mean(1),
df.index[3:],
) 

相关内容

  • 没有找到相关文章

最新更新