SAS中关于PDV的总结

什么是PDV


个人认为可以把PDV想象成一排用于存放变量值的盒子。每个盒子代表一个变量。


提交一个DATA步后,SAS会对这个DATA步进行编译,然后执行。


首先,PDV是在DATA步的编译阶段生成的。(编译会进行语法检查并创建一排整齐摆放的”盒子”);


然后,在DATA步的执行阶段,根据不同语句对PDV中变量的值进行清空或更改。(将盒子清空或换上新的物品);


最后,在RUN;语句或者OUTPUT;语句将PDV中变量的当前值输出到目标数据集中。KEEP,DROP语句或KEEP=,DROP=数据集选项会影响输出到目标数据集中变量的个数。(如果没有KEEP/DROP,将新建变量和数据集变量对应的盒子搬出到目标数据集;如果只有KEEP,则只搬KEEP指定的盒子;如果只有DROP,则不搬DROP指定的盒子;如果KEEP/DROP同时存在,则只搬KEEP-DROP后剩下的盒子

PDV中变量的个数及顺序


DATA步中所涉及到的所有的变量,包括新创建的、从其他数据集读取的(SET)、以及自动生成的变量。自动生成的变量包括:_ERROR_,_N_; 或是FIRST.VAR,_IORC_等由某个语句或选项所自动产生的变量。默认情况下,自动生成的变量不会输出到目标数据集中。


PDV中变量按照先来后到的原则,是根据其在DATA步中第一次出现的位置决定整个PDV中的变量顺序。同样,这是在DATA步的编译阶段确定的。(在SET语句中,数据集选项IN=所指定的变量会在数据集变量之前)PUT _ALL_; 语句会将PDV中所有的变量按照其在PDV中的顺序输出到log中。

例如下面这个例子:

  data test;     
          aaa=1;    
          set sashelp.class(keep=name sex in=in1);   
          by name;     

          bbb="bbb";  
          set sashelp.class(keep=age weight height in=in2); 
          put _all_;  
run;  

在PDV中共有13个变量,包括两个新创建的(aaa,bbb),5个数据集中的,6个自动生成的(in1,first.name,last.name,in2, _error_, _n_)。

顺序为:aaa, in1, name, sex, first.name, last.name, bbb, in2, age, weight, height, _error_,_n_。

关于PDV中变量值的RETAIN

一般情况下,DATA步的执行是一个循环的过程,也就是SAS运行到DATA步最后一句后会默认回到DATA语句继续执行。在回到DATA语句再次执行这个DATA步的代码的时候,就会涉及到是否对PDV中变量已有的值清空,这就是RETAIN要做的。      

这里用“一般情况下”,是因为有些情况下,SAS不会回到DATA语句,而是在RUN;语句就结束了。如:
  *** No data  read from outside;  
  data a;
      put _all_;
      x=1;
  run

  *** No data read  from the first iteration(_N_=1);
  data b;
     x=2
    put _all_;
     if x=1  then set  sashelp.class;
  run;  
       )

回到PDV:

a. 在DATA步刚开始执行的时候:
      自动生成变量会被附上初始值:_N_=1, _ERROR_=0,FIRST.VAR=1, LAST.VAR=1, 等等;
      如果RETAIN语句对某变量设置了的初始值,则对应的变量被设为指定的值;
      SUM语句(如a+1;)的变量会被初始化为0;
      其他的变量,包括新建变量和SET的数据集对应的变量都会被设为空值。

b. 当SAS执行过程中再次回到DATA语句时:
       自动生成变量的值会被retain;
       如变量来自RETAIN语句、SUM语句、或数据集中,则变量值会被retain;
       其他的变量会被置空。

例如,可以根据下面DATA步所产生的log来判断变量的retain情况:
  proc sort data=sashelp.class out=class; 
         by age; 
  run;  

  data
 test;
    put "==============================="; 
    put "At begnning: " _all_;

        aaa=_N_;

         set class(keep=name age in=in1);
         by age; 

         bbb+age; 

       retain ccc 0;     ccc=age+ccc; 
       retain ddd;     ddd=sum(ddd,age); 

    put "At ending  : " _all_; 
  run;  
SAS 中,`WHERE` 语句是一种非常高效的工具,用于在数据处理之前对数据集进行筛选。它可以在 `DATA` 步或 `PROC` 步中使用,主要作用是选择满足特定条件的数据观测行[^2]。 ### 基本语法 `WHERE` 语句的基本格式如下: ```sas WHERE logical-expression; ``` 其中 `logical-expression` 是一个逻辑表达式,用于指定筛选条件。例如,从数据集 `test1` 中筛选出性别为女性 (`sex='F'`) 且年龄大于 20 (`age>20`) 的观测: ```sas data test2; set test1; where sex='F' and age > 20; run; ``` 该语句创建了一个新数据集 `test2`,其中只包含满足条件的观测[^2]。 ### 多条件筛选 可以使用逻辑运算符(如 `AND`、`OR`、`NOT`)来组合多个条件,以实现更复杂的筛选逻辑。例如,筛选出年龄在 18 到 40 岁之间的男性: ```sas data young_male; set population; where sex='M' and age >= 18 and age <= 40; run; ``` ### 使用 WHERE 选项 除了在 `DATA` 步中直接使用 `WHERE` 语句,还可以在 `SET`、`MERGE` 或 `UPDATE` 语句中使用 `WHERE=` 数据集选项来筛选输入数据。例如: ```sas data filtered_data; set original_data(where=(age > 30)); run; ``` 此方法在处理大型数据集时特别有用,因为它可以在读取数据之前就进行筛选,从而减少内存使用和提高效率[^5]。 ### 与 IF 语句的对比 虽然 `WHERE` 语句和 `IF` 语句都能用于数据筛选,但它们的执行机制不同。`WHERE` 语句是在数据进入程序数据向量(PDV)之前进行筛选,而 `IF` 语句是在数据已经进入 PDV 后才进行判断。因此,`WHERE` 通常比 `IF` 更高效,尤其是在处理大型数据集或索引数据集时。 ### 注意事项 - `WHERE` 语句只能作用于已存在的变量,不能用于在 `DATA` 步中创建的新变量。 - 如果数据集已经建立了索引,`WHERE` 语句可以利用索引来加速数据访问。 - 在使用 `WHERE` 语句时,逻辑表达式的书写要准确,避免出现语法错误。 ### 示例代码 以下是一个完整的示例,展示了如何使用 `WHERE` 语句筛选出年龄在 41 到 64 岁之间的女性: ```sas data middle_age_female; set patient_data; where sex = 'F' and age >= 41 and age <= 64; run; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值