SAS 学习笔记 (二)— 数据管理

时间:2024-10-30 07:33:46

文章目录

          • 生成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), INprov 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) = 201931日
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步 → 报告
在这里插入图片描述