
本文介绍如何使用 Pandas 的 explode() 方法,高效地将包含起止年份(from_year/to_year)的宽表转换为按年展开的长表,避免循环,兼顾性能与可读性。
本文介绍如何使用 pandas 的 `explode()` 方法,高效地将包含起止年份(`from_year`/`to_year`)的宽表转换为按年展开的长表,避免循环,兼顾性能与可读性。
在时间序列分析或面板数据构建中,常需将“年份区间”形式的记录(如 1990–1993)展开为逐年重复的细粒度行。Pandas 自 0.25.0 版本起支持 explode() 方法,配合列表推导式生成 range 对象,是目前最简洁且性能最优的解决方案。
以下为完整实现代码:
import pandas as pd
# 原始数据
df = pd.DataFrame({
'from_year': [1990, 1987, 2000, 2010],
'to_year': [1993, 1992, 2000, 2011],
'id': [1, 2, 3, 4],
'gender': ['Female', 'Male', 'Male', 'Female']
})
# 核心步骤:构造 year 列为 range 对象,并 explode 展开
df['year'] = [range(start, end + 1) for start, end in zip(df.pop('from_year'), df.pop('to_year'))]
df_expanded = df.explode('year', ignore_index=True)
print(df_expanded)输出结果完全符合预期:
id gender year 0 1 Female 1990 1 1 Female 1991 2 1 Female 1992 3 1 Female 1993 4 2 Male 1987 ...(其余略)
✅ 关键优势说明:
- 零循环:避免 apply() + pd.concat() 或嵌套 for 循环,大幅减少 Python 层开销;
- 内存友好:range 对象惰性生成,不预先实例化全部整数,节省内存;
- 语义清晰:逻辑直白——先构造区间,再“炸开”,易于维护与调试。
⚠️ 注意事项:
- 确保 from_year ≤ to_year,否则 range(start, end+1) 将生成空序列,导致该行被丢弃(可提前用 df = df[df['from_year'] <= df['to_year']] 过滤);
- 若需严格保持原始行序(尤其涉及多索引或分组场景),建议在 explode 后显式调用 reset_index(drop=True);
- 对超大规模数据(百万级区间),可考虑 numpy.repeat + numpy.arange 手动向量化,但通常 explode 已足够高效。
总之,list-of-ranges + explode 是 Pandas 生态中处理此类“区间展开”任务的标准范式,兼具简洁性、可读性与生产级性能。


















