http://web5.pku.edu.cn/pucssr/SASbiancheng.pdf
本教程中的主题将向您介绍 SAS Enterprise Guide。您最好依次浏览这些主题。 |
概述 | |
启动项目并浏览主要窗口 | |
向项目添加 SAS 数据 | |
从文本文件导入数据 | |
关于 SAS 任务 | |
创建和修改列表报表 | |
创建条形图 | |
关于“查询生成器” | |
使用查询连接表 | |
将计算列添加至查询 | |
从查询生成“汇总表” | |
创建饼图 | |
执行线性模型分析 | |
将多个报表组合成单个文档 | |
使用过程流 | |
更多内容 |
简明SAS教程
by LongFei
version:0.11
SAS
统计软件
前言
本教程的内容主要是SAS的简单基本知识和SAS在多元统计分析中的应用。
侧重在SAS的应用,会介绍如何根据SAS的输出结果得到结论,但不会深入讲解其中的统计原理。
在每一章的开始,会简要概括本章内容和学习目标,以帮助同学们有针对性地进行学习。
代码讲解将由一条条的statement讲解来构成。
作者的话
这篇文章是为了整理自己最近复习SAS的心得笔记而写,旨在梳理自己的学习内容。
我以前修读多元统计分析课程时,SAS上机作业常常是照着课本和课件做的,对代码的含义一知半解,一旦提交了作业,几乎就会忘掉代码了。如今复习,由于已积累了较多的编程实践经验,对代码的理解也加深了。我把自己的理解写出来,希望能帮助正在或打算学习SAS的同学们。
原本只是打算写一个小教程,但写作过程中有点贪多求全,现在越写越多,只能强行“简明”了。
注意事项
本教程使用的SAS版本是9.4,SAS版本最低不低于9.3。
快速入门
本章介绍SAS编程的基本概念和逻辑,并写一个简单的示例程序,以期让初学者快速上手SAS编程。
学习目标
- 了解DataSet(数据集)、Procedure(过程),Statement和Option(选项)的概念
- 了解SAS程序执行流程和SAS代码基本语法结构。
- 了解简单日志信息的含义
- 写一个Hello World程序
基本概念
- DataSet(数据集)
- 一张表,每列代表一个变量,每行代表一个观测。数据集是SAS进行统计分析的基本单位。
- Procedure(过程)
- 简称为proc,SAS集成的各种统计分析功能的总称。可以使用不同的过程来完成不同的分析。
- Statement(语句)
SAS代码,无论分成多少行,都要以一个分号结束,这一条到分号结束的代码,就被称为一个statement或语句,这是SAS执行代码的基本单位。一条条的语句,构成了SAS程序。
statement之间是有层次关系的。顶层statement是一个独立执行单元的statement,比如data xxx;
,proc print;
,run;
等等。次级statement则需要依赖于顶层statement——先执行顶层statement,才能执行次级statement,典型的次级statement就是by xx;
,input a b;
等等。
次级statement是有使用范围的,需要在正确的顶层statement下才能被SAS执行,他们的主要作用是在细节上控制主statement的行为,在某些过程(proc)中,某些次级statement是必须设置的。比如说在排序过程(sort)里,就不能直接执行proc sort;
,而必须在它后面添加by 变量名;
来指定用于排序的变量后,才能执行。
以下示例代码的每一行都是一个statementdata xxx;
set a;
proc print data=xxx;
run;
- Option(选项)
- 选项是指写在statement语句后,分号前,以空格间隔的一系列单词或等式,比如
noprint
,data=xxx
等。它们通常不是必要的,但能控制statement的宏观行为如:指定用于分析的数据集,不输出结果,指定绘制直方的数量等等。
顶层statement和次级statement的option写法稍有不同。顶层statement的option是接空格如proc procname data=xxx noprint;
,而次级statement是接/
如histogram RM/normal nmidpoints=12;
程序编写流程
- data
- 代码以data作为标识符起头,称为data步(数据步)。数据步的作用是建立数据集,进行数据的读取和修改,后续可以提供给过程步进行统计分析。SAS提供了强大的数据输入功能,能够把各种格式的数据输入到SAS中。此外,还能在数据输入的过程中进行计算,生成新的数据列,甚至能处理缺失数据,功能十分强大。
- proc
- 代码以proc起头,称为proc步(过程步)。过程对指定的数据集进行统计分析。SAS提供了丰富多样的统计分析功能,还有各种选项可供细化。
- run
- 写下一个
run;
,就可以让SAS在读取到这一步时,运行前面的所有语句。如果没有这一条,则代码只是被SAS读取了,但不会运行。
我们编写SAS程序,正是按照上述的运行过程来做的:
1. data步——获取和整理数据
2. 写proc步——分析数据
3. 提交代码给SAS,得到output——输出分析结果
程序执行流程
在提交代码后,SAS会逐条读入statement。当读到run;这条statement时,SAS就会执行前面的所有statement,输出分析结果。如果我们的SAS程序中没有run;
语句,则程序会处于持续运行状态,但不会执行前面读取到的statement。
有些proc步的statement是持续性的,会阻止下一个proc的执行。这时就需要加一句quit;来终止该proc步。这是后话,待到用时再说。
在SAS 9.3以后,在默认设置下,proc步的分析结果会被输出到一个html文件上,这个html文件会被SAS用结果浏览器打开。如果不喜欢这种方式,可以使用ODS(Output Delivery System 输出交付系统)来改变输出方式和样式。这在后续的章节中会讲到。
基本语法
从上一节的SAS运行过程可以看出,要编写一个SAS程序,就需要编写data步和proc步的代码,它们有着相似的语法结构。编写完成之后,再写一行run;
让程序执行statement即可。
- Data步
Data步以data作为开头标识,空格后接自行设定的数据集名,生成一个数据集。下面接上各种statement描述如何处理这个数据集。Data步有自己的次级statement语句,只可在data步中使用。
一个完整data步的语法结构如下,以<>括起来的部分都是可选的,不必严格遵守下面的顺序:DATA datasetname;/* 设定数据集名 */
<code that defines the variables in the data set>;/* 定义数据集的变量 */
<code to enter data>;/* 输入数据 */
<code to create new variables>;/* 创建新变量 */
<code to assign missing values>;/* 设定缺失值 */
<code to output data>;/* 设定输出的数据集 */
<code to assign labels to variables>;/* 设定变量的标签 */
<and other data tasks>;/* 其它数据任务 */
- Proc步
Proc步以proc 作为开头标识,空格后接SAS过程名,再一个空格后接该过程的选项,最后仍以分号结束。分号后面接上多句次级statement,。同data步一样,proc有自己的次级statement语句。不过每一个过程的次级statement语句都不一样,有些能通用,有些则不能,有些还是必写的,需要具体问题具体分析。一般的语法结构如下,:
proc procname <options>;/* 启动过程步 对数据进行统计分析 */
<statements>/<options>;/* 次级statement,如果要添加选项,必须加/隔开 */
- run和quit
run;
和quit
都是一条statement语句,而且是不依赖于data步和proc步的statement。
当SAS执行了run;
时,它就会把前面读取到的所有data步或proc步的statement都执行完。如果一个程序里没有run;
,那么这个程序在提交后也不会被执行。
当SAS执行了quit;
时,它就会把某些会持续运行,占用SAS资源的的proc停掉,让SAS能够执行后面的proc。- 大小写问题
- 在SAS中,各种statement的关键字,如data,proc等,都是不区分大小写的。不过,在字符串中,则会区分大小写。
日志(Log)
在向SAS提交代码之后,务必检查日志里的内容,确认程序的执行情况。特别是需要关注错误和警告。
- 错误
- 红色的字表示错误(error),说明代码出错了,会导致程序在停止在SAS所提示的出错行,不再继续往下执行代码。
- 警告
- 绿色的字表示警告(warning),说明当前提示的这句代码可能有问题,有可能会让你得不到预期的结果,但程序还是能继续运行下去。
学会阅读日志能帮助快速地排除小BUG,避免不必要的时间浪费。
日志默认是打开的,如果没有打开,或者不小心关掉了。可以手动打开:菜单栏-->视图-->日志
Hello World
将以下代码复制到SAS的代码编辑器里并提交
data hellodata;
input ISay $ 1-20;
datalines;
Hello World One
Hello World Two
Hello World Three
;
proc print;
run;
会得到以下输出:
1 | Hello World One |
2 | Hello World Two |
3 | Hello World Thre |
数据输入和储存
本章介绍SAS的数据集的基本知识和data步中的数据输入方法。
学习目标
- 了解SAS数据集类型、结构和变量数据类型
- 掌握input的使用方法,能够精细地设定数据输入格式
- 掌握infile的使用方法,能够导入数据文件
- 掌握datalines的使用方法,能够手动输入数据
SAS数据集基本知识
数据集类型
数据集分为临时数据集和持久数据集两种类型。
- 临时数据集
- 数据集名是一个single name,也就是简单的名字,如:
data example;
,data dec2016
等。临时数据集的数据,会暂时储存在SAS程序里,但一旦关掉SAS,就会被销毁,想要重新使用数据的话,就需要再次提交输入数据的代码。 - 持久数据集
- 数据集名则是一个two-part name,也就是用一个
.
连接的复合名字,如:data research.2016
,data MyData.0001
等。这个复合名字的前半部分是SAS的 library(逻辑库)名,后半部分是数据集名。这样的数据集会以文件的形式被储存到硬盘上,具体的位置是library指定的路径。即使关掉了SAS,下次再打开,只需要分配逻辑库名,就能直接使用,无需再次提交数据输入的代码。
/* Ex 2.1 临时数据集和持久数据集的区别 */
/* 临时数据集实例
每一次重新打开SAS,要运行代码中的proc步,就必须先提交data步。
*/
data tempdata;/* 输入数据集 */
input t @@;
datalines;
1 2 3 4
;
proc print data=tempdata;/* 打印数据集 */
run;
/* 持久数据集实例
只有第一次需要提交全部的代码,之后数据集就会被以文件形式储存在MyData库中。之后要使用,只需要执行第一句分配逻辑库名,就可以直接提交proc步,而无需再次提交data步输入数据。
*/
libname MyData "D:\MyData";/* 分配逻辑库名 */
data MyData.tempdata;/* 输入数据集 */
input t @@;
datalines;
1 2 3 4
;
proc print data=MyData.tempdata;/* 打印数据集 */
run;
数据集的结构
数据集的结构就是一张表,每一列表示一个变量,每一行表示一个观测。以下是一个典型的SAS数据集
在第一行中,第一列的Obs表示观测的序号,后面的a b c分别是变量名
1 | 1 | 2 | 3 |
2 | 4 | 5 | 6 |
3 | 7 | 8 | 9 |
变量命名规则
SAS允许为变量自由命名,但存在一些规则:
- 可以设定长度为1-32的任意字母、数字或下划线,不能包含空格。
- 必须以字母或下划线开头
- 不区分大小写
- 最好具有描述性(就是说能从变量名看出这个变量的含义,少用诸如a,b,c这样无语义的变量名),这项规则是可选的,但建议尽量遵守。
一些正确的变量名: GENDER
AGE_IN_1999
AGEin1999
_OUTCOME_HEIGHT_IN_CM
WT_IN_LBS
一些错误的变量名: AGE IN 2000
2000MeaslesCount
S S Number
Question 5
WEIGHT IN KG
AGE-In-2000
变量数据类型
- 学习过编程语言的同学都知道,在编程语言中,变量的数据类型是很重要的。在SAS中,虽然没有明确指出,但实际上也是存在不同的数据类型的,分别如下:
- Numberic
- 数字型变量,也是SAS的默认变量类型。决定一个变量是不是数字型,只需要看它在逻辑上是否可以进行运算,如身高、体重之类,就可以用于计算,ID号、电话号码之类,不可用于计算,所以前两者是数字型变量,后两者不是。这种变量类型会自动忽略掉高位的0,如果你把ID号设置为数字类型,那么00012就会变成12。
- Character
- 字符型变量,也包括Text(文本)或String(字符串)。这种类型的变量不能用于运算,并且会区分大小写。如果你对性别变量分组,那么M和m会被分成不同的组。SAS默认会把数据看成数字型变量,所以必须要手动把诸如ID号之类的数字形式的变量设置成字符型变量。
- Date
- 日期型变量。要输入SAS的数据集中的日期变量可能会有多种多样的格式,比如10/15/09、01/05/2010或JAN052010等等。在后面会看到如何处理这多种多样的日期格式数据,并把他们转化为SAS能够用于分析的数据。实际上,在SAS数据集中储存的日期型变量数据是用整数表示的,这能很方便地进行数据操作。
变量数据类型实例程序
/* Ex 2.2 变量数据类型实例程序 */
data vartypes;
input id_num id_char $ weight_num @18 birth_date MMDDYY10.;/* 输入4个变量,分别是id_num(默认-数字型) id_char(字符型) weight_num(默认-数字型) birth_date(日期型,格式为:月/日/年) */
datalines;
0001 0001 60 03/07/2016
0002 0002 50 04/02/2016
0003 0003 30 12/31/2016
0004 0004 45 04/12/2016
0005 0005 49 04/07/2016
;
proc print data = vartypes;
run;
打印的结果如下:
1 | 1 | 0001 | 60 | 20520 |
2 | 2 | 0002 | 50 | 20546 |
3 | 3 | 0003 | 30 | 20819 |
4 | 4 | 0004 | 45 | 20556 |
5 | 5 | 0005 | 49 | 20551 |
可以看到id_num的0被去掉了,而birth_date变成了整数形式
数据的输入
数据的输入分为两步:首先,从外部文件或流式数据(in-stream data,可以简单地理解为直接嵌在代码里的数据)中读取原始数据,然后是将原始数据转化为SAS使用的标准数据集,需要设定一定的转化规则。
SAS提供的数据输入功能十分强大,但是实际用到的不多,只讲简单实用的部分即可。
读取原始数据
- 外部文件
- 使用infile语句进行读取。格式为
infile filepath;
。可以后接选项词做进一步的输入控制。常用的有DLM
,用于指定分隔符;FIRSTOBS
,用于指定从哪一行开始读数据;OBS
指定到哪一行结束读取。infile "D:\MyData\MyCSV.csv" DLM=',' FIRSTOBS=2 OBS=10
表明从D:\MyData\MyCSV.csv中读取数据,分割符为逗号,从第2行开始读,第10行结束。 - 流式数据
- 以
datalines;
开头,换行之后就可以写数据了,到最后换行,以一个分号结束即可。
如果要写入的数据中有分号,则可以以dalines4;
开头,最后结尾换成三个分号。
input语句用于设定如何将各种格式的数据转化成SAS使用的标准数据集。
设定转化规则
读入了原始数据之后,需要设定转化规则,用数学说原始数据集到SAS数据集的映射,把原始数据转化成标准的SAS数据集。SAS提供了多种多样的方法来确定转化规则,但一般来说,我们只需要使用input
语句来设定规则就足够了。 input
语句的通用的语法为:input <specification(s)> <@ | @@>;
specification(s)
表示一个或多个特殊的表述,内容可以包括变量,以圆括号括起来的变量列表,$符号,指针控制,列控制,格式化标识等等,非常复杂,具体可以通过SAS的官方帮助手册里查input Statement
进行了解。下面列举最常用的几种输入格式,能够解决绝大多数的输入问题。它们之间可以互相混合使用以完成最佳输入。
Freeform List Input
Freeform List Input(自由输入)是最简单也是最常用的。只需要设置变量列表,以及指定某些变量为字符类型即可,SAS会自动读取数据,数据之间以空格作为间隔符。
通用语法:input variable <$> ;
variable
为变量名,$是可选项,表明指定它前面的变量为字符类型。这最简单的语法,在大多数时候已经能满足学习中的数据需要了。这主要用于以作为空格间隔的原始数据。
/* Ex 2.3 Freeform List Input */
data test;
input x $ y z; /* x后接一个$,表明x是字符型变量,不省略高位的0 */
datalines;
001 2 3
004 5 6
007 8 9
;
proc print;
run;
输出结果:
1 | 001 | 2 | 3 |
2 | 004 | 5 | 6 |
3 | 007 | 8 | 9 |
Compact Data Format
Compact Data Format(紧凑输入)也是非常常用的,比起自由输入,只是增加了末尾用于控制数据输入指针的符号。
通用语法:input variable <@|@@>;
<@ | @@>
表示可以写@或@@或不写,这决定着读取数据的指针的行为。
- 不写:指针立刻换行
- @:指针暂不换行,直到下一个input或一轮循环结束。
- @@:指针不换行。循环结束也不换行。
紧凑输入指的是末尾添加@@
符号的写法,这可以让SAS连续地读取所有的数据。
/* Ex 2.4 Compact Data Format-input中@数量的区别 */
data test;
input x @; /*单个@,暂时不换行,直到下一个input或一轮循环结束 */
input y; /*没有@,下一个input语句会去读新的一行*/
input z @@; /*两个@,下一个input不换行,直接从下一个数据开始读*/
datalines;
1 2 3
4 5 6
7
;
proc print;
run;
输出结果:
1 | 1 | 2 | 4 |
2 | 5 | 6 | 7 |
Column Input
Column Input(列输入)是以列控制指针来控制输入的,可以以精确到具体列的形式进行数据的读取。
基本语法:input variable <$> startcol<-endcol> ...;
<$>
正是前面说的字符类型控制符。startcol
指明从哪一行开始读,<-endcol>
是可选项,指明到哪一行读取结束,不写的话,就默认取starcol
的值。
/* Ex 2.5 Column Input 列输入 */
data MyData;
input ID $ 1-3 SBP 4-6 DBP 7-9 GENDER $ 10 AGE 11-12 WT 13-15;
datalines;
001120 80M15115
002130 70F25180
003140100M89170
004120 80F30150
005125 80F20110
;
run;
输出结果
1 | 001 | 120 | 80 | M | 15 | 1 |
2 | 002 | 130 | 70 | F | 25 | 1 |
3 | 003 | 140 | 100 | M | 89 | 1 |
4 | 004 | 120 | 80 | F | 30 | 1 |
5 | 005 | 125 | 80 | F | 20 | 1 |
Formatted Input
Formatted Input(格式化输入)是用于将特殊的数据格式转化为SAS可识别的数据类型的,比如日期或者带小数点的数字。
通用语法:input formated-vars ;
formated-vars
指的是格式化变量,标准格式是:col-pointer variable informat
其中,col-pointer
指明从第几列开始读取数据,用@n
来表示,n为指定开始读取的列,variable
指出变量名,informat
指出输入的格式,所有的informat都必须以点号.或点号.后接1个数字的形式作结尾,具体格式表如下:
informat输入格式表
n. | n 列数据,数字类型 |
$n. | n列数据,字符类型,移除头部的空格 |
$CHARn. | n列数据,字符类型,保留头部的空格 |
COMMAn. | n列数据,数字类型,去除小数点或美元符号(比如$40,000会被读取为40000) |
COMMAn.m | n列数据,数字类型,其中带有2位小数,去除小数点或美元符号(比如$19,020.22会被读取为19020.22) |
MMDDYY8. | 输入日期,形如01/12/16(月-日-年)(注意Y2K问题) |
MMDDYY10. | 输入日期,形如04/07/2016(月-日-年) |
DATE7. | 输入日期,形如20JUL16(日月年) |
DATE9. | 输入日期,形如12JAN2016(日月年) (没有Y2K问题) |
需要特别说明地是,日期在SAS中是以整数的形式储存的,这样便于进行统计分析。如果需要输出日期的数据,则需要在输出时,特别指出输出格式。
/* Ex 2.6 Formatted Input */
data MyData;
input @1 SBP 3. @4 DBP 3. @7
GENDER $1. @8 WT 3. @12 OWE
COMMA9. @22 InputDate MMDDYY8.;
format InputDate MMDDYY8.; /* 指定InputDate的输出格式,没有这句则会输出整数 */
/* 列标尺
----+----1----+----2----+
*/
datalines;
120 80M115 $5,431.00 01/11/16
130 70F180 $12,122 01/12/16
140100M170 7550 01/12/16
120 80F150 4,523.2 01/12/16
125 80F110 $1000.99 01/12/16
;
proc print data=MyData;
run;
输出结果
1 | 120 | 80 | M | 115 | 5431.00 | 01/11/16 |
2 | 130 | 70 | F | 180 | 12122.00 | 01/12/16 |
3 | 140 | 100 | M | 170 | 7550.00 | 01/12/16 |
4 | 120 | 80 | F | 150 | 4523.20 | 01/12/16 |
5 | 125 | 80 | F | 110 | 1000.99 | 01/12/16 |
判别分析
判别分析的应用场景:对于总体,各自有自己的观测集,现在给出一个样本,需要判断它属于哪一个总体。
根据不同的判别指标和条件,我们可以用不同的衡量方法,来进行不同的判别分析,它们有各自不同的优劣。
距离判别
距离无疑是最直观的衡量方法,样本距离哪个总体近,就判它属于哪个总体。
具体地说,就是利用观测集来估计总体(或总体的某些关键统计量),然后以某种方式来衡量观测与总体的远近程度,然后选择最近的总体。
马氏距离
要判断距离,首先得明确计算距离的方法。现在我们希望了解的是给定样本到某个总体的距离。联系欧氏空间,很自然地就想到,这个距离可以定义成到总体的中心的距离,而总体的中心可以用它的均值向量来表示,为了方便计算,我们一般取距离的平方。此外,还要考虑总体的集中程度,越集中的,自然就越高,这个在一元下可以用方差表示,在多元下则是用协差阵来表示。由此想法,我们可以定义样品与总体的马氏距离为
对于多个总体,我们只需要比较的大小即可
特别地,在两总体比较中,我们可以定义一个线性函数,从而得到判别准则:
SAS程序
在SAS中,我们可以使用discrim过程来完成上述的各种判别分析。
通用语法是
proc discrim <options>;
class variable;
<other statements>;
class variable;
是必填的,它决定着要用什么变量来划分类别。然后我们可以根据不同的需求来添加options
和statement
完成统计分析。
马氏距离判别
统计软件SAS使用教程
百度空间 | 百度首页 | 登录
统计软件SAS使用教程 2007-06-16 23:31
|