
本文介绍使用 pandas 的 explode() 方法,配合列表推导式生成年份范围,将含起止年份的宽表高效转换为按年展开的时间序列长表,兼顾性能与可读性。
本文介绍使用 pandas 的 `explode()` 方法,配合列表推导式生成年份范围,将含起止年份的宽表高效转换为按年展开的时间序列长表,兼顾性能与可读性。
在处理人口统计、员工任期、政策有效期等场景时,常遇到以 from_year/to_year 表示时间区间的宽格式数据,而建模或可视化往往需要按年展开的长格式(即每行代表一个个体在某一年的状态)。最高效、简洁且符合 pandas 最佳实践的方案是:利用 range 构造年份列表,再通过 explode() 原地展开。
具体实现如下:
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['from_year'], df['to_year'])]
df_expanded = df.drop(columns=['from_year', 'to_year']).explode('year').reset_index(drop=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 ...(中间省略) 11 4 Female 2010 12 4 Female 2011
✅ 为什么这是最高效的方式?
- explode() 是 pandas 原生向量化操作,底层用 C 实现,远快于 apply() + pd.concat() 或循环拼接;
- range(x, y+1) 返回惰性迭代器(Python 3 中为 range 对象),内存友好,不预先生成完整列表;
- 整个流程无显式循环,代码简洁、易维护、可读性强。
⚠️ 注意事项:
- 确保 from_year ≤ to_year,否则 range 将生成空序列,导致该行在 explode 后消失(如需容错,可先用 df = df[df['from_year']
- 若数据量极大(百万级区间),可考虑 numpy.repeat + numpy.arange 手动向量化构造,但绝大多数业务场景中 explode 已足够高效;
- 如需最终列序为 ['id', 'year', 'gender'],追加 .reindex(columns=['id', 'year', 'gender']) 即可。
该方法自 pandas 0.25+ 支持,是当前社区公认的标准解法——简洁、健壮、高性能,推荐作为时间区间展开的首选模式。











