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

如何在Python的DataFrame中按标识符生成带编号的日期与分类列?

为日期列添加对应Category列的解决方案

原始数据集

import pandas as pd

df = pd.DataFrame(data = {'ID': ['Bob1','Jeff1','Sally2', 'Bob2','Bob1','Jeff1','Bob1','Willa5','Jeff1','Bob1','Sally2'], 'Dates': ['2024-01-10', '2024-08-28', '2024-07-03', '2024-02-05', '2024-01-28', '2024-02-19', '2024-04-01', '2024-07-22', '2024-09-27', '2024-06-06', '2024-01-11']})

需求说明

将原始长表转换为宽表:每个ID对应的多行日期转换为Date1、Date2等列,同时在每个日期列旁添加对应的Category1、Category2列;有日期的行对应Category值为1,无日期的位置填充nan,目标格式如下:

IDDate1Category1Date2Category2Date3Category3Date4Category4
Bob12024-01-1012024-01-2812024-04-0112024-06-061
Bob22024-02-051nannannannannannan
Jeff12024-02-1912024-09-271nannannannan
Sally22024-01-1112024-07-031nannannannan
Willa52024-07-221nannannannannannan

现有代码

已实现日期列的宽表转换,但缺少Category列:

df2 = df.groupby(by=['ID'])['Dates'].unique().to_frame().reset_index()
df3 = pd.concat([df2['ID'],df2['Dates'].apply(lambda x: pd.Series([i for i in x])).pipe(lambda df4: df4.set_axis([f'Date{i}' for i in range(1, len(df4.columns)+1)],axis = 1))], axis = 1)

解决方案

方法一:基于分组序号的透视转换(推荐)

该方法自动对应日期和Category的存在性,无日期的位置自动填充nan,完全匹配目标格式:

# 1. 为每个ID的记录添加分组内序号(从1开始)
df['seq'] = df.groupby('ID').cumcount() + 1

# 2. 添加Category列,值固定为1
df['Category'] = 1

# 3. 分别透视生成日期宽表和Category宽表
date_wide = df.pivot(index='ID', columns='seq', values='Dates').rename(columns=lambda num: f'Date{num}')
category_wide = df.pivot(index='ID', columns='seq', values='Category').rename(columns=lambda num: f'Category{num}')

# 4. 合并两表并按顺序排列列(Date1→Category1→Date2→Category2...)
combined = pd.concat([date_wide, category_wide], axis=1)
# 按序号排序列,确保日期和对应Category相邻
sorted_cols = []
max_seq = max(df['seq'])
for i in range(1, max_seq+1):
    sorted_cols.append(f'Date{i}')
    sorted_cols.append(f'Category{i}')
result = combined[sorted_cols].reset_index()

print(result)

方法二:基于现有代码扩展

如果想基于你已有的df3进行扩展,可按以下方式添加Category列并调整列顺序:

# 基于现有df3生成Category列,日期存在则为1,否则为nan
category_cols = pd.DataFrame()
for col in df3.columns[1:]:  # 跳过ID列
    seq_num = col.replace('Date', '')
    category_cols[f'Category{seq_num}'] = df3[col].apply(lambda x: 1 if pd.notna(x) else pd.NA)

# 合并日期列和Category列,重新排列顺序
final_cols = ['ID']
for i in range(1, len(df3.columns)):
    final_cols.append(f'Date{i}')
    final_cols.append(f'Category{i}')

result = pd.concat([df3, category_cols], axis=1)[final_cols]

print(result)

输出效果

两种方法最终都会生成符合目标格式的DataFrame:日期存在的位置Category为1,日期缺失的位置为nan。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 07:45:14