SAS_Base_Programming_Using_SAS_9.4(2019)个人理解

本文介绍了SAS编程中涉及的数据导入、变量处理、条件语句、循环、格式设置等基本操作,如使用PROCIMPORT导入数据,通过IF-ELSEIF-ELSE进行条件判断,用RETAIN保留变量值,用TRANSPOSE转置变量,以及如何创建和应用自定义格式等。
摘要由CSDN通过智能技术生成

导入tab文件

目录

导入tab文件

查找变量中的某些字段

编译阶段compliation phase 写入哪些部分?(以下错误的是)

.1可以直接写为1

Sumsec+  变量后直接跟“+”

retain设定初始值

length修改变量长度,一定要放在对应变量前的位置

"IF  ELSE IF  ELSE"  "IF THEN" 

transpose转置变量--需要回头再来学习

宏变量应用到title

nesting嵌套括号内优先级更高

set与merge

rename

in

do的嵌套与until、while

formtlib 设置自定义格式

intnk查找两个日期区间

intnx中的“b”“d”“e”

week为从周日计算

 left、scan、trim去除变量中的空格值

catx用符号将变量连接

upcase、lowcase与Propcase

compbl去掉多余空格变成1个空格

compress删除所有空格

substr截取变量长度或替换

关于ceil与floor

ceil

floor


  1. &与空格作为分隔符的文件时, dbms=dlm; delimiter="&";

tab作为分隔符时,dbms=tab ; delimiter= “09”x;

proc import datafile='C:\Users\Student1\cert\class.txt' dbms=tab

out=class
replace;
delimiter='09'x; run;
proc print data=class; run;

查找变量中的某些字段

proc print data=cert.class;
where name like "%DA%";
run;

  1. like可以换成contents与?
  2. index与find
     
    set cert.temp;
    where index(job,'word processing') > 0;
    run;
    proc print data=work.datapool;
    run;


    1).index与之前like的区别是不用体现var job 直接在index(job,“word processing”)
    2).找到不不区分大小写的:
    index(upcase(job),'WORD PROCESSING')
    index(lowcase(job),'word processing')


    find的用法跟index一样 目前没发现区别 都是where find(job,"word processing")>0

编译阶段compliation phase 写入哪些部分?(以下错误的是)

a.the data set descriptor-----> √
b.the first observation ------> X   
c.the program data vector-----> √
d.the _N_and_ERROR_-----> √


在编译阶段,将创建程序数据向量。程序数据向量包括两个自动变量_N_和_ERROR_。新SAS数据集的描述符部分在编译阶段结束时创建。描述符部分包括数据集的名称、观察结果和变量的数量,以及变量的名称和属性。直到执行阶段才写入观察结果

 


.1可以直接写为1

Sumsec+  变量后直接跟“+”

data work.stresstest;
set cert.tests;
TotalTime=(timemin*60)+timesec;
SumSec+totaltime;
run; 
(注:sumsec+后面 从0开始累加计算totaltime的值)

retain设定初始值

retain SumSec 5400;
 sumsec+totaltime;   
(注:retain一般与sumsec一起用啊)

length修改变量长度,一定要放在对应变量前的位置

data stress; 
 set cert.stress; 
 TotalTime=(timemin*60)+timesec; 
 retain SumSec 5400; 
 sumsec+totaltime; 
 length TestLength $ 6;        (字符变量后面加$ 并且针对的是变量的内容)
 if totaltime>800 then testlength='Long'; 
 else if 750<=totaltime<=800 then testlength='Normal'; 
 else if totaltime<750 then TestLength='Short'; 
run;

proc print data= stress;
run;
data work.newloan; 
 set cert.records; 
 TotLoan+payment; 
 if code='1' then Type='Fixed'; 
 else Type='Variable'; 
  length type $ 10; 
run;
 (新变量的长度由DATA步骤中的第一个引用决定,而不是由数据值决定。
你要设置length的话必须要在第一个变量前,目前的Type长度为5“Fixed”)

"IF  ELSE IF  ELSE"  "IF THEN" 

