
本文深入探讨了在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无法直接将其作为新列插入。
有时,为了规避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的行中,导致结果完全不准确。
例如,如果我们查看某个特定分组的滚动平均值,会发现其值与该分组的数据完全不匹配。
解决这个问题的关键在于,我们需要将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。
在Pandas中对分组数据计算滚动平均值并将其添加回原始DataFrame时,groupby().rolling().mean()操作会产生一个带有MultiIndex的Series,这与原始DataFrame的单级索引不兼容。解决此问题的正确方法是使用.droplevel(['group_key1', 'group_key2'])方法,将MultiIndex降维,使其索引与原始DataFrame的索引对齐。通过这种方式,可以确保计算结果的准确性,并避免常见的TypeError。
以上就是如何使用Pandas在分组数据上正确计算滚动平均值的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号