我有一个数据框,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
我尝试创建一个新列,首先将Open列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循环是不好的做法。
for i in range(0, len(df.Open)):
df['Avg'][i] =df.Open.shift(-3).iloc[i:i+4].mean()
我试着想办法使用apply
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
等
我无法想到这种优雅的做法。
谢谢。
答案 0 :(得分:3)
您可以使用pandas 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
答案 1 :(得分:1)
numpy
解决方案如所承诺的那样
注意:巨大的CAVEAT
这是一项先进的技术,不建议任何初学者使用!
使用它可能会意外地刮掉你的狮子狗秃头。小心!
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:],
)