微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SAS proc iml 用于根据接下来的两次观察的平均值来估算第一个月或第二个月的缺失销售额

如何解决SAS proc iml 用于根据接下来的两次观察的平均值来估算第一个月或第二个月的缺失销售额

我正在寻找一种在 sas 中使用 proc iml 估算未来两个月销售额平均值的方法。 正如你所看到的,有时我没有 201901 的销售额,有时在 201902 上丢失 例如,对于第一个条形码,我想找到 sales[1]= mean(sales[2],sales[3]) 并且我想为每个唯一的条形码执行此操作。

“表A”是这样的:

Obs. |  Barcode  |    date   |   sales   | Position
---------------------------------------------------------------
1    |21220000000|  201901   |     .     |   1

2   |21220000000|   201902|      311     |   2

3   |21220000000|   201903|      349     |   3

4   |21220000000|   201904|      360     |   4

5   |21220000000|   201905|      380     |   5

6   |21220000000|   201906|      440     |   6

7   |21220000000|   201907|      360     |   7

8   |21220000000|   201908|      390     |   8

9   |21220000000|   201909|      410     |   9

10  |21220000000|   201910|      520     |  10

11  |21220000000|   201911|      410     |  11

12  |21220000000|   201912|      390     |  12

13  |31350000000|   201901|      360     |   1

14  |31350000000|   201902|      .       |   2


                   .etc.
24  |31350000000|   201912|       .      |   12

25  |45480000000|   201901|      310     |   1     

26  |45480000000|   201902|        .     |   2

                   .etc.

我尝试过类似的东西,但它不起作用:

proc iml;
t_a= TableCreateFromDataSet("work","table_a");
call TablePrint(t_a); 

do i =1 to nrow(t_a);
  
      if t_a[i,4]=. and t_a[i,5]=1 then t_a[1,4]= mean(t_a[i+1,4],t_a[i+2,4]) ;
      
   i=i+1;
end;
run;

有没有办法在 proc iml 中使用矩阵或列表来做到这一点,或者您会推荐任何其他方式吗? 提前致谢!

解决方法

这个问题只涉及一个 ID 变量 (='BarCode') 和一个有缺失值的变量 (='Sales'),所以你真的只需要读取和处理两个向量。

一种有效的方法是迭代“条形码”变量(一个 ID 变量)的唯一级别并处理每个缺失值。因此,您可以将问题简化为“按组分析”,其中依次处理每个 ID 值。有几种方法可以在 IML 中执行 BY-group 分析。最容易理解和实现的是the UNIQUE-LOC technique。对于大数据,the UNIQUEBY technique is more efficient

以下示例使用 UNIQUE-LOC 技术:

proc iml;
use table_a;
   read all var {"BarCode"} into ID;
   read all var {"Sales"} into X;
close;

imputeX = X;             /* make copy of X */
u = unique(ID);          /* unique categories of the ID variable */
do i = 1 to ncol(u);     /* for each ID level */
   groupIdx = loc(ID=u[i]);
   y = x[groupIdx];      /* get the values for this level */
   k = loc( y=. );       /* which are missing? */
   if ncol(k)>0 then do; /* if some are missing,do imputation */
      n = nrow(y);
      startIdx = ((k+1) >< n);  /* starting location,don't exceed n */
      stopIdx  = ((k+2) >< n);  /* ending location,don't exceed n */
      values = y[ startIdx ] || y[ stopIdx ];
      mean = values[,:];      /* find mean of each row */
      y[k] = mean;              /* copy mean to missing values */
      imputeX[groupIdx] = y;    /* update imputed vector (optional: write data) */
   end;
end;

print ID[F=Z11.] X imputeX;
,

我认为这不是解决您的问题的好方法 PROC IML,但我可以告诉您您的特定方法哪里出错了。希望 Rick 或其他人可以停下来展示使用矩阵运算解决此问题的正确 IML 方法,或者您可以浏览 Do Loop,因为我相当确定 Rick 在那里有关于插补的文章。

也就是说,您在这里的问题是 SAS IML 对作为数据结构的表的支持并不多。它们是最近添加的,并且主要是为了更容易地从 SAS 将数据集导入 IML 而不会有很多麻烦。但是,您不能将它们视为 Pandas 数据框或类似数据;它们实际上只是您需要从中提取内容的数据存储设备。您需要将数据移动到矩阵中才能实际使用它们。

以下是我将您的非功能性代码直接转换为功能性代码的方法。同样,请记住这可能不是一个好的方法 - 矩阵有很多特性使它们擅长在这类事情上,如果你正确使用它们,你可能不会需要使用 DO 循环在此处进行迭代 - 您应该使用矩阵乘法来执行您想要的操作。这就是使用 IML 的真正意义所在;如果您只是在迭代,那么使用基础 SAS 来执行此操作,在基础 SAS 中编写相同的程序要容易得多(或者,如果您获得许可,则使用插补程序更好)。

data table_a;
input Obs Barcode   date  :$6.  sales  Position;
datalines;
1    21220000000    201901         .         1
2    21220000000    201902       311         2
3    21220000000    201903       349         3
4    21220000000    201904       360         4
5    21220000000    201905       380         5
6    21220000000    201906       440         6
7    21220000000    201907       360         7
8    21220000000    201908       390         8
9    21220000000    201909       410         9
10   21220000000    201910       520        10
11   21220000000    201911       410        11
12   21220000000    201912       390        12
13   31350000000    201901       360         1
14   31350000000    201902        .          2
24   31350000000    201912        .          12
25   45480000000    201901       310         1     
26   45480000000    201902         .         2
;;;;
run;

proc iml;
t_a= TableCreateFromDataSet("work","table_a");
call TablePrint(t_a); 

sales = TableGetVarData(t_a,4);
barcode = TableGetVarData(t_a,2);
do i =1 to nrow(sales);
     if missing(sales[i])  then do;    *if the sales value is missing,then ...;
      if i <= (nrow(sales) - 2) then do;    *make sure we are not going over the total;     
        if all(j(2,1,barcode[i])=barcode[i+1:i+2]) then do;  *and see if the rows are all the same barcode;
            sales[i] = mean(sales[i+1:i+2]);   *compute the mean!;
        end;
       end;
     end;
end;
      
call TableAddVar(t_a,'sales_i',sales);  *Put the matrix back in the table;

call TablePrint(t_a);  *Take a peek!;
quit;

我首先要做的是将 Barcode 和 Sales 列提取到矩阵中。条形码用于检查以确保我们是从相同的 ID 输入的。然后,我们检查该迭代是否缺少销售,并进一步确保我们不在最后两次迭代中(否则会给出超出范围的错误)。最后,我们将条形码与接下来的两个条形码进行比较并确保它们相同。 (老实说,我这样做的方法很愚蠢,但这是我能想到的最快方法。)如果这些都通过了,那么我们计算平均值。

最后,我们将矩阵重新添加到 t_a 表中,您可以在闲暇时将其导出回 SAS 数据集,或者使用它做任何您想做的事情!

同样 - 这不是一个很好的方法,它更像是“你的代码有什么问题”的直接回答。找到比这更好的插补解决方案!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。