SAS:我如何指出对某个值的具体观察?

时间:2013-03-19 20:28:20

标签: sas

我是SAS的新手,我正试图找出其他语言的基本内容。

我有一张桌子

ID  Number
--  ------
1   2
2   5
3   6
4   1

我想创建一个新变量,其中我将Number的一个观察值与其他观察值相加,如

Number2 = Number + Number[3]

ID  Number  Number2
--  ------  ------
1   2       8
2   5       11
3   6       12
4   1       7

如何获取Number的第三次观察值,并将其添加到新变量中Number的每次观察中?

2 个答案:

答案 0 :(得分:4)

有几种方法可以做到这一点;这是一个使用SAS POINT=选项:

data have;
   input ID  Number;
datalines;
1   2
2   5
3   6
4   1
run;

data want;
   retain adder;
   drop adder;
   if _n_=1 then do;
      adder = 3;
      set have point=adder;
      adder = number;
      end;

   set have;
   number = number + adder;
run;

RETAINDROP语句定义一个临时变量来保存您要添加的值。 RETAIN表示每次通过数据步骤都不会重新初始化值,DROP表示您不希望在输出数据集中包含该变量。

POINT=选项允许用户从SAS数据集中读取特定观察值。 _n_=1部分是一种控制机制,只执行一次代码,将变量adder分配给第三次观察的值。

下一部分一次读取一个观察数据集,并添加应用您的更改。

请注意,相同的数据集会被读取两次;一个方便的SAS功能。

答案 1 :(得分:2)

我首先建议Base SAS通常不会以这种方式工作;它不是不可能的,但通常你可以在不指向特定行的情况下解决大多数问题。

因此,虽然这个答案可以解决您明确的问题,但在现实世界的情况下,它可能不是有用的东西;通常在现实世界中,您有一个匹配键或除行号以外的其他一些元素'结合,如果你这样做,你可以更有效地做到这一点。您也可以通过使此操作更方便的方式重新排列数据结构。

那就是说,你给出的具体例子是微不足道的:

data have;
input ID  Number;
datalines;
1   2
2   5
3   6
4   1
;;;;
run;

data want;
set have;
_t = 3;
set have(rename=number=number3 keep=number) point=_t ;
number2=number+number3;
run;

如果你有SAS / IML(SAS的矩阵语言),这有点类似于R,那么这是一个非常不同的故事,无论是你执行此操作的可能性还是你如何做它

proc iml;
 a= {1 2, 2 5, 3 6, 4 1}; *create initial matrix;
 b = a[,2] + a[3,2]; *create a new matrix which is the 2nd column of a added 
                      elementwise to the value in the third row second column;
 c = a||b; *append new matrix to a - could be done in same step of course;
 print b c;
quit;

要使用 First 观察来做到这一点,它会更容易。

data want;
set have;
retain _firstpoint; *prevents _firstpoint from being set to missing each iteration;
if _n_ = 1 then _firstpoint=number; *on the first iteration (usually first row) set to number's value;
number = number - _firstpoint; *now subtract that from number to get relative value;
run;

我将在此详细阐述。 SAS按记录级别工作,每个记录在DATA步骤中独立处理。 (另一方面,PROC可能不会这样,尽管许多人在某种程度上这样做)。 SAS,如SQl和类似的数据库,并没有真正承认任何行是"首先"或"秒"或" nth&#34 ;;但是,与SQL不同,它确实让你假装它是基于当前的排序。 POINT =随机访问方法是实现此目的的一种方式。

但是,大多数情况下,您将使用数据中的某些内容来确定您要执行的操作,而不是与数据排序相关的操作。这里有一种方法可以做与POINT =方法相同的事情,但是使用ID的值:

数据想要; 如果 n = 1则设置为(where =(ID = 3)rename = number = number3); 设有; 数字2 =数+ number3的; 运行;

在数据步骤(_N_ = 1)的第一次迭代中,从HAVE获取行,其中Id = 3,然后从行中获取行(实际上它是这样做的:)

*check to see if _n_=1; it is; so take row id=3;
*take first row (id=1);
*check to see if _n_=1; it is not;
*take second row (id=2);
... continue ... 

SET语句中的变量会自动保留,因此NUMBER3会自动保留(yay!),并且不会在数据步循环的迭代之间设置为丢失。只要您不修改该值,它就会保留每次迭代。