Pandas对比两字符串列生成第三列:升级/降级状态标注问题
解决DataFrame新增class_desc列时的TypeError问题
问题背景
有一个包含old_class和new_class两列的DataFrame,列值仅为diamond、gold、silver三类。需求是新增class_desc列,根据新旧类别标注Upgrade(升级)、Downgrade(降级)或NA。但调用自定义函数时触发TypeError: status_desc() missing 1 required positional argument: new_class错误。
原始DataFrame代码:
import pandas as pd class_pd = pd.DataFrame({'old_class':['gold', 'gold' , 'silver'], 'new_class':['diamond', 'silver', 'silver']})
尝试的函数及调用代码:
def status_desc(class_pd, old_class, new_class): if ((class_pd['old_class'] == 'gold') & (class_pd['new_class'] == 'diamond') or \ (class_pd['old_class'] == 'silver') & (class_pd['new_class'] == 'diamond') or \ (class_pd['old_class'] == 'silver') & (class_pd['new_class'] == 'gold')): val = 'Upgrade' elif ((class_pd['old_class'] == 'diamond') & (class_pd['new_class'] == 'gold') or \ (class_pd['old_class'] == 'diamond') & (class_pd['new_class'] == 'silver') or \ (class_pd['old_class'] == 'gold') & (class_pd['new_class'] == 'silver')): val = 'Downgrade' else: val = 'NA' class_pd['class_desc'] = class_pd.apply(lambda x: status_desc(class_pd['old_class'], class_pd['new_class']), axis=1)
期望输出:
class_pd = pd.DataFrame({'old_class':['gold', 'gold' , 'silver'], 'new_class':['diamond', 'silver', 'silver'], 'class_desc':['Upgrade','Downgrade', 'NA']})
错误原因
- 函数定义冗余:
status_desc的第一个参数class_pd完全多余,使用apply(axis=1)时,传入的是DataFrame的单行数据,直接取该行的old_class和new_class值即可。 - 参数传递错误:调用时传入的是整列数据而非单行值,且函数要求3个参数但仅传入2个,导致参数缺失报错。
- 逻辑判断错误:函数内部使用整列的布尔运算,而非针对单行值进行判断。
修正方案
方案1:简化自定义函数+apply调用
先重新定义函数,直接接收每行的新旧类别值,通过等级映射简化判断逻辑:
def status_desc(old_class, new_class): # 定义等级优先级:silver < gold < diamond rank_map = {'silver': 1, 'gold': 2, 'diamond': 3} old_rank = rank_map[old_class] new_rank = rank_map[new_class] if new_rank > old_rank: return 'Upgrade' elif new_rank < old_rank: return 'Downgrade' else: return 'NA'
然后正确调用apply,传入单行的对应列值:
class_pd['class_desc'] = class_pd.apply(lambda x: status_desc(x['old_class'], x['new_class']), axis=1)
方案2:向量化操作(更高效,适合大数据量)
使用numpy.select实现向量化判断,避免循环,提升性能:
import numpy as np rank_map = {'silver': 1, 'gold': 2, 'diamond': 3} # 映射新旧类别到等级 old_rank = class_pd['old_class'].map(rank_map) new_rank = class_pd['new_class'].map(rank_map) # 定义判断条件和对应结果 conditions = [ new_rank > old_rank, new_rank < old_rank ] choices = ['Upgrade', 'Downgrade'] # 生成class_desc列 class_pd['class_desc'] = np.select(conditions, choices, default='NA')
验证结果
运行上述任意方案后,class_pd的输出与期望完全一致:
old_class new_class class_desc 0 gold diamond Upgrade 1 gold silver Downgrade 2 silver silver NA
内容的提问来源于stack exchange,提问作者Leena
相关产品推荐
相关产品推荐

