求助:在pandas expanding窗口应用二元numpy函数时出现无法理解的错误
解决pandas expanding窗口中apply调用二元numpy函数的问题
首先我先还原你可能遇到的代码场景(结合你的描述推测),比如你大概写了类似这样的代码:
import pandas as pd import numpy as np # 用numpy.sum模拟你的复杂二元函数 def loc_fun(a, b): return np.sum(a) + np.sum(b) df = pd.DataFrame({'A': [1,2,3,4], 'B': [5,6,7,8]}) # 触发报错的调用 df.expanding().apply(lambda x: loc_fun(x['A'], x['B']))
可能的错误原因
当对DataFrame使用expanding().apply()时,默认axis=0,此时每次传递给lambda的x是当前扩展窗口内的整个DataFrame子集(比如第n次调用时,x是前n行的DataFrame)。如果你的二元函数返回的是标量,这段代码其实可以运行,但如果函数返回数组/Series,或者你误解了参数传递的逻辑,就会触发错误。另外,如果你的需求是对窗口内逐行做二元运算而非聚合,当前写法也不符合预期。
正确的实现方式
根据你"将loc_fun应用于各列值的expanding窗口"的需求,分两种场景处理:
场景1:对两列的expanding窗口做聚合运算(返回标量)
如果你的二元函数是对两列的整个窗口数据做聚合(比如求和、点积等),直接从窗口子集中提取对应列传入函数即可,确保函数返回标量:
import pandas as pd import numpy as np def loc_fun(arr1, arr2): # 替换成你的复杂二元numpy操作,比如np.dot(arr1, arr2) return np.sum(arr1) * np.sum(arr2) df = pd.DataFrame({'A': [1,2,3,4], 'B': [5,6,7,8]}) # 正确调用:从窗口子集x中提取A、B列传入函数 result = df.expanding().apply(lambda x: loc_fun(x['A'], x['B']), raw=False) print(result)
这里raw=False是默认值,确保传入的是Series(numpy可以直接处理Series)。如果你的函数需要纯numpy数组,可以设置raw=True,此时传入的是numpy数组:
result = df.expanding().apply(lambda x: loc_fun(x[:,0], x[:,1]), raw=True)
场景2:对窗口内的每一行做二元运算(返回同长度结果)
如果你的需求是对每个expanding窗口内的每一行,用两列的值做二元运算(比如窗口内每行A和B的对应元素运算),需要调整函数逻辑,确保返回与窗口长度匹配的结果:
def loc_fun_window(window_df): # 对窗口内的每一行,执行二元numpy运算 return np.multiply(window_df['A'].values, window_df['B'].values) result = df.expanding().apply(loc_fun_window, raw=False) print(result)
此时返回的是DataFrame,每一行对应到当前窗口内的运算结果。
常见报错排查
- 返回值形状不匹配:如果函数返回的数组长度与窗口长度不一致,pandas会报错。确保返回值是标量(聚合场景)或与窗口行数相同的一维数组(逐行运算场景)。
- 参数类型错误:如果你的numpy函数需要纯数组,记得设置
raw=True,避免传入Series引发类型问题。 - axis参数混淆:如果设置
axis=1,expanding会按列扩展,传递给函数的是每列的窗口数据,这通常不是你想要的按行扩展的窗口。
内容的提问来源于stack exchange,提问作者user189035
相关产品推荐
相关产品推荐

