前几天讲了数据分析中SQL的基本使用方法以及具体案例分析思路,接下来会继续讲统计基础以及在SAS软件内的应用,在这之前,本文先进行SAS基础使用编程的基础介绍,后续会主要阐述SAS软件内的统计数学的应用,如分析或初步建模等,当然了,也先推荐大家有关统计学和SAS学习的书籍:统计学的两本书,分别是《深入浅出统计学》和《商务与经济统计学》,关于SAS的书籍《深入解析SAS——数据处理、分析优化与商业应用》,大家看完之后,会有一个初步的认识。
本文主要介绍SAS编程和数据处理,会分为几个部分。
一 读取外部数到SAS数据集
1,通过使用libname..语句为一个SAS逻辑库分配引用名(临时逻辑库WORK除外),但逻辑库名不能超过8个字符,必须以字母或下划线开头,其余字符必须是字母,数字或者下划线:例如,下面的SAS语句定义了一逻辑库,引用名为saslib
libname saslib 'C:sasdata';
2,SAS变量属性包括变量名,类型,长度,输出格式(format),输入格式(informat)和标签,其中类型分为字符型和数字型,录入,下面的SAS语句定义一部分变量
data saslib.sales;
input ID $ Dept $ Sales Date;
format Sales comma10. Date yymmdd10.;
informat Date date9.;
label ID=”员工ID” Dept=“部门” Sales=“销售数据”;
label Date=“销售时间”;
datalines;
上述代码就定义了变量名以及对应的类型,长度,输出或输入格式。
3.查看数据集的描述信息内容,如数据集属性内容,仍以saslib.sales为例
Proc contents data=saslib.sales;
run;
就可以看到上述定义的变量名以及对应的类型,长度,输出或输入格式。
二 对单个数据集的处理
1,keep或drop选取部分变量:data步可以通过读取原数据集的部分变量来建立新数据集,仍以saslib.sales,读取变量ID和Sales,并建立新的数据集sales1,代码如下:
data saslib.sales1;
set saslib.sales(keep=ID Sales);
run;
proc print data= saslib.sales1;
run;
新的数据集只有两个变量:ID和Sales,我们也可以用drop语句,指定drop=ID和Sales之外的其他变量,结果是一样的
2,操作数据集的观测
1)if—then语句:SAS内的条件语句,与SQL或者Excel的使用方法类似,直接举例如下:if x<y then c=5;
else c=12;
2)if 条件表达式 then delete:使用delete语句删除满足条件的观测,举例如下:
仍然是saslib.sales数据集,寻找销售数据(Sales)不为缺失值的观测并建立新的数据集saslib.sales2,代码如下:
data saslib.sales2;
set saslib.sales;
if Sales=” ” then delete;
run;
proc print data= saslib.sales2;
run;
上述代码就可以求出销售数据(Sales)不为缺失值数据集,也可以求出其他不为某些条件的数据集,只需把if内的条件表达式进行更改即可,举例如下:在saslib.sales数据集中,选取ID>10的观测输出到数据集saslib.sales1,并将销售数据(Sales)>100的观测输出到数据集saslib.sales2,代码如下:
data saslib.sales1
saslib.sales2;
set saslib.sales;
if ID>10 then output saslib.sales1;
if Sales>100 then output saslib.sales2;
run;
proc print data= saslib.sales1;
run;
proc print data= saslib.sales2;
run;
3)if—then的赋值语句:仍然以数据集saslib.sales为例,当ID=8时,Sales提高20%,
ID=10时,Sales提高10%,其他情况,Sales都提高5%,并生成新的数据集saslib.sales3下面有几种写法,得出的结果是一致的,代码如下:
data saslib.sales3;
set saslib.sales;
if ID=8 then Sales= Sales*1.2 ;
else if ID=10 then Sales= Sales*1.1;
else Sales= Sales*1.05;
run;
proc print data= saslib.sales3;
run;
第二种写法:
data saslib.sales3;
set saslib.sales;
select (Sales)
when(8) Sales= Sales*1.2;
when(10) Sales= Sales*1.1;
otherwise Sales= Sales*1.05
run;
proc print data= saslib.sales3;
run;
以上两种的结果是一样的。
3 分组与排序
1)sort by过程排序:要求数据集结果内的观测按照by语句中的变量进行升序或降序排列,仍然以数据集saslib.sales为例,要求输出的数据集saslib.sales4按照Sales进行降序排列,代码如下:
Proc sort data=saslib.sales out= saslib.sales4;
by descending Sales;
run;
2)找到分组的第一个和最后一个观测:仍然以数据集saslib.sales为例,取每组ID内最高和最低的Sales,生成新的数据集saslib.sales2,代码如下:
data saslib.sales2;
set saslib.sales;
by ID;
if first.ID or last.ID;
run;
4,循环和数组
1)迭代do语句:基本形式为
do 索引变量=开始值< to 结束值><by 递进值><while (表达式)><until(表达式)>;
SAS语句;
End;
举例如下:使用do循环生成数据集do1,数据集包含变量x和y,x的值为1、3、5,y为x的平方。代码如下:
Data work.do1;
do x=1 to 5 by 2;
y=x**2;
output;
end;
run;
2)do until语句:重复执行do循环的语句,直到条件为真。基本形式如下
do until (表达式);
SAS语句;
end;
举例如下:将给定字符串中包含的各个单词分开写入数据集中
data work.all;
length word $20;
drop string;
string=”the quick brown fox jumps over the lazy dog”;
do until(lengthn(word)=0);
count+1;
word=scan(string,count);
output;
end;
结果如下:
三 对多个数据集的处理
1,数据集的纵向串联
1)set语句纵向串联:基本形式如下
Data 新数据集;
set 数据集1 数据集2………;
Run;
举例如下,对数据集work.New1和work.New1进行纵向串联,生成新的数据集work.New12,代码如下:
data work.New1;
input Emp_ID $ Emp_Name $ @@;
datalines;
ET001 Jimmy ED003 Emy EC002 Alfred EQ004 Kim
;
run;
data work.New2;
input Emp_ID $ Emp_Name $ @@;
datalines;
EQ122 Molly ET121 Dillon ET124 Helen ED123 John
;
run;
data work.New12;
set work.New1 work.New2;
run;
proc print data=work.New1;
run;
proc print data=work.New2;
run;
proc print data=work.New12;
run;
结果如下:
2)by 语句穿插串联:所有舒服数据集先按照by变量排序,新的数据集也将按照该排序,基本形式如下:
Data 新数据集;
set 数据集1 数据集2………;
by 变量1 变量2…………;
Run;
2,merge by数据集的横向合并:使用by语句,也称为匹配合并,注意在使用by语句时,输入数据集必须按照by变量排序。这个点就不举例子了,和上篇文章内的SQL类似。
3,数据集的更改
modify语句进行单个数据集的更改:运用该语句可以更改原数据集中的变量,但是不能再原数据集中添加或者更改,举例如下:数据集work.inventory中包含产品,库存和价格的信息,先决定将每个产品的价格提高15%,代码如下:
data work.inventory;
modify work.inventory;
price=price*1.15;
run;
proc print data=work.inventory noobs;
run;
前后代码结果为:
4,使用自动变量first.与last.:data步如果使用了by语句,会自动生成两个数值型自动变量first.与last.变量,分别用来辨识by组合的第一条和最后一条观测,举例如下:
数据集Sales中包含了每位员工的销售额和员工所属部门以及性别数据,统计各部门男员工和女员工的总销售额,代码如下:
首先将数据集Sales按照Dept和Gender排序,在运用first.与last.变量计算:
proc sort data=work.sales;
by Dept Gender;
run;
data work.sales_dept;
set work.sales;
by Dept Gender;
retain sales_by_dept;
if first.Gender then
sales_by_dept=0;
sales_by_dept=sales_by_dept+sales;
if last.Gender;
keep Dept Gender sales_by_dept;
run;
proc print data=work.sales_dept noobs;
title 'Sales by Department by Gender';
run;
前后图表如下:
5,使用hash对象处理多个数据集:基本形式如下:
Declare object hash 对象名(<主题1:内容1 <,主题2:内容2,…………>>);
Hash 对象名.definekey(<主题1:内容1 <,主题2:内容2,…………>>);
Hash 对象名.definedata(<主题1:内容1 <,主题2:内容2,…………>>)
Hash 对象名. Definedone()
第一行定义hash的对象名称,第二行和第三行分别定义了对象的key变量和data变量,第四行表示hash对象定义结束。下面举例说明:
公司现有库存1000台汽车,每台车可以发往各个仓库,但是不同仓库给公司带来的边际收益不同,而且每个仓库有一定的容量限制,现在求每个仓库发多少车,同时公司的效益最高,下面是仓库收益数据集expected_profit和仓库容量数据集warehouse_constraint部分数据如下图:
代码如下:data work.allocation;
retain total_cars_before 1000;
length warehouse_id $6;
if _N_=1 then
do;
declare hash constraint(dataset: "work.warehouse_constraint");
constraint.definekey('warehouse_id');
constraint.definedata('capacity');
constraint.definedone();
call missing(warehouse_id,capacity);
end;
set work.expected_profit;
rc = constraint.find();
if rc = 0 and capacity>=1 and total_cars_before>=1 then
do;
capacity=capacity-1;
total_cars_after=total_cars_before-1;
rc=constraint.replace(key:warehouse_id, data: capacity);
if rc=0 then
do;
output work.allocation;
total_cars_before=total_cars_before-1;
end;
else put "Error: Replace capacity failed!";
end;
else if rc ne 0 then
put "Error: Failed to find warehouse capacity!";
keep warehouse_id capacity profit_margin total_cars_before total_cars_after;
run;
结果如下:
至此,SAS基本的编程就说完了,后续会进行SAS的统计与初步建模探讨。