SAS中的多do循环
我有一个2017年至2018年每周收入百分比的数据集。一些公司在2017年初没有数据,因为他们直到后来才开始盈利。周数分别为201701、201702-201752和201801-201852 我想做的是有104个新变量,称为WEEK0-WEEK103,其中WEEK0将有挣钱列的第一个非空列值。以下是数据示例:SAS中的多do循环,sas,iteration,do-loops,Sas,Iteration,Do Loops,我有一个2017年至2018年每周收入百分比的数据集。一些公司在2017年初没有数据,因为他们直到后来才开始盈利。周数分别为201701、201702-201752和201801-201852 我想做的是有104个新变量,称为WEEK0-WEEK103,其中WEEK0将有挣钱列的第一个非空列值。以下是数据示例: MON_EARN_201701 MON_EARN_201702 MON_EARN_201703 MON_EARN_201704 30
MON_EARN_201701 MON_EARN_201702 MON_EARN_201703 MON_EARN_201704
30 21 50 65
. . 30 100
. 102 95 85
然后,我希望我的数据具有以下列(示例)
这些只是一个非常大的数据集的小例子
我在想我需要尝试做一些do循环,所以到目前为止我尝试的是:
DATA want;
SET have;
ARRAY mon_earn{104} mon_earn_201701 - mon_earn_201752 mon_earn_201801 -mon_earn_201852;
ARRAY WEEK {104} WEEK0 - WEEK103;
DO i = 1 to 104;
IF mon_earn{i} NE . THEN;
WEEK{i} = mon_earn{i};
END;
END;
RUN;
这不起作用,因为当第一个值为空时,它不会填充周末0
如果需要更多信息,请发表评论,我会将其添加进来 如果是长格式,您可以这样做。在长格式中,您可能不需要它
proc sort data=have;
by ID week;
run;
data want;
set have;
by id; *for each group/id counter;
retain counter;
if first.id then counter=0;
if counter=0 and not missing(value) then do;
counter=1; new_week=0; end;
if counter = 1 then new_week+1;
run;
如果您确实需要广泛使用:
data want;
set have;
array mon_earned(*) .... ;
array week(*) ... ;
found=0; i=0;
do while(found=0);
if not missing(mon_earned(i)) then found=1;
i+1;
end;
z=0;
do j=i to dim(week);
week(z) = mon_earned(j);
z+1;
end;
run;
如果是长格式,您可以这样做。在长格式中,您可能不需要它
proc sort data=have;
by ID week;
run;
data want;
set have;
by id; *for each group/id counter;
retain counter;
if first.id then counter=0;
if counter=0 and not missing(value) then do;
counter=1; new_week=0; end;
if counter = 1 then new_week+1;
run;
如果您确实需要广泛使用:
data want;
set have;
array mon_earned(*) .... ;
array week(*) ... ;
found=0; i=0;
do while(found=0);
if not missing(mon_earned(i)) then found=1;
i+1;
end;
z=0;
do j=i to dim(week);
week(z) = mon_earned(j);
z+1;
end;
run;
您需要第二个索引变量,称之为
j
,以正确的周分配为目标j
仅在不缺少月收入时递增
此示例代码将“挤出”所有缺失的收入;即使是那些在某些收益发生后出现的缺失收益。比如说
收入:。10 . 120 . 25…
将压缩到周:
1012025…
data have;
array earn earn_201701-earn_201752 earn_201801-earn_201852;
do _n_ = 1 to 1000;
call missing (of earn(*));
do _i_ = 1 + 25 * ranuni(123) to dim(earn);
if ranuni(123) < 0.95 then
earn(_i_) = round(10 + 125 * ranuni(123));
end;
output;
end;
run;
data want;
set have;
array earn earn_201701-earn_201752 earn_201801-earn_201852;
array week(0:103);
j = -1;
do i = 1 to dim(earn);
if not missing(earn(i)) then do;
j+1;
week(j) = earn(i);
end;
end;
drop i j;
run;
您需要第二个索引变量,称之为
j
,以正确的周分配为目标j
仅在不缺少月收入时递增
此示例代码将“挤出”所有缺失的收入;即使是那些在某些收益发生后出现的缺失收益。比如说
收入:。10 . 120 . 25…
将压缩到周:
1012025…
data have;
array earn earn_201701-earn_201752 earn_201801-earn_201852;
do _n_ = 1 to 1000;
call missing (of earn(*));
do _i_ = 1 + 25 * ranuni(123) to dim(earn);
if ranuni(123) < 0.95 then
earn(_i_) = round(10 + 125 * ranuni(123));
end;
output;
end;
run;
data want;
set have;
array earn earn_201701-earn_201752 earn_201801-earn_201852;
array week(0:103);
j = -1;
do i = 1 to dim(earn);
if not missing(earn(i)) then do;
j+1;
week(j) = earn(i);
end;
end;
drop i j;
run;
听起来你只需要找到复制的起点 首先按日历月查看收入列表,直到找到第一个未丢失的值。然后将从那里开始的值复制到相对月份的新收益数组中
data want;
set have;
array mon_earn mon_earn_201701 -- mon_earn_201852;
array week (104);
do i = 1 to dim(mon_earn) until(found);
if mon_earn{i} ne . then found=1;
end;
do j=1 to dim(week) while (i+j<dim(mon_earn));
week(j) = mon_earn(i+j-1);
end;
run;
需要数据;
集有;
数组mon_earn mon_earn_201701——mon_earn_201852;
阵列周(104);
i=1时变暗(mon_earn)直到(found);
如果你赚了{i}ne。然后发现=1;
结束;
当(i+j听起来你只需要找到复制的起点时,就可以将j=1变暗(一周)
首先按日历月查看收入列表,直到找到第一个未丢失的值。然后从那里开始将值复制到按相对月列出的新收入数组中
data want;
set have;
array mon_earn mon_earn_201701 -- mon_earn_201852;
array week (104);
do i = 1 to dim(mon_earn) until(found);
if mon_earn{i} ne . then found=1;
end;
do j=1 to dim(week) while (i+j<dim(mon_earn));
week(j) = mon_earn(i+j-1);
end;
run;
需要数据;
集有;
数组mon_earn mon_earn_201701——mon_earn_201852;
阵列周(104);
i=1时变暗(mon_earn)直到(found);
如果mon_earn{i}ne.则find=1;
结束;
j=1时是否变暗(周)(i+j将您的数据转换为长格式,这将非常容易。如果是长格式,我将如何做?您可以排序,您可以从第一个不缺失值开始重新编号。您能否通过回答问题向我展示?我不明白如何重新编号整个数据集,因为每行的第一个不缺失值都是相同的不同的一周,我有100000多行。将您的数据切换到长格式,这将非常容易。如果数据是长格式,我将如何做?您可以排序,您可以从第一个不缺失的值开始重新编号。您能通过回答问题向我展示吗?我不知道如何在每个r时重新编号整个数据集ow的第一个非缺失值位于不同的一周,我有100000多行。感谢您的回答。我确实收到了错误“错误:数组下标0超出了第343行第16列中获得的数组mon_的维度1的范围[1-104]”。我假设我需要在数组中输入变量名,即mon_earn_201701-mon_earn_201752 mon_earn_201801-mon_earn_201852用于第一个数组?谢谢回答。我确实收到错误“错误:数组mon_earn的维度1在第343行第16列的数组下标0超出范围[1-104]”。我假设我需要在数组中输入我的变量名,即mon_earn_201701-mon_earn_201752 mon_earn_201801-mon_earn_201852作为第一个数组?谢谢你,这很有效。我将能够使用此方法处理我遇到的其他问题,再次感谢。如果这是一个愚蠢的问题,很抱歉,但我正在努力完全理解这是可行的,你能给我发个消息解释一下吗?什么是令人困惑的?有两个数组语句。阅读文档中的这些语句是如何工作的。有两个DO循环。再次阅读它们是如何工作的。SAS DO循环非常强大,因为你可以像这样将迭代循环与WHILE或UNTIL边界测试结合起来。TA中的索引RGET数组从1开始,当源数组中的项用完时停止。FOUND是一个缺失或1的数字变量。SAS将把非缺失值和非零值视为TRUE。因此循环将一直运行,直到找到第一个非缺失值。数组索引是整数。I、J和负1是整数。它们的总和为r整数,用作数组的索引。由于J从1变为…并且I是第一个值的位置,因此I+J-1是要复制的当前值的位置。请注意,您不需要使用goofy括号[]
或{}
新文档用于数据步骤代码中的数组。普通括号工作正常。我发现