proc步中的case...when...相当于data步中的if...then...,根据某种条件输出最终结果。本文以sashelp.classfit数据集为源数据,讲解的通俗易懂,该注释的都注释了,不懂你来打我!零基础的,那就慢慢等我分享SAS BASE的知识点吧,看心情更新,不爽还是你来打我
。
例一:先来看一个最基础的例子:
data test;
set sashelp.classfit;
run;
proc sql noprint;
create table test1 as /*创建一个表,便于我们比较前后变化*/
select *, /*选取test数据集的全部变量,同时注意这里要有逗号*/
case
when age gt 14 then "old"
when age lt 14 then "young"
else "middle" /*需要else语句*/
end as ageu length=10 /*新建的变量名称*/
from test;
quit;
需要注意的几点除了注释上写明的,还有以下几点
①:判断条件语句“ then”后面不能直接跟新建变量名称,即不能写 “then ageu='young' ”
②如果不新建变量名称,直接以end结尾,系统自动会新建一个变量名(最后一个)
③else这句话不能少,同时要注意,如果你的then语句后面跟的是字符型变量,那么else +"",如果你的then语句后面跟的是数值型变量,那么else +.,在本例中,“old”,“young”都是字符型,那么当满足大于14岁ageu为“old”,小于14岁ageu为“young”,至于其他的就为空,这时候就得写成 else "",否则会报以下错误:
这段SQL语句转换为DATA步程序如下:
data test2;
length ageu $10.;
set test;
if age gt 14 then ageu="old";
else if age lt 14 then ageu="young";
else ageu="middle";
run;
例二:对两个变量进行判断选择
比如我们对年龄的判断跟例一一样,但是还想加上对性别的判断,F为“femal”,M为“male”。可以通过以下程序:
proc sql noprint;
create table classdf as
select *,
case
when age gt 14 then "old"
when age lt 14 then "young"
else "middle"
end as ageu length=10, /*注意有逗号*/
case
when sex="F" then "femal"
when sex="M" then "male"
else "" /*注意这里要加else ,不能else sex="M" then "male",一直出错就是在这里*/
end as sexu length=5
from sde;
quit;
我因为少写了一个else " ",直接写成else sex="M" then "male",导致系统一直报错,还以为case...when...只能对一个变量起作用。
当你需要根据性别排序时,直接在最后加上order by sex,注意只能加在from xxx 的后面,同时注意别少了分号!
例三:利用sum函数和case...when...求观测个数以及分类求和。
比如我们想求女性有多少人,男性有多少人,程序如下:
proc sql noprint;
create table classdf as
select name,sex,age,
sum(case when sex="F" then 1 else 0 end ) as fesum,
sum(case when sex="M" then 1 else 0 end) as masum
from test
order by sex;
quit;
可知女性有9名,男性有10名,注意,一开始我想区别男女性,在女性的then后面数字改成2,如图
结果
当时我就好奇哪里来的20,男女加起来也不过19,才发现是10个2相加得来的。如果你将数字换成3,那么masum就是30了。
其实上面的两段程序改成data步就是:
if sex="F" then fesum=1,注意这样写是错的,因为这样只能实现横向的求值,最后还得把一列的观测加起来才是最终的总数。
怎么求总和大家自己试一试。是不是发现case when 和sum搭配直接帮我们把总数求出来了,否则用data步的话可能得proc transpose和sum转换来转换去。
然后我又试了一下,嘻嘻嘻
proc sql noprint;
create table classdf as
select name,sex,age,
sum(case when age^=. then age else 0 end )as fesum /*求age的总和*/
/* sum(case when sex="M" then 2 else 0 end) as masum*/
from test
order by sex;
quit;
又get了一个新技能,我上次还记得我还在找怎么竖向求和,在网上看到说用proc means等,但没有这种方法,这次学到了,还能实现分类别求和。当然了,也可以分性别输出(注意标点符号)
附上proc means函数结果
我觉得上面三个例子应该能满足日常工作要求,大家可以试试其他函数或者方法,说不定有其他新发现,写了这么多,不想写了,88!
/*************TWO HOURS LATER******************/
当我休息了一下的时候,才发现case...when...真打爷的麻烦,上面的所有功能,只需要简单的sum、having、group by 就能实现了。
1:求AGE总和
proc sql;
create table dfs as
select sex,name,age,sum(age) as sumage from test;
quit;
2:分性别求age总和
proc sql;
create table dfs as
select sex,name,age,sum(age) as sumage from test
group by sex /*注意group by 在having前面*/
having sex; /*直接一个sex就搞定,还不用分类,如果只需要男性,加一个判断条件就好了*/
quit;
害我白高兴一场,以为掌握了打通任督二脉的技巧,才发现最简单的才是最正宗的,case...when...以前真的都没用过。至于选择哪种,看你高兴吧。
小生初来乍到,有什么不足或者错误的地方,还望大家多多指正。接触临床编程研究不久,一切还在摸索学习中,,,,