自定义起始日的365天周期累计量可视化问题求助
解决方案:自定义年度区间的累计销量折线图
步骤1:优化区间分配函数(可选但推荐)
原函数使用apply循环效率较低,且可能遗漏部分日期,以下是矢量化优化后的版本,确保所有日期都能正确分配到对应自定义年度区间:
import pandas as pd import numpy as np def calculate_intervals(df, start_month, start_day): df = df.copy() # 避免修改原始数据集 # 初始化年份字段 df['Year'] = df['Date'].dt.year # 生成当前年份的区间起始日期 current_interval_start = pd.to_datetime(df['Year'].astype(str) + f'-{start_month}-{start_day}') # 对早于当前年起始日的日期,归属到上一年的区间 mask = df['Date'] < current_interval_start df.loc[mask, 'Year'] -= 1 # 重新计算区间的起始和结束日期 df['Interval_Start'] = pd.to_datetime(df['Year'].astype(str) + f'-{start_month}-{start_day}') df['Interval_End'] = df['Interval_Start'] + pd.DateOffset(years=1) - pd.DateOffset(days=1) # 生成区间标签 df['Interval'] = df['Interval_Start'].dt.date.astype(str) + ' - ' + df['Interval_End'].dt.date.astype(str) return df # 应用函数生成区间 df = calculate_intervals(df, start_month=7, start_day=6)
步骤2:计算区间内日期偏移与累计销量
- 计算每个日期相对于所属区间起始日的天数差(即X轴的0-364天)
- 按区间和日期汇总销量,再计算累计值
- 补全0-364天的完整序列,确保每个区间的折线覆盖全部时间范围
# 计算天数偏移 df['Day_Offset'] = (df['Date'] - df['Interval_Start']).dt.days # 按区间和日期汇总每日销量 daily_sales = df.groupby(['Interval', 'Date'])['Bushels'].sum().reset_index() # 计算每个区间的累计销量 daily_sales['Cumulative_Bushels'] = daily_sales.groupby('Interval')['Bushels'].cumsum() # 重新同步天数偏移字段 daily_sales['Day_Offset'] = (daily_sales['Date'] - daily_sales['Interval'].str.split(' - ').str[0].apply(pd.to_datetime)).dt.days # 生成0-364天的完整序列,补全缺失日期的累计值(前向填充) full_days = pd.DataFrame({'Day_Offset': range(365)}) plot_data = [] for interval in daily_sales['Interval'].unique(): interval_data = daily_sales[daily_sales['Interval'] == interval][['Day_Offset', 'Cumulative_Bushels']] merged = pd.merge(full_days, interval_data, on='Day_Offset', how='left') # 缺失日期用前一天的累计值填充,初始值为0 merged['Cumulative_Bushels'] = merged['Cumulative_Bushels'].ffill().fillna(0) merged['Interval'] = interval plot_data.append(merged) plot_df = pd.concat(plot_data)
步骤3:绘制自定义区间累计销量折线图
使用Matplotlib绘制折线图,每个自定义年度区间对应一条折线,X轴为区间起始日起的天数,Y轴为累计销量:
import matplotlib.pyplot as plt plt.figure(figsize=(12, 6)) # 遍历每个区间绘制折线 for interval in plot_df['Interval'].unique(): subset = plot_df[plot_df['Interval'] == interval] plt.plot(subset['Day_Offset'], subset['Cumulative_Bushels'], label=interval) # 设置图表属性 plt.xlabel('Days Since Interval Start') plt.ylabel('Cumulative Bushels Sold') plt.title('Cumulative Bushel Sales by Custom Annual Interval') plt.legend(title='Custom Interval', bbox_to_anchor=(1.05, 1), loc='upper left') plt.grid(True) plt.tight_layout() plt.show()
关键说明
- 优化后的区间分配函数通过矢量化操作替代循环,处理大数据集时效率提升明显
- 补全完整天数序列确保了每个区间的折线都能覆盖0-365天的范围,避免因部分日期无销量导致折线中断
- 前向填充缺失值符合累计销量的逻辑:无销量的日期,累计值与前一日保持一致
内容的提问来源于stack exchange,提问作者keg5038
相关产品推荐
相关产品推荐

