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

如何为DataFrame中无Year3的分组末尾添加指定数据行

优化实现:为缺失Year 3的产品分组补充数据

问题背景

原始DataFrame定义如下:

import pandas as pd

List = [['2024-05-25', 'Group 1', 'Year 1', 23466882], 
        ['2024-05-25', 'Group 1', 'Year 2', 458397284], 
        ['2024-05-25', 'Group 1', 'Year 3', 2344545], 
        ['2024-05-25', 'Group 2', 'Year 1', 6662345], 
        ['2024-05-25', 'Group 2', 'Year 2', 46342], 
        ['2024-05-25', 'Group 3', 'Year 1', 34234], 
        ['2024-05-25', 'Group 3', 'Year 2', 45222]]
df = pd.DataFrame(List, columns = ['Report_date', 'Product_group', 'Year', 'Sales'])

需求:针对每个Product_group,若不存在"Year 3"的行,则在该分组末尾添加一行数据,其中Sales固定为11000,Report_date和Product_group与该分组保持一致。

最初思路是拆分各分组逐个判断添加,但希望得到更高效的实现方案。

优化实现方案

方法1:透视表+堆叠补全(性能最优)

利用pandas的透视表将数据转为宽表,补全缺失的Year 3列后再转回长表,全程采用向量化操作,避免循环:

# 生成透视表,以Report_date和Product_group为索引,Year为列
pivot_df = df.pivot(index=['Report_date', 'Product_group'], columns='Year', values='Sales')
# 为缺失Year 3的分组填充默认值11000
pivot_df['Year 3'] = pivot_df['Year 3'].fillna(11000)
# 转回长表并重置索引
result_df = pivot_df.stack().reset_index(name='Sales')
# 按分组和年份排序,保持原数据的顺序逻辑(可选)
result_df = result_df.sort_values(['Product_group', 'Year'], ignore_index=True)

方法2:生成全量组合后合并(逻辑清晰)

先构造所有Product_group与目标年份的笛卡尔积组合,再与原数据左合并,填充缺失值:

# 获取所有唯一的Report_date和Product_group组合
group_date_pairs = df[['Report_date', 'Product_group']].drop_duplicates()
# 定义需要覆盖的年份列表
target_years = ['Year 1', 'Year 2', 'Year 3']
# 生成全量组合(笛卡尔积)
full_combinations = group_date_pairs.assign(key=1) \
    .merge(pd.DataFrame({'Year': target_years, 'key': 1}), on='key') \
    .drop('key', axis=1)
# 与原数据左合并,填充缺失的Sales值
result_df = full_combinations.merge(df, on=['Report_date', 'Product_group', 'Year'], how='left')
result_df['Sales'] = result_df['Sales'].fillna(11000)
# 排序整理结果
result_df = result_df.sort_values(['Product_group', 'Year'], ignore_index=True)

方法3:GroupBy+Apply(逻辑直观)

如果偏好分组处理的逻辑,可通过groupby结合apply批量处理,相比手动拆分分组更简洁:

def supplement_year3(group):
    if 'Year 3' not in group['Year'].values:
        # 构造补充行,复用分组的Report_date和Product_group
        supplement_row = pd.DataFrame({
            'Report_date': [group['Report_date'].iloc[0]],
            'Product_group': [group['Product_group'].iloc[0]],
            'Year': ['Year 3'],
            'Sales': [11000]
        })
        return pd.concat([group, supplement_row], ignore_index=True)
    return group

# 分组处理并合并结果
result_df = df.groupby('Product_group', group_keys=False).apply(supplement_year3).reset_index(drop=True)

方案对比

  • 方法1和方法2采用向量化操作,在数据量较大时性能远优于循环/手动拆分,推荐用于大规模数据集。
  • 方法3逻辑更直观,适合小规模数据或需要保留分组处理逻辑的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:43:15