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

SAS proc iml用于根据接下来两次观察的平均值估算第一个月或第二个月的缺失销售额,sas,sas-iml,Sas,Sas Iml,我正在寻找一种在sas中使用proc iml估算未来两个月平均销售额的方法。 正如你所看到的,有时我没有201901的销售额,有时也没有201902的销售额 例如,对于第一个条形码,我想找到sales[1]=meansales[2],sales[3],我想对每个唯一的条形码都这样做 表A如下所示: Obs. | Barcode | date | sales | Position ------------------------------------------------

我正在寻找一种在sas中使用proc iml估算未来两个月平均销售额的方法。 正如你所看到的,有时我没有201901的销售额,有时也没有201902的销售额 例如,对于第一个条形码,我想找到sales[1]=meansales[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中是否有使用矩阵或列表的方法,或者您会推荐其他方法?
提前谢谢你

我不认为这是解决您问题的好方法,但我可以告诉您,在您的特定方法中,哪里出了问题。希望Rick或其他人能过来看看使用矩阵运算解决这个问题的正确IML方法,或者你可以浏览一下,因为我相当肯定Rick在那里有关于插补的文章

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

下面是我将如何直接将非功能代码转换为功能代码。同样,请记住,这可能不是一个好方法-矩阵有很多特性,使它们擅长于这类事情,如果你使用正确,你可能不需要使用do循环来迭代-你应该使用矩阵乘法来做你想做的事情。这就是使用IML的真正意义所在;如果你只是在迭代,那么就用base SAS来完成,用base 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;
我首先要做的是将条形码和销售列提取到矩阵中。条形码是为了检查以确保我们是从相同的ID输入的。然后,我们检查该迭代是否缺少销售,并进一步确保我们不是在最后两次迭代中,否则会出现超出范围的错误。最后,我们将条形码与下两个条形码进行比较,确保它们相同。老实说,我这样做很愚蠢,但这是我能想到的最快的方法。如果这些都通过了,那么我们计算平均值

最后,我们将矩阵添加回t_a表,您可以在空闲时将其导出回SAS数据集,或者使用它执行任何操作


再说一遍,这并不是一个很好的方法,它更直接地回答了代码的问题。找到比这更好的插补解决方案

我不认为这是解决您问题的好方法,但我可以告诉您,在您的特定方法中,哪里出了问题。希望Rick或其他人能过来看看使用矩阵运算解决这个问题的正确IML方法,或者你可以浏览一下,因为我相当肯定Rick在那里有关于插补的文章

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

下面是我将如何直接将非功能代码转换为功能代码。同样,请记住,这可能不是一个好方法-矩阵有很多特性,使它们擅长于这类事情,如果你使用正确,你可能不需要使用do循环来迭代-你应该使用矩阵乘法来做你想做的事情。这就是使用IML的真正意义所在;如果你只是在迭代,那么就用base SAS来完成,用base 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;
我首先要做的是将条形码和销售列提取到矩阵中。条形码是为了检查以确保我们是从相同的ID输入的。然后,我们检查该迭代是否缺少销售,并进一步确保我们不是在最后两次迭代中,否则会出现超出范围的错误。最后,我们将条形码与下两个条形码进行比较,确保它们相同。老实说,我这样做很愚蠢,但这是我能想到的最快的方法。如果这些都通过了,那么我们计算平均值

最后,我们将矩阵添加回t_a表,您可以在空闲时将其导出回SAS数据集,或者执行任何操作 你想用它


再说一遍,这并不是一个很好的方法,它更直接地回答了代码的问题。找到比这更好的插补解决方案

这个问题只涉及ID变量='BarCode'和缺少值的变量='Sales',因此您实际上只需要读取和处理两个向量

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

以下示例使用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;

这个问题只涉及一个ID变量='BarCode'和一个缺少值='Sales'的变量,所以您实际上只需要读取和处理两个向量

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

以下示例使用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;

这是IML的要求吗?不是!这只是我的一种想法。也许使用lag会更容易,但我想避免额外的列。这是IML中的一个要求吗?不!这只是我的一种想法。也许使用lag会更容易,但我想避免额外的列。谢谢!只有在职位1缺少销售的情况下它才有效,但如果职位2缺少销售,它不会找到。谢谢!它只有在位置1缺少销售时才起作用,但如果位置2缺少销售,它就找不到。啊,我知道一定有办法将指数限制在最大值,但想不出怎么做-现在看起来很明显!对于那些不熟悉的人,>要了解更多关于elementwise MIN和MAX运算符以及如何记住它们的信息,请参见>有关elementwise MIN和MAX运算符以及如何记住它们的更多信息,请参阅