You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas按prisoner_type合并多列出现死循环与赋值报错求解

问题描述

首次在此提问,多日反复尝试未找到目标需求的最优实现方案,恳请大家提供帮助。
当前正在处理囚犯及判决相关调研数据:数据中prisoner_type列存储囚犯调研分类,每个囚犯类型对应5个记录罪名信息的列(并非所有列都会被使用)。需求为将不同囚犯类型对应的多组罪名列折叠合并为统一的5个罪名编码列+5个罪名类型列,添加到数据集后,每行仅需访问这10个新列即可获取对应罪名信息。
已构建字典存储每个囚犯类型对应的罪名编码、罪名类型源列名映射,外层字典键为囚犯类型,简化版本如下:

offense_variables= 
{  3: {'codes':{1:'V0114',2:'V0115',3:'V0116',4:'V0117',5:'V0118'},
      'off_types':{1:'V0124',2:'V0125',3:'V0126',4:'V0127',5:'V0128'}},
   8: {'codes':{1:'V0270',2:'V0271',3:'V0272',4:'V0273',5:'V0274'},
       'off_types': {1:'V0280',2:'V0281',3:'V0282',4:'V0283',5:'V0285'}}
}

最初实现思路为:

  • 创建10个新列:offense_1...offense_5和type_1...type_5
  • 使用pandas定位指定囚犯类型对应的所有行
  • 对照字典查询该囚犯类型下每个序号对应的罪名存储列名,将对应列的值赋值给新列

运行时出现两个问题:

  • 代码运行后无法终止,不清楚死循环原因
  • 抛出报错:"A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead"

原有问题代码:

pris_types=[3,8]

for pt in pris_types:
  # 调研中共记录5项罪名,因此需要5列存储罪名编码、5列存储罪名类型
  # 1和2仅为占位值    
  for item in [i+1 for i in range(5)]:
    dataset[f'off_{item}_code']='1'
    dataset[f'off_{item}_type']='2'
  
  # 使用.loc获取当前囚犯类型对应的行索引
  # 通过上述字典查询需要取值的源列名
  for item in [i+1 for i in range(5)]:                
    dataset.loc[dataset['prisoner_type'] == pt, \
    dataset[f'off_{item}_code']] = \
    dataset[offense_variables[pt]['codes'][item]]
    
    dataset.loc[dataset[prisoner_type] == pt, \
    dataset[f'off_{item}_type']] = \
    dataset[offense_variables[pt]['types'][item]]
错误原因与修正方案

代码共有5处核心问题,直接导致运行异常:

  • .loc索引参数错误:.loc第二个参数需要直接传入列名,原代码传入dataset[f'off_{item}_code'](整列Series),pandas会将Series值作为列名匹配,触发无意义的全量索引遍历,导致程序卡死
  • 字典键名不匹配:定义字典时罪名类型对应的键为off_types,代码中误写为types,会触发KeyError
  • 列引用语法错误:第二处行筛选时dataset[prisoner_type]未给prisoner_type加引号,会被识别为未定义变量,触发NameError
  • 新列初始化逻辑冗余:循环每个囚犯类型时都重复重置新列值为占位符,会覆盖之前循环的赋值结果
  • 赋值逻辑不规范:右侧直接传入全量列数据,容易触发SettingWithCopy警告

修正后可直接运行的代码:

import numpy as np

# 提前一次性初始化10个新列,用空值填充即可,无需占位符
for item in range(1, 6):
    dataset[f'off_{item}_code'] = np.nan
    dataset[f'off_{item}_type'] = np.nan

pris_types = [3, 8]
for pt in pris_types:
    # 提前生成当前囚犯类型的行筛选掩码,避免重复计算
    row_filter = dataset['prisoner_type'] == pt
    for item in range(1, 6):
        # 从映射字典取对应源列名
        source_code_col = offense_variables[pt]['codes'][item]
        source_type_col = offense_variables[pt]['off_types'][item]
        # 仅对筛选出的行做赋值,左右两侧用相同筛选逻辑,避免警告和索引错位
        dataset.loc[row_filter, f'off_{item}_code'] = dataset.loc[row_filter, source_code_col]
        dataset.loc[row_filter, f'off_{item}_type'] = dataset.loc[row_filter, source_type_col]

扩展提示:如果后续新增其他囚犯类型,只需将对应类型的列映射补充到offense_variables字典,同时将类型值加入pris_types列表即可,无需修改核心循环逻辑。

内容的提问来源于stack exchange,提问作者SecondStar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 18:06:07