SAS 学习笔记(九)— SAS宏

时间:2024-10-30 07:06:52

文章目录

      • 宏变量
      • 宏函数
      • symputx例程和symget函数
      • SQL过程步创建宏变量
      • 宏程序

宏变量

可以替代重复的变量和代码

  • 定义:%let indvars = ;

  • 引用 (解析):& (对文本串的替换)

  • 间接引用:& && &&&
    宏处理器对多个“&”处理规则是:从左到右扫描,若宏变量前仅含有一个“&”,则解析该宏变量;否则将相邻的两个“&”替换成一个“&”,重复上述扫描过程,直到解析过程完成

  • 输出:%put text; (后面默认就是文本串,不需要加引号;与put语句不同)

  • 输出所有系统自带 / 用户自定义 / 所有 的宏变量:%put _automatic_/_user_/_all_
    → . title ="today's date is &SYSDATE9 and today is &SYSDAY";
    当宏变量被嵌入在标题语句中,只能用双引号不能用单引号

  • 分隔符 . (句点)
    宏变量被引用时,SAS无法识别连接其后的文本,需要使用分隔符告知分隔符前的为宏变量部分。使用句点.作为宏变量分隔符。
    → . %LET libref=sashelp; proc print data=&libref..class; run;

  • 全局宏变量(由宏程序之外定义) VS. 局部宏变量

  • 删除:%symdel 宏变量名1 宏变量名2;


宏函数

宏字符串处理函数的参数可以是任意文本和(或)宏触发器:固定文本、宏变量引用、宏函数、宏调用。
固定文本参数不需要引号

  • 常用函数
宏函数 使用方法 功能
%upcase %upcase(string) 转换小写字母为大写字母
%substr %substr(string, n1, n2) 从字符串中提取子串
%scan %scan(string, n) 从字符串中提取一个词
%index %index(string) 在字符串中搜索指定文本
%eval 进行算术运算和逻辑运算
%sysfunc %str(argument) 执行SAS函数
%str 引用特殊字符(屏蔽(删除正常含义)特殊符号:+ - * / , < > = ; ’ " LT EQ GT LE GE NE AND OR NOT blank)
%nrstr %nrstr(title “S&P 500”; ) 引用特殊字符,包括SAS触发器

symputx例程和symget函数

实现在不同过程步中传递数据

  • Symputx例程 —— 把数据步的信息传给宏变量
    CALL SYMPUTX(“new_macro-variable”, value_in_string)
    • 参数1是我们正在创建的宏变量将存储数据步正在传递出的信息
    • 参数2是字符串格式的值
    • 新的宏变量是文本型,用匹配引号括起来
  • Symget函数 —— 把宏变量的信息传给数据步
    symget(“macro-variable”)
    • 参数可以是宏变量的名字,字符串变量或者字符表达式。
  • 动态赋值宏变量
proc means data = hsb2 n;
  var write;
  where write>=55;
  output out=w55 n=n;
run;
proc print data = w55;
run;
data _null_;
  set w55;
  call symputx('n55', n);
run;
%put &n55 Observations have write >=55;

// 结果:9 Observations have write >=55
// 注意: 不能用%LET语句

data hsb2_55;
  set hsb2;
  w55 = symget('n55')+0;  //实现类型的自动转换(从文本到数值)
run;
proc print data = hsb2_55;
  var write w55;
run;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

SQL过程步创建宏变量

  • 基本语法(同SQL语言)
proc sql <options>;
	select 变量列(逗号分隔) into : macro_var1 - :macro_var3
	from 表列(t1,t2,t3)
	where 行筛选
	having 组筛选
	order by 排序 <desc>
	group by 组排序 ;
quit;
//注意:sql语句中只有最后有分号
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 例子
proc sql;
  select sum(write>=55) into :w55
  from hsb2;
quit;
%put w55 is &w55;
// 结果:w55 is 9

proc sql;
  select mean(write) into :write1 - :write3
  from hsb2
  group by ses;
quit;
%put write1 to write3 are &write1, &write2 and &write3;
// 结果:write1 to write3 are 52.66667, 54.8 and 50.4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

宏程序

%macro %mend

data file1 file2 file3 file4;
  input a @@;
  if _n_ <= 3 then output file1;
  if 3 < _n_<=  6 then output file2;
  if 6 < _n_ <= 9 then output file3;
  if 9 < _n_ <=12 then output file4;
cards;
1 2 3 4 5 6 7 8 9 10 11 12
;
run;

// 利用宏程序把若干数据集合并成一个数据集
data all;
  set  file1    file2    file3    file4
  ;
run;

%macro combine;
  data all_1;
    set
    %do i = 1 %to 4;
      file&i
    %end; 
    ;
  run;
%mend;


//SAS宏的系统选项--mprint: 它会打印出由宏执行产生的SAS语句。
options mprint;
%combine          
//结果:MPRINT(COMBINE):   data all_1;
//      MPRINT(COMBINE):   set file1 file2 file3 file4 ;
//      MPRINT(COMBINE):   run;


// 带参数的宏
%macro combine(num);
  data big;
    set
    %do i = 1 %to &num;
      file&i
    %end; 
    ;
  run;
%mend; *executing the macro program;
%combine(3)
// 结果:
// MPRINT(COMBINE):   data big;
// MPRINT(COMBINE):   set file1 file2 file3 ;
// MPRINT(COMBINE):   run;


%macro gen(n,start,end);
  data generate;
    do subj=1 to &n;
	  x=int(&End-&start+1)*ranuni(0)+&start);
	  output;
	end;
run;
proc print data=generate noobs;
  title "Randomly Generated Data Set with &n Obs";
  title2 "Values are integers from &start to &end";
run;
%mend gen;

  • 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
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66