*
SAS基础2
数据集
SAS数据集有两类:
SAS数据文件
SAS数据视图
SAS数据文件同时描述信息和存储数据值
SAS数据视图并不实际存储数据,而只是一个查询语句
*
class是数据视图
class1是数据文件
SAS数据集、常量、变量与观测
数据集(Dataset)
SAS数据集是SAS可以管理的结构化的数据,只有SAS数据集中的数据才能被SAS过程步处理。
数据集包含两部分内容:
1. 描述部分: (数据结构)
数据名称、类型、长度、格式等
2. 数据部分: (数据)
包含实际数据值
SAS数据值被安排在一个矩阵式的表状结构中
SAS数据集、常量、变量与观测
观测(Observation)
描述被观测对象的单一整体(如一个人、一个实验动物等)某些所研究特性的一系列数据值称为一个观测,又称观察
在SAS数据集中每一行数据是一个观测(记录)
变量(Variable)
变量指定了数据的某一特性
在SAS数据集中,每一个观测是由各个变量的数据值组成
在数据集中每一列数据是一个变量(属性/字段)
SAS数据集、常量、变量与观测
变量的命名
首字符要以字母或者下划线开始,不能有空格;
只能包含字母、数字、下划线,大小写不敏感;
特殊字符(如$,@,#)不允许在SAS名中使用
合法变量名如:
A A1 abc name age total …
SAS系统保留的特殊变量名(自动变量),以下划线开始和结尾,如
_N_: data步循环执行的次数
_ERROR_: data步执行过程中遇到错误时就会自动被置为1
_numeric_:所有数值变量
_character__:所有字符变量
_all_ :所有变量
SAS数据集、常量、变量与观测
变量特性
变量特性:名称、类型、长度、输入格式、输出格式和标记
两种类型:数值型
字符型(后跟“$”符号)
数据格式用来识别和显示各种数据
长度特性:是指存贮的字节数。缺省长度是32(为了存贮长度与缺省值不同的变量,需使用LENGTH语句)
标签(label)用来补充变量的信息
SAS数据集、常量、变量与观测
使用变量前不需要定义
定义变量特性的两种常用方法:
明确地说明 – input 语句
在首次出现时给出定义 – 赋值语句:等号( =)
例如:
DATA NULL_;
C='BAD';
PUT C;
input C $;
PUT C;
cards;
a
b
;
RUN;
SAS数据集、常量、变量与观测
多个变量的简化表示
如果要一次定义或指定多个同种类型变量,可以使用缩写形式:
INPUT NAME $ VAR1 VAR2 VAR3 VAR4 VAR5 VAR6;
可以写成:
INPUT NAME $ VAR1-VAR6;
注意:
字符型变量NAME不包含在这个缩写清单中
这些变量要求类型相同,或全是数值型的或全是字符型的。
SAS数据集、常量、变量与观测
缺失值
当一个变量由于某种原因没有得到(可能没有观测到,或由于数据错误,或由于计算错误),称该值为缺失值(NULL)
数值型在SAS中用“.”表示;
字符型在SAS中用“ ”表示
SAS数据集、常量、变量与观测
常量 (Constant)
其值是固定不变的量
经常用于赋值、运算等语句中
常量分为以下三类:
数值常量: -5
字符常量:“Hello” “ABC” ‘Zhangli’
日期、时间、日期时间常量:后接D,T,DT
‘1JAN2000’D
‘9:25:19’T ; ’18jan00:9:27:25’DT
‘1JAN2000:10:30:05’DT
十六进制常量
‘45435’x,0c1x.
SAS数据集、常量、变量与观测
自动变量
自动变量是由数据步语句自动创建的
这些自动变量被加入到程序数据向量(PDV)中,但是并不输出到数据集中。
自动变量在重复过程中被保留,而不是被设定为缺失
_n_:观测序号
_error_:错误信息变量
_all_:所有变量
_nemric_:所有数值变量
_charactor_:所有数值变量
:同一by组的第一个观测
Last. Variable:同一by组的最后一个观测
SAS函数
函数是一个功能模块,包括三个要素:
函数名、参数、返回值
函数的作用:根据参数计算函数值并返回
例:y = SUM ( 1, 2, 3) ;
函数名:SUM
参数:1, 2, 3
返回值:6 (函数运算结果)
参数格式:
1. 用逗号分割:SUM(x1, x2, x3)
2. 用简化形式:SUM(OF x1-x3)
3. 用列表形式:SUM(OF x1 x2 x3)
SAS操作符(运算符)
算术操作符
**(乘方 ) *(相乘 ) /(相除) +(相加 ) -(相减)
作用:进行数学运算,得到数值结果
例: y = x ** 2 + b;
C = (12 – 4) * 2;
注意:如果算术算符有一个运算对象是缺失值,运算结果也是缺失值。
例如,y=x3 + . ; 则y的值为缺失值(.)
SAS操作符(运算符)
比较操作符:
=(EQ) 等于 ^=(NE) 不等于
>(GT) 大于 <(LT) 小于
>=(GE) 大于等于 <=(LE) 小于等于
^> 不大于 ^< 不小于
IN 等于列表中的一个 <>取最大值 ><取最小值
作用:比较二值的大小,如成立,结果为 逻辑真值 1;如不成立,结果为 假值 0
例:y = 3 > 2; (结果 y 值为 1)
x = “ABC” > “ABD”; (结果x值为 0)
注意
字符运算对象在字符之间从左到右被比较
字符次序用机器排列次序确定(即按ASCII码排列序列)
比较运算符可以连用, 缺失值最小
逻辑操作符(布尔运算符)
& (AND)与 | (OR)或 ^ (NOT)非
作用:进行逻辑运算,结果仍为逻辑值,真(1),假(0)
在表达式里通常用来连接一系列比较式, 例如:
age=25 AND sex= ’ 男’ ;age=25 AND sex= ’ 女’
||(连接):用来连接字符串
SAS操作符(运算符)
SAS表达式
用操作符将常量、变量、函数等连接起来进行运算,最终会产生一个值(表达式的值)
运算优先级:算术 > 比较 > 逻辑
例:
X+1
3
LOG(Y)
PART/ALL*100
1-EXP(N/(N-1))
AGE<100
STATE='NC'丨 STATE='SC'
SAS操作符(运算符)
*
运算次序
关于运算次序,SAS有如下的三个准则:
准则1:在括号里的表达式先计算;
准则2:较高优先级的运算先被执行;
准则3:对于相同优先级的算符,左边的运算先被执行。
各运算符的优先等级(排在前面的优先):
1级: **,^(not)
2级 :*,/
3级 :+,-
4级 :<,<=,=,^=,>,>=,^>,^<
5级 :and
6级 :| (or)
准则3的例外情况:
1) 对第一级,右边的先做;(not 也是,注意乘方)
2**3**2 <=> 2**(3**2)
2) 当两个比较算符围着一个量时,则等价于一个and运算。例如:
12<age<20 <=> 12<age and age<20
SAS程序的基本结构
Sas程序的基本结构
环境设置语句
数个完成单个动作的操作步
过程步(proc step)
利用建立的数据集完成统计分析任务
数据步(data step)
创建和修改用于统计分析的数据集
一个简单的SAS程序示例
libname a “d:\”;
data ;
input num score;
cards;
1 78
2 65
3 84
;
run;
proc print;
run;
环境设置语句
数据步
过程步
操作步
数据步
数据步是产生数据集的一组语句
一个数据步可以建立一个或多个数据集。在一份程序中可以有多个数据步
数据步程序还可以对已建立了的数据集进行修改和产生输出
数据的输出位置通过 DATA 语句设定
数据的来源位置通过 SET 语句或 INPUT 语句设定
其中 SET 语句所设定的来源为 SAS 数据表
而 INPUT 语句所设定的来源为外部文件
一般来说,数据步本身其实是一个循环(loop),数据集中有几行数据,则数据步执行几遍,建立的数据集中则有几个观测
数据步流程
数据步由 DATA 语句开始
对输入数据中的每一观测,都执行数据步一遍,当执行到数据步的最后一条程序语句时,将变量的当前值写入数据集中
然后SAS程序再回到数据步的第一条语句继续执行,读取下一个观测。就这样不断循环读取观测,从而建立起完整的数据集
数据步结束
遇到run语句或另一个数据步/程序步时就结束了
数据步骤尾部隐含了两个语句
一是 OUTPUT 语句,用于在数据处理操作完成后输出数据到指定的位置
一是 RETURN 语句,用于回到数据步骤的开始
例:
DATA FITNESS;
INPUT NUM SEX $ AGE WEIGHT HEIGHT;
RATIO=WEIGHT/HEIGHT;
CARDS;
1001 F 19 47
1002 M 20 55
1003 F 18 49
;
RUN;
Num Sex Age Weight Height
Ratio
1001 F 19 47
1002 M 20 55
1003 F 18 49
数据步流程
FITNESS
数据步语句
DATA 语句
INPUT语句
CARDS语句
赋值语句
SET语句
其它语句
(1) DATA语句
格式 :
DATA 数据集名 ;
功能 :
标志数据步的开始,并定义所建数据集的名称
例 :
DATA a;
DATA b;
DATA ;
系统自动会建立以DATA为前缀的数据集,data1, data2…datan等
默认数据集(_LAST_)
默认数据集相当于一个缓冲区,总是会被新建的数据集所覆盖
(2) INPUT语句
格式 :
INPUT 变量名表;
功能 :
读入由语句指定的数据列;为相应数据定义变量名;
确定变量格式及读入方式
3种描述记录值的方法:
1) 列表输入或自由格式
例:INPUT NAME $ AGE HEIGHT@@;
说明:
$表示NAME为字符型变量;
原始数据是标准的数值或字符,空格默认为分隔符
@@ 表示连续读入记录;
如果缺省,表示仅读CARDS下每行第一个记录
列表方式的特殊情况——格式修饰符
: 标明从非空格开始读取变量值直到遇到以下情况:下一个空格列或预先定义的变量长度已经读满;
data test; input lastname :$15. ; cards; Smith 123 Highway Longlastname 527 Avenue
& 指明字符型输入值可能嵌有一个或几个空格,因为空格在正常情况下用来分割不同的数据值;
2) 列方式
2) 列方式
例:INPUT NAME $1-20 SEX $22 AGE 24-25;
说明:
要求各变量数据在数据区排列在固定区域
原始数据是标准的数值或一般字符格式
*3) 格式化输入
例: INPUT NAME $ 10. HEIGHT ;
说明:
要求在变量后给出一个输入格式,用来说明变量的数据类型和字段的宽度
对于省略W和D值的输入格式,使用系统缺省值
起始列号
终止列号
$w.:标准字符输入格式
:标准数值输入格式
(3)CARDS语句和RUN
CARDS/ DATALINES
格式
CARDS/ DATALINES ;
数据块
;
功能
引导数据行
说明
放在数据步的最后,每个数据步只能有一个数据块
RUN
执行前面的语句
例:
data a1;
input num $ name $ weight @@;
cards;
081 kong 082 wang
;
proc print;
run;
(4)INFILE语句
INFILE语句指定从哪一文件中读入数据,可以是磁盘文件或是crads/datalines指定的输入数据;
格式:
DATA语句;
INFILE语句;
INPUT语句;
[其它数据步语句;]
;
注意
INFILE语句必须在Input 语句之前;
CARDS语句和INFILE语句都用于指定数据库内容;
分别对应两种数据输入方式:直接输入和外部文件输入.
例:
DATA test;
INFILE ' d:\';
INPUT x1-x3;
RUN;
1 2 3
4 5 6
7 8 9
data test;
infile cards delimiter='/,';
input sbp dbp @@;
cards;
120/80, 115/70,105/75, 150/95, 135/85, 100/60
;
(5) 赋值语句
格式:
Z = X + Y ;Y = Y + 1;
功能:
创建或修改变量
data b1;
input x y @@;
z=sqrt(x);
y=abs(y-z);
cards;
;
proc print;
run;
例:
1 2 4 4 16 6
创建
修改
(6) SET语句
格式:
SET 数据集1 数据集2...;
功能:
从已经存在的SAS数据集中读取观测值或纵向连接数据集
例
DATA B; SET A;
把数据集A读入数据集B
DATA C; SET A B;
将A和B纵向联接起来,存放在数据集C中
SAS程序实例
data b1;
input name $ age height @@;
cards;
;
proc print;
run;
data b2;
input name $ age height;
cards;
;
proc print;
run;
data b3;
set b1 b2;
proc print;
run;
fang 17 ning 19
zhou 20
wang 18
cheng 21
MERGE语句
语句格式
MERGE 数据集1 数据集2...;
功能:
将多个数据集中的观测合并为新数据集中的一个观测;
SAS系统合并观测的方式依赖于BY语句的使用
例
DATA C;
MERGE A B;
将A和B横向连接起来,存放在数据集C中
BY语句和SORT过程
BY语句
格式:
By [Descending] 变量名1, [Descending] 变量名2…
功能
数据步中,BY语句规定分组变量。用于控制SET,MERGE,UPDATE或MODIFY语句的操作
SORT
格式
Proc sort data=输入数据集 out=输出数据集 可选项;
by <descending> 变量1 ……;
Run;
功能
按照By 关键字后的变量对数据集排序
*
横向并接(Join)
一对一合并:按观测的序号进行合并
Data 新数据集;
merge 数据集1 数据集2 数据集3 …;
Run;
匹配合并:根据公共变量值进行合并
步骤1:各个数据集按某相同关键词排序:
Proc sort data=数据集 out =新数据集;
by 关键词;
Run;
步骤2:横向并接:
Data 新数据集;
merge 数据集1 数据集2 数据集3 …;
by 关键词;
Run;
Data 1 data 2 com1
X Y X Y
x1 + y1 = X1 Y1
x2 y2 X2 Y2
x3 X3
Data com1;
Merge data1 data2;
Run;
Data 1 data 2 com1
Z X Z Y Z X Y
1 x1 1 y1 1 X1 Y1
2 x2 + 1 y2 = 1 X1 Y2
3 x3 3 2 X2
3 X3
Data com1;
Merge data1 data2;
By Z;
Run;
例:一对一合并
data student;
input num name $ sex$;
cards;
89100 lanyin f
89101 hanyang m
89102 sunlin f
89103 zhangli m
data test;
input t1-t3;
cards;
89 76 90
78 88 74
96 98 92
data studtest;
merge student test;
proc print;
run;
例:匹配合并
data test;
input num t1-t3;
cards;
89100 89 76 90
89102 78 88 74
89103 96 98 92
proc sort data=student;
by num;
proc sort data=test;
by num;
proc print data=student;
proc print data=test;
data mer;
merge student test;
by num;
proc print;
run;
*
两个或多个数据集的拼接
纵向拼接(UNION)
直接拼接
Data 新数据集;
Set 数据集1 数据集2 数据集3 …;
Run;
交叉拼接
如果两个数据集D1和D2已经按某公共变量排过序,在连接两数据集时想将公共变量值相同的数据连在一起,可使用BY语句进行交叉连接
Data 新数据集;
Set 数据集1 数据集2 数据集3 …;
by 公共变量;
Run;
Data 1 data 2 com1
X x X
x1 + x1 = x1
X2 x3 x2
x1
x3
Data com1;
set data1 data2;
Run;
Data 1 data 2 com1
X x X
x1 + x1 = x1
X2 x3 x1
x2
x3
Data com1;
set data1 data2;
By x;
Run;
课堂练习
建立数据集st1,包含以下数据:
建立数据集st2,包含以下数据:
将st1、st2纵向合并,存放在数据集st中,并生成新变量z,z为y值取常用对数。
思考
如何通过数据集的连接生成中国A股上市公司2012年的相关信息,包括公司的证券代码、会计期间、营业总收入、净利润、基本每股收益;
*
上机操作(1)
国泰安下载数据集包含月个股回报率文件与大股东收益信息数据 ;
将两个数据集分别导入SAS;
新建数据集统计每只股票的平均换手率
运用SAS分别将大股东信息和新建数据集进行横向合并;
创建SAS永久数据库,将新的数据集放入所创建的永久数据库Res_sas,将其命名为total。
将SAS数据集total导出,生成Excel表格。
*
Set语句的其它运用
复制数据集,即生成与原数据集完全一样的数据集
命令操作
Data 新数据集名;
set 旧数据集名;
Run;
菜单操作
更多精细的控制需要设置数据集选项或者使用一些语句
筛选数据集中的观测
加入或剔除数据集中的变量
(7) DELETE语句
格式 :
DELETE;
功能:
停止处理当前观测,该观测值不被读入到创建的数据集,SAS系统返回到DATA步的开头处理其他观测
DELETE语句与条件语句配合,可以实现用数据源的部分数据来建立数据集
例
data a;
set ;
delete;
run;
实现的功能是?
(8) IF等语句
if 条件语句
格式 :
IF 表达式 THEN <ELSE >
功能
当表达式的值为真时执行THEN后的SAS语句
IF SEX=‘M’ THEN DELETE;
说明
在THEN之后只允许使用一个语句,如果要执行几个语句,则应用DO-END把要同时执行的几个语句用括起来
IF-THEN/ELSE 语句可以嵌套。
(9)If 子集语句
格式:
IF expression;
功能
使用求子集IF语句,使SAS系统仅继续处理符合IF语句条件规定的观测值, 因而所得到的数据集是原数据集的子集
说明:
如果表达式为真(非零且不缺项),SAS系统继续为正在建立的观测值执行DATA 步中的语句
如果表达式的值是假(0或缺项),SAS系统马上返回到DATA步的开始,去进行另一次执行而不输出上一个观测值
如: IF SEX=‘F’;
等同于(IF SEX=‘M’ THEN DELETE;
在结果数据集中所包含的仅仅是SEX的值为‘F’的那些观测值。
(10)WHERE 语句
格式:
WHERE 条件表达式;
功能:
从输入数据集中时读入符合条件的观测,即WHERE语句读入数据集之前选择观测
例:WHERE x>50 and y>50
说明:
省略该语句时,读入整个数据集
只复制部分观测
data males;
set ;* set (where sex=’M’);
where sex=’M’;
run;
data males;
set ;
if sex=’M’;
run;
data males;
set ;
if sex^=’M’ then delete;
run;
data males;
set ;
if sex=’M’ then output;
run;
*
只复制部分变量
drop和keep语句:
规定输出数据集要保留或删除的变量
Data new;
set old;
drop x1 x2 x3;
Run;
Data new;
set old;
keep x1 x2 x3;
Run;
Data new (drop or keep=x1 x2 x3);
set old;
Run;
*
更改变量名
Rename语句
更改变量名
Drop,keep,rename语句一起使用时,drop和keep先起作用
Data new;
set old;
rename x1=y1 x2=y2 x3=y3 …;
Run;
*
应用运算符进行数据操作
1、生成新的变量
Data new;
set old;
x1=x**2;
x2=log(x)-2;
x3=x+y;
if year=2000 then dum=0;
else dum=1;
Run;
*
2、对数据进行筛选
(1)剔除数据缺失的样本
Data new;
set old;
if x=. then delete;
Run;
*
(2)剔除某些特定的样本(如金融行业)
Data new;
set old;
if code='000562' or code='000001' or code='000563' or code = '600015' or code='600016' or code='600030' or code='600036' or code='600816' or code='600000' or code='601998' or code='601328' or code='601166' or code='601318' or code='601398' or code='601628' then delete;
Run;
*
(3)剔除某些异常值
Data new;
set old;
if x>=(GE) 某个数值 then delete;
Run;
或:Data new;
set old;
if >x> ;
Run;
*
上机操作(2)
对生成的最终数据集total进行如下操作:
(1)剔除金融业上市公司;
(2)剔除每股收益为负的上市公司;
(3)建立一个新的变量,把数据集中换手率用小数表示;
(4)建立一个新的变量,表示除第一大股东外其它股东所持有的股份比例
(5)在数据集total中,第一大股东持股比例在50%以上且每股收益超过1元的公司有多少家?
*
SAS数据处理小技巧
*
(1)put和input语句和函数
PUT语句输出信息到:
LOG窗口;OUTPUT窗口;
FILE语句规定的外部文件。
PUT函数对数值型变量规定输出格式
格式: Put(variable,format.)
例如将数值型变量转化成字符型变量
Data test2;
set test1;
x2=put(x1, 8.);
Run;
*
Input函数:对字符型变量定义输出格式
格式:
INPUT(variable, <?|??> format.)
功能:
将输入变量转化成其它类型变量
Data test2;
set test1;
x2=input(x1, 8.);
Run;
现有一个数据流:a23 223 bc4 36 3c5 11d 400 620,按下面要求创建SAS数据集
a23 223
bc4 36
11d 400
data test;
input a $ @@;
length id $5;
id=lag(a);*上一个循环步的a;
no=input(a, best.);*转换为数值型;
if no^=. and input(id, best.)=. then output;
drop a; *从输出数据集剔除变量;
cards;
a23 223 bc4 36 3c5 11d 400 620
;
proc print;
run;
*
(2)Substr语句
Substr——字符截取函数
格式:
Substr(s,p,n)
功能:
从字符串s中的第p个字符开始抽取n个字符的子串
Data test2;
set test1;
x2=substr(x1,2,4);
Run;
*
(3)output语句
输出的两种形式
Output语句
将当前观测输出到Output语句指定的数据集
自动输出
如果不存在output语句,执行完最后一个数据步语句,自动将当前观测输出到数据集
通过output语句可同时生成多个子数据
格式:
Data 数据集1 数据集2 …;
set 原数据集;
if 条件 then output 数据集1 ;
if 条件 then output 数据集2 ;
……
Run;
Data test1 test2;
set total;
if eps<0 then output test1;
if eps>=0 then output test2;
Run;
(4)BY语句
格式:
By [Descending] [] 变量名1, [Descending] []变量名2…
功能
数据步中,BY语句规定分组变量。用于控制SET,MERGE,UPDATE或MODIFY语句的操作
FIRST.变量和LAST.变量
SAS系统对每个BY组创建两个自动变量: 和 , 用来标识每个BY组的第一个和最后一个观测
对于一个BY组的第一个观测值,取1,其余取0
对于一个BY组的最后一个观测值,取1,其余取0
这些变量不含在新产生的数据集中
(5)Sort语句(排序语句)详解
格式
Proc sort data=输入数据集 out=输出数据集 可选项;
by <descending> 变量1 ……;
Run;
较为有用的可选项有:
(1)noduplicates/noduprec/nodup,在排序之后,检查和删除相邻的重复观测
注意:此选项不同于nodupkey,它比较的是整个观测,而不仅仅是by的关键值
(2)nodupkey,检查和删除by的关键值重复的观测
例几个记录组合信息
proc sort data= out=lstkinfo;
by stktype;
data a;
set lstkinfo ;
by stktype;*股票类型;
if first. Stktype then num=0;
num+1;
keep stktype num ;
if then output;
run;
累加语句
*
上机作业(3)
去国泰安下载2011年A股的股票市场交易数据库
(1)将该数据集导入库 SAS 的逻辑库GTA_sas;
(2)按市场类型统计数据集中的股票数量,年个股交易股数和年个股交易天数的平均值,最小,最大值.
PROC SQL
通过调用SAS的SQL过程使用SQL语言
PROC SQL继承了SQL,所以和其它SAS过程步有一定的区别
PROC SQL持续运行直至遇到QUIT语句、DATA步,或其它SAS过程。因此,不用在每个SQL语句中重复PROC SQL
SQL 过程语句有多个子句
SELECT语句在检索数据的同时会在输出窗口输出数据,使用NOPRINT选项可以阻止该项输出
用ORDER BY语句可以代替SORT过程来完成排序
RUN语句在PROC SQL语句中不起作用
PROC SQL
SELECT语句是PROC SQL的主要工具。使用SELECT语句可以识别、检索和操作表中的数据,使用SELECT子句可以设定查询条件
语句格式
PROC sql [outobs=n];
SELECT [DISTINCT]目标字段/列 表
[INTO 宏变量列表]
FROM 数据源
[WHERE sql表达式]
[GROUP BY分组字段列表 ]
[HAVING sql表达式]
[ORDER BY 排序字段表】;
QUIT;
例 算出A股市场股票2011年的交易天数
proc sql;
create table a as
select stkcd, count(*)as trday
from
where '1jan2011'd<=date<='31dec2011'd
group by stkcd
having substr(stkcd,1,1) in ('0','6') or substr(stkcd,1,2)='99';
quit;
股票代码|Sto
ck Code trday
-----------------------------------
000002 212
000007 241
000011 230
000016 239
600601 241
600604 232
600651 239
600653 240
proc sort data= where '1jan2011'd<=date<='31dec2011'd and substr(stkcd,1,1) in ('0','6') or substr(stkcd,1,2)='99‘out= a;
by stkcd;
data a;
set a;
retain trday ;
if =1 then trday=1;
else trday+1;
by stkcd;
if last. Stkcd then output;
proc print data =a;
var stkcd trday;
run;
小结
建立SAS数据集的方法
数据流
DATA语句; INPUT语句; [其它数据步语句;] CARDS; ;
外部文件
DATA语句;
INFILE语句;
INPUT语句;
[其它数据步语句;]
Proc import datafile=‘路径+文件名’ out=数据集 [DBMS=标识名][replace];
…Run;
菜单
小结
数据集的复制与修改
SET语句把一个已有数据集复制到一个新数据集,同时还可以进行修改
格式一
DATA <新数据集名>;
SET <数据集名>;
[KEEP <欲保持的变量名列表>;]
[DROP <欲丢弃的变量名列表>;]
[IF <条件> [THEN <语句>];]
RUN;
格式二
DATA <新数据集名>;
SET <数据集名>[<选项>];
[IF <条件> [THEN <语句>];]
RUN;
小结
拆分数据集
SET和OUTPUT语句可以根据某一分类原则把数据行分别存放到不同的数据集
DATA <新数据集1> <新数据集2> …;
SET <数据集名>[<选项>];
[WHEN(<条件1>) OUTPUT <新数据集1>;]
[WHEN(<条件2>) OUTPUT <新数据集2>;]
…
RUN;
数据集的纵向合并
DATA <新数据集名>;
SET <数据集1>[(IN=<变量名1>)] <数据集2>[(IN=<变量名2>)] …;
[IF <变量名1> = 1 THEN <变量名>=<值1>;]
[IF <变量名2> = 1 THEN <变量名>=<值2>;]
RUN;
小结
数据集的横向合并
DATA <新数据集名>;
MERGE <数据集列表>;
[BY <变量1> [<变量2>…]];
RUN;
PROC sql [outobs=n];
Create table 表名 as
SELECT [DISTINCT]目标字段/列 表
[INTO 宏变量列表]
FROM 数据源
[WHERE sql表达式]
[GROUP BY分组字段列表 ]
[HAVING sql表达式]
[ORDER BY 排序字段表】;
QUIT;
一般来说,SAS数据文件又分为:
普通的SAS数据文件:SAS格式的数据文件。
接口数据文件:以其它数据软件格式储存数据的数据文件。SAS提供对应的引擎来对这些文件中的数据进行读取和编写,如ORACLE DB2,SYBASE,ODBC,BMDP,SPSS和OSIRIS。
SAS视图一般分为两种:
Native View, 由数据步或者SQL过程创建。
Interface View, 由SAS/ACCESS软件创建。Interface View可以读写其它数据库管理系统(DBMS)中的数据库,如DB2或 ORACLE数据库等。
Data 数据集名称/ view=数据集名称;
… SAS语句….;
Run;
proc sql;
create view as select * from ;
quit;
PROC SQL视图为一个带有名称的PROC SQL查询。它可以读写的数据源同数据步视图。
*
数据集的结构分为两部分:描述部分和数据部分。描述部分包括了对数据集的结构定义,具体有数据集的名称、建立的日期时间、变量和观测的个数、变量属性及其他信息,通过描述部分,一个数据集的基本框架就被确定下来了。数据部分用于存储具体数值。
在SAS数据集中,列(column)被称为变量(variable),行(row)被称为观测(observation);可能在有些软件系统中,列被 称为属性(attribute),行被称为记录(record),也就是概念上观测相当于记录,不过在SAS中记录(record)通常用来指用做输入的 文件或数据块中的行,并不一定与观测一一对应,可以是一个记录对应多个观测,或者多行记录对应于一个观测。严格来说,统计上使用变量与观测是正确的。
Tips:这里还是说一下SAS的变量命名规则: ·首字符要以字母或者下划线开始; ·名称中只能包含字母、数字和下划线; ·变量名可以是大写,可以是小写,也可以是混合写的,但是SAS会当作是同一个变量名,也就是大小写不敏感; ·不要与系统保留的字段同名,比方_N_; ·变量名长度,是32位,版和版是8位; 说明:其实这些规则同样适用于命名数组、逻辑库、数据集、宏变量、宏名、函数等等,不同的地方是长度限制可能不一样,具体可以查看帮助文件。
3.变量(variable) 变量的命名规范跟其他语言基本相同,要以字母或下划线开始,不要使用系统保留的名称等;需要指明的是SAS的变量名是大小写不敏感的,最多32个字符,不 像SPSS一样,SAS并不支持中文变量名,但是可以用变量标签(label)对变量进行说明,变量标签支持中文,最多256个字符。 自动变量(automatic variable) 自动变量是在程序中被SAS自动创建的变量,这些变量名有着特殊的用途,下面介绍一下在data步中的两个自动变量,过程步中的自动变量在具体的过程中讲解。 _N_ _N_在data步开始执行前被初始化为1,然后data步自循环一次该变量增加1,也就是_N_代表data步循环执行的次数。这个变量存在于每一个数据集中,但是一般不会显示也不会被打印。 _ERROR_ _ERROR_在data步执行前被初始化为0,当data步执行过程中遇到错误时就会自动被置为1,而且会在LOG窗口中打印出来,这样有利于调试程序的时候定位错误出现的位置以及出现错误时采取相应的处理。
2.数据类型(Data type): 我们在学其他编程语言的时候可能学到很多数据类型,但是SAS将各种各样的数据简化为两种类型,即数值型(numeric)和字符型 (character)。那么这里就有问题了,像C语言那样丰富的数据类型而且实际上也存在各种类型的数据,SAS是如何处理的呢?这里就是SAS的特别 之处了,两种基本的数据类型外加丰富的数据格式就能识别和显示各种各样的数据了,但是前提是你要告诉SAS怎么去识别和显示数据,按照什么格式去识别和显 示数据,这里就涉及到SAS里面一个比较复杂的问题,数据格式,输入数据需要指明输入格式(informat),输出数据需要指明输出格式 (format),这个内容请参看后面的有关章节,这里先了解一下。 另外一个问题,从数据类型角度我们把语言分为强类型的和弱类型,强类型的比方说C语言,在使用变量之前得先定义变量,而且必须指定一种数据类型。而SAS 则是弱类型的,也就是在用使用变量之前是不需要定义的,变量的类型取决于数据的类型或者预先定义的格式。这个在后面的程序中可以更多的感受到。
数值变量是SAS系统以浮点(floating-point)方式存储的数据变量,数值变量包括日期和时间。
数值变量的值只能是数值。
字符变量可以由阿拉伯字母、数字0-9以及其它一些特殊字符组成。
字符变量的值可以是字符、字母、特殊字符和数值。字符变量名后跟一个美元号($)表示该变量是字符型而不是数值
变量的属性(attribution) 通常说起变量,就是指变量的名称。其实变量名只是变量的属性之一。 打开一个数据集,然后选定任意一列,点击右键查看属性就会发现第一个选项卡是general,这个对话框里面的内容即为变量的属性,包括变量名、类型、标签、长度及其输入输出格式。 变量名用来标识变量,区分不同的变量;类型是指变量是字符型还是数值型;标签用来补充变量的信息,特别是SAS变量不支持中文命名的情况下可以将中文说明 写在变量标签里;长度是变量所有容纳的最多字符的字节数或最大数值的字节数,在没有指定的情况下通常由input语句读取第一个观测值确定下来,当然可以 用语句事先指定;输入输出格式用来输入输出数据,让SAS能对内部与外部的数据能实现转换,
变量的长度是指存贮变量值的字节数。缺省长度为8个字节。
变量的输人格式是指SAS系统读人变量值的方式。
变量的输出格式是指SAS系统展现变量值的方式。
变量的标签是指变量名的描述性标识,它至多可用256个字符
如何创建变量?(Create Variables) SAS是弱类型的语言,使用变量前不需要定义,可以在数据步中直接使用变量,当然更多的情形是在用input语句读取数据时。如果是要预先定义变量的格式,则用format语句、informat语句、length语句或attrib语句都可以创建变量。
变量列表(variable list) 在一个数据集中,变量按照第一次的出现的顺序(也就是在数据集中的顺序)被SAS系统存储为一个系列,这个系列就是一个完整的变量列表。而实际上我们在操作变量的时候只需要选取其中部分变量,而有了这个完整的变量列表就可以在许多语句中使用缩写的变量列表了。 在SAS中,可以使用4种缩写的变量形式: (1)数字系列 如果有一系列变量是这样定义的,相同的名字后面加上一个连续的数字,就可以采用数字系列的缩写,如 x1, x2, x3, …, xn可以缩写为 x1-xn (2)变量名系列 变量名系列就依赖于变量在SAS数据集中出现的顺序,如 x--a 就表示从x变量开始一直到a变量结束这一系列变量,结合自动变量就可以更加灵活的使用变量列表,如 x-numeric-a 表示从x变量开始到a变量结束之间的所有数值型变量, x-character-a 表示从从x变量开始到a变量结束之间的所有字符型变量, (3)前缀名系列 如果有一系列变量具有相同的前缀名,比方说SALES_JAN, SALES_FEB, SALES_MAR… 则可以使用下面的形式表示这一系列变量名, sales: 打印这些变量,则 proc print; var sales:; run; 对这些变量求和,则 sum (of sales:) (4)特殊的变量列表 包括三个自动变量代表的变量列表 _ALL_ 全部变量 _CHARACTER_ 全部字符型变量 _NUMERIC_ 全部数值型变量
4.常量(constant): 常量与变量是一个相对的概念。变量是用来存储数值的,而且是可以重新赋值的,而常量是用来表示固定的值,是不可改变的。常量可以是是一个数字、字符串或者其他特殊记号。常量和变量还有运算符一起是构成表达式的元素。 常量的类型,SAS使用四种类型常数,另外,十六进制常量单独列出来讲。
字符常数(character) 字符常数是用引号(单引号/双引号)引起来的1-32767个字符组成的字符串,如, 'Tom', "Tom"等 如果是字符串中包含引号,该怎么办? 两种方法 方法一:如果包含单引号,怎么用双引号引起来,相反,则用单引号引起来,如, "Tom's" 表示Tom's 'Tom"s' 表示Tom''s 方法二:对包含在字符串中的引号可以写成连续的两个引号,如, 'Tom''s' 表示Tom's "Tom""s"表示Tom''s
数值常数(numeric) 数值常数就是指在SAS语句中的数字,可以包含数字、小数点、符号和特殊记号E,如, 1, -5, +49, , 01, , -10等等 注意:若一个数值常数大于10E32-1,则必须表示成科学计数法。
日期、时间和日期时间数值常数(data, time, and datetime) 为了将日期、时间或日期时间值表示成常数,使用在输入格式和输出格式中被使用的相同的记法,TIME., DATA.和DATATIME.。格式值用单/双引号引起来,并跟随一个表示格式的字母D(日期)、T(时间)或DT(日期时间)。如, '1jan2006'd; '9:25't; '9:25:19pm't; '18jan2002:9:27:05am'dt;
十六进制常量(hexadecimal) 十六进制字符常量:是用引号引起来的一串偶数个的十六进制字符,并跟随一个X,如, '534153'x 而且可以在这一串十六进制字符中使用逗号分隔使得易读但不影响十六进制常数的值,只是这里的逗号必须按偶数个来分隔。如上面的常数可以写为, '53,41,53'x 十六进制数值常量:通常,十六进制数值常数用一个数字开始(一般是0),紧跟着很多十六进制位,并用字母x结尾。这个常数可以包括最多16个有效的十六进制位,如, 0c1x, 9x
AS函数调用有下面三种形式: function-name (argument-1<. . .,argument-n>) function-name (OF variable-list) function-name (OF array-name{*})
至于自定义函数,SAS并不支持自定义函数,不过它有相应的其他语法结构来实现这个功能,那就是宏。有关宏更多详细的信息请参看后面有关的章节。
5.运算符(operators) 在SAS中,算符包括运算符、括号和函数。其中运算符可以分为两种,前缀运算符和中缀运算符,中缀运算符包括算术、比较、逻辑、特殊运算符。
前缀运算符(prefix operator) 前缀运算符可以用于变量、常数、函数以及括号括起来的表达式,包括正号(+)、负号(-)及非运算(NOT)。如, +y -25 -cos(angle1) +(x*y)
中缀运算符(infix operator) ·算术运算符:+, -, *, /, **, 加减乘除在各种语言里面都是一样,只是乘方可能有些差别,SAS是使用**; ·
比较运算符:= (EQ), ^=(NE), >(GT), <(LT), >=(GE), <=(LE), IN()前面这些运算符分别代表等于、不等于、大于、小于、不小于、不大于,等于列表中一个。其实平常用的话只要知道用符号就行,括号里面的字母是跟符号等价的,了解一下的好处是可以看懂别人的代码,不至于以为是变量名或者英文单词。 在SAS语法中,比较运算符是可以连用的,例如 if (90=<x<=100) then grade='A';
比较准则:
数值和字符都可以比;
结果为真赋值1,假赋值0;
字符值从左到右逐个按ASCII码排列序列进行比较;
缺失值参加比较时,它比任何有效值都小。
··逻辑运算符:&(AND), |(OR), ^(NOT), 分别代表与或非,括号里面单词跟符号等价。
其他特殊运算符:<>, ><, || <>(max)取最大值,例如: a=; b=; min=(a<>b); 则min变量等于。 ><(min)取最小值。 ||(连接):用来连接字符串,例如: a="Hello, "; b='SAS'; c='System!'; new=a||b||c; 则new变量等于'Hello, SAS System!'
变量的类型转换(Type Conversions) 对于变量类型之间(字符型与数值型)的转换,SAS有一套规则如下, ·如果字符变量与数值运算符在一起使用,则SAS将字符变量转换为数值; ·如果字符变量与数值变量进行比较符运算,则SAS将字符变量转换为数值; ·如果数值变量与字符运算符在一起使用,则SAS将数值变量转换为字符; ·如果在一个赋值语句中,左边跟右边的类型不一,则将右边的类型转换成左边的类型; 以上这些转换规则是SAS自动完成的,并且在LOG窗口中打印一个警告信息,指示这个转换发生的地方。以上这些情况在编程的时候最好是不要出现,因为虽然 是自动完成,但是转换的结果不一定是我们预期的,比方说字符变量转换成数值时产生的是一个无效的数值,结果就造成了缺失值,当然SAS会在LOG窗口中提 示出错信息,同时置自动变量_ERROR_的值为1。
程序数据矢量(program data vector)中包含了所有变量的信息,每个变量就是这个矢量的一个维度。程序数据矢量相当于一行临时数据,它充当了从输入到输出的中转站,第 7~9 步的数据操作就通过它来进行。在每一轮循环的开始,程序数据矢量中的数据变量的值都被自动设为缺失值。程序数据矢量中除了包含了数据操作涉及的所有变量 外,还隐含了两个自动变量 _N_ 和 _ERROR_。_N_ 标识了数据的行号,在每一轮循环开始时自动加 1。_ERROR_ 是个二元变量,默认为 0,遇到错误(数据读入错误、格式转换错误、数学计算溢出等)时值为 1。
输入缓存(input buffer)只有在通过外部文件读入数据时才会用到,而从 SAS 数据表中读入数据就不会用到。在通过 INPUT 语句读入外部数据时,SAS 先一次读入一行存储在输入缓存中。
为什么程序的最后都要加一句run?这个问题还不太好解释,每一个程序应至少在最后有一个run语句,表明前面的所有语句可以提交运行了,如果没有这一 句,SAS会以为你后面还有语句要输入,从而将一些非立即执行的语句保留在编译缓冲区中,等待后续命令发出后一起执行,这有时会把事情弄得很糟。出于减少 麻烦的需要,建议大家养成在每一个数据步或程序步后都写上一句run的习惯。
Submit命令和run语句有什么区别?这是初学者最爱问的一个问题,也同样是一个难以回答的问题。简单地讲,run是程序语句,可在程序中多次出现, 它表示前面的程序段已经全部写完,可以作为一个或几个整体提交运行了,而Submit则是SAS命令,只在最后程序运行的时候发出,表示将程序正式提交运 行。如果你还不明白,那么我还是来给你打个比方,run语句是你对SAS说“我想让您做的就是这些了”,而Submit命令就是对SAS说“现在开始为我 做这些事,好吗”,明白了吗?
数据步的自循环(Data step's Built-in Loop): 如果要学习SAS,最首先要掌握的就是SAS程序的结构及运行机制,而其中最关键的又是data步的自循环,如果不能够理解这一点,那后面的内容就如空中楼阁,是不稳固的。 首先,数据步程序是一行一行的执行,这就意味着变量在使用之前必须创建。这一点很容易理解,几乎所有的语言都是如此。 其次,数据步程序是一个观测一个观测读取。当程序正确的执行到数据步的最后一个语句时,就将该次读取的一条观测写入数据集,然后又重新开始执行数据步,继续读取观测值,这就是数据步的自循环。也就是相当于数据步的最后隐含包括了两个语句,output与return语句。 第一个问题是读取的数据在执行到最后写入数据集之前保存在哪里?input语句执行后,SAS将读取的数据暂时先保存在内存缓冲区,然后执行后面的语句, 后面的语句可以对暂存在内存缓冲区中的变量值进行修改,到最后才将整条数据写入数据集,写入数据集的数据就不能在当前data步中再修改。 第二个问题,在data步中间使用return语句会怎么样?自然是按照用户的意思进行执行,当遇到return语句时就重新执行数据步,读取下一条观测值,而跳过return后面的语句。 第三个问题,在data步中间使用output语句呢?那么程序会在执行到output语句那里就把放在内存缓冲区里面的观测值写入数据集,而不是等到整个data步执行完了再写入。 弄清楚这三个问题了应该弄明白data步的自循环是怎么回事了。而且会发现原来data步不一定是一次只可以读取一条观测,完全可以两条或者更多条一次的读取,比如重复input语句,并且在每条语句之后加一条output语句,就可以实现了。
中data步语句又分为五类:文件操作语句、运行语句、控制语句、信息语句、窗口语句。 ·文件操作语句:用于操作文件,这些文件用于输入数据集;或者用于输出。 ·运行语句(动作语句):用于创建、修改或删除变量;或者用来操作记录;或者用来错误信息。 ·控制语句:实现流程控制的语句。 ·信息语句:给出关于数据集的附加信息,包括数据集中变量的信息。 ·窗口语句:用于显示输出或者接受输入。 大部分的语句将在本教程中相应位置讲到,想快速获得其用法请参看附录2——SAS常用语句一览。
特殊数据集 ·空数据集(_NULL_) 如果执行data步只是使用put语句输出一些结果,没有必要创建数据集,则可以使用空数据集,如 data _NULL_; 这相当于执行data步时创建了一个数据集,但是这个数据集并不建立任何变量和写入任何记录,空数据集的好处是可以加快执行效率,减少占用计算机资源。 ·默认数据集(_LAST_) SAS将最近创建的数据集另外保存在_LAST_数据集中,当执行data步或proc步没有指定作为输入的数据集时,系统会调用这个默认的数据集;也可以用options语句来指定默认数据集,如options _last_=;。 默认数据集相当于一个缓冲区,总是会被新建的数据集所覆盖。 ·自动命名数据集(Automatic Naming Sets) 如果在数据步data语句后没有新建数据集也没有空数据集,如, data; 则系统自动会建立以DATA为前缀的数据集,data1, data2…datan等
括号中的数据集选项可以对数据集进行如下操作:
重新命名变量;
选择需要的观测;
输出数据集中保留或删除的变量;
数据集加密
(2) 数据集选项 SAS数据集选项有37个之多,共分为5大类,分别是控制数据集,控制变量,控制记录,控制索引及其他。下面就一些常见的选项进行介绍,更多详细准确的信息请参看帮助文件。 ·控制数据集 label= 给数据集指定一个标签 index= 给数据集定义一个索引 type= 对一个特殊结构的数据集规定这个数据集的类型 pw= 对SAS文件指定一个只读、写入和修改的口令 read= 对SAS文件指定一个只读的口令 write= 对SAS文件指定一个写入的口令 alter= 对SAS文件指定一个修改的口令 ·控制变量 rename= 给某些变量改名 keep= 处理或输出的数据集中保留一些变量 drop= 从处理或输出的数据集中删除一些变量 ·控制记录 firstobs=m 从第m个记录开始处理 obs=n 到第n个记录结束处理 where= 选择满足规定条件的记录 ·其他选项 sortdeby= 提供数据集已经被排序的信息,使用这个选项可以加快某些过程的处理速度,如sort, sql以及by语句等。
INPUT语句 用于向系统表明如何读入每一条记录。它的主要功能有:
读入由语句指定的数据列。
为相应的数据域定义变量名。
确定变量的读入模式。
7.行固定标识符(Line-Hold Specifiers) 行固定标识符在下面两种情况下将指针控制在同一个数据行: ·一个数据行用多个input语句读取数据(@) ·一个数据行含有多个观测值(@@)
@ (trailing at-sign, 单尾符) 通常,在Data步的每个input语句读取一个新数据行,@的作用将当前数据行固定下来,直到遇到下一个input语句才解固,这样一来可以让多个input语句读取同一个数据行。试比较下面两段代码, data test1; input a b; input c d; cards; 1 2 3 4 5 6 7 8 ; 执行结果test1数据集是 a b c d 1 2 5 6 而在将第一个input语句改为input a b @; 则结果是, a b c d 1 2 3 4 5 6 7 8 我想这样解释还是比较清楚了,但是可能还不明白这个符号到底有什么意义,前面的语句直接写成input a b c d;就好了,何必这么麻烦呢?下面一个例子就会领略到它的真正用处, data freeways; infile 'c:\MyRawData\'; input type $ @; if type = 'surface' then delete; input Name $ 9-38 AMTraffic PMTraffic; run; 可以选择性的读取数据。
@@ (double trailing at-sign, 双尾符) 通常情况下,SAS会认为你的每一个数据行仅仅代表一个观测记录;如果不是这样,手头上的数据恰恰是连在一起的,一个数据行不止一条观测记录,则需要用到@@,我觉得《The Little SAS Book》这本书将这个符号解释的很形象, This line-hold specifier is like a stop sign telling SAS, "Stop, hold that line of raw data." SAS will hold that line of data, continuing to read observations until it either runs out of data or reaches an INPUT statement that does not end with a double trailing @. @@就像一个停止信号,告诉SAS,你现在给我打住,不要把指针往下面一行移动了,读取下一条记录还是从现在的位置继续开始,除非这一行数据读完了,或者遇到不带双尾符的input语句。 例如: data test; input name $ age @@; datalines; John 13 Monica 12 Sue 15 Stephen 10 Marc 22 Lily 17 ;
Tips:之所以称之为单/双尾符,是因为它们必须放在input语句的最尾端。
3.列表方式 (1)列表方式的语句格式 INPUT <pointer-control> variable <$> <&> <@ | @@>; INPUT <pointer-control> variable <:|&|~> <informat.> <@ | @@>; (2)什么情况下应用列表方式? ·输入的值彼此之间至少有一个空格隔开; ·用小数点(.)而不是空格表示丢失值; ·字符型数据的最大长度默认是8个字节,除非在length,attrib或informat语句中规定了字符型变量的长度; (3)列表方式的特点 ·列表方式输入是使用最多的功能最强大以及最为方便的输入方式; ·在指针控制符和格式修饰符的帮助下,列表方式可以读取几乎所有格式的数据; 基于以上两点,也许这就是列表方式也被称为自由格式的原因。 (4)列表方式的特殊情况——格式修饰符 ·: 标明从非空格开始读取变量值直到遇到以下情况:下一个空格列;预先定义的变量长度已经读满;数据行结束; 比如下面的例子,第一列数据最长是15个字符但不是一样长,如果小于15个字符的数据值可能会读到下一个数据值,那么就需要用到:符号。 data test; input lastname :$15. ; cards; Smith 123 Highway Longlastname 527 Avenue ;
·& 指明字符型输入值可能嵌有一个或几个空格,因为空格在正常情况下用来分割不同的数据值; 例如: data test; input name $ & score; cards; Joseph 11 Joergensen red Mitchel 13 Mc Allister blue Su Ellen 14 Fischer-Simon green ; 注意,基于&符号的特性,因而包含空格的数据需要与其后面的数据用两个或两个以上的空格隔开。 上面是包含一个空格的情况,那么包含两个或更多的空格呢?经过作者多次测试也没有发现SAS怎么去解决这个问题,还真不知道SAS到底支持不支持读取包含多个空格的数据。
·~ 指明当读字符值时,INPUT语句用一种特殊方法处理单引号和双引号及分隔符。用此修饰符,当把引号内的字符值赋予变量时没有将分隔符作为分隔处理,并保 留这些引号。此选项仅当在INFILE语句中与选项DSD一起使用时才有效;否则它被忽略。当用户在INFILE语句中使用选项DSD时,若INPUT语 句中没有“~”修饰符(缺省时),在引号内的字符变量值赋结变量之前把引号去掉;若使用修饰符“~”,则引号被保留作为这个值的一部分。就像使用 “&”和“:”修饰符一样,用户在有输人格式或不用输人格式时都可以使用修饰符“~”。 例如: data scores; infile datalines dsd; input Name : $9. Score1-Score3 Team ~ $25. Div $; datalines; Joseph,11,32,76,"Red Racers, Washington",AAA Mitchel,13,29,82,"Blue Bunnies, Richmond",AAA Sue Ellen,14,27,74,"Green Gazelles, Atlanta",AA ;
2.列方式 (1)列输入方式的语句格式 INPUT variable <$> start-column<-end-column><.decimals><@|@@>; 说明: variable 变量名 $ 跟在变量后面,表明这个变量是字符型变量 start-column 起始列号 end-column 结束列号,如果变量值只包含一列,则可省略 .decimals 如果输入值中没有包含一个隔开整数部分与小数部分的小数点,decimals用来显性的指明小数部分 @ 单尾符 @@ 双尾符 举例说明: input name $ 1-10 pulse 11-13 waist 14-15 gender $ 16; (2)什么情况下应用列输入方式? ·变量值在所有的数据行上出现在相同的位置(列)上; ·数据是标准的数值型或字符型格式; (3)列输入方式的特点 ·输入值可以按任何顺序读取,而不管它们在记录中什么位置; ·字符型数据中可以在中间嵌套空格; ·字符型数值可以输入1-32767个字符; ·数值或数值中的一部分可以再次被读取,例如: input id 10-15 group 13; (4)列输入方式如何处理缺失值和空格? ·空区域或只有(.)的区域被看成缺失值; ·列输入方式忽略在所指定区域中开头和结尾部分的空格,如果你想保留数值型数据中包含作为0的空格,或者字符型数据中开头或结尾的空格,那就需要使用格式输入方式
4.格式化方式 (1)格式化方式的语法格式 INPUT <pointer-control> variable informat. <@ | @@>; INPUT <pointer-control> (variable-list) (informat-list) <@ | @@>; INPUT <pointer-control> (variable-list) (<n*> informat.) <@ | @@>; 说明: ·语法格式一是标准格式,即在变量后面紧跟一个输入格式来指明该变量读取数据时的格式,例如: input item $10. jan comma5. feb comma5.; ·语法格式二和三都是变量列表方式,用于很多变量都采用相同格式的情况。例如: input (name score)(:$10 ); 如果变量列表的格式都是一样的,可以只写一个格式,例如下面两个input语句是等价的, input (score1-score5)(4. 4. 4. 4. 4.); input (score1-score5)(4. ); <n*> informat. 给出读上述变量列表时所使用的一些输入格式。“n*”用来规定在输入列表中后面的输入格式重复n次。例如: 上面的input语句可以写成 input (score1-score5)(5*4. ); 是不是发现这个格式似乎没有存在的必要,看了下面的例子就知道它的用处了, input (g1-g5)(3*, 2*); Tips: 格式列表各格式之间是可以用逗号隔开的,也可以用空格隔开;但是变量列表各变量之间只能用空格隔开。 (2)什么情况下需要使用格式化输入? 顾名思义,格式化输入适用于读取非标准数据、非默认长度数据或者需要统一格式的数据
所有输入格式必须包含一个点(.)作为名字的一部分;
对于省略W和D值的输入格式,使用系统缺省值
3.输入格式的类型 ·数据输入格式用于告诉SAS系统去读取数值数据到数值变量中; ·字符输入格式用于告诉SAS系统去读取字符数据到字符变量中; ·日期时间输入格式用于告诉SAS系统去读数据值到表示日期、时间和日期时间的变量中; ·列二进制输入格式用于告诉SAS系统读取列二进制数或多穿孔格式存储的数据; ·使用proc format扩展的用户自定义输入格式。
4.数值变量的格式 数值变量的输入格式有40种之多,这里只能对常用的一些格式做一些介绍,至于更详细准确的信息请查看帮助文件。 ·输入格式:读取标准数据 说明:其中w是给定的包括这个值域列数的宽度值; d 代表小数点右边的位数,范围是0-31,如果是读取包含小数点的数值,则忽略d值; 可以读取任何位置的数值,可以读取包含小数点和用科学计数法表示的值;数值的前面、中间或后面可以有空格,但是读取时会自动去掉空格。 如读取23,input x ;结果为 ; 带空格时,如读取2 3,input x 3.;结果为23; 读取,input x ; 结果是,有小数点的数据忽略d值,所以是而不是 注意这里是说有小数点就忽略d值,并不是有小数位才忽略d值,例如: 读取,input x ;结果为234000,而 读取234000,input x ;则结果为23400.
·输入格式:转换空格为0 格式恰恰是对格式的补充,读取数据时,将数值域中间或尾部的空格用0填充 如读取'34 ',input x 4.;结果为3400,而input x ;结果为340
·输入格式:移走数值中被嵌入的字符 输入格式将输入数值中被嵌入的字符(如逗号、空格、$、%、破折号和圆括号)移走,而且将带有圆括号的数值作为负数读取。 如读取(5,000);input x ;结果为-500; 这里的圆括号并不需要将数值括起来的一对括号,只要左边括号SAS就会将其当负数处理,如 用input x ;读取上面数据结果为-50; 输入格式移走被嵌入的字符可以是混合的,如 用input x comma7.读取(32-4,1结果为-3241;
·输入格式:读科学计数法数值 通常格式是不必要的,因为输入格式能够读取用E表示法的数值。
5.字符变量的格式 字符变量的输入格式总共有18种,常见的有$w.和$charw.,更多的字符输入格式请参看帮助文件。 ·$w.输入格式:读取标准字符数据 默认情况下,SAS读取字符数据的长度最多为8个字节,而要读取更长的字符数据则需要用到该格式,w值给出包括字符值的这个域的列数。$w.输入格式会自 动清除字符值开头的空格,也就是读取字符数据时会自动的左对齐。另外,如果读取的数据中仅仅包含空格和单独一个点,则SAS会将其转换为空格,因为它将一 个点看作缺失值;而多个点则按正常字符读取。 如用input name $7.; 读取'? John '结果为'John ';当格式中宽度比数据实际的宽度要宽时,则在后面填充空格, 如用input name $10.; 读取' John'结果为'John '; 用input name $3.; 读取' . '结果为' ';而 用input name $3.; 读取'. .'则结果为'. .'。
列范式
data a1;
input num $1-3 name $5-8 weight 10-13;* input num $1-3 name $5-8 weight 10-13 .1;
cards;
081 kong
082 wang
;
proc print;
run;
格式方式
data a1;
input num $ 3. name $ 5. weight ;
cards;
081 kong
082 wang
;
proc print;
run;
INFILE语句 用于从外部文件读入数据,必须出现在INPUT语句之前。它的主要功能是:
确定一个包含原始数据的外部文本文件。
语句与infile语句结合 语法格式 INFILE file-specification <options > <operating-environment-options>; options options可以更好地控制打开文件,infile语句的选项有31项之多,这里只选取一些常用实用的予以讲解,更多详细准确的用法请参考帮助文档。 FIRSTOBS=record-number 从指定的行开始读取记录 OBS=record-number 读取到指定的行结束 DELIMITER=delimiters| DLM=delimiters 指定一个字符或多个字符替换空格作为分隔符(对列表方式输入而言),delimiters可以是分隔字符表也可以是分隔变量。 数据中使用不同的字符来分隔数据,将出现的所有单个字符连在一起用引号引起来即构成分隔字符表,例如: data bp; infile datalines delimiter='/,'; input sbp dbp @@; datalines; 120/80, 115/70, 105/75 150/95, 135/85, 100/60 ; 也可以先用变量定义分隔字符表,然后在delimiter选项中使用该变量,例如: d='/,'; infile datalines delimiter=d;
data zachary;
infile cards dlm=',';
input x@@;
x1=put(x,);
put x1;
cards;
,,,,,,,,,
;
run;
是否还记得前面讲过的,数据集的结构分为两部分:描述部分和数据部分。 首先,SAS会逐个读取set语句中每个数据集的描述部分,看看都有哪些变量,然后创建一个数据向量,相当于一个缓冲区,包含所有源数据中的变量以及data步中set语句之后创建的变量。 然后,SAS开始读取set语句中第一个数据集的第一条记录,先写入前面创建的数据向量,然后执行其他语句,data步结束时候将数据向量保存的值写入目标数据集。就这样逐个数据集逐个记录进行读取写入,直到最后一个数据集的最后一条记录。 回到前面那个问题,当各数据集变量不一致时,当某个数据集缺少其他数据集中的变量值时,那就没有给数据向量赋值,该变量值就为缺失值。 相 同的变量如何处理呢?似乎这个问题问的很废话,可是如果变量只是名称相同而属性不同呢,SAS会以第一次读取到这个变量的属性(变量标签,长度等)为 准,也就是说set语句中,排在前面的数据集优先。如果变量长度不足以存储后面数据集中同名变量的变量值,就会将多余的长度截断;如果类型不匹配,就会产 生错误,不产生新的数据集,并且在LOG窗口中予以提示。 另外,如果在set语句之后还有对源数据集中的变量值进行修改,那么目标数据集中的变量值是修改过的数据集。
横向合并即是变量的合并,按照记录号的顺序或者某个关键变量的数值将不同的数据集中的不同变量合并在一起组成新的数据集,新数据集中的变量数是所有源数据集中不重复变量的总和。
不用BY语句时,MERGE 语句是将按观测的序号进行合并。新数据集中观测值数为 MERGE语句中所列出的各数据集中观测值数的最大者。如果某个数据集的观测值用完,则该数据集观测值各变量的值由缺项值代替。
如果一个变量在多个数据集中出现,则在新的数据集中,该变量名只出现一次。且该变量的值为在MERGE语句中列在最右边的有相应变量数据集中的值。
合并的运行机制。
首先,SAS读取merge语句中各数据集的描述部分信息,弄清楚都有哪些变量,然后创建一个数据向量,相当于一个缓冲区,包含所有源数据中的变量以及data步中merge语句之后创建的变量。
然后,就开始依次读取各个源数据集中的第一条记录,写入这个数据向量,然后执行merge语句之后的data步语句,执行到data步结束时将数据向量中的数据写入目标数据集中。就这样逐个数据集逐个记录进行读写,直到读取指针到达包含最多记录的数据集的最后一条记录。
通过了解SAS合并数据集的机制,就很容易理解,为什么各数据集含有相同的变量最后新的数据集中的取值是最有一个源数据集中的值。
一对一合并
不用BY语句时,MERGE 语句是将按观测的序号进行合并。新数据集中观测值数为 MERGE语句中所列出的各数据集中观测值数的最大者。如果某个数据集的观测值用完,则该数据集观测值各变量的值由缺项值代替。
如果一个变量在多个数据集中出现,则在新的数据集中,该变量名只出现一次。且该变量的值为在MERGE语句中列在最右边的有相应变量数据集中的值。
匹配合并
为实现匹配合并,对于所有要合并的数据集要求它们至少有一个变量是相同的,并且每个数据集都应按该变量排过序。BY语句被用来标识匹配变量。
对匹配变量的处理(BY变量)
匹配合并操作将从观测值具有当前BY值的每一个数据集中合并所有数据。
当一个输入数据集用尽一个BY组中的观测值时,在该BY组中的最后一个观测的值被保留且用来同其它数据集的该BY组中的剩余观测值的值合并。如果一个输入数据集不包括某一BY组中的任何观测值,则该数据集提供缺项值给新数据集。
新数据集的变量即原数据集的变量,观测值个数是各个数据集中观测值个数的和。
变量不同
新数据集将包括所有的变量。从某个数据集获得的观测值中,对于该数据集中没有的变量将用缺项值填充。
清空数据集
.流程结构:顺序、选择、循环 程序语言中的流程结构用于控制各计算操作执行的次序。每一种结构化语言编写的程序都由由顺序、选择、循环三种结构构成,SAS也是如此,不同语言之间只是关键字不一样罢了。
顺序结构就是指程序执行是按照代码书写的顺序进行的。下面主要讲选择和循环结构。
选择结构 语句一: IF expression THEN statement; <ELSE statement;>
语句二: SELECT <(select-expression)>; WHEN-1 (when-expression-1 <..., when-expression-n>) statement; <... WHEN-n (when-expression-1 <..., when-expression-n>) statement;> <OTHERWISE statement;> 根据它的语法结构发现有两种写法,举例如下 既可以把表达式放在select语句这里,when语句那里只需要选择表达式的值;也可以select语句这里为空,整个选择条件放到when语句中;而不能两种方式混合使用。 方法一 select(x); when (2) put ‘two’; end; 方法二 select; when (x=2) put ‘two’; end; 错误的方法 select (x); when (x=2) put ‘two’; end; 对于select选择结构还有一点要注意的地方,就是select与end之间的程序的执行顺序,这跟其他语言(如C语言)可能有点差别,那就是只要有一个条件满足那么就会跳出选择结构,而不是继续执行下面的语句,这样一来就不需要显性的去跳出选择结构。
循环结构 语句一: DO WHILE (expression); ...more SAS statements... END;
语句二: DO UNTIL (expression); ...more SAS statements... END;
语句三: DO index-variable=start <TO stop> <BY increment> <WHILE(expression) | UNTIL(expression)>; . . . more SAS statements . . . END; 例如: do i=1 to 10; do i='01JAN90'd to '01JAN90'd by 1; do i=10 to 0 by -1 while(month='JAN'); 这个就是常见的步长型循环结构,而且还可以结合While与Until使用来终止循环。那么这里如果do后面什么都不写是否是“无限”循环了呢?留作读者思考。
语句四: DO item-1<,…item-n><WHILE(expression) | UNTIL(expression)>; . . . more SAS statements . . . END; 例如: do count=2,3,5,7,11,13,17; do month='JAN','FEB','MAR'; do i='01JAN2001'd,'25FEB2001'd,'18APR2001'd; 这个语句是SAS比较特殊的循环结构,可以对枚举的项目依次执行,终止循环就是执行完这些列举的项目。
语句五: DO over array-name; . . . more SAS statements . . . END; 例如: data test; input sc01-sc05; array s sc01-sc05; do over s; s= s*100; end; cards; ; 这个语句也是SAS比较特殊的循环结构,专用于数组,将数组的每一个元素访问一遍。
语句块 DO; ...more SAS statements... END; 有时候我们需要把很多语句放在一起执行,特别是放在选择结构和循环结构中,这相当于有些语言的一对{}。
如何跳出选择结构和循环体? continue语句:用于跳出当次循环,重新执行循环体并计算是否满足条件。 leave语句:用于终止循环和选择结构,不再执行循环语句而转到循环语句之后紧接的语句。 return语句:用于跳出当次data步自循环,重新执行data步。 go to语句与标号:用于跳转到指定标号的语句,但该语句要求与当前语句是在同一个data步中。在大多数情况下,使用go to语句的程序段完全可以用do;...end;程序块或者if…else结构来代替,而且使用go to语句会使程序显得复杂、难以理解和维护,所以建议还是少用。但是这个语句既然存在还是有一些用处的,可以用来跳出某些深层嵌套的结构,如跳出多层循环。
如果表达式为真(非零且不缺项),SAS系统继续为正在建立的观测值执行DATA 步中的语句。如果表达式的值是假(0或缺项),SAS系统马上返回到DATA步的开始,去进行另一次执行而不输出上一个观测值。
如: IF SEX=‘F’;
等同于(IF SEX=‘M’ THEN DELETE;
在结果数据集中所包含的仅仅是SEX的值为‘F’的那些观测值。
可以是数值型也可以是字符型,但若是字符型,输出格式也必须是字符型,数值型则不受限制
不会
data a;
input a $ @@;
length id $8;
id=lag(a);*上一个a;
no=input(a, ??best.);*转换为数值型
if no^=. and input(id, ??best.)=. then output;
drop a;
cards;
a23 223 bc4 36 3c5 11d 400 620
;
run;
In this example, the question mark (?) modifier tells SAS not to print the invalid data error message if it finds data errors. The automatic variable _ERROR_ is set to 1 and input data lines are written to the SAS log.
y=input(x,? );
Because the double question mark (??) modifier suppresses printing of error messages and input lines and prevents the automatic variable _ERROR_ from being set to 1 when invalid data are read, the following two examples produce the same result:
y=input(x,?? 2.);
y=input(x,? 2.); _error_=0;
data test;
input a $ @@;
length id $8;
id=lag(a);*上一个a;
no=input(a, ?best.);*转换为数值型;
if no^=. and input(id, ?best.)=. then output;
drop a;
cards;
a23 223 bc4 36 3c5 11d 400 620
;
run;
proc print;
run;
data test;
input a $ @@;
length id $8;
id=lag(a);*上一个a;
no=input(a, ??best.);*转换为数值型;
if no^=. and input(id, ??best.)=. then output;
drop a;
cards;
a23 223 bc4 36 3c5 11d 400 620
;
proc print;
run;
(1)语法格式 PROC SORT <collating-sequence-option> <other option(s)>; BY <DESCENDING> variable-1 <...<DESCENDING> variable-n>; proc sort一些常用的选项: ·数据集选项 data= 输入数据集,缺省时使用最近创建的数据集 out= 输出数据集,缺省时表示排序后覆盖源数据集 by语句 缺省情况下,是按照变量进行升序排列(ascending),降序则要显性的用descending指明。 特别的是,这两个关键字应该写在变量的前面,而其他语言可能相反,如SQL将排序关键字放在变量之后。
(3)实例 对数据集按年龄大小进行排序,相同年龄的观测仍然按原来的次序。 proc sort data=age equals; by age; run;
proc sql;
select stktype , count(stkcd)as number
from
group by stktype;
quit;
PROC SQL继承了SQL,所以和其它SAS过程步有一定的区别。
PROC SQL持续运行直至遇到QUIT语句、DATA步,或其它SAS过程。因此,不用在每个SQL语句中重复PROC SQL。
SQL 过程语句有多个子句。
SELECT语句在检索数据的同时会在输出窗口输出数据,使用NOPRINT选项可以阻止该项输出。
用ORDER BY语句可以代替SORT过程来完成排序。
RUN语句在PROC SQL语句中不起作用。
proc SQL可以用来创建、修改、删除数据集,包括操作变量和观测,甚至可以插入一条或几条记录,而SAS本身的语法是不支持的;可以为数据集建立各种索引;还可以对数据集进行排序、连接、合并。所有的这些功能不需要SAS系统其他语句的支持,仅仅是在proc SQL中就可以全部完成。 除了熟悉而且习惯使用SQL的用户外,还在以下一些场合更适合使用proc SQL: (1)向数据集中插入记录 依靠SAS语法则需要将插入的记录先读入一个数据集,然后追加到另一个数据集,而proc SQL可以一步完成; (2)对列进行操作 SQL语言面向集合的特点决定了它特别适合于对整列进行运算,例如,求列和,列平均等等,而SAS语法要做这个工作要么是编写繁琐的data步,要么是使用统计描述的过程。 (3)访问其他数据库数据 使用proc SQL中connect语句和disconnect语句进行连接数据库和断开数据库。 虽然proc SQL是SAS的一个过程,但是它内部的语句还是遵循SQL语言的语法规则,例如: ·proc sql过程包含很多子语句,子语句内的项用逗号分开,而在SAS语言中用空格分开; ·当提交proc sql语句时,它就被执行,不需要规定run语句,当然写了run;也不会错,SAS会忽略; 另外,proc SQL还有一些额外的功能: ·select语句用于查询,也自动输出打印数据,除非在proc sql语句选项中规定noprint,所以通常不需要额外使用proc print; ·select语句和create view语句已经包含一个order by子句用于排序,因此不需要额外使用proc sort; 每一个支持SQL的数据库都会对ANSI SQL进行扩展,proc sql也不例外,例如: ·proc SQL保留的关键字比ANSI SQL要少,例如group在ANSI SQL中是作为关键字,但是在proc SQL中可以用来命名变量; ·proc SQL支持SAS的输入输出格式、变量标签等; ·proc SQL不支持注释语句; …… 上面这些只是零星的一点总结,更多的比较请参看帮助文档中的详细说明。