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

如何用SAS高效对比指定基准月与后续3个月的销售增长率?

SAS高效计算基准月与后续3个月销售增长率方案

问题背景

需要对比指定基准月(1月、5月、9月)与各自后续3个月的销售增长率/跌幅;数据特点为SKU非全年销售,部分SKU无完整12个月数据;当前采用条件赋值生成对应月份销售额再计算比值的方法,效率偏低,寻求更简洁高效的实现方式。

示例数据

SKU |  Sales | Month_number | Month
561     2           1          Jan
561     2           2          Feb
561     6           3          MAR
561     6           4          APR
191     5           8          AUG
191     10          9          SEP
191     10          10         OCT
191     12          11         NOV
.. ETC

当前低效代码

Data want;
Set have;
if month = 'Jan' then JanSales = Sales;
if month = 'MAR' then MarSales = sales;
MarJan = Marchsales/Jansales;
format Marjan percent8.2;
run;

问题分析

当前方法需手动逐个赋值目标月份,扩展性差(新增基准月或后续月份需重复编写条件),且当SKU数据分散时会产生大量缺失值,计算效率低下,尤其不适用于大规模数据集。


高效解决方案

方法1:BY组+临时数组(推荐,高扩展性与效率)

利用SAS的BY组分组和临时数组存储月度销售额,通过月份编号直接索引匹配基准月数据,避免重复条件判断,适合大规模数据场景。

/* 先按SKU和月份排序,确保同SKU数据连续 */
proc sort data=have;
    by SKU Month_number;
run;

data want;
    set have;
    by SKU;
    /* 定义临时数组存储1-12月销售额,索引对应Month_number */
    array sales_arr[12] _temporary_;
    retain sales_arr:;
    
    /* 处理新SKU时重置数组 */
    if first.SKU then call missing(of sales_arr[*]);
    
    /* 将当前月份销售额存入对应数组位置 */
    sales_arr[Month_number] = Sales;
    
    /* 计算1月基准与后续3个月的增长率 */
    if Month_number in (2,3,4) then do;
        if not missing(sales_arr[1]) then growth_Jan = (Sales - sales_arr[1])/sales_arr[1];
    end;
    /* 计算5月基准与后续3个月的增长率 */
    if Month_number in (6,7,8) then do;
        if not missing(sales_arr[5]) then growth_May = (Sales - sales_arr[5])/sales_arr[5];
    end;
    /* 计算9月基准与后续3个月的增长率 */
    if Month_number in (10,11,12) then do;
        if not missing(sales_arr[9]) then growth_Sep = (Sales - sales_arr[9])/sales_arr[9];
    end;
    
    /* 格式化增长率为百分比 */
    format growth_Jan growth_May growth_Sep percent8.2;
run;

优势:无需手动枚举月份,新增基准月仅需修改条件判断;临时数组不占用输出数据集内存,BY组处理效率远高于多次条件赋值。


方法2:PROC TRANSPOSE转置后计算

先将每个SKU的月度数据转置为宽表,再直接通过列名引用计算增长率,适合需要直观查看各月份数据的场景。

/* 转置为宽表,每个SKU一行,月度销售额列名为Sales_1到Sales_12 */
proc transpose data=have out=have_wide prefix=Sales_;
    by SKU;
    id Month_number;
    var Sales;
run;

/* 计算各基准月对应的增长率 */
data want_wide;
    set have_wide;
    /* 1月与后续3个月 */
    growth_Jan_Feb = (Sales_2 - Sales_1)/Sales_1;
    growth_Jan_Mar = (Sales_3 - Sales_1)/Sales_1;
    growth_Jan_Apr = (Sales_4 - Sales_1)/Sales_1;
    /* 5月与后续3个月 */
    growth_May_Jun = (Sales_6 - Sales_5)/Sales_5;
    growth_May_Jul = (Sales_7 - Sales_5)/Sales_5;
    growth_May_Aug = (Sales_8 - Sales_5)/Sales_5;
    /* 9月与后续3个月 */
    growth_Sep_Oct = (Sales_10 - Sales_9)/Sales_9;
    growth_Sep_Nov = (Sales_11 - Sales_9)/Sales_9;
    growth_Sep_Dec = (Sales_12 - Sales_9)/Sales_9;
    
    /* 格式化所有增长率为百分比 */
    format growth_: percent8.2;
run;

优势:计算逻辑直观易懂,无需复杂循环或数组操作;注意:若SKU数量极大,宽表会占用较多内存,适合中小规模数据集。


方法3:自合并匹配基准月数据

通过提取基准月数据,再与原数据集自合并,直接关联后续月与对应基准月的销售额,逻辑简单,适合对数组操作不熟悉的用户。

/* 提取1、5、9月的基准数据 */
data base_data;
    set have;
    where Month_number in (1,5,9);
    rename Sales = base_Sales Month_number = base_month;
run;

/* 自合并,匹配每个后续月对应的基准月数据 */
data want_merge;
    merge have base_data(keep=SKU base_month base_Sales);
    by SKU;
    /* 匹配1月基准的后续3个月 */
    if base_month=1 and Month_number between 2 and 4 then do;
        growth_rate = (Sales - base_Sales)/base_Sales;
        base_month_name = 'Jan';
    end;
    /* 匹配5月基准的后续3个月 */
    else if base_month=5 and Month_number between 6 and 8 then do;
        growth_rate = (Sales - base_Sales)/base_Sales;
        base_month_name = 'May';
    end;
    /* 匹配9月基准的后续3个月 */
    else if base_month=9 and Month_number between 10 and 12 then do;
        growth_rate = (Sales - base_Sales)/base_Sales;
        base_month_name = 'Sep';
    end;
    /* 仅保留有效增长率记录 */
    if not missing(growth_rate);
    format growth_rate percent8.2;
run;

优势:无需数组或转置操作,逻辑清晰易维护;合并操作效率稳定,适合各类规模数据集。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:40:37