简单的Do-Loop:检查之前的行数据是否相同

时间:2014-04-04 14:37:19

标签: loops sas do-loops

我习惯在MatLab中编码,在使用Do Loops时,SAS对我来说仍然是新手。我的目标是检查当前行上方/之前的行,以查看当前行号和上一行号是否匹配。如果第一行上方的矢量数据与当前行匹配,我希望能够检查它。

Num(列向量)= 123,123,134,156,290,348,596,569,569

/*---- Do-Loop ----*/
data full;
set work.Test;
 count=_N_;

do i=1 to count;
    Current = Num(i);
    Prev = Num(i-1);
end;

run;

给我"当前"应引用向量的第i个单元格" Num"和"上一页"应该在" Current"之前引用第i个单元格。细胞。有人能帮助我吗?

3 个答案:

答案 0 :(得分:1)

SAS与Matlab的显着不同之处在于Matlab具有向量和矩阵,而基本SAS则没有。 Base SAS比矩阵语言更接近SQL;你操纵行内的列。如果您希望将SAS视为矩阵语言,请查看您是否获得SAS-IML许可(PROC SETINIT; RUN;应该向您显示您已获得许可的内容,或询问您的SAS管理员)。那种语言与Matlab非常相似。

至于使用基础SAS来解决这个问题,你所做的事情取决于你的目标。如果仅将每行与前一行[或下一行进行比较,因为这两个目标相同],您可以使用PROC COMPARE轻松完成此操作。

例如:

data class_one/view=class_one;
set sashelp.class(firstobs=2);
run;

proc compare base=sashelp.class compare=class_one out=class_compare;
run;

PROC COMPARE有很多选项可以让它完全符合您的要求,有关详细信息,请参阅documentation

您也可以非常轻松地将匹配合并到下一行。

data want;
merge sashelp.class(in=a) sashelp.class(in=b firstobs=2 rename=(...) keep=...);
... do stuff ...
run;

您需要重命名来自第二个数据集的变量,因为它们会覆盖第一个数据集的变量,并使用keep选项仅保留您的&# #39;重新使用 - 而keep使用ORIGINAL名称,而不是重命名的名称。然后在...do stuff...中放置您正在使用的任何代码来将行与下一行进行比较。如果'前一行'很重要(即,你想要行[2..n]作为最终输出,而不是[1..n-1]),然后将firstobs = 2移动到第一个数据集。 (这告诉它跳过第一个观察,因此一个数据集从1开始,一个从2开始,然后两个迭代超过它。)

如果您只是检查行号,这会更容易一些。你可以这样做:

data want;
set have;
by num notsorted; *notsorted is needed unless you do expect it to be in numeric order;
if first.num then first_obs_for_rownum=1;
if last.num then last_obs_for_rownum=1;
run;

显然你可以用then条款做其他事情,我只是想明确他们做了什么。 if first.num and last.num表示rownumber的行是唯一的(至少,按照数据集的顺序 - 如果它未排序,则相同的num可能出现在其他地方,但不会立即出现在该行之前/之后)。 first.num是一个1/0变量,指示前一行是否具有num的不同(1)或相同(0)值; last.num是一个1/0变量,指示下一行是否具有num的不同(1)或相同(0)值。那些可以用于任何变量(所以first.id first.name等适用于那些变量),只要它们以某种方式出现在by语句中;如果你有一个多变量by语句,每次重置该变量左边的任何变量时都会重置它们。

答案 1 :(得分:0)

我附加了一个代码,用于检查上一行的值并检查当前值,如果有更改则更新列。

如果这有帮助,请告诉我。

Data Me;     
Input Pid Visit Dose;    
Cards;    
1 1 2    
1 2 3    
1 3 4    
1 4 4    
;
Run;

Data Me;
Set Me;
Length Dose_Change_Why $20.;
Dose_Change_Why = " ";
Run;

%Macro Chg;

Proc Sql;
Select Count(Dose) into:Cnt From Me;
Quit;

Data _null_;
Cnt = "&Cnt.";
Call Symput('Cnts', Compress(Trim(Cnt)));
Run;

Proc Sql;
Select Dose into:Dos1-:Dos&Cnts. From Me;
Quit;

%Do i = 1 %To &Cnt.-1;

Data _null_;
i = &i.;
j = &i. + 1;
Call symput('j', Compress(Trim(j)));
Run;

%If "&&Dos&i." ne "&&Dos&j." %Then %Do;
%Put &&Dos&i. &&Dos&j.;
Proc Sql;
Update Me set Dose_Change_Why = "Reason for change" Where Visit = &j.;
Quit;
%End;

%End;

%Mend;

%Chg;

Proc Print;
Run;

答案 2 :(得分:0)

也可以通过滞后函数实现。

Data Me; 
Input Pid Visit Dose;
Cards;
1 1 2
1 2 3
1 3 4
1 4 4
;
Run;

Data Me(Drop=Dose1); 
Set Me;
Dose1 = Lag(Dose);
If _n_ gt 1 and Dose ne Dose1 Then Why = "Reason";
Run;