目录
什么是宏
怎样编写宏
实例
Step1. 特例实现
Step2. 替换参数,封装为宏
Step3. 调用宏
什么是宏
SAS中的宏类似于R中的函数,但SAS没有R灵活。就我的理解,SAS中无论是DATA步还是PROC步几乎每个程序都要指定要操作哪一个数据集,这里的数据集就相当于R中的data.frame,也就是说SAS中几乎只有数据集一种数据格式,而R中除data.frame这种数据对象类型外,还有向量、数组、因子、列表等类型,数据类型更丰富也相对灵活。
那什么是函数呢?回想高中数学的知识,函数是从原象到象的一种映射。我的理解,函数是一种过程,能实现一类功能,给它一个输入,还你一个输出。程序中的函数就是一段可复用的代码。
怎样编写宏
我编写宏/函数的一般习惯是,先用某个具体案例,把想要实现的过程实现;接着把可以变动的参数替换为变量,也就是函数参数;封装起来就得到了想要的函数。也即从特殊到一般的思路。
实例
climate_3
数据集包含一些气象监测数据资料,部分变量存在异常值,例如999999,999900
等,可能是由于监测值缺失,数据清理阶段,需要处理这些异常值,本例选择用中位数替换异常值。由于数据集中的变量很多,逐一处理会很麻烦,因此可以借助宏来实现,提高效率。
Step1. 特例实现
首先,对climate_3
数据集中的max_air_pre
变量进行异常值识别与替换。
*查看变量max_air_pre的基本情况*;
proc univariate data=climate_3 normal plot;
var max_air_pre;
run;
可见,存在极个别异常值。本例中将距离四分位数超过3倍IQR(四分位数间距)的数据归为异常值。为此需要获得上下四分位数Q1,Q3,IQR(Q3-Q1)和中位数。
*查看变量基本情况并保存到数据集a中*;
proc means data=climate_3 n nmiss mean stddev min q1 median q3 max range ;
var max_air_pre;
output out=a mean=mean median=median q1=q1 q3=q3 ;
run;
数据集a:
*计算判断异常值的上下限*;
data a;
set a;
IQR3=(q3-q1)*3;
lower=q1-IQR3;
upper=q3+IQR3;
call symputx('lower',lower); *将数据集a中的lower变量值保存到宏变量lower中*
call symputx('upper',upper);
call symputx('median',median);
run;
*打印宏变量*;
%put &=lower &=upper &=median;
*替换异常值*;
data climate_3;
set climate_3;
if max_air_pre <&lower. or max_air_pre > &upper then max_air_pre= &median.;
run;
*检查*;
proc univariate data=climate_3 normal plot;
var max_air_pre;
run;
Step2. 替换参数,封装为宏
* 用中位数替换离群值 *;
%macro replace_outlier(data,variable);
proc univariate data=&data normal plot;
var &variable;
run;
proc means data=&data;
var &variable;
output out=a median=median q1=q1 q3=q3;
run;
data a;
set a;
IQR3=3*(q3-q1);
lower=q1-IQR3;
upper=q3+IQR3;
call symputx('lower',lower);
call symputx('upper',upper);
call symputx('median',median);
run;
data &data;
set &data;
if &variable. < &lower. or &variable. >&upper. then &variable. = &median.;
run;
proc univariate data=&data normal plot;
var &variable;
run;
%mend;
Step3. 调用宏
像R中调用函数一样,调用宏即可实现将指定数据集的指定变量中异常值替换为中位数。
%replace_outlier(climate_3,max_air_pre);
%replace_outlier(climate_3,min_air_pre);
如果觉得本文有用,别忘记收藏呦~