Pandas用apply+lambda调用带floor及条件判断的自定义函数报错如何解决
问题1:添加floor后触发TypeError的解决
错误原因
math.floor仅支持传入单个数值类型参数,你代码中apply默认按列遍历,传入func的x是整列的Series对象,(1-x)*(y+1)*0.9运算后仍然是Series,无法直接传给math.floor。
修复方案
改用pandas自带的向量化floor方法,替换math.floor即可:
# 不需要导入math.floor def func(x,y): return ((1-x)*(y+1)*0.9).floor()
如果要保留math.floor的调用,也可以对Series逐元素调用方法:
from math import floor def func(x,y): return ((1-x)*(y+1)*0.9).apply(floor)
问题2:新增条件判断后触发ValueError的解决
错误原因
if x == 1:中的x是Series对象,x==1返回的是布尔类型的Series(每个元素对应原x位置是否等于1),Python无法直接判断一整组布尔值的真值,因此报错。
修复方案
使用numpy的向量化条件判断函数np.where替代原生if判断,适配Series输入:
import pandas as pd import numpy as np from math import floor d = {'ind': ['a', 'b', 'c'], 'col1': [1, 2, 3], 'col2': [4, 5, 6], 'col3': [7, 8, 9], 'spec': [9, 6, 3]} df = pd.DataFrame(data=d).set_index('ind') def func(x,y): # 三个参数分别为:判断条件、条件成立返回的值、条件不成立返回的值 return np.where( x == 1, y, ((1-x)*(y+1)*0.9).apply(floor) ) df2 = df.apply(lambda x: func(x, df.spec)) print(df2)
如果更倾向于逐元素处理逻辑,也可以调整apply的遍历维度,逐行传入每行的数值和spec值计算:
def func(row, col_name): x = row[col_name] y = row['spec'] if x == 1: return y else: return floor((1-x)*(y+1)*0.9) # 逐行遍历计算每一列的结果 df2 = pd.DataFrame({ col: df.apply(lambda row: func(row, col), axis=1) for col in ['col1', 'col2', 'col3'] })
内容的提问来源于stack exchange,提问作者lucas
相关产品推荐
相关产品推荐

