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

如何优雅实现宽表转长表并合并分析师评分数据集?

优雅合并分析师与评分数据集的方案

需求说明

需要将存储分析师姓名的df1与对应评分的df2合并为df_desire格式:保留有分析师姓名的行,对应匹配同编号的评分(评分允许为NaN),最终按公司名称排序。

数据集定义

import pandas as pd
import numpy as np

df1 = pd.DataFrame({
    'company name': ['A','B','C'],
    'analyst 1 name': ['Tom','Mike',np.nan],
    'analyst 2 name': [np.nan,'Alice',np.nan],
    'analyst 3 name': ['Jane','Steve','Alex']
})

df2 = pd.DataFrame({
    'company name': ['A','B','C'],
    'score 1': [3,5,np.nan],
    'score 2': [np.nan,1,np.nan],
    'score 3': [6,np.nan,11]
})

# 目标结果
df_desire = pd.DataFrame({
    'company name': ['A','A','B','B','B','C'],
    'analyst': ['Tom','Jane','Mike','Alice','Steve','Alex'],
    'score': [3,6,5,1,np.nan,11]
})

现有实现

当前代码通过concat拼接两个melt后的结果,但会产生重复列,需要额外清理:

pd.concat([
    df1.melt(id_vars='company name', value_vars=['analyst 1 name','analyst 2 name','analyst 3 name']),
    df2.melt(id_vars='company name', value_vars=['score 1','score 2','score 3'])
], axis=1)

更优雅的实现方案

方案1:利用wide_to_long自动匹配编号

借助列名中的数字后缀(1/2/3),wide_to_long可以直接将宽表转为长表并对齐编号,代码简洁且扩展性强(新增分析师/评分列无需修改代码):

# 将df1转为长表,提取分析师编号
df1_long = pd.wide_to_long(
    df1, 
    stubnames='analyst', 
    i='company name', 
    j='num', 
    sep=' ', 
    suffix='\\d+'
).reset_index()

# 将df2转为长表,提取评分编号
df2_long = pd.wide_to_long(
    df2, 
    stubnames='score', 
    i='company name', 
    j='num', 
    sep=' ', 
    suffix='\\d+'
).reset_index()

# 按公司和编号合并,清理无效行并整理格式
df_desire = pd.merge(df1_long, df2_long, on=['company name', 'num'])
df_desire = (df_desire
             .dropna(subset=['analyst'])  # 过滤无分析师姓名的行
             .drop('num', axis=1)
             .sort_values('company name')
             .reset_index(drop=True))
df_desire.columns = ['company name', 'analyst', 'score']

方案2:melt后提取编号合并

如果需要更灵活的列名处理,可先melt再提取编号进行合并:

# 处理df1:melt后提取数字编号
df1_melt = df1.melt(id_vars='company name', var_name='idx', value_name='analyst')
df1_melt['idx'] = df1_melt['idx'].str.extract('(\\d+)')

# 处理df2:同理提取编号
df2_melt = df2.melt(id_vars='company name', var_name='idx', value_name='score')
df2_melt['idx'] = df2_melt['idx'].str.extract('(\\d+)')

# 合并后清理格式
df_desire = pd.merge(df1_melt, df2_melt, on=['company name', 'idx'])
df_desire = (df_desire
             .dropna(subset=['analyst'])
             .drop('idx', axis=1)
             .sort_values('company name')
             .reset_index(drop=True))

两种方案均能直接生成目标格式,避免了重复列的问题,代码更简洁易维护。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 04:33:48