多个条件查询要使用if else 就像多个where要使用where also一样,最后一个else不需要加if:
 

if totaltime>800 then TestLength='Long'; 
 else if 750<=totaltime<=800 then TestLength='Normal'; 
 else put 'NOTE: Check this Length: ' totaltime=; 
run;                      
(注:  else put “想说的”  变量=  就能看到不满足条件的具体值是多少了)

  if tolerance='D';
 TotalTime=(timemin*60)+timesec;     
(注:if后直接加分号时,只显示为D时与totaltime的值 )

if   tolerance='D'; 
 then TotalTime=(timemin*60)+timesec; 
(两者效果一样)

transpose转置变量--需要回头再来学习

proc transpose data=cert.trials out=transtrials3; /* #1 */
var cholesterol triglyc uric; /* #2 */
id name; /* #3 */
by testdate; /* #4 */
run;
proc print data=transtrials3; /* #5 */
run; 
(这个目前不理解 为什么用id 后 跟name 与 testdate没事 其他就报错 日志显示重复)

宏变量应用到title

%let TitleX=PROC MEANS Of Only &Cyl_Count Cylinder Vehicles;
%let Cyl_Count=12;
Title "&TitleX";
proc means data=sashelp.cars;
 where Cylinders=&Cyl_Count;
 var MSRP;
run;    
(注:这个要注意的是  字符型的宏变量要用引号 数值型则不带引号 带了会报错)

nesting嵌套括号内优先级更高


if finlexam>=95
 and (research='A' or
 (project='A' and present='A'))
 then Grade='A+';

