《SAS编程演义》笔记(5-7章)

亦应帷幄运鸿筹:数据库集

修改数据集

MODIFY master-data-set <(data-set-options)> transaction-data-set <(data-set-options)> <CUROBS=variable> < NOBS=variable> <END=variable> <UPDATEMODE=MISSINGCHECK|NOMISSINGCHECK>;

BY by-variable;

  • master-data-set:主数据集(Master Dataset),存放原始数据。
  • transaction-data-set:事物数据集(Transaction Dataset),存放匹配变量、需要修改的变量及其新值。
  • CUROBS=variable:将当前生成的数据集观测存储到临时变量variable中
  • NOBS=variable:将主数据集和事物数据集总观测数存储到临时变量variable中
  • END=variable:创建并命名一个临时变量variable,用1和0标记是否为最后一条记录。

MODIFY master-data-set <(data-set-options)> KEY=index </UNIQUE> <KEYRESET=variable> <NOBS=variable> <END=variable>;

  • KEY=index:指定索引
  • KEYRESET=variable:是否从索引头部查找

MODIFY master-data-set <(data-set-options)> <NOBS=variable> POINT=variable;

  • POINT=variable:随机读取由variable指定的观测

MODIFY master-data-set <(data-set-options)> <NOBS=variable> <END=variable>

MODIFY比SET更高效。MODIFY语句直接修改原数据集,不生成新数据集。SET语句打开原数据集,重新生成一份新数据集(即使新数据集与原数据集同名)。因此使用MODIFY语句时,DATA语句后必须是原数据集,但使用SET语句时则无所谓。

1
2
3
4
5
6
7
8
9
10
11
data class;
set sashelp.class;
weight = weight*0.4536; /*lbs->kg*/
height = height*0.0254; /*in->m*/
run;
data sashelp.class;
modify sashelp.class;
weight = weight*0.4536; /*lbs->kg*/
height = height*0.0254; /*in->m*/
run;

MODIFY比MERGE更高效。MODIFY语句进行匹配修改观测时,因其采用动态WHERE语句,不像MERGE需要事先排序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
data raw;/*主数据集*/
name="吴源燚";gender="";age=2;Location="SH";output;
name="WUYY";gender="M";age=.;Location="SH";output;
run;
data new;/*事物数据集*/
name="吴源燚";gender="M";
name="WUYY";age=25;output;
name="WUYY";age=30;output;
run;
data raw;
modify raw new;
by name;
replace; /*默认可省略*/
run;

MODIFY语句是对原数据集里观测进行修改,但是不能改变数据集结构,即不能新增变量也不能新增观察。

1
2
3
4
5
6
7
8
9
10
11
data sashelp.class class_female;
modify sashelp.class;
if sex ="F" then do;
output class_female;
remove sashelp.class;
end;
else do;
height=height+5;
replace sashelp.class;
end;
run;

更新数据集

UPDATE master-data-set <(data-set-options)> transaction-data-set <(data-set-options)> <END=variable> <UPDATEMODE=MISSINGCHECK|NOMISSINGCHECK>;

BY by-variable;

  • master-data-set:主数据集,存放原始数据。
  • transaction-data-set:事物数据集,存放匹配变量、需要修改的变量及其新值。
  • END=variable:创建并命名一个临时变量variable,用1和0标记是否为最后一条记录。
  • UPDATEMODE:是否用事物数据集里的缺失值更新主数据集
    • 是:NOMISSINGCHECK
    • 否:MISSINGCHECK
  • by-variable:指定匹配变量,主数据集和事物数据集按变量的值 匹配

主数据集和事物数据集需先按BY变量排序;UPDTATE只有一种用法,其后必须跟BY语句;主数据集中,BY变量的值应该唯一,否则只会更新相同值的首条记录,事物数据集中BY变量值可以不唯一,更新的数据集最终会以最后一条为准。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
data raw;/*主数据集*/
name="吴源燚";gender="";age=2;Location="SH";output;
name="WUYY";gender="M";age=.;Location="SH";output;
run;
data new;/*事物数据集*/
name="吴源燚";gender="M";
name="WUYY";age=25;output;
run;
proc sort data=raw; /*排序*/
by name;
run;
proc sort data=new;
by name;
run;
data want; /*用事物数据集更新主数据集*/
update raw new;
by name;
run;

行列转置

