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

为分组后的DataFrame补全缺失日期并实现ffill填充

解决DataFrame分组补全日期并保留字符串列值的问题

核心问题分析

你遇到的问题本质是:分组补全日期时,字符串列需要保留对应分组的固定值,而数值列按前向填充(ffill)。之前的错误要么是日期列未转为Datetime类型导致索引不匹配,返回全NaN;要么是错误地给字符串列填充了0,破坏了分组的原有标识。

解决方案步骤

1. 预处理:确保日期列是Datetime类型

这是避免reindex返回全NaN的关键前提:

df['日期'] = pd.to_datetime(df['日期'])

2. 生成全局完整日期范围

基于整个DataFrame的最小、最大日期,生成连续的日期序列(可根据需求调整时间粒度):

full_date_range = pd.date_range(
    start=df['日期'].min(),
    end=df['日期'].max(),
    freq='D'  # 按天生成,可替换为'H'小时、'M'月等
)

3. 分组处理:补全日期+保留字符串列+数值列ffill

使用groupby结合apply对每个分组单独处理,核心是用分组本身的固定值填充字符串列,而非统一填0:

# 先提取所有字符串列作为分组键
str_cols = [col for col in df.columns if df[col].dtype == 'object']

def process_group(group):
    # 将日期设为索引,方便重索引补全
    group_indexed = group.set_index('日期')
    # 重索引到全局日期范围,生成缺失行
    filled_group = group_indexed.reindex(full_date_range)
    
    # 填充字符串列:每个分组的字符串值是固定的,取分组首行值填充所有缺失行
    for col in str_cols:
        filled_group[col] = filled_group[col].fillna(group[col].iloc[0])
    
    # 数值列执行前向填充,若首行无数据可按需追加fillna(0)
    num_cols = [col for col in df.columns if df[col].dtype in ['int64', 'float64']]
    for col in num_cols:
        filled_group[col] = filled_group[col].ffill()  # .fillna(0)  # 可选:填充首行NaN
    
    # 重置索引,将日期变回普通列
    return filled_group.reset_index().rename(columns={'index': '日期'})

# 执行分组处理
result_df = df.groupby(str_cols, group_keys=False).apply(process_group)

测试示例

用模拟数据验证效果:

import pandas as pd

# 构造测试数据
data = {
    '品类': ['A', 'A', 'B', 'B'],
    '区域': ['华东', '华东', '华南', '华南'],
    '日期': ['2023-01-01', '2023-01-03', '2023-01-02', '2023-01-04'],
    '销量': [100, 150, 80, 120]
}
df = pd.DataFrame(data)
df['日期'] = pd.to_datetime(df['日期'])

# 执行处理代码
full_date_range = pd.date_range(start=df['日期'].min(), end=df['日期'].max())
str_cols = ['品类', '区域']

def process_group(group):
    group_indexed = group.set_index('日期')
    filled_group = group_indexed.reindex(full_date_range)
    for col in str_cols:
        filled_group[col] = filled_group[col].fillna(group[col].iloc[0])
    filled_group['销量'] = filled_group['销量'].ffill()
    return filled_group.reset_index().rename(columns={'index': '日期'})

result_df = df.groupby(str_cols, group_keys=False).apply(process_group)
print(result_df)

输出结果会补全所有缺失日期,字符串列保留对应分组的值,销量列按前向填充:

日期 品类  区域     销量
0 2023-01-01  A  华东  100.0
1 2023-01-02  A  华东  100.0
2 2023-01-03  A  华东  150.0
3 2023-01-04  A  华东  150.0
4 2023-01-01  B  华南   80.0
5 2023-01-02  B  华南   80.0
6 2023-01-03  B  华南   80.0
7 2023-01-04  B  华南  120.0

关键注意事项

  • 分组键必须包含所有字符串列,确保每个分组的字符串值唯一,避免填充错误。
  • 如果数值列的分组首行(最早日期)无数据,ffill后会保留NaN,可根据业务需求在ffill后追加.fillna(0)单独处理数值列。
  • 调整pd.date_range的freq参数可适配不同时间粒度的补全需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:24:58