求助:在Pandas中使用Multiprocessing调用滚动函数返回NaN的问题
Pandas滚动窗口+多进程返回NaN的问题分析与解决
嘿,我来帮你捋清楚这个问题~你遇到的NaN和lambda报错,本质上都是Pandas滚动窗口结合多进程时的维度匹配和函数序列化问题,咱们一步步拆解:
为什么滚动+多进程会返回NaN?
Pandas的rolling()默认是按列(axis=0)处理的,每个滚动窗口传入给函数的是一段一维Series/数组,而不是你可能预期的行或二维数据。
如果你的原square函数是按行/二维结构写的(比如试图取行索引、按列切片),那它拿到一维输入时就会因为维度不匹配,无法正确计算,最终返回NaN。而多进程环境下,数据是序列化传递的,这种维度不匹配的问题会直接暴露出来,不像单进程可能还能容错。
为什么修改square函数后正常?
你修改后的函数应该是适配了一维输入的情况——比如直接对输入的每个元素做平方操作(return x ** 2),这样不管是单进程还是多进程,函数都能正确处理滚动窗口传入的一维数据,自然就能得到正确结果。
lambda报错的原因与解决
你用的lambda大概率是没有适配一维输入,或者遇到了序列化问题:
- 如果你写的lambda是按行/二维结构操作(比如
lambda x: x.iloc[:,0]**2),那拿到一维Series时就会报错,因为iloc[:,0]是针对二维数据的操作。 - 原生
multiprocessing对lambda的序列化支持不好,lambda函数无法被pickle序列化,所以传递给子进程时会报错。
解决方法:
- 把lambda改成普通的
def定义函数,确保它能处理一维输入,比如:def square(x): return x ** 2 - 如果一定要用lambda,可以用
swifter这类专门优化Pandas多进程的库,它对lambda的支持更好,比如:import swifter df.rolling(window=2).swifter.apply(lambda x: x**2)
完整的多进程滚动处理示例
这里给你一个正确的多进程处理滚动窗口的写法,按列拆分任务,避免维度问题:
import pandas as pd from multiprocessing import Pool # 适配一维输入的函数 def square(x): return x ** 2 # 创建测试数据 df = pd.DataFrame({'a': [1,2,3,4,5], 'b': [6,7,8,9,10]}) # 定义单列处理函数 def process_single_col(col_name): return df[col_name].rolling(window=2).apply(square) # 多进程处理 if __name__ == '__main__': with Pool(processes=2) as pool: # 给每个列分配一个进程处理 results = pool.map(process_single_col, df.columns) # 将结果合并成DataFrame df_rolling_multi = pd.concat(results, axis=1) print(df_rolling_multi)
这个例子里,我们把每列的滚动任务拆分给不同进程,每个进程处理的是单列的一维滚动窗口数据,完美匹配函数的输入要求,不会返回NaN。
内容的提问来源于stack exchange,提问作者unmark1
相关产品推荐
相关产品推荐

