新闻中心

如何使用Pandas在分组数据上正确计算滚动平均值

2025-11-21
浏览次数:
返回列表

如何使用pandas在分组数据上正确计算滚动平均值

本文深入探讨了在Pandas中对分组数据计算滚动平均值时遇到的常见问题,特别是TypeError: incompatible index of inserted column with frame index错误以及结果不准确的情况。通过分析groupby().rolling().mean()操作产生的多级索引问题,文章详细介绍了如何利用droplevel()方法来解决索引不兼容性,从而实现对DataFrame正确地添加分组滚动平均值列,确保计算结果的准确性和数据的完整性。

在数据分析中,对分组数据计算滚动统计量(如滚动平均值)是一项常见的操作。Pandas库提供了强大的groupby()和rolling()方法来支持此类计算。然而,在使用这些方法并将结果赋值回原始DataFrame时,用户可能会遇到TypeError: incompatible index of inserted column with frame index错误或得到不符合预期的计算结果。本文将详细解析这个问题的原因,并提供一个简洁有效的解决方案。

理解问题:分组滚动平均值的索引不兼容性

首先,让我们通过一个示例数据集来重现并理解这个问题。

import pandas as pd
import numpy as np

# 创建示例DataFrame
df = pd.DataFrame({
    'a': np.random.choice(['x', 'y'], 8),
    'b': np.random.choice(['r', 's'], 8),
    'c': np.arange(1, 8 + 1)
})

print("原始DataFrame:")
print(df)

一个可能的输出如下:

原始DataFrame:
   a  b  c
0  y  s  1
1  y  r  2
2  y  s  3
3  y  r  4
4  y  s  5
5  x  r  6
6  y  r  7
7  x  r  8

现在,我们尝试按照列'a'和'b'进行分组,然后计算列'c'的窗口大小为3的滚动平均值,并直接将其赋值给原始DataFrame的新列'ROLLING_MEAN':

# 尝试直接赋值(会导致TypeError)
# df['ROLLING_MEAN'] = df.groupby(['a', 'b'])['c'].rolling(3).mean()

如果直接执行上述代码,Pandas会抛出TypeError: incompatible index of inserted column with frame index。这是因为df.groupby(['a', 'b'])['c'].rolling(3).mean()这个操作的返回值是一个带有多级索引(MultiIndex)的Series。这个多级索引包含了分组键('a'和'b')以及原始DataFrame的索引。例如,单独查看其输出:

intermediate_result = df.groupby(['a', 'b'])['c'].rolling(3).mean()
print("\ngroupby().rolling().mean()的中间结果(带有MultiIndex):")
print(intermediate_result)

一个可能的输出(注意索引结构):

groupby().rolling().mean()的中间结果(带有MultiIndex):
a  b   
x  r  5    NaN
      7    NaN
   s  3    NaN
y  r  1    NaN
      4    NaN
      6    5.0
y  s  0    NaN
      2    NaN
Name: c, dtype: float64

(请注意,示例输出中的索引值和原始DataFrame的索引值可能因为np.random.choice的随机性而有所不同,但关键在于其索引结构是a, b和原始索引的组合。)

由于这个Series的索引与原始DataFrame的单级整数索引不兼容,Pandas无法直接将其作为新列插入。

CA.LA CA.LA

第一款时尚产品在线设计平台,服装设计系统

CA.LA 94 查看详情 CA.LA

错误的.values使用及其影响

有时,为了规避TypeError,用户可能会尝试在.mean()后面加上.values:

# 尝试使用.values(会避免TypeError,但结果不准确)
df['ROLLING_MEAN_VALUES'] = df.groupby(['a', 'b'])['c'].rolling(3).mean().values
print("\n使用.values后的DataFrame(结果不准确):")
print(df)

虽然.values操作会提取Series中的数值数组,避免了索引不兼容的错误,但它破坏了数据与原始DataFrame行的对应关系。.values只是简单地按顺序提取数值,而没有考虑原始DataFrame的行索引。这意味着计算出的滚动平均值会错误地分配到DataFrame的行中,导致结果完全不准确。

例如,如果我们查看某个特定分组的滚动平均值,会发现其值与该分组的数据完全不匹配。

解决方案:使用 droplevel() 移除多级索引

解决这个问题的关键在于,我们需要将groupby().rolling().mean()返回的Series的多级索引降维(droplevel),使其只保留原始DataFrame的行索引。这样,生成的Series就能与原始DataFrame的索引对齐,从而实现正确的赋值。

droplevel()方法可以从MultiIndex中移除一个或多个级别。在本例中,我们需要移除代表分组键的'a'和'b'级别。

# 正确的解决方案:使用 droplevel()
df['ROLLING_MEAN'] = df.groupby(['a', 'b'])['c'] \
                        .rolling(3).mean() \
                        .droplevel(['a', 'b'])

print("\n使用droplevel()后的DataFrame(结果正确):")
print(df)

一个可能的输出如下:

使用droplevel()后的DataFrame(结果正确):
   a  b  c  ROLLING_MEAN
0  y  s  1           NaN
1  y  r  2           NaN
2  y  s  3           NaN
3  y  r  4           NaN
4  y  s  5      3.000000
5  x  r  6           NaN
6  y  r  7      4.333333
7  x  r  8           NaN

结果验证: 让我们手动验证一个分组的计算。假设在上述输出中,df的索引4对应的行是y, s, 5,并且其ROLLING_MEAN是3.000000。 如果df的原始数据是:

   a  b  c
0  y  s  1
1  y  r  2
2  y  s  3
3  y  r  4
4  y  s  5