PROC TRANSPOSE <DATA=input-data-set> <DELIMITER=delimiter> <LABEL=label> <LET> <NAME=name> <OUT=output-data-set> <PREFIX=prefix> <SUFFIX=suffix>;

BY <DESCENDING> variable-1 <<DESCENDING> variable-2> <NOTSTORED>;

COPY variable(s);

ID variable;

IDLABEL variable;

VAR variable(s);

RUN;

  • DATA=input-data-set:待转置数据集名称
  • DELIMITER=delimiter:ID语句有多个变量时,变量值之间所加的连字符
  • LABEL=label:转置变量的标签存储在新数据集中的变量名,默认_LABEL_
  • LET:当ID变量的值有重复时使用,此时只有每组ID的最后一条观测被转置
  • NAME=name:转置变量在新数据集中的名字,默认为_NAME_
  • OUT=output-data-set:转置后数据集名称
  • PREFIX=prefix:给转置变量在新数据集中的变量名加前缀
  • SUFFIX=suffix:给转置变量在新数据集中的变量名加后缀
  • BY:制定分组转置的变量,如果没有加NOTSTORED选项,原数据集应该先用PRCO SORT语句按BY语句指定的变量排序
  • COPY:拷贝变量,此变量不转置,直接拷贝到新数据集中
  • ID:标识变量,用此变量的值标识转置后变量的名称,多个标识变量时,需要DELIMITER指定连字符
  • IDLABEL:给转置后的变量添加标签
  • VAR:待转置的变量,SAS将对此变量进行行列互换操作
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
31
32
33
34
35
36
37
data wide; /*创建宽表*/
input SID $ Programming Stats English;
datalines;
S01 98 100 80
S02 84 98 94
S03 89 92 88
;
run;
proc transpose data=wide out=long(rename=(_name_=Coursename col1=Score));
var Programming Stats English;
by SID;
run;
data long(keep= SID Coursename Score);
set wide;
array scores{*} Programming Stats English;
do i=1 to dim(scores);
Coursename=vname(scores{i});
Score=Scores{i}
end;
run;
proc transpose data=long out=Rewide(drop=_name_);
var Score;
by SID;
id Coursename;
run;
data Rewide(keep=SID Programming Stats English);
format SID Programming Stats English;
array Course{3} Programming Stats English;
do i=1 to 3;
set long;
Course{i}=Score;
end;
run;

横向拼接(并接)

一对一读入(One-to-one Reading)

  • 用多SET语句并接多个数据集,当数据集里的观测数不等时,SAS读完观测数最少的那个数据集后即停止执行。
  • 当多个数据集里的变量有重复时,后面的值会覆盖前面的值。
1
2
3
4
5
6
7
8
9
10
data class1(keep=name sex) class2(keep=age height weighr);
set sashelp.class;
output class1;
output class2;
run;
data class;
set class1;
set class2;
run;

一对一并接(One-to-one Merging)

  • 数据不对等时,不会停止执行。
1
2
3
data class;
merge class1; class2;
run;

匹配并接(Matching Merging)

  • 在使用MERGE语句前需用PROC SORT过程给匹配变量排序,在其之后需紧接BY语句指定匹配变量。
  • 可同时MERGE多个数据集,对于相同的变量,后一个数据集里的值会覆盖前一个数据的值。
  • 并接两个数据集时,BY变量可能不唯一。一个数据集重复的BY值有m个,另一数据集重复的BY值有n个,则MERGE后,这些重复的BY值将产生m*n条结果。
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
31
32
33
34
35
36
37
38
39
40
41
42
data class1(keep=name sex) class2(keep=name age height weight);
set sashelp.class;
out class1;
if _n_ in (1, 5, 10, 15) then output class2;
run;
data class2;
ser class2;
if name="Janet" then name="Janey";
run;
proc sort data=class2;
by name;
run;
proc sort data=class2;
by name;
run;
data class_left; /*左连接*/
merge class1(in=ds1) class2(in=ds2);
by name;
if ds1;
run;
data class_right; /*右连接*/
merge class1(in=ds1) class2(in=ds2);
by name;
if ds2;
run;
data class_inner; /*内连接*/
merge class1(in=ds1) class2(in=ds2);
by name;
if ds1 and ds2;
run;
data class_full; /*全连接*/
merge class1(in=ds1) class2(in=ds2);
by name;
if ds1 or ds2;
run;

纵向拼接(串接)

