今天在书中看到一个挺有意思的东西,分享给大家,同时我觉得这也是我们编程过程中需要注意的一个点。
是不是觉得我周末也在学习,放狗屁,我是学习5分钟,玩耍29小时,只是因为要写文章让你们刚好看到造成的错觉。周末也不出去玩,就是混时间,反正现在时间过得飞快,一天很快就过去了。
先看一段代码:
data aes;
input @1 subject $3.
@5 adverse_event $15.;
datalines;
101 Headache
102 Rash
102 Fatal MI
102 Abdominal Pain
102 Constipation
;
run;
data death;
input @1 subject $3.
@5 death 1.;
datalines;
101 0
102 0
;
run;
data aes2;
merge death aes;
by subject;
if adverse_event = "Fatal MI" then death = 1; /*注意这里*/
run;
proc print data = aes;
run;
我们看AES数据集,里面的adverse_event=“Fatal MI”只有一条记录,如果不看输出,我们应该认为AES2里面只有一条记录会等于1,但是结果却出乎我们的意料,或者说出乎我的意料。因为我写程序一般不会直接对数据集中已经存在的变量直接赋值,因为知道肯定会出现各种各样的意外情况。
看下输出,发现subject=“102”的3条记录death都是1,为什么?
是因为SAS在merge,set,update数据集的时候,会自动把变量的值都retain下来,因为death变量已经存在于DEATH数据集,所以里面的death的值会被retain下来(而且是通过判断条件重新衍生的值)。
When you assign death = 1 for “Fatal MI,” the subsequent records
within that BY group are also set to 1.
通过上面这段话,我们做几个测试,比如在102下面增加一个受试者,看下值还会被retain下来吗?
①:只在AES数据集增加受试者,DEATH数据集不增加
发现值并没有retain下来,我们接着在DEATH数据集加上103受试者
所以,这种做法的关键就是by后面的变量,只在变量同样的值下期作用
②:我们set一下看看,发现类似的情况也发生了,但是需要注意的一点就是在adverse_event=“Fatal MI”之前的数据,即使是同一个人,值也不会继承下来。
所以我的建议就是平时写程序的时候不要这样写,要是by变量有好几个,更是丈二和尚摸不着头脑,要么新建一个变量,要么rename一下。大家知道会发生这种情况就好了。
------------------------------------------
说到retain,我再讲一下retain的一种用法,以前好像也说到过,就是把变量提到数据集最前面,但是要注意,如果data步里面有计算,然后你还想把变量提前,最好不要用retain。否则也是会有意想不到的结果。
我们以SASHELP.CARS为例:
data test;
set sashelp.cars;
run;
假设变量太多,我们左右拖动太麻烦,于是我们想把这3个变量提前,加上retain就好了。
data test;
retain EngineSize Cylinders Horsepower;
setsashelp.cars;
run;
需要注意的是在set之后再retain就不起作用了。
网友评论