如何用Pandas将起止日期数据扩展为面板数据(附示例)
使用Pandas扩展员工任职时间数据的实现步骤
给定表1的员工任职数据(包含Person、Company、Begin date、End Date字段,日期格式为MM/YYYY),需要通过Pandas自动扩展为表2的格式,补全每个月份的任职状态,空档期标记为Unemployed。
原始数据(表1)
| Person | Company | Begin date | End Date |
|---|---|---|---|
| Mr. Bun | Company A | 8/1984 | 10/1984 |
| Company B | 1/1985 | 3/1985 |
预期结果(表2)
| Person | Year | Company |
|---|---|---|
| Mr. Bun | 8/1984 | Company A |
| 9/1984 | Company A | |
| 10/1984 | Company A | |
| 11/1984 | Unemployed | |
| 12/1984 | Unemployed | |
| 1/1985 | Company B | |
| 2/1985 | Company B | |
| 3/1985 | Company B |
实现步骤
- 填充Person列空值:原始数据中部分行Person字段为空,用
ffill()方法向前填充,确保每行都对应正确的人员。 - 转换日期格式:将
Begin date和End Date转换为Pandas datetime类型,指定格式为%m/%Y,方便后续生成时间序列。 - 生成单条记录的月份序列:对每行数据,生成从入职到离职的所有月份,存储为列表列。
- 展开月份序列:将包含月份列表的列展开为单行对应单个月份的结构。
- 生成完整时间范围基准:找出整个数据的最早开始日期和最晚结束日期,生成该区间内的所有月份,作为基准序列。
- 匹配任职状态:将展开后的任职数据与基准序列合并,未匹配到公司的月份填充为
Unemployed。 - 调整输出格式:将日期转换回
MM/YYYY格式,调整列顺序为Person、Year、Company,并处理Person列的重复显示(仅保留第一行姓名,后续行留空)。
完整代码示例
import pandas as pd # 模拟原始数据(实际可通过pd.read_csv等方法读取) df = pd.DataFrame({ 'Person': ['Mr. Bun', None], 'Company': ['Company A', 'Company B'], 'Begin date': ['8/1984', '1/1985'], 'End Date': ['10/1984', '3/1985'] }) # 填充Person列空值 df['Person'] = df['Person'].ffill() # 转换日期列为datetime类型 df['Begin date'] = pd.to_datetime(df['Begin date'], format='%m/%Y') df['End Date'] = pd.to_datetime(df['End Date'], format='%m/%Y') # 生成每行的月份序列(MS表示每月第一天) def generate_month_series(row): return pd.date_range(start=row['Begin date'], end=row['End Date'], freq='MS') df['Months'] = df.apply(generate_month_series, axis=1) # 展开月份序列为单行单月 expanded_df = df.explode('Months').drop(columns=['Begin date', 'End Date']) # 生成完整时间范围的基准月份序列 min_start = df['Begin date'].min() max_end = df['End Date'].max() all_months = pd.date_range(start=min_start, end=max_end, freq='MS') all_months_df = pd.DataFrame({'Months': all_months, 'Person': df['Person'].iloc[0]}) # 合并数据并填充失业状态 result_df = pd.merge(all_months_df, expanded_df, on=['Person', 'Months'], how='left') result_df['Company'] = result_df['Company'].fillna('Unemployed') # 转换日期格式并调整列顺序 result_df['Year'] = result_df['Months'].dt.strftime('%m/%Y') result_df = result_df[['Person', 'Year', 'Company']] # 处理Person列的重复显示 result_df['Person'] = result_df['Person'].where(result_df['Person'].shift() != result_df['Person'], '') # 打印结果 print(result_df)
内容的提问来源于stack exchange,提问作者SChatcha
相关产品推荐
相关产品推荐

