如何在Python Pandas中利用列名实现宽表转长表
解决Pandas宽表转长表的需求
嘿,这个需求其实很常见,咱们用Pandas的melt结合pivot就能轻松搞定,步骤清晰又好理解,我给你一步步演示:
首先先还原你的原始DataFrame:
import pandas as pd import numpy as np df = pd.DataFrame({ 'student_id': [100, 101, 102], 'q1.cta1_count': [0, 1, 1], 'q1.cta1_date': [np.nan, '2019-03-26', '2019-03-25'], 'q1.cta1.reminder_count': [0, 1, 0], 'q1.cta1.reminder_date': [np.nan, '2019-03-31', np.nan] })
接下来分四步完成转换:
第一步:用melt把宽表转成基础长格式
这一步会把所有非student_id的列“拉长”,变成包含原列名和对应值的行结构:
melted = df.melt(id_vars='student_id', var_name='col', value_name='value')
此时melted的核心结构大概是这样:
| student_id | col | value |
|---|---|---|
| 100 | q1.cta1_count | 0 |
| 101 | q1.cta1_count | 1 |
| ... | ... | ... |
第二步:拆分原列名,提取type和metric
观察原列名的规律:最后一个下划线前面的部分是咱们要的type(比如q1.cta1、q1.cta1.reminder),后面的是metric(count或date)。用str.rsplit从最后一个下划线处拆分:
melted[['type', 'metric']] = melted['col'].str.rsplit('_', n=1, expand=True)
第三步:用pivot把metric转成列
这一步把count和date从行转成列,直接得到咱们想要的核心结构:
df_long = melted.pivot(index=['student_id', 'type'], columns='metric', values='value').reset_index()
第四步:整理格式和排序
最后去掉多余的列名层级,调整顺序并按需求排序:
# 移除列名的层级标签 df_long.columns.name = None # 按student_id和type排序,重置索引 df_long = df_long.sort_values(['student_id', 'type']).reset_index(drop=True)
最终得到的df_long就是你要的长格式:
student_id type count date 0 100 q1.cta1 0 NaN 1 100 q1.cta1.reminder 0 NaN 2 101 q1.cta1 1 2019-03-26 3 101 q1.cta1.reminder 1 2019-03-31 4 102 q1.cta1 1 2019-03-25 5 102 q1.cta1.reminder 0 NaN
这个方法通用性很强,不管你的type前缀有多少个点,只要最后是_count或_date的格式,都能完美适配~
内容的提问来源于stack exchange,提问作者Hamideh
相关产品推荐
相关产品推荐

