自定义Lambda计算Pandas Series元素差值报错的解决及DataFrame扩展
自定义Pandas元素差值计算的问题解答
问题背景
给定如下Pandas Series s:
3/28/22 127943 3/29/22 127970 3/30/22 127997 3/31/22 128019 4/1/22 128052 4/2/22 128059 4/3/22 128065 4/4/22 128086 4/5/22 128106 4/6/22 128144
尝试用lambda函数实现类似diff()的元素间差值计算时,写出了如下代码:
s.apply(lambda i, j: j - i for i, j in zip(s[:-1], s[1:]))
触发了以下错误:
File ~\Anaconda3\lib\site-packages\pandas\core\apply.py:412, in Apply.agg_list_like(self) 410 # if we are empty 411 if not len(results): --> 412 raise ValueError("no results") 414 if len(failed_names) > 0: 415 warnings.warn( 416 depr_nuisance_columns_msg.format(failed_names), 417 FutureWarning, 418 stacklevel=find_stack_level(), 419 ) ValueError: no results
错误含义
这个错误的核心是apply()方法的使用逻辑完全错误:
s.apply()是对Series的每个单独元素执行传入的函数,它只支持接收单个参数的函数,但你传入的是一个生成器表达式,完全不符合apply()的单元素处理逻辑。- 生成器没有被正确执行,也无法匹配
apply()的调用规则,最终没有生成任何有效计算结果,因此触发"no results"报错。
修复方法(针对错误代码)
如果非要用zip+lambda的方式实现,不能用apply(),而是直接通过生成器生成差值后转为Series:
import pandas as pd diff_series = pd.Series([j - i for i, j in zip(s[:-1], s[1:])], index=s.index[1:])
也可以用生成器表达式直接构造Series:
diff_series = pd.Series((j - i for i, j in zip(s[:-1], s[1:])), index=s.index[1:])
更佳实现方案
直接使用Pandas内置的diff()方法是最优解——它专门为相邻元素差值计算设计,代码简洁且执行效率更高:
diff_series = s.diff().dropna()
diff()默认计算当前元素与前一个元素的差值,返回的Series第一个值为NaN,用dropna()可以去掉空值,结果和自定义方式完全一致。
扩展到DataFrame
无论是自定义方式还是内置方法,都可以直接扩展到DataFrame:
内置方法(推荐):
DataFrame的diff()方法会对每一列单独计算相邻元素差值,用法和Series一致:# 假设df是目标DataFrame df_diff = df.diff().dropna()自定义方式:
遍历DataFrame的每一列,对列执行自定义差值计算后合并结果:df_diff = pd.DataFrame() for col in df.columns: col_diff = pd.Series([j - i for i, j in zip(df[col][:-1], df[col][1:])], index=df.index[1:]) df_diff[col] = col_diff
内容的提问来源于stack exchange,提问作者Nemo
相关产品推荐
相关产品推荐

