一、建立逻辑库和数据集并调用
建立逻辑库的目的只有一个,就是将电脑硬盘上的某一个文件夹和SAS的一个库关联起来。
我的电脑E盘下有个SAS文件夹,此文件夹专门用来存放SAS数据,现在想在这个文件夹中新建一个SAS数据集,该如何做?
1.在SAS中新建一个库,取名为T,并将T和E:/SAS关联起来,用libname语句即可完成。
LIBNAME T "E:/SAS";现在T就等价于“E:/SAS”
2.新建数据集。T后面加点(.)再加数据集地名字。
DATA T.HEIGHT;
INPUT NAME$ HEIGHT;
DATALINES;
A 179
B 177
C 190
D 183
;
RUN;
现在,关掉之前的SAS程序,将height数据集输出到屏幕,该如何做?
再次打开时,逻辑库中没有T这个逻辑库,但是E:/SAS文件夹下是有height数据集的。
重新建立关联,逻辑库的名字可任取,然后通过逻辑库名+.数据集名的方式即可调用该数据集,代码如下:
LIBNAME TZ "E:/SAS";
PROC PRINT DATA=TZ.HEIGHT;
TITLE "THIS IS HEIGHT DATASET";
RUN;
建立数据集的方法还有很多种,可以通过其他资料查找,然而,我们在建立数据集的时候,使用一种方法即可,此处的这种方法也是一种十分常用的方法。
二、数据库操作(增删改查)
当数据量比较大的时候,数据集就称为数据库,SAS中的数据库言语就是SQL语言,和MySQL的操作也类似。
1.查询
查看某一个变量:VAR
比如,查看数据集HEIGHT中的NAME这个变量有哪些值:
PROC PRINT DATA=TZ.HEIGHT;
TITLE "ONE VARIABLE OF HEIGHT--NAME";
VAR NAME;
RUN;
查询变量属性:CONTENTS函数
LIBNAME T "E:/SAS";
PROC PRINT DATA=T.A;
TITLE "T.A";
RUN;
PROC CONTENTS DATA=T.A;
TITLE "THE ABSTRACT OF T.A";
RUN;
条件查询/拆分:where语句
(1)按照条件进行查询数据
where作为参数时:(WHERE=(条件语句));where作为单独语句时:WHERE 条件语句;
注意:如果变量为字符型,则在写WHERE语句时,变量值要用英文双引号引起来。
例如:查找身高为190的人的名字NAME:
PROC PRINT DATA=TZ.HEIGHT;
TITLE "THE NAME OF HEIGHT 190";
VAR NAME;/*只查看NAME这个变量,换言之就是只显示身高这个变量*/
WHERE HEIGHT=190;
RUN;
查询NAME为A的人的身高:
DATA Z;
SET TZ.HEIGHT;
WHERE NAME="A";/*A要用英文双引号*/
RUN;
PROC PRINT DATA=Z;
TITLE "Z";
RUN;
因为没有在PROC步中加VAR语句,所以显示姓名和身高两个变量的值,如果还有其他变量,那么同样也会显示出来,因为我们没有对其进行限制,下面加入VAR语句:
DATA Z;
SET TZ.HEIGHT;
WHERE NAME="A";/*英文双引号*/
RUN;
PROC PRINT DATA=Z;
TITLE "Z";
VAR HEIGHT;
RUN;
(2)按照条件拆分数据集
以上只能获得单个数据集,倘若要根据某个条件将原数据集拆分成几个子数据集呢?该如何作?
DATA X Y;/*这里的X Y为拆分后的数据集,用来接收通过条件语句拆分好的数据集,当然,数据集可以很多个,一个,两个,三个,四个甚至更多个都是可以的*/
SET 被拆分的数据集;
IF条件语句 THEN OUTPUT X;/*如果数据满足条件,则将这个数据集输出到X*/
ELSE OUTPUT Y; /*如果不满足条件,则将数据集输出到Y*/
RUN;
DATA X Y;
SET TZ.HEIGHT;
IF NAME="A" THEN OUTPUT X;/*A要用英文双引号引起来*/
ELSE OUTPUT Y;
run;
PROC PRINT DATA=X;
TITLE "DATASET ONE ---- X";
RUN;
PROC PRINT DATA=Y;
TITLE "DATASET TWO ---- Y";
RUN;
补充:IF 后面一定跟THEN;
ELSE 后面直接跟结果,不需要THEN;
ELSE IF 后面一定要跟THEN;
2.修改
修改变量名:原来的数据集的变量名不能直接修改,可以通过间接的方法,新建一个数据集,将原来的数据集复制到这个新建的数据集,同时修改变量名。
DATA TZ.HEIGHT2;
SET TZ.HEIGHT;
RENAME NAME=NAMES;
RUN;
PROC PRINT DATA=TZ.HEIGHT2;
TITLE "HEIGHT2";
RUN;
修改变量属性:变量就三大属性:数字型、字符型和日期型。
比如,将数字型HEIGHT修改为字符型HEIGHT2:
变量名=PUT(被修改的变量名,需要修改成何种类型)
LIBNAME TZ "E:/SAS";
DATA TZ.HEIGHT3;
SET TZ.HEIGHT;
HEIGHT2=PUT(HEIGHT,8.);/*将数字型HEIGHT修改为字符型HEIGHT2*/
RUN;
PROC PRINT DATA=TZ.HEIGHT3;
TITLE "HEIGHT3";
RUN;
PROC MEANS DATA=TZ.HEIGHT3;
RUN;
比如,将字符型HEIGHT2改成数字类型HEIGHT3:
变量名=INPUT(被修改的变量名,需要修改成何种类型)
DATA TZ.HEIGHT4;
SET TZ.HEIGHT3;
HEIGHT3=INPUT(HEIGHT2,best8.);/*将数字型HEIGHT2修改为字符型HEIGHT3*/
RUN;
PROC PRINT DATA=TZ.HEIGHT4;
TITLE "HEIGHT4";
RUN;
PROC MEANS DATA=TZ.HEIGHT4;
RUN;
修改变量值:利用条件查询精准地找到某条记录地某个值,然后修改。
3.增加
增加可分为纵向拼接和横向合并两种,即使增加一条记录,也必须先建立一个数据集,再通过纵向拼接的方式,将两者合并。
纵向拼接:set 变量1 变量2 变量3 ...注:在一次纵向合并中,总共可以纵向合并50个数据集。同时可以对合并的数据集作出限制,drop + keep + rename,drop:删除某个变量,keep:保留某个变量,rename:重命名某个变量。drop=a, keep=b, rename=(c=d); a、b、c、d为变量名。数据集后使用这些限定时,需要用括号括起来,如:set A (drop=a) B(keep=b) C(rename=(c=d));
LIBNAME TZ "E:/SAS";
DATA TZ.A;
INPUT a b c;
DATALINES;
1 2 3
4 5 6
;
RUN;
PROC PRINT DATA=TZ.A;
TITLE "A";
RUN;
DATA TZ.B;
INPUT a b e;
DATALINES;
5 6 7
8 9 10
;
RUN;
PROC PRINT DATA=TZ.B;
TITLE "B";
RUN;
DATA TZ.C;
SET TZ.A TZ.B;
RUN;
PROC PRINT DATA=TZ.C;
TITLE "C";
RUN;
/*Add restriction command*/
DATA TZ.D;
SET TZ.A(DROP=a) TZ.B(KEEP=b RENAME=(b=c));/*B中只保留b变量,并且将b重命名c,因此B中此时原来的b变量就变成了c变量*/
RUN;
PROC PRINT DATA=TZ.D;
TITLE "D";
RUN;
DATA TZ.E;
SET TZ.A(DROP=a) TZ.B(KEEP=a b e RENAME=(b=c));/*B中保留a b e 变量*/
RUN;
PROC PRINT DATA=TZ.E;
TITLE "E";
RUN;
小结:纵向合并只会按照相同的变量名进行合并,如果变量名不相同,则合并后新增一列该变量,原数据集中没有这个变量的那些列就空出来。
横向合并:
在纵向拼接中,是根据变量的名字来进行的,即按照列的方向;那么在横向合并时,根据同样的原理,就应该是按照每一行的名字来合并,行名相同的合并为一条记录,这是最简单的理解,如果再推广一下,不一定是行名,也可以根据某一列中相同的元素来合并。数据集的一行可以代表一个研究对象的信息,假设现在有两个数据集,每个数据集3条记录,都是关于同一组研究对象的信息,A数据集包含变量:NAME,ID,GENDER;B数据集包含变量:ID,HEIGHT,WEIGHT;现在要将A、B两个数据集按照ID合并。通过merge和by完成,merge后直接跟数据集的名字,by后跟合并所依据的变量名,但是这个变量名必须是排序好的,否则不能合并,如果是乱序的,则要先排序后合并。也就是说要想完成横向合并,就要先解决排序的问题,排序又可分为升序和降序,默认是升序,降序的参数为descending+变量名。根据这样的思路,先了解排序的实现。
PROC SORT DATA=数据集名字 OUT=排序后的数据集名字 NODUPLICATES;
BY 排序所依据的变量名1;
BY 排序所依据的变量名2;
RUN;
两个变量名说明是排序后再排序,先按照变量1排序,再按照变量2排序,以上默认是升序。其中DATA=是原来的数据集,OUTPUT=是排序后新的数据集,NODUPLICATES参数的意思是“没有重复”,也就是说排序时候如果遇到序号一样且所有信息都一样的记录,就将其删掉,如果只是序号一样,而其他信息不一样,就不会删除。在实例代码中可以验证这点。以上是升序,那么降序怎么实现呢?
PROC SORT DATA=数据集名字 OUT=排序后的数据集名字 NODUPLICATES;
BY DESCENDING 变量名1;
BY DESCENDING 变量名2;
RUN;
代码实例:
(1)先生成A,B 两个数据集
DATA A;
INPUT NAME$ ID GENDER$;
DATALINES;
A 1 M
B 2 W
C 3 M
;
RUN;
PROC PRINT DATA=A;
TITLE "DATASET A";
RUN;
DATA B;
INPUT ID HEIGHT WEIGHT;
DATALINES;
3 179 70
1 170 72
2 169 65
2 169 65
2 180 75
;
RUN;
PROC PRINT DATA=B;
TITLE "DATASET B";
RUN;
(2)按照ID进行降序排序,同时注意在删除重复记录时只是序号相同而其他信息不同的记录会不会也被删除。
PROC SORT DATA=A OUT=A2 NODUPLICATES;
BY DESCENDING ID;
RUN;
PROC PRINT DATA=A2;
TITLE "A2";
RUN;
PROC SORT DATA=B OUT=B2 NODUPLICATES;
BY DESCENDING ID;
RUN;
PROC PRINT DATA=B2;
TITLE "B2";
RUN;只是序号相同而其他信息不同的记录不会被删除
(3)横向合并 注:这里的条件BY同样要写成BY DESCENDING,否则不能执行。
DATA ROWBIND2;
MERGE A2 B2;
BY DESCENDING ID;/*这里不能只写BY*/
RUN;
PROC PRINT DATA=ROWBIND2;
TITLE "ROWBIND2";
RUN;A数据集少了一条记录,所以会重复匹配ID=2的记录
4.删除
删除变量:
删除变量也不能直接删除,要通过SET语句和DROP语句