SET语句

  • SET语句后可以跟多个数据集或数据集列表
  • 最终的数据集不会自动剔除重复行
  • 为匹配的列值为空
  • 字符型变量的长度为第一次出现的数据中的定义长度,后面相同的字段如果比前面更长,则会被截断,因此建议在SET语句前先用LENGTH语句申明其长度。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
data class1 class2 class3(keep=name sex) class4(keep=name age height weight);
set sashelp.class;
if _n_ < 10 then do;
output class1;
output class2;
end;
else do;
output class2;
output class4;
end;
run;
data class;
set class1 class2;
run;
data class;
set class2 class4;
run;

PROC APPEND

PROC APPEND BASE=<libref.>SAS-data-set <APPENDVER=V6> <DATA=<libref.>SAS-data-set> <ENCRYPTKEY=key-value> <FROCE> <GETSORT> <NOWARN>;

RUN;

  • BASE=<libref.>SAS-data-set:指定基础数据集,追加数据集的观测将写入此数据集中
  • APPENDVER:指定追加机制的版本,可以是V6或V7
  • DATA=<libref.>SAS-data-set:指定待追加数据集
  • ENCRYPTKEY=key-value:AES加密键值
  • FORECE:当追加数据集里的变量不在BASE数据集,或者变量类型和长度不同时,强制追加,不过此时LOG中会有警告信息,可以用NOWARN屏蔽
  • GETSORT:把BASE数据集的排序标识复制到追加数据集中
1
2
proc append base=class3 data=class4 force;
run;

制作变量字典

利用ODS OUTPUT语句抓取PROC CONTENTS背后的数据

1
2
3
4
5
6
ods output Position=codebook;
proc contents data=sashelp.cars order=varnum;
run;
proc export data=codebook outfile="d:\codeBook.csv" dbms=csv replace;
run;

数据集信息

数据集权限有读、写、修改和全局四种,分别用READ=、WRITE=、ALTER=、PW=来设置。格式为:密码1/密码2,具体有五种形式:

  • 密码1:设置密码
  • 密码1/密码2:修改密码1为密码2
  • 密码2:不管旧密码是什么,设置新密码为密码2
  • 密码1/:删除密码
  • /:删除密码
1
2
3
4
5
6
7
proc datasets lib=sashelp; /*获取描述信息*/
contents data=class;
run;
proc datasets lib=sashelp;/*修改描述信息*/
modify class(label="学生测试数据集" read=r2017);
quit;

数据集操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
proc datasets;
copy in=sashelp out=work; /*数据集集体拷贝*/
select class; /*选择数据集*/
quit;
proc datasets lib=work;
change class=student; /*数据集改名*/
quit;
proc datasets lib=work;
delete students; /*删除数据集*/
quit;
proc datasets lib=work kill memtype=data; /*删除Work库中所有数据集*/
run;
proc datasets lib=work;
save class; /*仅保留class*/
run;

变量信息

PROC DATASETS不是打开数据集,逐行操作,而是对数据集的描述信息直接操作,或者直接操作整体数据集。因此相比逐条操作的SET语句,PROC DATASETS在效率上要高很多。

PROC DATASETS配合MODIFY语句,可以修改变量的格式、标签以及重命名变量。

1
2
3
4
5
6
proc datasets;
modify sashelp.class;
format height weight 3.0;
rename sex=gender;
label name="姓名" gender="性别";
quit;

SAS字典

SAS Dictionary库是一个只读的SAS逻辑库,里面包含了与SAS会话相关的元数据(描述数据的数据),如数据集名、变量名、变量类型以及变量长度等这些描述变量的变量。

1
2
3
4
proc sql;
title "Dictionary库中所有的表";
select unique memname memlabel from dictionary.dictionaries;
quit;

SAS字典库里的表与其对应的SASHELP库下的视图

Dictionary库下的表名 SASHELP库下的视图名 主要作用
TABLES Vtable 包含了诸如逻辑库名、数据文件名、数据文件的类型、观测值数、变量数等诸多信息
COLUMNS Vcolumn 包含了变量名称、类型、长度和格式以及标签等诸多信息
MEMBERS Vmember 包含了逻辑库名称、数据文件名、数据类型、路径等诸多信息
FORMATS Vformat 包含了系统自带的格式信息
1
2
3
proc sql;
describe table dictionary.column; /*查看columns表结构*/
quit;

