SAS中的自动变量、变量列表总结笔记
写SAS程序时我们会用到一些带下划线的变量如_N_, _ERROR_,这些变量在某些时候能给写程序带来很大的便利,本次笔记是尝试对这些变量种类和用法的总结。
在查阅一些SAS书籍和SAS帮助中心文档后,个人认为这类变量可以分成自动变量、变量列表、语句里的临时变量以及宏里面的自动变量:
本次文章主要总结自动变量和变量列表,临时变量归属于SET/MERGE等各个语句、数量众多,和宏里的自动变量一并之后再总结。
自动变量 Automatic Variables
专门指代DATA步执行时系统产生的变量,在官网文档中提到了这几个:_CMD_, _ERROR_, _IORC_, _N_, _MSG_, FIRST.variable, LAST.variable。
常用基础变量(N, ERROR)
其中_N_, _ERROR_是里关联使用的基础变量,_N_用来表示SAS处理数据循环经过的迭代次数,_ERROR_表示DATA步中程序是否出错,默认值为0,遇到错误为1。
data test_error_n;
input raw_value $;
/* 尝试将字符转换为数字 */
num_val = input(raw_value, best.);
/* 1. _N_ :记录当前是第几次循环 */
loop_count = _N_;
/* 2. _ERROR_ :如果转换失败,_ERROR_ 会自动变 1 */
if _ERROR_ = 1 then do;
put "【警告】: 第 " _N_ " 行发生错误。";
put " 原始数据为: " raw_value;
end;
else do;
put "【成功】: 第 " _N_ " 行处理正常。";
end;
datalines;
100
ABC
200
;
run;
/* 得到结果 */
【成功】: 第 1 行处理正常。
NOTE: 函数 INPUT 的参数无效,位置: 行 74 列 15。
【警告】: 第 2 行发生错误。
原始数据为: ABC
规则: ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0
92 ABC
raw_value=ABC num_val=. loop_count=2 _ERROR_=1 _N_=2
【成功】: 第 3 行处理正常。输入的数据类型和规定的类型不一致,因此报错。
BY分组变量(FIRST.variable, LAST.variable)
你没看错,BY里常用的分组变量FIRST/LAST也是自动变量,分组之后可以对其选出第一条,对其操作
/* 1. 准备数据 */
proc sort data=sashelp.class out=class_sorted;
by Sex;
run;
/* 2. 分组计数 */
data check_first_last;
set class_sorted;
by Sex;
is_first = first.Sex;
is_last = last.Sex;
if first.Sex then count = 0;
count + 1;
if last.Sex then put "分组结束: " Sex= " 总人数=" count;
run;
分组结束: Sex=F 总人数=9
分组结束: Sex=M 总人数=10特殊场景变量(IORC, CMD, MSG)
_IORC_,用于处理数据读写异常等自动变量,当顺序读取或者原地更新的时候,发生找不到记录的现象就会停止报错,通过IORC,可以拦截这个错误,决定是否继续让程序运行。
/* 1. 准备数据:客户表(必须建立索引) */
data customers(index=(cust_id));
input cust_id name $;
datalines;
101 Alice
102 Bob
;
run;
/* 2. 准备数据:交易表(无需排序,且包含一个不存在的客户 999) */
data transactions;
input cust_id amount;
datalines;
101 50
999 200 /* 这是一个脏数据,客户表中没有 999 */
102 80
;
run;
/* 3. 使用 _IORC_ 进行容错匹配 */
data result;
set transactions;
set customers key=cust_id / unique;
if _iorc_ ^= 0 then do;
put "【警告】: 交易记录中的客户 " cust_id " 在客户表中不存在!";
name = "Unknown";
_error_ = 0;
end;
run;
【警告】: 交易记录中的客户 999 在客户表中不存在!至于_CMD_, _MSG_,是制作简易交互界面的功能(第一次知道SAS还能做交互界面),在SAS EG和Web端如SAS viya上无法显示窗口。
其实还有一个_NULL_,工作中也用到过,它可以不让语句里的数据集输出到硬盘且直接获得调试结果,运行速度更快,在实际工作中主要用在调试打印和生成宏变量。
data _null_;
set sashelp.class end=last_row;
/* 1. 累加计算年龄 */
retain sum_age 0;
sum_age + age;
/* 2. 输出 */
if last_row then do;
put "===============================";
put "【统计完成】 总年龄是: " sum_age;
put "===============================";
call symputx('total_age_macro', sum_age);
end;
run;
%put 这里的总年龄是宏变量的值: &total_age_macro;
===============================
【统计完成】 总年龄是: 253
===============================变量列表(SAS Variable Lists)
其实变量列表在官方文档里是一种语法的概念,既包含了语句、也包含了一些变量合集,比如:
示例
除了变量列表范围,这里还提到了个FUNCTION: OF,可以和之前的变量列表进行连用,直接用示例说明:
data numbered_range;
input Score1-Score4 8.;
/* 用of运算符选择变量,3个总计结果一致 */
Total_Score1 = sum(of _NUMERIC_);
Total_Score2 = sum(of Score1-Score4);
Total_Score3 = sum(of Score:);
datalines;
10 20 30 40
5 5 5 5
;
run;结合这些OF、':'的写法,用好这些下划线变量,能够在很短的代码里完成一些复杂的工作:
data name_range;
set sashelp.baseball;
/* 保留cr开头的列 */
*keep cr:;
/* 保留name到 nhits之间的列 */
*keep name--natbat;
/* 找出所有字符串变量里,包含'And'的行 */
if index(catx(' ', of _CHARACTER_),'And');
/* 用数组的方式,把所有为空的数值型变量,填充为0 */
array nums[*] _NUMERIC_;
do i = 1 to dim(nums);
if nums[i] = . then nums[i] = 0;
end;
/* 用数组的方式,把所有字符型变量改成大写 */
array chars[*] _CHARACTER_;
do j = 1 to dim(chars);
chars[j] = upcase(chars[j]);
end;
/* 数据开始第一次循环时,打印全部变量及其值 */
if _N_ = 1 then put _ALL_;
run;