没有合适的资源?快使用搜索试试~ 我知道了~
首页[SAS]跟crackman学SAS编程
[SAS]跟crackman学SAS编程
需积分: 44 215 浏览量
更新于2023-05-27
评论
收藏 1.84MB PDF 举报
[SAS]跟crackman学SAS编程 crackman的sas编程序列,觉得对大家可以对sas的细节问题有一定的理解!
资源详情
资源评论
资源推荐

1.简单举例,假设我有 4 个 TXT 文件,每个文件中 1 个数值变量,共 5 个观测(如 1 2 3 4 5),
数据分析前,需要先用循环语句对这几个文件的数据预处理,
我现在的问题在于怎么用 SAS 语句读取文件,以前做的分析全用 VB 程序编的:
1.例如,VB 语句可以这样写:
For i=1 to 4
open “E:” & i & “.txt” for Input As 1
While Not EOF(1)
Input #1, b
a(m) = b
m = m + 1
Wend
Close 1
Next i
2.尝试用 SAS 语句:
data a;
do i=1 to 4 by 1;
infile “E:” i “.txt”;
end;
input v ;
run;
———问题:SAS 语句在“Infile”那行的“i”处提示错误,数据读不进去……请问 SAS 语句中有什
么方法可以实现以上用途吗?
——–请各位高手不吝相助,不胜感激~~~
hopewell 答案:
data temp;
do in=1 to 4;
fname=cats(‘d:’,in,’.txt’);
do until(last);
infile XXX filevar=fname end=last;
input v;
output;
end;
end;
stop;
run;
此处注意几点:
1.DO 循环:很巧妙的注意到了 D 盘下 TXT 文件名的规律性,都是一个数字命名的文件名,
用变量 IN,采用 CATS 字符串连接函数,循环创建 D 盘下的 TXT 文件名变量 FNAME;
2.在读取文本数据时,很多人都知道用 INFILE,以及 INFILE 基本参数,XXX 是文件名,filevar
是打开或者关闭指定的文件名,end=last 是定义一个变量了解是否读到文件的结尾处,这里
的 LAST 与 until 里面的 last 保持一致
3.STOP,这里为什么用 STOP,这个很重要,如果你去掉 STOP,那么你会发现无线循环下去。
所以当我们在 DATA 步里面制定读取的数据是以随机方式读取的时候,例如这个里面的 IN,
或者是在 SET 里面的 POINT 等,需要用 STOP。Because SAS does not detect an end-of-file with

this access method, you must include program statements to prevent continuous processing of
the DATA step.
在这里提出一个思路:我们在解决这类问题的时候,先考虑是一个文件的时候,你如何写程
序,如何读取,如果是两个文件的时候,程序与读取一个文件时程序有什么不同,这种不同
是什么原因导致,这个不同是否有规律可循,寻找到规律你就有思路了.
2.sql 应用
原程序和解答在这里,想分解一下答案程序
data a;
input nbr code;
datalines;
13900000000 10102345
13900000000 10102346
13900000000 10102347
13900000000 10102348
13900000001 10102345
13900000001 10102346
13900000001 10102349
13900000002 10102345
13900000002 10102347
13900000002 10102349
13900000003 10102345
13900000003 10102346
13900000003 10102348
13900000003 10102349
;
run;
proc sql;
create table b as
select
a.code as prom_1
,b.code as prom_2
,count(distinct a.nbr) as Csr_Cnt
from a a
inner join a b
on a.code<b.code
and a.nbr=b.nbr
group by
a.code
,b.code
;
quit;
首先 soporaeternus 哥们的 SQL 确实很不错,学 SQL,可以看看他的程序,学习的地方太多
了。

对于这个程序思路如下:
首先利用在 SQL 中的同一个数据集不同的别名,克隆另外一个相同的数据集,利用 ON 语句
中条件,以及 INNER JOIN 进行 CODE 的组合,这个是解决问题的关键,先形成组合。因为不
同 NBR 的 CODE 组合,有些相同,有些不相同,于是用 GROUP BY 来排除重复的组合,保证
组合的唯一性,为后面计算 NBR 提供正确唯一的组合。因为不同的 NBR 可能存在相同的 CODE
组合,反过来,同一个的 CODE 组合存在不同的 NBR,因为我们计算的是 NBR 的个数,因此
我们在 GROUP BY 限定了 CODE 组合的唯一性,然后利用 COUNT 函数来计算 NBR 的个数,
思路就是这样,想起来其实也不难,关键是面对数据的时候要快速的理清思路很关键。这里
指的学习是:克隆相同的数据集,GROUP BY 保证 CODE 组合的唯一不重复.
3.sql 中宏变量的赋值
data a2;
num=0;
do _n_=1 by 1 until(last._col0);
set a1;
by _col0;
num+1;
output;
end;
run;
proc sql;
select max(num) into : obs
from a2;
quit;
%macro aa();
data a3;
do i=1 by 1 until(last._col0);
set a1;
by _col0;
array m(*) m1-m%left(&obs.);
m(i)=rate3_change;
end;
drop i rate3_change;
run;
%mend;
%aa;
这个哥们先后用转置和数据实现了按照要求读入数据并实现既定的数据集格式
先分析这个哥们的程序:
1.建立数据集 A1,并进行排序,为后面的 SET 做一个准备
2.在建立数据集 A2 的时候,设置一个变量 NUM,这个变量是表示有每一_COLO 重复的次数,
这个很关键,因为后面就是根据重复的次数来设置数组的。
3.将每一个_COLO 重复的次数的变量 NUM,用 SQL 赋值给一个宏变量,然后作为数组的界
值,而且随着_n_的不同,引起的 NUM 不同,导致数组的界值不同,因为相同的_COLO 的