(优先计算最内括号内的project='A' and present='A)

set与merge
 

1. data work.concat;
 set cert.therapy2012;
 set cert.therapy2013;
run;


2. data work.concat;
 set cert.therapy2012 cert.therapy2013;
run;


3. data merged; 
 merge a b; 
 by num; 
run;


4. proc sort data=cert.demog; 
 by descending id; 
run; 
proc sort data=cert.visit; 
 by descending id; 
run; 
data work.merged; 
 merge cert.demog cert.visit; 
 by descending id; 
run; 

rename

data work.merged; 
 merge cert.patdat (rename=(date=BirthDate))
 cert.visit (rename=(date=VisitDate));
 by id; 
run; 

in

data work.merged; 
 merge cert.patdat(in=inpat 
 rename=(date=BirthDate)) 
 cert.visit(in=invisit
 rename=(date=VisitDate)); 
 by id; 
 if inpat =1 and invisit=1;
run; 
proc print data=work.merged; 
run;



(这样可以排除缺失值 
可以通过以下两种方式指定前面示例中的子集IF语句。第一个IF语句专门检查值1。第二个IF语句检查一个既不缺失也不为0的值(对于IN= variables,它总是为1)。

if inpat=1 and invisit=1; 
if inpat and invisit;

关于merge中几个要点:
1. by的顺序必须相同 不一致报错
2.相同变量后不同数值时 比如 id=1 表1 age=23 表2 age=24 表2会覆盖表1
3.不被覆盖就rename 排除缺失值用数据集 后 (in=xx) ; by xxx;if xx = 1 and。。。
4.set a c 如果a中只有id name

b只有id sales

这个公式第二个观测值 为missing  他会按表顺序 a name 1 2 3 4 然后 b sale 1 2 3 4 第二个观测值为name2 pale为missing

不同语句的用法:concatenate(连接) 中 :1.set a;
                             set c; 显示交集

do的嵌套与until、while

do主要有两个要点 :  

*1.嵌套 nesting  
 每一个do语句都要加end  中间的capital + 2000  为从初始值2k开始   
capital+interest为interest累计


data work.earn;
 do year=1 to 20;
 Capital+2000;
 do month=1 to 12;
 Interest=capital*(.075/12);
 capital+interest;
 end;
 end;
run;

2.data work.invest;    
  *(until为从2000起始循环多少次到50000  如果10次最大到不了就用capital+4000尝试)
 do year=1 to 10 until (Capital>=50000);
 capital+2000;
 capital+capital*.10;
 end;
run;

3.data work.invest;      *while会在开始时循环时求值,如果条件不符合直接循环失败
 do while(Capital>=50000);
 capital+2000;
 capital+capital*.10;
 Year+1;
 end;
run;

UNTIL表达式在DO循环的底部求值。
因此,DO循环总是至少执行一次。
WHILE表达式在执行DO循环之前求值。因此,如果条件最初为false,则DO循环永远不会执行。

举例:到达 250时 或者使用10加仑时 gallons=1 to 10 ... ; while(Distance<=250) 换成until (Distance>=250)
---while 与 until 相反 while(le)要包含你要的条件 until则需要大于你要的条件 (ge)

formtlib 设置自定义格式

libname formtlib 'c:\sas\formats\lib';
proc format library=formtlib fmtlib;
run;

*fmtlib直接展示将关键字FMTLIB添加到PROC FORMAT语句中,
将显示目录中所有格式的列表,以及它们值的描述

首先建立永久的格式数据集 lib为library缩写
 

libname formtlib 'C:\Users\Student1\formats\lib';
proc format lib=formtlib; *不加这个lib=xxx 会自动创建临时的work.formtlib
value gender
 1 = 'Male';
 value agegroup
 13 -< 20 = 'Teen'
 20 -< 65 = 'Adult'
 65 - HIGH = 'Senior';
 value $col
 'W' = 'Moon White'
 'B' = 'Sky Blue'
 'Y' = 'Sunburst Yellow'
 'G' = 'Rain Cloud Gray';
run;

 现在将格式存在了永久数据库中,还要将格式输出才可以替换:这一步实测必须有才行不然报错输出找不到这些变量名

proc format;
 value gender
 1 = 'Male'
 2 = 'Female';
 value agegroup
 13 -< 20 = 'Teen'
 20 -< 65 = 'Adult'
 65 - HIGH = 'Senior';
 value $col
 'W' = 'Moon White'
 'B' = 'Sky Blue'
 'Y' = 'Sunburst Yellow'
 'G' = 'Rain Cloud Gray';
run;

 设置完成后format

data work.carsurvey;
 set cert.cars;
 format Sex gender.   Age agegroup.   Color $col.   Income Dollar8.;
run;
proc print data=work.carsurvey;
run;

使用low/unknown选择不在范围内的变量

proc format lib=formtlib; * 设置格式 low-<13="child"   other = "unknown";
 value agefmt
 low-<13='child'
 13-<20='teenager'
 20-<65='adult'
 65-high='senior citizen'
 other='unknown';
run;

使用“||”将变量组合在一起

Assignment=site||"/"||dept;

intnk查找两个日期区间

*查找当月工作满20年的员工:

data work.anniversary;
 set cert.mechanics(keep=id lastname firstname hired); 
Years=intck('year',hired,today()); 
 if years=20 and month(hired)=month(today());   
*当月工作满20年  如果不加month(hired)=month(today()) 会导致 含有其他月份
run;
proc print data=work.anniversary; 
 title '20-Year Anniversaries'; 
run;

intnx中的“b”“d”“e”

month后加5个月  b表示该月起始1号  m中间  d 最后

MonthX=intnx('month','01jan2018'd,5,'b'); 21336 (June 1, 2018)
MonthX=intnx('month','01jan2018'd,5,'m'); 21350 (June 15, 2018)
MonthX=intnx('month','01jan2018'd,5,'e'); 21365 (June 30, 2018)

week为从周日计算

 left、scan、trim去除变量中的空格值

不区分空格与逗号时

LastName=scan(name,1,' ,');

*就等于LastName=scan(name,1)  空格与逗号是默认的分隔符,所以也可以不列出
*trim 去掉尾随的空格值    
"||"连接符 不会移除空格值    
left的作用是把这个name里的空格先去掉,
就是Mary前的空格用left去掉,然后再用trim去掉其他空格  
(不用left跟不用trim一个效果,全都有空格 可能必须都得用)

data work.nametrim; 
length Name $ 20 First Middle Last $ 10; 
Name= 'Jones, Mary Ann, Sue'; 
First = left(scan(Name, 2, ',')); 
Middle = left(scan(Name, 3, ',')); 
Last = scan(name, 1, ','); 
FullName = trim(First) || trim(Middle) ||Last; 
drop Name;
run;
proc print data=work.nametrim;
run;

注意:一般lastname后面不添加空格,不用使用trim

catx用符号将变量连接

data work.newaddress(drop = address city  state   zip);
set  cert.temp;
newaddress=catx(', ',address,city,zip);
run;

proc print data =work.newaddress;
run;

*最终显示为、address,city,zip三个变量的观测值用“,”相连接

upcase、lowcase与Propcase

upcase & lowcase & propcase


*大小写:
 Job=upcase(job);   
 Contact=lowcase(contact);

*首字母大写
 Contact=propcase(contact);

compbl去掉多余空格变成1个空格

*多余空格都变成一个空格,
如果一个变量在COMPBL函数返回值之前没有被赋值,
那么该变量将被赋予第一个参数的长度。 





data _null_;
 string='125         E   Main     St';
 length address $10;
 address=compbl(string);
 put address;
run;


这里address=compbl(string);之前为
length address $10,所以显示为10个长度  125 E Main(算上单一空格)
未显示完全

compress删除所有空格

data _null_;
 a='A B C D';
 b=compress(a);
 put b=;
run;

*b=ABCD   还有很多附件内容这个  从a到x 的 compress  留着以后再说吧 

substr截取变量长度或替换

*1.放在等号右边 截取数据  features=substr(VIN,4,5);



data work.agencyemp(drop=middlename); 
 set cert.agencyemp; 
 length MiddleInitial $ 1;
 MiddleInitial=substr(middlename,1,1); *这里最终结果为M  首字母且只有一位
run;
proc print data=work.agencyemp;
run;




*2.substr 放在=左边 替换相应的数据



substr(test,4,2)= “92”;

test------------->test
S7381K2 → S7392K2
S7381K7 → S7392K7

总而言之,当SUBSTR函数位于赋值语句的右侧时,该函数提取子字符串;
当SUBSTR函数位于赋值语句的左侧时,该函数将替换字符变量的内容。
将Phone中的前三位为622的观测值换成433
先找到622的位置,这里用exchange来代替,然后drop删掉



data work.temp2(drop=exchange);
 set cert.temp;
 Exchange=substr(phone,1,3);
 IF EXCHANGE ="622" THEN 
 substr(phone,1,3)='433';
run;
proc print data=work.temp2;
run;      

*不用if会把所有前三位替换成433  如果想只替换622需要用if then

关于ceil与floor

e-12   如果参数在一个整数的1E-12范围内,函数返回该整数

ceil内向上取整数到1,floor向下取整数到0

ceil

data _null_;
 var1=2.1;
 var2=-2.1;
 a=ceil(var1);
 b=ceil(var2);
 put "a=" a;
 put "b=" b;
run;

a=3
b=-2

-----------------------------


data _null_;
 c=ceil(1+1.e-11);
 d=ceil(-1+1e-11);
 e=ceil(1+1.e-13)
 put "c=" c;
 put "d=" d;
 put "e=" e;
run;

c=2
d=0
e=1

----------------------------------------


data _null_;
 f=ceil(223.456);
 g=ceil(763);
 h=ceil(-223.456);
 put "f=" f;
 put "g=" g;
 put "h=" h;
run;

f=224
g=763
h=-223

floor

data _null_;
 var1=2.1;
 var2=-2.1;
 a=floor(var1);
 b=floor(var2);
 put "a=" a;
 put "b=" b;
run;

a=2
b=-3

------------------------
data _null_;
 c=floor(1+1.e-11);
 d=floor(-1+1e-11);
 e=floor(1+1.e-13)
 put "c=" c;
 put "d=" d;
 put "e=" e;
run;

c=1
d=-1
e=1

---------------------------
data _null_;
 f=floor(223.456);
 g=floor(763);
 h=floor(-223.456);
 put "f=" f;
 put "g=" g;
 put "h=" h;
run;

f=223
g=763
h=-224

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值