问题描述
我正在寻找一种在 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 数据集,或者使用它做任何您想做的事情!
同样 - 这不是一个很好的方法,它更像是“你的代码有什么问题”的直接回答。找到比这更好的插补解决方案!