pandas基于DataFrame现有列值生成新列及自定义函数报错解决
原有自定义函数的逻辑问题
两个版本的函数核心错误都是写了for循环但完全没使用循环遍历的单个元素item,全程在对整列Series做操作,再叠加细节逻辑错误,才会触发各类报错:
- 第一版函数问题:
- 提前把
Code列转为字符串时,NaN会被转为小写的'nan',和你判断条件里的大写'NaN'完全不匹配,所有行都会走到else分支 - else分支里对整列Series做转float、转int操作,既会因为未被过滤的NaN触发非有限值无法转整数的错误,直接把Series传入Python原生
int()也会触发类型错误
- 提前把
- 第二版函数问题:
- 循环内直接判断
tCode > 0是拿整列Series和0做比较,pandas无法直接判定整列的布尔值结果,直接触发真值歧义报错 - 代码中使用的
numStr变量从未定义,就算判断逻辑写对也会触发变量不存在的错误 - 判断逻辑不严谨:仅用
>0判断有效值,没有兼容Code为0、负数的场景,也没有用pandas标准的空值判断方法。
- 循环内直接判断
可直接运行的实现代码
推荐优先用pandas向量化写法,不用显式写循环,运行效率更高,逻辑也更清晰:
import pandas as pd import numpy as np # 用可空整数类型转换Code列,避免NaN导致的转int报错 code_valid = df['Code'].astype('Int64') # 按规则生成新列,插入到指定位置 df.insert( loc=4, column='Term Code', value=np.where( code_valid.notna(), '(' + code_valid.astype(str).str.rjust(2) + ')', ' ' ) ) # 期望输出中无原Code列,可直接删除 df = df.drop(columns=['Code'])
如果你更习惯用循环写法,修正后的函数逻辑如下:
def gen_term_code(code_col): res = [] for val in code_col: if pd.isna(val): res.append(' ') else: # 用f-string直接格式化,数字占2位右对齐,拼接后刚好是4位长度 res.append(f'({int(val):2d})') return res # 调用时保留Code列的float64类型即可,无需提前转字符串 df.insert(4, 'Term Code', gen_term_code(df['Code'])) df = df.drop(columns=['Code'])
以上两种写法跑出来的结果和你给出的期望输出完全一致,Term Code列的每个元素长度均为4,空值对应4个空格,数值对应( X)格式的字符串。
内容的提问来源于stack exchange,提问作者Billy
相关产品推荐
相关产品推荐

