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

Python处理同分隔符多义的字符串拆分及人员数据清洗问题

业务数据清洗与统计解决方案

原始业务数据

记录编号一级人员二级人员日期工作时长
1Tim David, Cameron Green - (Division 1)01/01/20235
2Tim David - (Division 1)Mitch, Eli Kin Marsh - (Division 2)02/02/20233
3David Warner - (Division 2), Travis Head - (Division 3)03/04/20231
4Cameron Green - (Division 1)Tim David - (Division 1)07/01/20232

预期统计结果

部门人员月份工作时长
Division 1Tim DavidJan-237
Division 1Tim DavidFeb-233
Division 1Cameron GreenJan-237
Division 2Mitch Eli Kin MarshFeb-233
Division 2David WarnerApr-231
Division 3Travis HeadApr-231

现有问题与尝试

问题1:人员姓名拆分歧义

逗号既用作不同人员的分隔符(如记录1),也用作姓名内部的分隔符(如记录2),现有代码无法正确拆分出目标人员列表:

  • 记录1期望输出:['Tim David', 'Cameron Green']
  • 记录2期望输出:['Mitch Eli Kin Marsh']

尝试的Python代码

import re
import pandas as pd

def split_names(row):
    string = row['level 2 person']
    pattern = '([\w\s,-]+)'
    names = re.split(pattern, string) 
    name_list = list()
    for name in names:
        replacements = [('-', ''), ('(', ''), (')', '')]
        for char, replacement in replacements:
            if char in name:
                name= name.replace(char, replacement)
        name_list.append(name)        
    while("" in name_list): # remove empty elements
        name_list.remove("")
    return name_list

df['names'] = df.apply(split_names,axis=1)

问题2:部门自动分配

部分人员无单独部门标注(如记录1的两人共享Division 1),需要自动为这类人员匹配对应部门,生成与人员列表长度一致的部门列表。


完整解决方案

步骤1:解析二级人员的姓名与部门

利用字符串规律(部门固定格式为- (Division X)),先拆分人员块再提取对应部门,同时处理姓名内部的逗号:

import re
import pandas as pd

def parse_level2(row):
    text = row['二级人员']
    result_names = []
    result_divisions = []
    
    # 先判断是否是多人员共享单个部门的情况
    shared_div_match = re.search(r' - \(Division (\d+)\)$', text)
    if shared_div_match:
        division = f'Division {shared_div_match.group(1)}'
        name_text = re.sub(r' - \(Division \d+\)$', '', text)
        # 拆分不同人员,替换姓名内的逗号为空格
        names = [n.strip().replace(',', ' ') for n in name_text.split(',')]
        result_names.extend(names)
        result_divisions.extend([division]*len(names))
    else:
        # 单个人员带部门,或多人员各带部门的情况
        person_blocks = re.split(r',\s*(?=[A-Z][a-z]+[^-,]+ - \(Division)', text)
        for block in person_blocks:
            if ' - (' in block:
                name_part, div_part = block.split(' - (', 1)
                division = div_part.rstrip(')')
                clean_name = name_part.replace(',', ' ').strip()
                result_names.append(clean_name)
                result_divisions.append(division)
    return pd.Series([result_names, result_divisions])

df[['二级人员列表', '二级部门列表']] = df.apply(parse_level2, axis=1)

步骤2:解析一级人员的姓名与部门

同样处理一级人员的姓名和部门提取:

def parse_level1(row):
    text = row['一级人员']
    if pd.isna(text) or text.strip() == '':
        return pd.Series([[], []])
    name_part, div_part = text.split(' - (', 1)
    division = div_part.rstrip(')')
    clean_name = name_part.replace(',', ' ').strip()
    return pd.Series([[clean_name], [division]])

df[['一级人员列表', '一级部门列表']] = df.apply(parse_level1, axis=1)

步骤3:合并并展开人员数据

将一级、二级人员数据合并,展开为单行单人员的记录格式:

# 合并人员与部门列表
df['人员列表'] = df['一级人员列表'] + df['二级人员列表']
df['部门列表'] = df['一级部门列表'] + df['二级部门列表']

# 展开列表,每行对应一个人员
exploded_df = df.explode(['人员列表', '部门列表']).drop(
    columns=['一级人员', '二级人员', '一级人员列表', '一级部门列表', '二级人员列表', '二级部门列表']
)

# 转换日期为目标月份格式
exploded_df['月份'] = pd.to_datetime(exploded_df['日期'], format='%d/%m/%Y').dt.strftime('%b-%y')

步骤4:统计月度总时长

按部门、人员、月份分组求和:

final_df = exploded_df.groupby(['部门列表', '人员列表', '月份'])['工作时长'].sum().reset_index()
final_df.columns = ['部门', '人员', '月份', '工作时长']

执行上述代码后,final_df即可得到预期的统计结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 01:17:46