在指定逻辑库、数据集以及数据文件类型时,需用引号,且引号里面的字母是大学。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
proc sql; /*从字典库中获取SASHELP库下所有数据集信息*/
create tables desds as select memname, nobs, nvar from dictionary.tables
where libname="SASHELP" and memtype="DATA";
quit;
proc sql; /*从视图中获取SASHELP库下所有数据集信息*/
create tables desds as select memname, nobs, nvar from sashelp.vtable
where libname="SASHELP" and memtype="DATA";
quit;
proc sql; /*从字典库中获取数据集CARS的所有变量信息*/
create table varlist as select name, type, length, label from dictionary.columns
where libname="SASHELP" and memname="CARS";
quit;
proc sql; /*从视图中获取数据集CARS的所有变量信息*/
create table varlist as select name, type, length, label from sashelp.vcolumn
where libname="SASHELP" and memname="CARS";
quit;

间有山川亦奇秀:函数例程

函数语法

可用于DATA步赋值语句、IF语句、WHERE表达式(语句或选项)、宏语句、PROC REPORT以及PROC SQL语句中。PRCO SQL的SELECT语句里的函数作用是纵向的,而其他函数的作用则是横向的。

function-name(argument-1<…*argument-n>)

function-name(OF variable-list)

function-name(OF array-name[*])

function-name(<argument|OF variable-list| OF array-name[*]> <…, <argument|OF variable-list| OF array-name[*]>>)

  • function-name:函数名称
  • argument:参数,可以是变量名、常数、表达式、甚至还可以是其他函数
  • OF variable-list:参数列表
  • OF array-name[*]:数组名称,注意要带[*]
