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

如何在Python Pandas中为两列组合生成指定额外行

问题描述

输入数据集

我在Python Pandas中有如下DataFrame:

import pandas as pd

data = [
    (1, '2023-10-10', '2023-09-25', 1, 20, 11),
    (1, '2023-10-10', '2023-10-04', 0, 10, 10),
    (1, '2023-05-05', '2023-05-01', 0, 10, None),
    (2, '2023-02-13', '2023-02-10', 0, 25, 10),
    (2, '2023-02-13', '2023-02-02', None, 12, None)
]

df = pd.DataFrame(data, columns=['id', 'survey', 'event', 'col1', 'col2', 'col3'])

输入数据集

数据集字段说明

  • id:客户ID
  • survey:调研日期(数据类型为object)
  • event:事件日期(数据类型为object)
  • col1、col2、col3:其他变量(实际数据集包含更多此类变量)

需求

需要为id和survey的每个组合生成新行,要求:

  • id和survey列保持原有值不变
  • col1、col2、col3列填充NaN值
  • event列填充该id和survey组合中不存在的日期,范围从survey日期向前回溯至前一个月的对应日期(例如id=1且survey='2023-10-10'时,event需包含2023-10-10至2023-09-10的所有日期,假设每个月都有31天)
  • 统一假设每个月有31天,无需考虑实际月份天数

期望输出示例

为id和survey的每个组合,生成survey日期向前31天内未在event列中出现的所有日期对应的行,新行的col1、col2、col3列填充NaN:

data = [
    (1, '2023-10-10', '2023-09-25', 1, 20, 11),
    (1, '2023-10-10', '2023-10-04', 0, 10, 10),
    (1, '2023-10-10', '2023-10-09', None, None, None),
    ...
    (2, '2023-02-13', '2023-01-13', None, None, None) 
]

df = pd.DataFrame(data, columns=['id', 'survey', 'event', 'col1', 'col2', 'col3'])

解决方案

可以通过以下步骤实现需求:

步骤1:转换日期列类型

先将survey和event列转为datetime类型,方便后续日期运算:

df['survey'] = pd.to_datetime(df['survey'])
df['event'] = pd.to_datetime(df['event'])

步骤2:生成每个(id, survey)组合的完整日期范围

按id和survey分组,为每个分组生成从survey日期减31天到survey日期的所有日期,并构建对应空值行:

def generate_missing_dates(group):
    survey_date = group['survey'].iloc[0]
    start_date = survey_date - pd.Timedelta(days=31)
    # 生成包含首尾的完整日期序列
    date_range = pd.date_range(start=start_date, end=survey_date, freq='D')
    # 构建新行,id和survey沿用分组值,event为生成的日期,其余列填充NaN
    new_rows = pd.DataFrame({
        'id': group['id'].iloc[0],
        'survey': survey_date,
        'event': date_range,
        'col1': None,
        'col2': None,
        'col3': None
    })
    return new_rows

# 对每个分组应用函数,生成完整日期对应的行
full_date_rows = df.groupby(['id', 'survey']).apply(generate_missing_dates).reset_index(drop=True)

步骤3:合并并去重,保留原数据行

将原数据与生成的空值行合并,然后按id、survey、event去重,优先保留原数据中的非空行:

# 合并原数据和生成的空值行
combined_df = pd.concat([df, full_date_rows], ignore_index=True)
# 去重,保留首次出现的行(原数据行会先被保留)
final_result = combined_df.drop_duplicates(subset=['id', 'survey', 'event'], keep='first')
# 可选:将日期列转回原字符串格式
final_result['survey'] = final_result['survey'].dt.strftime('%Y-%m-%d')
final_result['event'] = final_result['event'].dt.strftime('%Y-%m-%d')

结果说明

执行后final_result即为目标DataFrame:原有数据行全部保留,同时补充了每个(id, survey)组合中缺失的日期行,补充行的col1、col2、col3均为NaN。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:26:37