一直以来,大众了解的SAS都是数据集操作,使用的方法是数据步和过程步。但其实,SAS这个庞大的系统中还隐藏了另一个平行世界——IML,在这个世界里,你需要一个像操作MATLAB一样的矩阵思维。 今天我们将介绍如何在SAS里玩穿越,将数据从矩阵变成SAS数据集,从SAS数据集再变成矩阵。它将大大方便我们的使用。
在SAS里玩穿越 | 【SAS Says·扩展篇】IML:穿越
本文要解决三个问题:
第一个问题:如何把SAS数据集转换为矩阵来处理?
把数据集转换成矩阵来,在很多情况下处理起来会方便得多,比如可以轻易的实现“如果第三行第五列的数字比第三行第六列的数字大,就把第二行第七列的数字增加1”这种问题。当然,方便的地方还远远不止这些。
第二个问题:如何把矩阵转换成数据集来处理?
SAS的优势在于强大的统计模块,无论是回归、检验,还是数据管理SQL,甚至是贝叶斯,都可以方便快速的实现,因此,将矩阵转换成数据集来做统计分析,真好。
第三个问题:如何直接在IML模块中处理数据集?
当然,IML模块也提供了直接编辑数据集的功能。
最后再来一个附加问题:如何直接读入外部的文件。
好了,让我们一块来探索一下吧!
本集学习完之后,SAS的IML模块就告一段落,最后面是Ansta给自己布置的一道作业,大家可以一起来做一下,然后相互交流~
第一个问题:将SAS数据集转换为矩阵
Read语句可以将数据集转化为矩阵,但前提是数据集必须已经打开,而打开数据集用use或edit,即:
红色为必须语句,黄色为可选语句。首先要用use或edit语句将数据集打开,然后再用read语句转换成矩阵。
我们来看一个例子:
SAS自带的数据,在sashelp逻辑库下有一个class数据集:
我们现在要将所有男性数据读入矩阵boy中:
proc iml; use sashelp.class; read all into boy where(sex="男"); print class; quit;
Var,选择的变量不填,SAS就默认把所有数值型变量读入矩阵,生成一个数值矩阵。也可以手工选择字符矩阵:
proc iml; use sashelp.class; read all var {name sex} into boy2 where(sex="男"); print class; quit;
好,第一个问题就这么愉快的结束了。
第二个问题:将矩阵转换为数据集
和数据集转换成矩阵差不多,将矩阵变成数据集,也需要先打开一个新数据集,也就是创建一个数据集(create语句),然后讲矩阵放到这个数据集中(append语句):
我们把前面包括年龄、身高、体重三个变量的矩阵boy写入数据集。
在写入数据集之前,首先生成一个ID变量,,一遍标识出不同的人,方法就是用第一讲用到的水平连接符,复习→:
proc iml; use sashelp.class; read all into boy where(sex="男"); id={1,2,3,4,5,6,7,8,9,10}; id_boy=id||boy; create boy var {id age height weight}; append from id_boy; quit;
矩阵变成数据集之后,就可以用SAS的各种强大的统计模块做分析了。
好,第二个问题也就这么愉快的结束了!
第三个问题:直接在IML模块中处理数据集
首先我们也还是要使用use语句打开数据集。
(1)列出观测值
List 观测值范围 var {选择变量名} where (条件) ;
(红色背景是必须要有的,黄色背景是可以省略的)
观测值范围
- All:所有观测值
- Current:当前观测值
- Next:下一个观测值
- After:当前观测值之后的所有观测值
- Point 记录号:指定观测值
以逻辑库SAShelp中的air数据集为例:
我们试一下读取所有international airline travel小于120的观测值,和只读取第6行的观测值:
proc iml; use sashelp.air; list all where (air<120); quit;
proc iml; use sashelp.air; list point 6; quit;
(2)删除观测值
use 数据集; edit 数据集; delete 观测值范围 where(条件);
(红色背景是必须要有的,黄色背景是可以省略的,下同,不再重复)
观测值范围和上面的差不多:
- Point 记录号:删除某行数据。
- All 删除所有观测值。
有一份10人的score数据,数据集的名字叫score
现在想删除第二个人James的记录。
proc iml; use score; list all; edit score; delete point 2; list all ; quit;
可以看出,当删除之后,James不见了。
(3)数据排序
close 数据集; sort 数据集 out=排序后的数据集 by descending 排序变量
对一个数据集进行排序,首先要保证它不是打开状态,因此要用close语句关闭掉。
仍然对sashelp中的air数据排序,按照变量international airline travel (thousands)来排序(对应变量名为AIR):
proc iml; close sashelp.air; sort sashelp.air out=sorted by descending air; quit;
执行语句后,生成了一个降序排列的sorted数据集。
(4)简单统计分析
IML模块可以直接对数据集进行简单的描述性统计。
use 数据集; summary var {变量1 变量2 ...} class {分类变量1 分类变量2 ...} stat {mean std};
Class语句选择分类变量,如想分性别查看,stat列出需要的统计量,如果不列的话默认给出:min、max、mean、std
如还是air这个数据,想看international airline travel的均值和方差:
proc iml; use sashelp.air; summary var {AIR} stat { mean std }; quit;
最后的一个附加问题:如何读入外部文件?
步骤是这样的:
用infile语句将外部文件读入SAS;
用create语句创建一个SAS数据集;
用do data-append-end语句将外部文件装进SAS数据集中,举个例子:
现在有外部文件d:testSet.txt,想要读入SAS,变量名分别为a、b、c
proc iml; infile 'D:testSet.txt'; create temp var {a b c}; do data; input a b c; append; end; close temp; quit;
这样,文件就读入SAS的work逻辑库中,数据集名字为temp。
作业: 用两种方法实现如下数据的回归分析
Sashelp逻辑库中有一个关于GNP的数据sashelp.gnp,要求用1961、1962、1963三年的数据建立回归模型:
GNP = consump invest
用的变量有:
- GNP-gross national product ($billions)
- Consump-personal consumption expenditures
- Invest-gross private domestic investment
要求给出系数、R2、t检验的p值,提示:
SAS常用的的概率密度函数
①标准正态分布函数PROBNORM(x)
计算服从标准正态分布的随机变量u小于给定x的概率。即p(u<X)。如:
y=PROBNORM(-2.58),结果为0.005。
②t分布概率函数PROBT(x,df,nc)
计算自由度为df,非中心参数为nc的t分布随机变量小于给定值x的事件的概率,当nc=0或不规定这项时,分布为中心分布。如y=probt(0.95),结果为0. 975。
③F分布概率函数PROBF(x,dfl,df2,nc)
计算服从分子自由度为dfl,分母自由度为df2的F分布的随机变量小于给定值x的事件的概率,当分布为中心分布时,nc=0或不规定该项。
这是Ansta给自己布置的作业,大家也可以试一试,再对照proc reg的结果看一下,之后会给出我自己修改的代码,我也是在学习,希望能和大家一起交流。