文章目录
- 生成SAS数据集
- 修改SAS数据集
- 合并SAS数据集
- 使用SAS数据集
- SAS运算符
- SAS函数
- 总结
生成SAS数据集
数据源:键盘输入、文本文件(txt, csv, dat)、excel、DBMS(SAS/ACCESS)……
/* 从excel导入数据集(不要求) */
proc print data = sasxls.dataset;
run;
- 1
- 2
- 3
新数据集的建立方式
1、VIEWTABLE / 菜单系统(不要求)
2、SAS / ACCESS(不要求)
3、用 Import 菜单
4、编程:用 DATA 步 (INPUT / INFILE / SET)
- 用DATA步建立新数据集的框架
DATA libref.dataset 或'路径名';
[INFILE '路径名' <options>;] ①
(变量属性设定)
ATTRIB
TYPR
LABEL
FORMAT
INFORMAT
LENGTH
[INPUT x $ y z] ②
(其他语句-数据的操作和使用)
PUT x= y= ;
(输入部分)
[datalines或cards;
~~~~~~~~~~~~~~数据行1
~~~~~~~~~~~~~~ ……
~~~~~~~~~~~~~~数据行n
;] ② /*datalines必须是DATA步中最后一条语句*/
RUN;
/*方式①是从文件读入,方式②是直接从键盘输入,分开使用*/
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- INFILE语句中的可选项
FIRSTOBS=n1 从第n1行开始读
OBS=n2 读前n2行(行和观测数不一定相等,可能一个观测包含多行数据)
MISSOVER 一行数据读完后先为这行中没有赋值的变量分配缺失值,再转到下一行(默认情况下是转到下一行继续读取数据)
TURNCOVER 一个变量字段超过了数据行的结尾,先读取数据至这一行的结尾,再转到下一行(默认情况下是转到下一行继续读取数据)
DLM=',' 以逗号(或其他符号)为分隔符(多个连续的分隔符看成一个)
DLM='09'X 使用制表符作为分隔符
DSD 以逗号为分隔符(①忽略引号括起来数据值中的分隔符 ②不把引号作为数值的一部分读取 ③把两个连续的分隔符视为缺失值)
(如果分隔符不是',',可以同时使用DLM=''和DSD)
ENCODING=utf8 中文字符转译
LRECL=x 读取长度为x的长记录(通常一行数据的字符个数不超过256个,如果超过则使用该选项)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- INPUT语句中的格式设定
/* 四种设定读入格式的方式(可混合使用)*/
INPUT <指针> <修饰符> 变量 格式控制尾符
(list方式): 变量名 <$> <:输入格式>
(column方式): 变量名 <$> 始列-终列
(formatted方式): <指针[@n或+n]> 变量名 输入格式
(named方式): 变量名 = <$> 始列-终列
/* 可选用的符号 */
/: 指示跳到下一个原始数据行
#n: 列指针(读入输入数据缓冲位置的第n行 - 适合读入含多种类型被拆分多行的数据行)
@'character': 列指针-从特定字符之后开始读取
@n: 定位符(第n格)
+n: 移位符(右移n格); +(-n):左移n格
:(冒号修饰符): 令SAS读取到空格或者数据行的结束为止
(e.g.读取rott vet bills [:$20.]→[rott] vs [$20.]→[rott vet bills] vs [$]→[rott])
@: 单尾符(不换行,等待下一个input语句)【书P61】
@@:双尾符(形成输出记录时输入也不换行,分配完当前行所有数据后,才会换行)(当一数据行含有多个观测时使用@@)
(@和@@都是屏蔽input读数据时自动换行的功能,只对一个数据步内的input过程有效)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 变量属性设定
data sales;
ATTRIB name LABEL="姓名" LENGTH=$6
date LABEL="日期" FORMAT=yymmdd10. INFORMAT=mmddyy8.
amount LABEL="金额" FORMAT=10.2 ;
input name $ 1-6 date amount;
datalines ;
王永成 10/15/98 17665
李宏志 1/3/1999 18178
贺 佳 11/5/99 16254
;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
修改SAS数据集
- 用SET语句读取和修改逻辑库中的数据集
(SET语句每次从SAS数据集中读取一条观测,供DATA步处理)
DATA new_dataset;
SET dataset(选项语句);
其他操作语句;
RUN;
/* SET选项语句 */
(选择和重命名变量)
KEEP = variable-list
DROP = variable-list
RENAME = (oldvar = newvar)
(选择观测)
FIRSTOBS = n1 OBS = n2
WHERE = (condition)
/* 特殊WHERE运算符(只能用于where表达式中的运算符)*/
BETWEEN-AND: 介于 e.g. where x between a and b;
IS NULL: 判断缺失 e.g. where x is null/missing;
IS MISSING: 判断缺失
CONTAINS('~'): 包含(选择包含指定的子字符串的观测,区分大小写)
LIKE: 匹配 e.g. where x like '%N'; where x like 'T_M%';
(通配符:%(代替任意数量的字符) / _(代替一个字符))
SOUNDS LIKE: 近似匹配
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 重组数据集
first.byvar last.byvar 两个临时标志变量的使用
- 1
无论是字符型还是数值型缺失值都必须用点(.)表示
N: 特殊变量,数据步循环计数值
合并SAS数据集
数据串接(顺接)
DATA new;
SET A(IN=ia) B(IN=ib);
BY ID; /*一定要先用PROC SORT按ID排序*/
RUN;
/* 使用BY语句:直接堆叠
不使用BY语句:交错连接 */
/* IN为数据集指示变量
IF ia=1; 保留来自数据集A的观测
IF ib=1; 保留来自数据集B的观测
IF ia=1 AND ib=1; 返回数据集A和B共有的观测(匹配行VS非匹配行) */
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
数据并接
DATA new;
MERGE A B;
BY ID;
RUN;
/*选项等于串接一样*/
- 1
- 2
- 3
- 4
- 5
使用SAS数据集
赋值语句var = expression;
保留语句: 保留变量最近的一次的值(供累加或求和运算使用) (一般在INPUT语句中需要添加保留语句)RETAIN variable-list <initial-value>;
累加语句:var + expression;
相当于 retain var; var = var + expression
/* 累加 */
data sales;
retain total 0; /*如果没有retain保留语句,total结果不对*/
input amount @@;
total = total + amount; /* retain句和这句可以直接用累加语句代替:total + amount; */
datalines;
1 2 3 4
;
run;
/* 分组累加 */
data sales;
input id qtr amount @@;
datalines;
001 1 1 001 2 5 001 3 10 001 4 20
002 1 5 002 2 10 002 3 5 002 4 15
;
run;
proc sort data=sales;
by id;
run;
data new;
set sales;
by id;
if first.id=1 then total=0; /* 代表各组首次出现(1是标志变量,每组的第一个数值为1,其余为0) */
total+amount;
if last.id=1; /*各组最后一次出现 */
run;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
条件语句:
①IF condition(C) THEN statement1(S1) ; ELSE S2;
②IF condition THEN DO; S1; S2; S3; END;
(添加DO可执行多条语句)
条件判断,优先将出现情况频率最高的作为第一判断条件
③IF condition THEN S1; ELSE IF condition THEN S2; ELSE (IF condition THEN) S3;
(不建议使用三层以上 if-else 的嵌套)
④ IF expression
= IF expression(反) THEN DELETE
取子集
/*实现数据集的拆分*/
data classm classf;
set class;
if sex='F' then output classf;
else output classm;
run;
- 1
- 2
- 3
- 4
- 5
- 6
选择语句(分支结构):
① SELECT(选择表达式); WHEN(值列表) 语句; WHEN(值列表) 语句; …… OTHERWISE 语句; END;
→ 判断是否相等
② SELECT; WHEN(条件) 语句; WHEN(条件) 语句; …… OTHERWISE 语句; END;
→ 拓展到所有的比较运算
值列表尽可能按照频次大小降序排列,提高判断效率
循环语句(以下多种形式可单独或混合使用):
① 标准DO循环 DO 指标变量=起始值 TO 结束值 BY 步长; 循环体语句……; (LEAVE;/CONTINUE;) END;
(LEAVE相当于C++中的break;)
② 当型循环:DO WHILE(循环继续条件); 循环体语句……; END;
③ 直到型循环:DO UNTIL(循环退出条件); 循环体语句……; END;
(先执行循环体,再判断循环退出条件)
④ 嵌套循环:DO-END语句中再嵌入另一个DO-END语句
输出语句:( PUT / OUTPUT )
*PUT
① 显示数值结果:PUT x y;
② 显示带有变量名的结果:PUT x= y= ;
③ 显示文本:PUT "text";
输出过程中不产生换行 :put i @;
put 语句的输出结果默认呈现在log窗口。在PUT语句前用file print;
可以将输出结果转向输出窗口。
将输出结果指定到文件: file '路径';
*OUTPUT
把当前的观测写入到指定输出的数据集中OUTPUT 数据集名1 数据集名2 ...;
(如果没有指定数据集名,则默认保存到data步所指定的数据集中)
data normal50;
da k=1 to 50;
x = normal(0);
output; /*这里如果不加output或output放在end之后(不加时默认),只能输出k=51时的一个数据 */
end;
run;
*----------------------------;
/*改变数据的输出格式(数据集的重组/转置)*/
data stu;
input no g1-g4;
datalines;
1 3.3 3.4 3.5 3.6
2 3.3 3.0 2.8 3.0
;
run;
data tran(drop=g1-g4 i);
set stu;
/*grade=1;gpa=g1;output;
grade=2;gpa=g2;output;
grade=3;gpa=g3;output;
grade=4;gpa=g4;output;*/
array g{4} g1-g4; /*使用数组*/
do i=1 to 4;
grade=i;
gpa=g{i};
output;
end;
run;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
数组语句:
- 数值型数组定义
ARRAY 数组名(维数说明) 数组元素名列表 (初始值表);
(如果不定义数组元素名列表,则自动生成元素名称 为数组名1 数组名2……
) - 字符型数组定义
ARRAY 数组名(维数说明) $ 元素长度说明 数组元素名列表 (初始值表);
- 临时数组:
ARRAY 数组名(维数说明) _TEMPORARY_ (初始值表);
(数组元素只由数组名和序号决定,没有对应的变量名) - 维数说明:
一维(1) 、多维(m,n) 、下标下界:下标上界(95:97)
星号(*)代表不确定长度-由元素列表的变量个数决定(动态化操作)
取数组维度值:DIM( )
、取数组元素值:a(i)
数组求和:SUM(of a{*})
SAS运算符
- 算术运算符
+, -, *, /, **(乘方), ||(字符串连接)
- 比较运算符(算数符/助记符)
=(EQ), ^=(NE), >(GT), <(LT), >=(GE), <=(LE), IN
→prov IN('北京','上海','天津')(逗号可加可不加)
- 逻辑运算符
&(AND), |(OR), ^(NOT), ||(连接两个字符串), <>(取两个运算值中较大的一个), ><(取两个运算值中较小的一个)
/真/假 → 1/0 ; 非0/0 → 真/假
(比较运算符尽量用算数符,逻辑运算符尽量用助记符)
SAS运算优先级表
SAS函数
书P88-92、102
- 分布函数和分布密度函数
分布函数值 = CDF('分布', x, <参数表>);
密度值 = PDF('分布', x, <参数表>);
概率值 = PMF('分布', x, <参数表>);
对数密度值 = LOGPDF('分布', x, <参数表>);
对数概率值 = LOGPMF('分布', x, <参数表>);
'分布':BERNOULLI, BETA, BINOMIAL, CAUCHY, CHISQUARED, GAMMA, F, EXPONENTIAL,
GEOMETRIC, HYPERGEOMETRIC, LAPLACE, LOGISTIC, LOGNORMAL, POISSON, NEGBINOMIAL,
NORMAL, GAUSSIAN, PARETO, T, UNIFORM, WALD, IGAUSS, WEIBULL (可以只写前四个字母)
典型分布的分布函数值:
PROBNORM(x); → P(U<=x),U ~ N(0,1)
PROBCHI(x,df,nc); → nc=0或不写:中心卡方分布
PROBGAM(x,a); → a:形状参数
PROBBETA(x,a,b);
PROBF(x,ndf,ddf,nc); → ndf:分子*度,ddf:分母*度
PROBBNML(p,n,m);
PROBT(x,df,nc);
POISSON(lambda,n);
PROBNEGB(p,n,m);
PROBHYPR(nn,k,n,x,r);
PROBBNRM(x,y,r); → 标准二元正态,r为相关系数
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 分位数函数 (F(x_p)=p → x_p为X的p分位数)
CINV(p,df,nc); → 计算卡方分布的分位数
BETAINV(p,a,b);
FINV(p,ndf,ddf,nc);
TINV(p,df,nc);
PROBIT(p); → 计算标准正态分布的分位数
GAMINV(p,a);
- 1
- 2
- 3
- 4
- 5
- 6
- 样本统计函数
fun(of 变量列表); → 自动屏蔽缺失值
N(of x1-xn); / N(x,y,...); *统计非缺失数据的个数;
NMISS(of x1-xn); / NMISS(x,y,...); *统计缺失数据的个数;
MEAN(); MAX(); MIN(); SUM(); VAR(); STD(); RANGE();
STDERR(); *标准误; CV(); *变异系数;
CSS(); *偏差平方和(校正平方和)-计算非缺失自变量关于均值的偏差平方和 ; USS(); *未校正的平方和;
SKEWNESS(); *偏斜度; KURTOSIS(); *峰度;
ORDINAL(k,x1,x2,...,xn); *返回数值列表x1,x2...xn中第k小的数;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 随机数函数
UNIFORM(seed); / RANUNI(seed); *产生均匀分布随机数;
NORMAL(seed); / RANNOR(seed); *标准正态分布随机数;
X = M + sqrt(SQ)RANNOR(seed); Y = exp(X); *一般正态分布随机数和对数正态随机数;
RANEXP(seed);
RANGAM(seed,a);
RANCAU(seed);
RANBIN(seed,n,p);
RANPOI(seed,lambda);
RANTRI(seed,h); *三角分布随机数;
RANTBL(seed,p1,p2,...,pn); *离散分布(多项分布)随机数;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 其他数值函数
CEIL(x);*向上取整; FLOOR(x);*向下取整; INT(x);*取整; ROUND(x);*四舍五入取整;
ABS(x); MOD(x,y); SQRT(x);
DIGAMMA(x);*对x计算GAMMA函数对数的导数; GAMMA(x);*对x计算完全GAMMA函数;
LOG(); LOG2(); LOG10(); EXP(); ERF(); *计算误差函数;
SIN(); COS(); TAN(); SINH(); COSH(); TANH();
LAGn(x); *返回该自变量x前n条观测中该变量的值;
DIFn(x); *返回该自变量x减去前n条观测中该变量的值;
e.g. 环比:pct1 = dif(x)/lag(x); 同比:pct2 = dif12(x)/lag12(x);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 字符串函数
UPCASE(s); *把字符串s转化为大写字母; LOWCASE(s);
SUBSTR(s,p,n); *从字符串s的第p个字符开始取n个字符的字串;
- 1
- 2
- 日期常数和函数
日期时间直接作为数值型常数:'ddmmyy'd
DATE(); TODAY(); DATETIME(); TIME(); HOUR(); MINUTE();
SECOND(); YEAR(); MONTH(); DAY(); WEEKDAY(); QTR();(季度值)
MDY(m,d,y); → y年m月d日 HMS(h,m,s); → h时m分s秒 DHMS(date,h,,m,s);
DATEPART(datetime); *取datetime中的日期部分:
INTNX(interval,from,n); *计算从from开始经过n个间隔后的SAS日期; e.g. INTEX('month','15Dec2018'd,3) = 2019年3月1日
INTCK(interval,from,to); *计算从日期from到日期to中间经过interval间隔的个数; e.g. INTCK('year','15Dec2018'd,'1Jan2020'd) = 2
- 1
- 2
- 3
- 4
- 5
- 6
- 7
. 使用birthdate计算age:CurrentAge = INT(YRDIF(BirthDate, TODAY(), 'AGE'));
- 函数变量引用方式
-:规律引用 eg. var1-var3 → var1 var2 var3
--:无规律引用(取决于data步内部变量名顺序)
e.g. INPUT y a c h r; b = c + h; → PUT y--b;
名称前缀列表:e.g. SUM(DOGaaa,Dogdddd,Doghhh); → SUM(OF Dog:)
特殊名称列表:_ALL_ ...
- 1
- 2
- 3
- 4
- 5
总结
原始数据/SAS表 → DATA步 → SAS表 → PROC步 → 报告