如何用Pandas拆分扁平化JSON生成的多列员工信息DataFrame?
解决嵌套JSON扁平化DataFrame的拆分问题
针对你提到的列名格式(如employee_0_salary、employee_0_skills_0_id),可以通过正则解析列结构+长格式转换的方式实现需求,以下是具体步骤和代码:
方法一:正则解析+分步转换(适配复杂结构)
这种方法适合列名格式不完全统一的场景,容错性更强:
1. 解析员工相关列的结构
先提取所有employee_开头的列,通过正则拆分出员工索引、属性名称、技能索引等信息:
import pandas as pd import re # 正则匹配规则:匹配employee_<员工号>_<属性>_<技能号>_<技能属性>的结构 pattern = re.compile(r'employee_(\d+)_([a-z]+)(?:_(\d+)_([a-z]+))?') # 筛选员工相关列并解析 employee_cols = [col for col in df.columns if col.startswith('employee_')] col_details = [] for col in employee_cols: match_result = pattern.match(col) if match_result: emp_idx, attr, skill_idx, skill_attr = match_result.groups() col_details.append({ 'col_name': col, 'emp_idx': int(emp_idx), 'attr': attr, 'skill_idx': int(skill_idx) if skill_idx else None, 'skill_attr': skill_attr }) col_df = pd.DataFrame(col_details)
2. 转换薪资数据为长格式
单独提取薪资列,转换为id + emp_idx + salary的结构:
# 筛选薪资列 salary_col_list = col_df[col_df['attr'] == 'salary']['col_name'].tolist() salary_temp = df[['id'] + salary_col_list] # 转长格式并提取员工索引 salary_long = salary_temp.melt(id_vars='id', var_name='temp_col', value_name='salary') salary_long['emp_idx'] = salary_long['temp_col'].str.extract(r'employee_(\d+)_salary').astype(int) salary_long = salary_long.drop('temp_col', axis=1)
3. 转换技能ID数据为长格式
同样处理技能ID列,得到id + emp_idx + skill_idx + skills_id的结构:
# 筛选技能ID列 skill_col_list = col_df[(col_df['attr'] == 'skills') & (col_df['skill_attr'] == 'id')]['col_name'].tolist() skill_temp = df[['id'] + skill_col_list] # 转长格式并提取索引 skill_long = skill_temp.melt(id_vars='id', var_name='temp_col', value_name='skills_id') skill_long[['emp_idx', 'skill_idx']] = skill_long['temp_col'].str.extract(r'employee_(\d+)_skills_(\d+)_id').astype(int) skill_long = skill_long.drop('temp_col', axis=1)
4. 合并数据得到目标结构
将薪资和技能数据按id和emp_idx合并,保留需要的列:
# 合并数据(how='left'确保所有技能行都被保留,可根据需求调整) final_df = pd.merge(skill_long, salary_long, on=['id', 'emp_idx'], how='left') # 整理列顺序并去除空值(可选) final_df = final_df[['id', 'salary', 'skills_id']].dropna(subset=['salary', 'skills_id'])
方法二:用wide_to_long快速转换(适配规整结构)
如果所有员工相关列的格式完全统一(比如每个员工都有salary和多层skills),可以用Pandas的wide_to_long工具分两步完成,代码更简洁:
# 第一步:将员工层级转为长格式 emp_long = pd.wide_to_long(df, stubnames=['employee'], i='id', j='emp_idx', sep='_', suffix='\\d+') emp_long = emp_long.reset_index() # 第二步:将技能层级转为长格式 skill_long = pd.wide_to_long(emp_long, stubnames=['skills'], i=['id', 'emp_idx'], j='skill_idx', sep='_', suffix='\\d+') # 提取目标列并重命名 final_df = skill_long.reset_index()[['id', 'employee_salary', 'skills_id']].rename(columns={'employee_salary': 'salary'})
注意:这种方法要求列名严格遵循employee_<n>_<attr>、employee_<n>_skills_<m>_<attr>的格式,否则会出现匹配错误。
内容的提问来源于stack exchange,提问作者Nathi
相关产品推荐
相关产品推荐

