【问题标题】:SAS: How do I point to a specific observation of a value?SAS:我如何指出对某个值的特定观察?
【发布时间】:2016-07-04 15:04:44
【问题描述】:

我对 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 的每个观察值?

【问题讨论】:

  • 你有 SAS/IML 还是只有基础 SAS?

标签: sas


【解决方案1】:

有几种方法可以做到这一点;这是使用 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 功能。

【讨论】:

    【解决方案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 和类似数据库一样,并不真正承认任何行是“第一”或“第二”或“第 n”;但是,与 SQL 不同的是,它确实允许您根据当前排序假装它是。 POINT= 随机访问方法是实现此目的的一种方法。

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

    数据需要; 如果 n = 1 然后设置 have(where=(ID=3) rename=number=number3); 设置有; 数字2=数字+数字3; 运行;

    在数据步骤的第一次迭代中 (_N_=1) 从 HAVE 中取出 Id=3 的行,然后按顺序从 have 中取出行(真的是这样做的:)

    *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 会自动保留(耶!)并且不会在数据步循环的迭代之间设置为丢失。只要您不修改该值,它将在每次迭代中保留。

    【讨论】:

    • 好的,我可以看到与 MATLAB 和 R 相比,它并不是那么微不足道。我同意在现实世界的场景中你会有一个密钥,但我只是认为它会像使用 MATLAB 和 R 一样简单. 在我的具体示例中,我有一个日期系列(SAS 日期编号),我想将第一次观察的日期减去所有观察结果,以便从 0 获得时间偏移量。这会更简单吗?
    • 实际上会容易得多。首先,SAS 具有经常执行数据集级操作的 PROC(本质上是编译的二进制文件); ETS 是一个带有可能工作的时间序列 PROC 的模块(我没有使用它们的经验,但这就是整个模块的重点)。我将在答案中添加第一次观察保留的示例。
    猜你喜欢
    • 1970-01-01
    • 2015-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多