2

我习惯在 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;

对我来说,“Current”应该引用向量“Num”的第 i 个单元格,而“Prev”应该引用“Current”单元格之前的第 i 个单元格。有谁能够帮我?

4

3 回答 3

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可以让它完全符合您的要求,请参阅文档了解更多详细信息。

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

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

但是,您需要重命名来自第二个数据集的变量,否则它们将覆盖第一个数据集的变量,并使用该keep选项仅保留您正在使用的变量 - 并keep使用原始名称,而不是重命名的姓名。然后在...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 变量,指示上一行是否具有不同 (1) 或相同 (0) 的值numlast.num是一个 1/0 变量,指示下一行是否具有不同 (1) 或相同 (0) 的值numfirst.id first.name只要它们by以某种方式出现在语句中,它们就可以用于任何变量(因此等对这些变量起作用);如果你有多个变量by语句,每次重置该变量左侧的任何变量时都会重置它们。

于 2014-04-04T16:10:51.690 回答
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;
于 2017-05-04T09:42:48.680 回答
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;
于 2017-05-04T09:58:17.253 回答