rate3_change 能在一个观测里体现出来。
这个里面最关键的是寻找宏循环中数组的界值与_COLO 重复次数,用了一个 NUM 和宏变量
&obs.
值得学习的一点.
4.data step 及宏调用
在这里提供了两个循环调用宏的方法,一个是用另外一个宏循环调用外部的已经编写好的宏
另外一个是在 data 步里面调用宏。
%macro outer;
%do i=1 %to 10;
%inner2(0, 1, &i);
%end;
%mend;
%outer
这个是第一个方法,其实这个方法我最熟悉也经常用的一个方法,封装在另外一个宏循环里
面,结构清晰,不容易出错。
其实在这里给我们写程序提供了一个思路,对于一个比较复杂的程序来说,我们要学会功能
分解,结构化的去设计程序。例如在这个程序里面,
我们讲重复需要实现的过程或者步骤写成一个宏程序,设置好宏参数。解决一个比较复杂问
题的时候,将问题分解成若干个小问题,对于每一个问题或者每一个功能写成一个宏模块,
但是一定要设计好参数,这个参数是与其他结构模块相互沟通的接口。就想现在建房子一样,
都是组合式,每一个部门都是标准化设计,然后组合在一起实现一个整体的需要或者整体的
功能。
hopewell 的程序里面提供一个宏宇 data 步交互的方法
%macro inner(x,y,z);
%put NOTE:*** Macro inner: x=&x y=&y z=&z ***;
%mend inner;
data _null_;
do i=1 to 3;
call execute(cats(‘%inner(0,1,’,put(i,best.),’)'));
/* %inner(0,1,i);*/
end;
run;
其实要说难理解应该是 call execute(cats(‘%inner(0,1,’,put(i,best.),’)'));
其实这句话里面 cats 连接字符函数,最后得出的结果其实就是 call execute(‘%inner(0,1,i)’)
但是在这里如果直接写 call execute(‘%inner(0,1,i)’)岂不是更简洁?
如果说是没有参数,call execute(‘%inner’) 这样是可以的,但是如果是参数,就注意,如果
写成 call execute(‘%inner(0,1,i)’),他会解析成一个宏调用,%inner(0,1,i),同时 DATA 步停止,
而不是我们想的%inner(0,1,1)这样,因此要想得到%inner(0,1,1)这样解析结果,就要对 I 进行
一个处理,把%inner(0,1,1)看做一个字符串,对于这个字符串变化的那个需要用 put 函数将
其转换一个字符,用 cats 来连接。
至于 call execute 的使用方法:可以看看下面一个我转载的帖子
[功能]解析参数,如果解析后的值是 sas 语句(sas statement),则在下一个步边界(step

boundary)执行;如果此值为 macro 语言元素(macro language element),则立即执行.
用于在 data step 中与 macro 机制进行交互.
[分类]
宏(macro)
[语法]
CALL EXECUTE(argument);
[参数]
argument
指定一个产生宏调用或者 sas 语句的字符表达式或者常量.argument 可以是:
一个字符串,放入引号内
data 步的字符变量,不要使用引号括住
一个字符表达式,数据步解析成宏文本表达式(macro text expression)或者 sas 语句.
[详细]如果参数被解析成一个宏调用,则宏立刻运行,在这个宏执行时,data 步的执行暂停.
如果参数被解释成一个 sas 语句,或者宏的执行产生 sas 语句,这些语句在 call execute
子程序的所在的 data 步结束后才执行.
[CALL EXECUTE 子程序同步(timing)详解]
当想有条件的执行 macro 时,CALL EXECUTE 很有用.但牢记,如果 call execute 产生 macro
language elements,
则他们立即执行;如果 call execute 产生 sas language statements,或者 macro language
elements 产生 sas language statements,这些 statements 在当前 data step 执行后执行.
下面两个例子阐述用户使用 call execute 常有的问题
例 1:
data prices;/* ID for price category and actual price */
input code amount;
cards;
56 300
99 10000
24 225
;
%macro items;
%global special;
%let special=football;
%mend items;
data sales;/* incorrect usage */
set prices;
length saleitem $ 20;
call execute(’%items’);
saleitem=”&special”;
run;
在 DATA SALES step 中,在 data 步编译时,对 SALEITEM 的赋值需要 macro 变量 SPECIAL 的值.但
是直到 data step 执行时,call execute 才产生这个值.所以,在 log 中能看一个
未解析宏变量的消息,并且 SALEITEM 的值为&special.
在这个例子中,去掉宏定义或者把 DATA SALES 步放到宏 ITEMS 中更好.在这两种情况下,
call execute 都不必要,也没什么用处.下面是此程序正确的一个版本
剩余124页未读,继续阅读








weixin_44523404
- 粉丝: 1
- 资源: 13
上传资源 快速赚钱
我的内容管理 收起
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助

会员权益专享
安全验证
文档复制为VIP权益,开通VIP直接复制

评论0