1
2
3
4
5
6
7
8
9
10
11
data _null_;
array ex{7} (95 93 92 99 98 85 94);
avg_function1=mean(ex1, ex2, ex3, ex4, ex5, ex6, ex7); /*单个参数*/
avg_function2=mean(of ex1 ex2 ex3 ex4 ex5 ex6 ex7); /*变量清单*/
avg_function3=mean(of ex1-ex7); /*变量清单*/
avg_function4=mean(of ex:); /*变量清单*/
avg_function5=mean(of ex[*]; /*数组名*/
put (avg_function1 avg_function2 avg_function3 avg_function4 avg_function5) (=);
put avg_function1= avg_function2= avg_function3= avg_function4= avg_function5=;
/*put avg_function1 avg_function2 avg_function3 avg_function4 avg_function5;*/
run;

例程语法

主要用于DATA步的CALL语句中,不能用于赋值语句和表达式。

CALL routine-name(argument-1<…*argument-n>)

CALL routine-name(OF variable-list)

CALL routine-name(OF array-name[*])

CALL routine-name(<argument|OF variable-list| OF array-name[*]> <…, <argument|OF variable-list| OF array-name[*]>>)

  • routine-name:函数名称
  • argument:参数,可以是变量名、常数、表达式、甚至还可以是其他函数
  • OF variable-list:参数列表
  • OF array-name[*]:数组名称,注意要带[*]
1
2
3
4
5
6
7
8
9
10
data tmp;
array str{3} $20 ("统计思维","SAS编程演义","数据整理与图标呈现");
length result1-result5 $50;
call catx("-", result1, str1, str2, atr3);
call catx("-", result2, of str1 str2 atr3);
call catx("-", result3, of str1-atr3);
call catx("-", result4, of str:);
call catx("-", result5, of str[*]);
put (result1 result2 result3 result4 result5) (=);
run;

自定义函数

借助PROC FCMP的FUNCTION语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
proc fcmp outlib=sasuser.funcs.trial;
function study_day(intervention_date, event_date); /*定义函数study_day*/
n=event_date - intervention_date;
if n >= 0 then
n = n + 1;
return(n);
endsub;
run;
options cmplib=sasuser.funcs;
data _null_;
start='15Feb2010'd;
today='27Mar2010'd;
sd=study_day(start, today);
put sd=;
run;

高频函数和例程

功能类别 函数名及其功能
数组处理 DIM:返回数组元素个数
HBOULD:返回数组上界
LBOULD:返回数组下界
字符处理 STRIP:掐头去尾移除空格
SUBSTR:提取、置换字符
TRANSLATE、TRANSTRN、TRANWRD:替换、移除字符
UPCASE、LOWCASE、PROPCASE:大小写转换
SCAN:扫描整个字符串,返回某部分字符串
FIND、FINDC、FINDW:查找字符,返回其位置
INDEX、INDEXC、INDEXW:查找字符,返回其位置
CATS、CATT、CATX及其CALL例程:字符串拼接
日期时间 DATE、TODAY:获取当前日期
YEAR、MONTH、DAY:分别截取年、月、日
MDY:月、日、年组合成完整日期
HOUR、MINUTE、SECOND:分别截取时、分、秒
HMS:时、分、秒组合成完整时间
INTCK:计算日期、时间、日期时间间的间隔
INTNX:给定间隔的下一个日期、时间、日期时间
统计描述 N、NMISS:分别统计非缺失、缺失的个数
SUM:求和
MEAN:均数
STD、STDERR:标准差、标准误
CV:变异系数
IQR:分位数间隔
MISSING:判断是否缺失
宏函数 CALL SYMPUT、CALL SYMPUTX:DATA步赋值宏变量
SYMEXIT:判断宏变量是否存在
SYMGET:DATA步运行阶段获取宏变量值
截断函数 TRAN:强行截断
ROUND:四舍五入
INT、CELL、FLOOR:直接取整、向上取整、向下取整
变量信息 VNAME:获取变量名
VTYPE:获取变量类型
VLABEL:获取变量标签
特殊函数 INPUT、PUT:数据类型转换
LAG、DIF:不同观测号间的值与差值

翩跹翠袖拂云裳:巧用格式

格式名

<$>format-name<w>.<d>

$:标明是否为字符格式,有$的为字符格式,无则为数字格式

format-name:格式名称,可以是SAS系统自带也可以是用户在PROC FORMAT的VALUE语句中自定义的

w:格式的宽度

d:小数的位数

.:w和d均可以没有,但其之间的点必须保留

1
2
3
4
5
6
7
/*获取系统内置格式清单*/
proc sql;
create table SysFormats as select distinct fmtname from dictionary.formats;
quit;
proc print data= SysFormats;
run;

常用输入格式

类别 格式名 作用简介
字符 $CHARw. 读入带空格的字符
$w. 标准字符格式
日期时间 ANYDTDTEw. “万能”读入日期格式
ANYDTDTMw. “万能”读入日期时间格式
ANYDTTMEw. “万能”读入时间格式
DATEw. 读入格式为ddmmyy或ddmmyyyy的日期
DATETIMEw. 读入格式为ddmmyy hh:mm:ss或ddmmyyyy hh:mm:ss的日期时间
DDMMYYw. 读入格式为ddmmyy<yy>或者dd-mm-yy<yy>格式的日期,连字符可以是- . /
HHMMSSw. 读入格式为hh:mm:ss或hhmmss的时间
MMDDYYw. 读入格式为mmddyy或mmddyyyy的日期
数字 COMMAw.d 读入数字时移除数字间的逗号
w.d 读入标准数字格式
PERCENTw.d 读入百分比数字

常用输出格式

类别 格式名 作用简介
字符 $w. 标准字符格式,w表示变量的宽度
$IPCASEw. 把字符转成大写,相当于UPCASE函数
日期时间 DATETIMEw.d 显示日期时间格式为ddmmmyy:hh:mm:ss.ss
DATEw. 显示日期格式为ddmmmyy,ddmmmyyyy,或dd-mmm-yy
YYMMDDw. 显示日期格式为yymmdd或<yy>yy-mm-dd
HHMMw.d 显示时间格式为hh:mm
数字 BESTw. SAS自动选择最合适的数字格式
COMMAw.d 带千分位的数字格式
DOLLARw.d 带美元符号的格式
PERCENTw.d 显示百分比形式
PVALUEw.d 统计P值显示格式
w.d 标准的数字格式
Zw.d 前面位数不够补0填充

自定义格式

PROC FORMAT <option(s)>;

EXCLUDE entry(s);

INVALUE <$>name<(informat-option(s))><value-range-set(s)>;

PICTURE name<(format-option(s))> <value-range-set-1<(picture-1-option(s))> <value-range-set-2<(*picture-2-option(s))>> …>;

SELECT entry(s);

VALUE <$>name<(format-option(s))> <value-range-set(s)>

RUN;

  • option(s):PRCO FORMAT的一些选项,如:
    • library=:指定格式存放位置
    • ctnlin=:指定格式定义输入数据集
    • ctnlout=:指定格式定义到出数据集
  • EXCLUDE:剔除某些条目
  • INVALUE:定义输入格式
    • name:输入格式名,前面有$表示为字符格式名
    • informat-option(s):输入格式选项
    • value-range-set(s):数据映射
  • PICTURE:创建打印数字的模版
  • VALUE:定义输出格式
    • name:输出格式名,前面有$表示为字符格式名
    • informat-option(s):输出格式选项
    • value-range-set(s):数据映射,其形式可以是:value-or-range-1 <, value-or-range-2, …>=formatted-value|[existing-format]

直接用输入数据来定义格式时,输入数据集里必须包含五个重要字段名:FMTNAME、START、END、LABEL以及TYPE。

1
2
3
4
5
6
proc format cntlout=fmt; /*自定义格式,导出格式定义数据*/
value $sexf F="男性" M="女性";
run;
proc format library=work cntlin=fmt(keep=fmtname start end label type); /*用数据集定义格式*/
run;
  • 格式命名:格式命名长度不得超过32个字符(包括$),且不得以数字结尾
  • 数据映射中,数据范围写法:
    • 单独的值映射:如「F=”男性” M=”女性”」,「1=”低” 2=”中” 3=”高”」
    • 值范围的映射:如「18.5-24.9=”正常”」,「’A’-‘D’=”Class1”」
    • 单用连字符“-”时,是闭区间,包括两边边界值。如果希望不包括边界,可在其前加“<”,如:「18.5-<25=”正常”」
    • 可用关键词LOW,HEIGH,OTHER:如「low-<65=”<65岁” 65-high=”>=65岁”」
    • 可以嵌套格式名,但是需要将嵌套的格式名置于中括号内或小括号里的双竖线中,如:「.=”缺失” other=[yymmdd10.];」
  • 定义好的格式,如果在DATA步用FORMAT关联变量,则为永久性的;如果只在过程步用FORMAT关联变量,则为临时性的。

格式妙用

格式的使用范围

1
2
3
4
5
6
7
8
9
10
11
12
13
data _null_; /*DATA步 PUT语句中指定*/
set sashelp.class(obs=5);
put name sex $sexf.;
run;
prco print data=sashelp.class(obs=5); /*PROC步FORMAT语句指定*/
var name sex;
format sex $sexf.;
run;
proc sql; /*Proc sql中format选项*/
select name, sex format=$sexf. from sashelp.class(obs=5);
quit;

变量重分组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
data obese; /*创建测试数据集*/
length status $ 15;
set sashelp.class;
BMI = weight*0.4536/(height*0.0254)**2;
run;
proc format; /*自定义格式*/
value obefmt low-18.5="Underweight" 18.5-25="Normal"
25-30="Overweight" 30-high="Obese";
run;
proc freq data=obese; /*愿变量+格式直接统计新分类的频数*/
table bmi;
format bmi obefmt.;
run;

统计分析过程

1
2
3
4
5
6
7
8
9
10
/*在统计分析过程里,直接用自定义格式给变量重分组*/
proc format;
value obefmt low-18.5="Underweight" 18.5-high="Normal or above";
run;
proc logistic data=obese;
class sex;
model bmi(event="Underweight")=age sex;
format bmi obefmt.;
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
proc format; /*自定义格式*/
value $missfmt ' '="Missing" other="Not Missing"; /*引号中有多少空格都一样*/
value nmissfmt .="Missing" other="Not Missing";
run;
data class; /*创建测试数据集*/
set sashelp.class;
if rannor(123)<0.5 then call missing(sex);
if rannor(456)<0.05 then call missing(age);
run;
proc freq data=class; /*统计缺失、非缺失频数*/
table sex age/missing;
format sex $missfmt. age nmissfmt.;
run;
data cclass;
set class;
if name='Henry' then sex=' ';
run;
proc freq data=cclass; /*统计缺失、非缺失频数*/
table sex age/missing;
format sex $missfmt. age nmissfmt.;
run;

条件显示

利用自定义格式,可以依据不同的条件,按不同风格显示值。

1
2
3
4
5
6
7
8
9
10
11
proc format;
value obefmt low-18.5="red" 18.5-high="black";
run;
proc report data=obese nowd split='~' style(report)=[background=white foreground=black];
column name sex age bmi;
define name/display;
define sex/display;
define age/display;
define bmi/format=4.1 style=[foreground=obefmt.];
run;