Pandas循环计算3行分组平均值未修改DataFrame问题排查与优化
无法修改DataFrame的B列?每3行分组计算A列平均值并赋值的问题
需求与示例
需要处理一个包含90行数据的DataFrame:每3行作为一组,计算每组A列的平均值,将该平均值赋值给对应组的所有行的B列。
原DataFrame示例:
import pandas as pd df = pd.DataFrame({'A': [2, 3, 4, 7, 9, 8], 'B': [0, 0, 0, 0, 0, 0]})
目标DataFrame示例:
df = pd.DataFrame({'A': [2, 3, 4, 7, 9, 8], 'B': [3, 3, 3, 8, 8, 8]})
尝试的代码
x=0 for i in df['A']: if x<90: y = (df['A'][x]+ df['A'][(x +1)]+df['A'][(x +2)])/3 df['B'][x] = y df['B'][(x+1)] = y df['B'][(x+2)] = y x=x+3 print(y)
遇到的问题
代码能打印出正确的平均值y,但无法修改DataFrame的B列数据。
问题原因
- 链式赋值的不确定性:你使用的
df['B'][x]属于链式索引操作。Pandas中,df['B']返回的可能是原DataFrame数据的视图而非副本,后续的[x]索引再赋值时,操作可能只作用于临时副本,无法同步到原DataFrame。这种赋值方式是Pandas不推荐的,行为不可靠。 - 循环逻辑冗余:
for i in df['A']会遍历DataFrame的每一行(90次),但你的逻辑只需要每3行处理一次,多余的循环会在x≥90时跳过,虽然不影响结果,但属于无效遍历。
更优实现方法
方法1:使用groupby + transform(推荐)
这是Pandas处理分组广播的惯用方法,无需手动循环,效率远高于逐行操作:
import pandas as pd # 构造90行的示例数据(以6行示例为例扩展) df = pd.DataFrame({'A': [2,3,4,7,9,8] + list(range(84)), 'B': [0]*90}) # 按每3行分组,计算A列均值并广播到对应组的B列 df['B'] = df['A'].groupby(df.index // 3).transform('mean')
df.index // 3会生成每个行对应的分组标签(0,0,0,1,1,1,...29,29,29),实现每3行一组的分组逻辑。transform('mean')会将每组的均值广播到该组的所有行,直接赋值给B列即可完成需求。
方法2:改进循环(不推荐,仅作参考)
如果一定要用循环实现,需使用.iloc进行位置索引,避免链式赋值的问题,同时处理最后一组可能不足3行的情况:
x = 0 total_rows = len(df) while x < total_rows: # 确定当前组的结束位置,处理最后一组不足3行的情况 end_idx = min(x + 3, total_rows) # 计算当前组A列的平均值 group_mean = df['A'].iloc[x:end_idx].mean() # 给当前组的B列赋值 df['B'].iloc[x:end_idx] = group_mean x += 3
内容的提问来源于stack exchange,提问作者Niv Reznik
相关产品推荐
相关产品推荐

