如何在Pandas中对DataFrame相邻行应用函数并规避内存问题
如何在不传递整个DataFrame的情况下实现迭代累加操作?
嘿,我来帮你梳理一下这个问题~首先,先明确你想要实现的效果:让每行的值等于前一行更新后的值加上当前行的原始值,最终结果其实和Pandas内置的cumsum()函数输出完全一致,这是最简洁高效的方案,先给你看这个:
import pandas as pd df = pd.DataFrame({'col1': [1, 2, 3], 'col2': [4, 5, 6]}) df = df.cumsum() print(df) # 输出: col1 col2 0 1 4 1 3 9 2 6 15
这个方法是矢量化操作,Pandas内部做了极致优化,完全不会有大DataFrame的内存问题,也不需要传递整个DataFrame到处跑,是首选方案。
但如果一定要用你设想的「自定义函数处理相邻两行」的方式,那我们可以避开apply(axis=1)(因为它没法获取前一行的更新后数据),用下面两种可行的方式:
方法1:迭代行索引+自定义行处理函数
这个方法完全符合你的要求:自定义函数只接收两个行对象(Series),不需要传递整个DataFrame,每次只处理两行数据,内存压力极小:
import pandas as pd def update_row(prev_row, curr_row): # 接收前一行和当前行,返回更新后的当前行 return pd.Series( [prev_row['col1'] + curr_row['col1'], prev_row['col2'] + curr_row['col2']], index=curr_row.index ) # 初始化原始DataFrame df = pd.DataFrame({'col1': [1, 2, 3], 'col2': [4, 5, 6]}) # 第一行保持不变,作为初始的前一行 prev_row = df.iloc[0] # 从第二行开始迭代处理 for i in range(1, len(df)): curr_row = df.iloc[i] updated_row = update_row(prev_row, curr_row) # 原地更新当前行 df.iloc[i] = updated_row # 更新前一行的引用,用于下一次迭代 prev_row = updated_row print(df)
方法2:用滚动窗口(rolling)结合自定义函数
如果你更倾向于用Pandas的API风格,也可以用窗口大小为2的滚动窗口,对每个窗口应用自定义函数:
import pandas as pd def process_window(window): # window是当前窗口的DataFrame,长度为1(第一行)或2(后续行) if len(window) == 1: # 第一行没有前一行,直接返回原值 return window.iloc[0] # 拆分窗口中的前一行和当前行 row1, row2 = window.iloc[0], window.iloc[1] # 返回更新后的当前行 return pd.Series( [row1['col1'] + row2['col1'], row1['col2'] + row2['col2']], index=window.columns ) df = pd.DataFrame({'col1': [1, 2, 3], 'col2': [4, 5, 6]}) # 设置窗口大小为2,min_periods=1允许第一行的窗口只有1行 result = df.rolling(window=2, min_periods=1).apply(process_window, raw=False) print(result)
为什么你的df.apply(axis=1)思路不可行?
这里要解释一下:df.apply(axis=1)是逐行独立处理,每次调用函数只能拿到当前行的原始数据,无法获取前一行的更新后的值;而且apply的处理是基于原始DataFrame的,不会实时反映你对DataFrame的修改,所以没法直接用它实现你想要的迭代累加逻辑。
内容的提问来源于stack exchange,提问作者Fernando S. Peregrino
相关产品推荐
相关产品推荐

