假设您有一个表格,其中包含每个计数器的用户名,计数器和分数。
data have;
input user $ counter score;
cards;
A 1 .
A 2 .
A 3 40
A 4 .
A 5 20
A 6 .
B 1 30
B 2 .
C 1 .
C 2 .
C 3 .
;
run;
某些计数器之间缺少一些分数,并且您希望将前一个计数器的分数设置为相同。所以结果如下所示:
A 1 40
A 2 40
A 3 40
A 4 40
A 5 20
A 6 20
B 1 30
B 2 30
C 1 .
C 2 .
C 3 .
我设法使用lag
函数向前填充缺失的分数值,如下所示:
data result1a;
set have(keep=user);
by user;
*Look ahead;
merge have have(firstobs=2 keep=score rename=(score=_NextScore));
if first.user then do;
if score= . then score=_NextScore;
end;
else do;
_PrevScore = lag(score);
if score= . then score=_PrevScore;
end;
output;
run;
然后我使用descending
上的counter
功能向后排序表格,如下所示:
proc sort data = result1a out= result1b;
by user descending counter ;
run;
然后最后我将在raaranged表中向前填充缺失值(根据初始表向后),再次使用lag
函数,如下所示。
我在lag
中使用了do-loop
函数,因为我想更新每一步中的前一个值(例如,值40将从第一个得分转到最后一个得分一路分组)。
然而,我得到了奇怪的结果。所有缺失值都不具有实际价值。关于修复最后一个数据步骤的想法吗?
data result1c;
set result1b;
by user;
if first.user then do;
if score= . then score=_NextScore;
else score = score;
end;
else do;
_PrevScore = lag(score);
if score= . then
score=_PrevScore;
else score = score;
end;
output;
run;
答案 0 :(得分:2)
不需要使用lag
,请使用retain
(或等效内容)。这是一个双DoW循环解决方案,它在一个datastep中完成(有效地,一次读取 - 它缓冲读取,因此这与单次读取一样高效。)
首先,我们遍历数据集以获得找到的第一个分数,因此我们可以获取初始prev_score值。然后设置它,并重新循环该用户的行并输出。这里没有实际的retain
,因为我自己正在进行循环,但它与retain prev_score;
类似,这是一个正常的数据步循环。我实际上并不retain
,因为我希望在遇到新用户时它会丢失。
data want;
do _n_ = 1 by 1 until (last.user);
set have;
by user;
if missing(first_score) and not missing(score) then
first_score = score;
end;
prev_score = first_score;
do _n_ = 1 by 1 until (last.user);
set have;
by user;
if missing(score) then
score = prev_score;
prev_score = score;
output;
end;
run;
答案 1 :(得分:1)
Import-Csv $SAMTemp2 | ForEach-Object {
If($_.SO -eq "NW"){
$_.SO = $_.ProdProj
}
$_
} | Export-Csv $SAMTemp -NoTypeInformation
是一个常被误解的功能。这个名字意味着当你调用它时,SAS会回顾前一行并获取值,但事实并非如此。
实际上,lag()
是一个创建具有n个值的“队列”的函数。当你调用lag<n>()
时,它会将x的当前值推送到该队列中并从中读取先前的值(当然每次推送只发生一次)。因此,如果条件中有lag<n>(x)
,则仅在满足该条件时才会发生推送。
要解决您的问题,您需要为每一行运行lag()函数,并在得分更正后运行:
lag<n>()
编辑:我对滥用滞后感到不知所措,并没有提出可行的替代方案。因为你正在修改分数,所以根本不使用滞后是一个坏主意。保留将在这里工作:
data result1c;
set result1b;
by user;
if first.user then do;
if score= . then score=_NextScore;
else score = score;
end;
else do;
if score= . then
score=_PrevScore;
else score = score;
end;
_PrevScore = lag(score);
output;
run;