Pandas使用自定义函数填充列报真值歧义错误的解决方法
Pandas自定义函数填充列触发真值歧义错误的解决方法
错误原因
你遇到的Truth is ambiguous报错以及逻辑不生效问题,由以下几个写法错误共同导致:
- 循环逻辑错误:
for x in df默认遍历DataFrame的列名,并非逐行遍历数据行 - 条件判断错误:
if df['Type'] == 'sell'是对整列做等值判断,返回的是一组布尔值序列,Python的if分支判断需要单个真值,Pandas无法直接将整组布尔值转换为单个True/False,因此抛出真值歧义错误 - 赋值逻辑错误:调用盈亏计算函数后没有接收返回值,反而将函数对象本身追加到结果列表,即使不报错也无法得到正确数值
- 语法笔误:传参时写了重复赋值
openPrice=openPrice=df['Price'],属于无效语法 - 冗余操作:提前用
insert插入空值列后续再覆盖,属于多余步骤
正确实现方案
优先使用Pandas向量化运算实现,无需写显式循环,性能远高于逐行遍历,也不会触发布尔判断相关错误:
import pandas as pd fxContactSize = 100000 bid = 0.6821 ask = 0.6830 df = pd.read_excel("Template.xlsx") # 向量化逐行匹配逻辑计算盈亏 df["SimulatedPnL"] = round( fxContactSize * df["Volume"] * ( # 空单(sell):开仓卖出、平仓买入,平仓成交价为当前ask (df["Type"] == "sell") * (df["Price"] - ask) # 多单(buy):开仓买入、平仓卖出,平仓成交价为当前bid + (df["Type"] == "buy") * (bid - df["Price"]) ), 2 )
如果你需要保留原有两个自定义计算函数的结构,可以用df.apply指定axis=1逐行传参计算:
import pandas as pd fxContactSize = 100000 bid = 0.6821 ask = 0.6830 df = pd.read_excel("Template.xlsx") def long_calc(lot, contract, closePrice, openPrice): pnl = round((lot*contract)*(closePrice-openPrice), 2) return pnl def short_calc(lot, contract, openPrice, closePrice): pnl = round((lot*contract)*(openPrice-closePrice), 2) return pnl def row_pnl_calc(row): if row["Type"] == "sell": return short_calc( lot=row["Volume"], contract=fxContactSize, openPrice=row["Price"], closePrice=ask ) else: return long_calc( lot=row["Volume"], contract=fxContactSize, openPrice=row["Price"], closePrice=bid ) df["SimulatedPnL"] = df.apply(row_pnl_calc, axis=1)
补充说明
- 数据量超过1万行时,第一种向量化实现的运算速度是apply逐行遍历的数十到数百倍,优先选择
- 注意外汇交易的报价对应逻辑:bid是市场买盘价(你卖出时的成交价),ask是市场卖盘价(你买入时的成交价),上述代码已经匹配了多空平仓的对应成交价,如果你的业务有特殊规则可以自行调整参数
内容的提问来源于stack exchange,提问作者Jimmy
相关产品推荐
相关产品推荐