对于分组 ('y', 's'),其 c 列的值序列是 1, 3, 5。

  • 索引0 (c=1): NaN (窗口不足3)
  • 索引2 (c=3): NaN (窗口不足3)
  • 索引4 (c=5): (1 + 3 + 5) / 3 = 3.0。 这与输出结果一致。

注意事项

  1. 索引对齐的重要性: Pandas的核心优势之一是其强大的索引对齐功能。在进行复杂的转换和合并操作时,始终要关注Series或DataFrame的索引结构,确保它们能够正确对齐。
  2. rolling() 的 min_periods 参数: 默认情况下,rolling()要求窗口中有足够的非NaN值才能进行计算。例如,rolling(3)表示需要至少3个值才能计算平均值。可以通过设置min_periods参数来改变这一行为,例如rolling(3, min_periods=1)表示只要有1个值就可以计算。
  3. 链式操作的可读性: 当进行多步操作时,使用括号和换行符可以提高代码的可读性,如示例中所示。

总结

在Pandas中对分组数据计算滚动平均值并将其添加回原始DataFrame时,groupby().rolling().mean()操作会产生一个带有MultiIndex的Series,这与原始DataFrame的单级索引不兼容。解决此问题的正确方法是使用.droplevel(['group_key1', 'group_key2'])方法,将MultiIndex降维,使其索引与原始DataFrame的索引对齐。通过这种方式,可以确保计算结果的准确性,并避免常见的TypeError。

以上就是如何使用Pandas在分组数据上正确计算滚动平均值的详细内容,更多请关注其它相关文章!


# 自定义  # 精准客户关键词排名  # 林芝seo公司选择火星  # 从化seo推广优化公司  # 网站推广外包怎么找  # 免费seo优化在线咨询  # 合肥网站建设哪家效果好  # 鄂尔多斯抖音营销推广  # 沈阳网站推广哪家有名好  # 黑龙江网站推广哪家强些  # 玉林农产品网络营销推广  # 常见问题  # 将其  # 这个问题  # 不兼容  # 让我们  # 移除  # 如何使用  # 不准确  # 多个  # 递归 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 怎样在Excel中做仪表盘_Excel仪表盘设计与关键指标展示方法  印象笔记如何设离线包出差查阅_印象笔记设离线包出差查阅【离线阅读】  Golang如何使用const iota_Go iota常量计数器讲解  word邮件合并后日期格式不对怎么改_Word邮件合并日期格式修改方法  python3时间如何用calendar输出?  Python类型检查:优化关联可选属性的Mypy推断策略  AO3最新入口2025公告_AO3中文官网合集  mc.js免安装版 mc.js一键畅玩入口  Excel Power Pivot如何处理XML数据源 构建高级数据模型  vivo手机互传视频怎么操作_vivo手机互传视频详细传输方法  铁路12306改签能改到更早的车次吗_铁路12306改签提前车次规则  铃兰之剑为这和平的世界希里技能组及加点推荐  win11 arm版怎么安装 M1/M2 Mac虚拟机安装ARM win11的方法  Pandas DataFrame:高效添加条件计算列  Win11 USB传输速度慢怎么解决 Win11 USB驱动更新与设置  护手霜蹭到袖口上了如何清洗? 怎样避免留下一圈油印?  2025-2030年全球乘用车销量预测:新能源成增长主力  J*aScript:在map操作中高效处理空数组  蛙漫限时开放最深处链接_蛙漫全站漫画会员同款秒开地址  如何在Python中使用Optional类型处理可变对象并避免Pylint警告  Win10系统怎么查看已安装更新_Win10卸载有问题的更新补丁  AO3网页版最新入口合集 Archive of Our Own在线访问指南  CKEditor 5 自定义构建在React应用中渲染失败的调试与解决  豆包手机助手发布技术预览版:直接嵌入手机系统!努比亚样机发售  不会效仿卡普空!《铁拳》制作人澄清:不采取赛事付费|直播|  包子漫画官方网站在线链接-包子漫画在线阅读平台主页地址  sublime如何处理大型CSV文件的列对齐_sublime高级表格编辑插件指南  mc.js游戏直达 mc.js网页免下载版本秒进地址  PHP中SSG-WSG API的AES加密实践:正确使用初始化向量  126邮箱网页版官方入口 126邮箱账号在线登录平台  在J*a中如何使用BigDecimal进行高精度计算_BigDecimal类应用指南  React Router v6 教程:构建认证保护的私有路由与重定向策略  深入理解与实现最大堆的Heapify过程:常见错误与修正  Flexbox布局实践:实现粘性导航栏与底部固定页脚  如何在网页中实现特定地点的随机图片展示  蓝湖怎样用切图标注提对接效率_蓝湖用切图标注提对接效率【设计对接】  MAC怎么在地图App里使用“四处看看”_MAC体验部分城市的3D实景街景  NRF24L01数据传输深度解析:解决大载荷接收异常与分包策略  J*aScript生成器_j*ascript异步迭代  MAC怎么让Dock栏只显示当前运行的应用_MAC终端命令实现极简Dock栏  2025AO3夸克浏览器通道_AO3手机HTTPS安全入口分享  AO3官方在线访问地址 Archive of Our Own最新镜像合集  Windows7怎么硬盘安装 Windows7提取ISO镜像到非系统盘并运行setup.exe实现硬盘直装【教程】  PHP表单数据传递:如何通过隐藏输入字段获取动态ID  J*aScript Promise链中如何正确终止后续.then执行并处理错误  外媒分析《GTA6》定价:卖100美元可以但真没必要!  AI抖音网页版免费视频入口 AI抖音网页端最新视频实时观看  微博网页版首页入口 微博电脑端官网登录链接  UC浏览器如何安装插件 UC浏览器添加扩展程序详细教程【进阶】  Safari浏览器输入栏卡顿如何解决 Safari搜索建议与缓存清理 

搜索