使用具有滞后的前向后方法填充缺失值

时间:2017-03-22 20:02:31

标签: sas lag missing-data

假设您有一个表格,其中包含每个计数器的用户名,计数器和分数。

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;

2 个答案:

答案 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;