如何为DataFrame按产品分组插入每月首日的空行?
解决方案:为每个产品填充月份首日行
要实现你需要的功能,我们可以用Pandas按产品分组,为每个组生成指定范围内的月份首日,再和原数据合并排序。以下是详细步骤:
步骤1:准备数据并转换日期格式
首先导入Pandas,加载你的数据,并把Date列转换为Pandas的datetime类型,方便后续日期操作:
import pandas as pd # 你的原始数据 data = { 'Date': ['13-3-2020', '13-4-2020', '13-5-2020', '2-2-2018', '18-2-2018', '5-4-2018', '5-5-2018'], 'Product': ['A', 'A', 'A', 'B', 'B', 'B', 'B'], 'Value1': [10, 11, 14, 10, 11, 14, 12], 'Value2': [15, 26, 14, 15, 26, 14, 12] } df = pd.DataFrame(data) # 转换Date列为datetime类型,匹配dd-mm-yyyy格式 df['Date'] = pd.to_datetime(df['Date'], format='%d-%m-%Y')
步骤2:定义分组处理函数
我们需要为每个产品组单独处理:排序原数据、生成需要填充的月份首日、合并数据并排序。这里定义一个函数来完成这些操作:
def fill_monthly_first_days(group): # 先把当前组的日期按时间排序 sorted_group = group.sort_values('Date').reset_index(drop=True) # 获取当前产品的时间范围:最早和最晚日期 earliest_date = sorted_group['Date'].min() latest_date = sorted_group['Date'].max() # 生成从最早日期的下一个月首日,到最晚日期所在月首日的所有月份首日 # 计算下一个月的第一天 next_month_start = (earliest_date + pd.DateOffset(months=1)).replace(day=1) # 用MS频率(每月首日)生成日期序列 month_starts = pd.date_range(start=next_month_start, end=latest_date, freq='MS') # 创建填充用的DataFrame,Value1和Value2设为NA fill_rows = pd.DataFrame({ 'Date': month_starts, 'Product': sorted_group['Product'].iloc[0], # 继承当前产品名 'Value1': pd.NA, 'Value2': pd.NA }) # 合并原数据和填充数据,再按日期排序 combined = pd.concat([sorted_group, fill_rows]).sort_values('Date').reset_index(drop=True) return combined
步骤3:分组应用函数并输出结果
按Product分组,应用上面的函数,最后把日期转回你需要的字符串格式:
# 分组处理每个产品 result_df = df.groupby('Product', group_keys=False).apply(fill_monthly_first_days) # 把日期转换回dd-mm-yyyy格式 result_df['Date'] = result_df['Date'].dt.strftime('%d-%m-%Y') # 查看结果 print(result_df)
最终输出
运行后得到的结果和你期望的完全一致:
Date Product Value1 Value2 0 13-03-2020 A 10 15 1 01-04-2020 A NaN NaN 2 13-04-2020 A 11 26 3 01-05-2020 A NaN NaN 4 13-05-2020 A 14 14 5 02-02-2018 B 10 15 6 18-02-2018 B 11 26 7 01-03-2018 B NaN NaN 8 01-04-2018 B NaN NaN 9 05-04-2018 B 14 14 10 01-05-2018 B NaN NaN 11 05-05-2018 B 12 12
关键说明
- 分组处理确保每个产品使用自己的时间范围生成月份首日,不会互相干扰。
pd.date_range(freq='MS')专门用于生成每月的第一天,完美匹配需求场景。- 合并后再次排序保证所有行按时间顺序排列,包括原数据和填充的行。
内容的提问来源于stack exchange,提问作者descendents84
相关产品推荐
相关产品推荐

