Python Pandas:计算组内的移动平均值
Posted
技术标签:
【中文标题】Python Pandas:计算组内的移动平均值【英文标题】:Python Pandas: Calculate moving average within group 【发布时间】:2019-04-19 17:03:35 【问题描述】:我有一个包含 100 个对象的时间序列的数据框:
object period value
1 1 24
1 2 67
...
1 1000 56
2 1 59
2 2 46
...
2 1000 64
3 1 54
...
100 1 451
100 2 153
...
100 1000 21
我想用窗口 10 计算 value
列的移动平均值。我想我必须做类似的事情
df.groupby('object').apply(lambda ~calculate MA~)
然后按对象将此系列合并到原始数据框?无法确定确切的命令
【问题讨论】:
移动平均线的行数会更少,应该将它们分配到哪些时段? 最好这样做:对于周期 1,MA 等于周期 1 的值。从周期 2 开始,MA = (value_1 + value_2) / 2,依此类推,直到 10。 10 点之后,这是一个正常的移动平均线 我正在尝试使用 pd.rolling_mean(),但还没有弄明白 【参考方案1】:您可以将rolling 与transform
一起使用:
df['moving'] = df.groupby('object')['value'].transform(lambda x: x.rolling(10, 1).mean())
rolling
中的 1
用于表示最少的句点数。
【讨论】:
哦,太美了!我爱熊猫! 这是推荐的方式:我打算用pd.rolling_mean
回答并收到弃用警告。所以,谢谢你今天教我一些东西@zipa
如何使用talib.BBANDS() 计算组内的Bolinger Band 值?以下代码给出错误。 (BBANDS() 返回一个元组(上、中、下)。)df['bb_up'], df['bb_mid'], df['bb_low'] = df.groupby('object')['value'].transform(lambda x: talib.BBANDS(x))
【参考方案2】:
您可以在groupby
对象上直接使用rolling
:
df['moving'] = df.groupby('object').rolling(10)['value'].mean()
新版pandas使用直接赋值给列时会报错,所以使用:
df['moving'] = df.groupby('object').rolling(10)['value'].mean().reset_index(drop=True)
【讨论】:
嗨,我收到一个错误:TypeError: incompatible index of inserted column with frame index
。不知道是什么问题...
这清除了错误,但 df['avg'] 对我来说完全是空的。我的熊猫版本是 0.24.2
@SarahMesser 那是因为您在每个组中只有一个值,请检查 object
是否只有唯一值,这意味着您计算滚动的每个组只有一个值,因此您得到NaN's
糟糕。我删除了列表理解中的“句点”循环,以简化数据框并使示例最小化。如您所说,将其添加回固定的空值。
我在 mean() 和 reset_index() 之间添加了一个 shift(1),因为我不想在计算 period-2 的平均值时包含 period-2 的值...这似乎通过将多索引中的值从一个“对象”组转移到下一个来混淆值。手动构建的小型数据框似乎也依赖于原始索引。可能有必要运行df.sort_values(by=['object', 'period']).reset_index(drop=True)
在你的groupby-rolling构造,以保证索引对齐。【参考方案3】:
如果您在多列上进行分组,所提供的答案可能不会产生预期的结果。
下面应该删掉它:
df['moving'] = df.groupby(['col_1', 'col_2', 'col_3']).rolling(10)['value'].mean().droplevel(level=[0,1,2])
【讨论】:
这应该是最佳答案+1! (.droplevel 可以替换为 .reset_index,顺便说一句)。【参考方案4】:扩展来自@Sandeep Kadapa 的答案:
df['moving'] = df.groupby('object').rolling(10)['value'].mean().reset_index(drop=True)
reset_index
的原因是因为在df.groupby
之后我们最终得到了一个多级索引并且在分配时我们会得到错误TypeError: incompatible index of inserted column with frame index
【讨论】:
【参考方案5】:将列创建为链式方法:
(
df
.assign(
column_name = lambda x:
x
.groupby(['object'])['value']
.transform(lambda x: x.rolling(10)
.mean())
)
)
【讨论】:
【参考方案6】:这些解决方案假定数据框以特定方式(按对象和周期)排序。例如,如果数据被组织在面板中(按期间和对象),那么分配将失败。一种与排序顺序无关的通用解决方案如下:
df.loc[:, 'value_sma_10'] = df.groupby(by='object')[['object', 'period']].rolling(window=10, min_periods=1, on='period').mean().reset_index(level='object')['value']
【讨论】:
以上是关于Python Pandas:计算组内的移动平均值的主要内容,如果未能解决你的问题,请参考以下文章
Python/Pandas - 结合 groupby 平均值和最小值
python pandas groupby分组后的数据怎么用