Categories
日常应用

七天搞定SAS(七):常用统计模型

本系列连载文章:

其实最后一天,反而是任务最繁重的。这一天,需要纵览SAS的各个常用的统计模块。BTW,在用惯了ggplot2之后,再也不认为有任何理由用其他软件画图了...所以SAS的图形模块自动被我无视(貌似很多SAS用户也一直在吐槽这东西着实不好使)。

SAS里面的概要统计:PROC MEANS

其实前几天也说过了PROC MEANS,不过这里稍稍补充一点置信区间的东西吧。其实它的参数真的挺多的:

    • CLM:双侧置信区间
    • CSS:调整平方和
    • CV:变异系数
    • KURTOSIS:峰度
    • LCLM :单侧置信区间——左侧
    • MAX:最大值
    • MEAN:均值
    • MIN:最小值
    • MODE:众数
    • N :非缺失值个数
    • NMISS:缺失值个数
    • MEDIAN(P50):中位数
    • RANGE:范围
    • SKEWNESS:偏度
    • STDDEV:标准差
    • STDERR:均值的标准误
    • SUM:求和
    • SUMWGT:加权求和
    • UCLM:单侧置信区间:右侧
    • USS:未修正的平方和
    • VAR:方差

ode variance

  • PROBT:t统计量对应的p值
  • T:t统计量
  • Q3 (P75):75%分位数,etc.
  • P10:10%分位数,etc.

在调用CLM的时候需要指定ALPHA:

DATA booklengths;
INFILE 'c:\MyRawData\Picbooks.dat';
INPUT NumberOfPages @@;
RUN;
*Produce summary statistics;
PROC MEANS DATA=booklengths N MEAN MEDIAN CLM ALPHA=.10;
TITLE 'Summary of Picture Book Lengths';
RUN;

结果如下:

2013-12-09 15_46_26-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS里面的相关性分析:PROC CORR

虽然correlation一直被各种批判,但是往往在拿到数据的第一步、毫无idea的时候,correlation还是值得一看的参考指标。SAS里面的PROC CORR提供了相应的功能。

PROC CORR DATA = class;
VAR Television Exercise;
WITH Score;
TITLE ’Correlations for Test Scores’;
TITLE2 ’With Hours of Television and Exercise’;
RUN;

SAS的相关性分析结果输出如下:

2013-12-09 15_47_04-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS里面的基本回归分析:PROC REG

类似于R中的lm(),这个实在是没什么好说的了,最基本的最小二乘法。

DATA hits;
INFILE 'c:\MyRawData\Baseball.dat';
INPUT Height Distance @@;
RUN;
* Perform regression analysis;
PROC REG DATA = hits;
MODEL Distance = Height;
TITLE 'Results of Regression Analysis';
RUN;

SAS的输出结果如下:2013-12-09 15_47_46-The Little SAS Book(Fourth).PDF - Adobe Reader

 

包含了回归模型的基本统计量。我们一般更关注的回归系数:

2013-12-09 15_49_16-The Little SAS Book(Fourth).PDF - Adobe Reader

到这里,我的感慨就是:真的很像Stata呀!值得注意的是,REG有很多可选的参数,对于这些参数是干嘛用的,最权威的自然还是SAS官方的文档:http://support.sas.com/documentation/cdl/en/statug/63033/HTML/default/viewer.htm#statug_reg_sect007.htm。其实熟悉了SAS的语法和工作模式之后,具体到某个模型还是看官方文档比较舒服。不愧是商业软件啊,文档写的都很专业,有很多模型选择问题其实看看文档就能多少明白一些了。

比如PROC REG的参数就有:

Table 73.1 PROC REG Statement Options
Option Description
Data Set Options
DATA= names a data set to use for the regression
OUTEST= outputs a data set that contains parameter estimates and other
model fit summary statistics
OUTSSCP= outputs a data set that contains sums of squares and crossproducts
COVOUT outputs the covariance matrix for parameter estimates to the
OUTEST= data set
EDF outputs the number of regressors, the error degrees of freedom,
and the model to the OUTEST= data set
OUTSEB outputs standard errors of the parameter estimates to the
OUTEST= data set
OUTSTB outputs standardized parameter estimates to the OUTEST= data
set. Use only with the RIDGE= or PCOMIT= option.
OUTVIF outputs the variance inflation factors to the OUTEST= data set.
Use only with the RIDGE= or PCOMIT= option.
PCOMIT= performs incomplete principal component analysis and outputs
estimates to the OUTEST= data set
PRESS outputs the PRESS statistic to the OUTEST= data set
RIDGE= performs ridge regression analysis and outputs estimates to the
OUTEST= data set
RSQUARE same effect as the EDF option
TABLEOUT outputs standard errors, confidence limits, and associated test
statistics of the parameter estimates to the OUTEST= data set
ODS Graphics Options
PLOTS= produces ODS graphical displays
Traditional Graphics Options
ANNOTATE= specifies an annotation data set
GOUT= specifies the graphics catalog in which graphics output is saved
Display Options
CORR displays correlation matrix for variables listed in MODEL and
VAR statements
SIMPLE displays simple statistics for each variable listed in MODEL and
VAR statements
USCCP displays uncorrected sums of squares and crossproducts matrix
ALL displays all statistics (CORR, SIMPLE, and USSCP)
NOPRINT suppresses output
LINEPRINTER creates plots requested as line printer plot
Other Options
ALPHA= sets significance value for confidence and prediction intervals and tests
SINGULAR= sets criterion for checking for singularity

SAS里面的基本方差分析:PROC ANOVA

方差分析也就不赘述了,其实我感觉没有回归分析更用的普遍...这俩东西某种程度上也是一回事儿,看怎么理解了。

PROC ANOVA DATA = basket;
CLASS Team;
MODEL Height = Team;
MEANS Team / SCHEFFE;
TITLE ”Girls’ Heights on Basketball Teams”;
RUN;

SAS的输出如下:

2013-12-09 15_50_40-The Little SAS Book(Fourth).PDF - Adobe Reader

先是用作分类的变量的基本统计。然后是模型的基本统计:

2013-12-09 15_50_34-The Little SAS Book(Fourth).PDF - Adobe Reader

最后是各个组的分析结果(两两比较,由于指定了SCHEFFE参数):

2013-12-09 15_51_16-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS中的离散被解释变量模型:PROC LOGISTIC和PROC GENMOD

最简单的离散被解释变量模型就是logit了,在SAS里面有直接的PROC LOGISTIC。官方文档在此:http://support.sas.com/documentation/cdl/en/statug/63033/HTML/default/viewer.htm#logistic_toc.htm

语法自然是一如既往的简单:

proc logistic;
model y=x1 x2;
run;

结果返回:

The LOGISTIC Procedure

 

Model Information
Data Set WORK.INGOTS
Response Variable (Events) r
Response Variable (Trials) n
Model binary logit
Optimization Technique Fisher's scoring

Number of Observations Read 19
Number of Observations Used 19
Sum of Frequencies Read 387
Sum of Frequencies Used 387

首先自然是模型的统计信息。然后是数据的统计:

Response Profile
Ordered
Value
Binary Outcome Total
Frequency
1 Event 12
2 Nonevent 375

Model Convergence Status
Convergence criterion (GCONV=1E-8) satisfied

然后是假设检验:

Model Fit Statistics
Criterion Intercept
Only
Intercept
and
Covariates
AIC 108.988 103.222
SC 112.947 119.056
-2 Log L 106.988 95.222

Testing Global Null Hypothesis: BETA=0
Test Chi-Square DF Pr > ChiSq
Likelihood Ratio 11.7663 3 0.0082
Score 16.5417 3 0.0009
Wald 13.4588 3 0.0037

最后是参数估计:

Analysis of Maximum Likelihood Estimates
Parameter DF Estimate Standard
Error
Wald
Chi-Square
Pr > ChiSq
Intercept 1 -5.9901 1.6666 12.9182 0.0003
Heat 1 0.0963 0.0471 4.1895 0.0407
Soak 1 0.2996 0.7551 0.1574 0.6916
Heat*Soak 1 -0.00884 0.0253 0.1219 0.7270

而对于泊松模型,则需要PROC GENMOD。我觉得我一一个列出这些模型已经超出了这篇笔记的范围了...所以干脆就改成简单翻译一下各个PROC的主要模型吧。说过了,学习模型不是主要的目的——模型终究不该通过软件来学...虽然SAS的user guide真的还算是比较好的统计学教材呢。

SAS里面的PROC一览

除了上面说到的PROC,SAS当然还有更多强大的模块。我就顺手一一点开看看这些东西都能做什么...

Categories
游来游去

Shanghai, Yesterday Once More

DSC06635
静与动,inside of the Shanghai Art Museum.

昨天,难得的冬日好阳光,约了三五好友打发时光,却也落得中间几个小时的独行时间,沿着南京东路细细的走了走。越走越熟悉,然后恍然大悟原来同样的路,3年前的这个时候也曾步行而过。那是第一次来上海,那是瞻仰大都市风貌的时候,那是还年轻的抱怨着上海公交车好贵的时候...其实真的,只是过了三年而已。很短,却仿若一个世纪的梦一般长。

DSCN4665
第一次来上海,惊叹于路边的咖啡屋...摄于2009年11月。

DSCN4685
印象颇深的LAN[蘭],至今也不知道是不是餐厅。摄于2009年11月。

南京东路还是一如既往的繁华,繁华到不敢轻易的认知那些看起来有些眼熟的店铺。浮生若梦,不知道在这来来往往的游人脚步中,有多少还会再次相逢。还好有相机为伴,索性仿若第一次来到上海,再次以一个纯粹的游客心情来体会这座迷离的城市。不知道是失落,还是充盈。

DSC06559
南京东路的夕阳, Sunset on the East Nanjing Road, Shanghai.

原来记忆中长长的南京东路并不是那么的长,走走便到了人民广场。念及上海美术馆不久之后就要关门谢客了,赶紧冲进去补拍几张照片——由此也可见我的心是多么的不纯粹,根本不是为了看展览而来的,就是为了看一眼这个古典建筑内部的繁华。

DSC06653
背靠背, Side by side, inside of the Shanghai Art Museum.

DSC06647
冷与暖, cold and warm, inside of the Shanghai Art Museum.

经常会不自觉的驻足在熙熙攘攘人群中的书报摊,这些摊贩们对于潮流文化有着超乎异常的敏锐直觉。果不其然,在一堆八卦杂志之中,《丰乳肥臀》就这么风姿卓绝的挤站着。

DSC06582
九江路上的报摊

走累了就会开始找吃的,比如隐藏在南京西路伊势丹下面的鲷鱼烧...真的吃,好好吃!赶上开业特价买一送一,就毫不客气的红豆奶油抹茶三种口味各入手一个。刚出炉的鲷鱼烧外壳脆脆的里面软软的,口感极佳。

DSC06671
鲷鱼烧

DSC06676
满满的一大袋鲷鱼烧

夜晚的迷离自然需要电影的神奇为伴。艾伦伍迪的新片《To Roma with Love》自然成为了不错的选择。只是在正式上映之前,只有在这种小小的咖啡书屋里面可以一睹为快。不过,真的叫这家咖啡书屋有点委屈它了,人家实则是大名鼎鼎的“私人图书馆”。

DSC06686
2666私人图书馆,静安别墅。

有意思的是上次无意路过也顺手拍了一张,一白一黑,还是蛮有情调来对比看看的。

DSC06688
Day and night, 2666 private library, Jing'an House.

还有一些总是能无意挖掘的神秘地盘,比如这座夜色中的城堡。

DSC06539
人民公园内的餐厅,inside of the Renmin Park at night.

大概是私人的狂欢之所吧,正巧碰到三位婀娜多姿的青年女孩携手走进去。不敢贪恋她们的背影,只有稍稍记录一下这曲径的神秘。

DSC06543
通往狂欢的曲径,Roda towards the restaurant, inside of the Renmin Park, Shanghai.

Yesterday once more, 但也不尽那么的相同一致。在不同的时间,相同的地点,记录下不同或者相同的画面。却也是人生颇有意思的一件事儿。至少,可以在越来越觉年老体衰之时,打发一下时间吧。总觉得陷入回忆是不好的,可是难得回忆如此温馨。

Categories
日常应用

七天搞定SAS(六):宏的编写、程序调错

本系列连载文章:

在SAS各种繁杂的PROC之后,还要来看看MACRO才可以嘛。又不能写函数...

SAS中的MACRO:宏编写

MACRO主要是DO和%LET的各种组合,前者负责循环后者负责变量。

一个例子:

%LET flowertype = Ginger;
* Read the data and subset with a macro variable;
DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
IF Variety = "&flowertype";
RUN;
* Print the report using a macro variable;
PROC PRINT DATA = flowersales;
FORMAT SaleDate WORDDATE18.;
TITLE "Sales of &flowertype";
RUN;

这段代码可以做什么呢?很简单,替换文字。我们指定了一个SAS MACRO中的变量flowertype,在执行MACRO的时候他会被自动翻译成标准的SAS代码。这样执行的结果就是:

2013-12-09 15_57_22-The Little SAS Book(Fourth).PDF - Adobe Reader

看到了吧,标题已经被替换了。

一段MACRO以%macro开始,然后以%mend结束。

* Macro to print 5 largest sales;
%MACRO sample;
PROC SORT DATA = flowersales;
BY DESCENDING Quantity;
RUN;
PROC PRINT DATA = flowersales (OBS = 5);
FORMAT SaleDate WORDDATE18.;
TITLE 'Five Largest Sales';
RUN;
%MEND sample;
* Read the flower sales data;
DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
RUN;
* Invoke the macro;
%sample

这样执行之后的结果就是:

2013-12-09 15_58_09-The Little SAS Book(Fourth).PDF - Adobe Reader

虽然SAS不可以直接写函数,但是MACRO还是有参数可以传入的。

* Macro with parameters;
%MACRO select(customer=,sortvar=);
PROC SORT DATA = flowersales OUT = salesout;
BY &sortvar;
WHERE CustomerID = "&customer";
RUN;
PROC PRINT DATA = salesout;
FORMAT SaleDate WORDDATE18.;
TITLE1 "Orders for Customer Number &customer";
TITLE2 "Sorted by &sortvar";
RUN;
%MEND select;
* Read all the flower sales data;
DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
RUN;
*Invoke the macro;
%select(customer = 356W, sortvar = Quantity)
%select(customer = 240W, sortvar = Variety)

这样传入的参数会自动作为变量被替换掉。结果如下:

2013-12-09 15_59_26-The Little SAS Book(Fourth).PDF - Adobe Reader

当然MACRO中也会有需要判断的时候,这就是IF上场之时啦:

%MACRO dailyreports;
%IF &SYSDAY = Monday %THEN %DO;
PROC PRINT DATA = flowersales;
FORMAT SaleDate WORDDATE18.;
TITLE 'Monday Report: Current Flower Sales';
RUN;
%END;
%ELSE %IF &SYSDAY = Tuesday %THEN %DO;
PROC MEANS DATA = flowersales MEAN MIN MAX;
CLASS Variety;
VAR Quantity;
TITLE 'Tuesday Report: Summary of Flower Sales';
RUN;
%END;
%MEND dailyreports;
DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
RUN;
%dailyreports

比如周二,那么翻译出来的SAS代码就是:

DATA flowersales;
INFILE 'c:\MyRawData\TropicalSales.dat';
INPUT CustomerID $ @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
RUN;
PROC MEANS DATA = flowersales MEAN MIN MAX;
CLASS Variety;
VAR Quantity;
TITLE 'Tuesday Report: Summary of Flower Sales';
RUN;

最终得到的结果为:
2013-12-09 16_00_55-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS中使用CALL SYMPUT:用数据值赋予变量

如果有的时候需要数据集中的值来给MACRO中的变量赋值,我们就需要使用CALL SYMPUT了。

* Read the raw data;
DATA flowersales;
INFILE 'c:\MySASLib\TropicalSales.dat';
INPUT CustomerID $4. @6 SaleDate MMDDYY10. @17 Variety $9. Quantity;
PROC SORT DATA = flowersales;
BY DESCENDING Quantity;
RUN;
* Find biggest order and pass the customer id to a macro variable;
DATA _NULL_;
SET flowersales;
IF _N_ = 1 THEN CALL SYMPUT("selectedcustomer",CustomerID);
ELSE STOP;
RUN;
PROC PRINT DATA = flowersales;
WHERE CustomerID = "&selectedcustomer";
FORMAT SaleDate WORDDATE18.;
TITLE "Customer &selectedcustomer Had the Single Largest Order";
RUN;

这样的结果就成了:

2013-12-09 16_01_50-The Little SAS Book(Fourth).PDF - Adobe Reader

看出来这里面的逻辑了么?我们先对数据集flowersales进行了排序,然后选择第一名的订单用户,赋值给selectedcustomer这个变量,然后就可以直接在后面用&selectedcustomer调用这个变量值,去查找属于他的观测记录了。

SAS MACRO的DEBUG调试

这里就是一些基本的找错技巧了:

  • 避免最常见的语法错误:先写一般的SAS语句,然后去替换需要用到变量的部分。
  • 引号问题:如果用单引号,那么SAS不会替换里面的变量值;如果用双引号,那么里面&variable的值会被替换掉。所以酌情注意。
  • SAS的报错记录:有MERROR(找不到macro)、SERROR(找不到变量)、MLOGIC(SAS将在日志中输出详细的执行情况)、MPRINT(SAS将在日志中输出翻译出来的SAS代码)、SYMBOLGEN(SAS将在日志中输出变量当时的赋值)。

SAS常见程序错误

最常见的大概就是少了结尾的分号...这里的报错一般是:

ERROR 180-322: Statement is not valid or it is used out of proper order.

或者其他类似的语句无法被SAS理解的。

还有就是输入数据不正确或者有缺失值什么的...这个我觉得在数据源是数据库管理系统的时候,不是什么问题...

还有就是数值型被转换成文本型...报错类似于:

NOTE: Character values have been converted to numeric values at the places
given by:(Line):(Column).

我们利用PUTLOG可以一步步的输出SAS计算的过程:

9 * Keep only students with mean below 70;
10 DATA lowscore;
11 INFILE ’c:MyRawDataClass.dat’;
12 INPUT Name $ Score1 Score2 Score3 Homework;
13 Homework = Homework * 2;
14 AverageScore = MEAN(Score1 + Score2 + Score3 + Homework);
15 PUTLOG Name= Score1= Score2= Score3= Homework= AverageScore=;
16 IF AverageScore < 70;
17 RUN;

这样也有利于查错。

其他的可以直接看报错信息来判断,不赘述了。

Categories
Uncategorized

Protected: To Roma with Love

This post is password protected. To view it please enter your password below:

Password:

Categories
日常应用

七天搞定SAS(五):数据操作与合并

本系列连载文章:

数据集操作永远是逃不掉的问题,最简单的就是两个数据集的合并——当然不是简简单单的行列添加,按照某一主键或者某些主键合并才是最常用的。在SAS中,要熟悉的就是SET这个声明,可以用改变数据集等等。

生成新变量

这里一个比较简单的例子,就是有一个现成的数据集,我们想增加一个变量。

DATA averagetrain;
SET 'c:MySASLibtrains';
PeoplePerCar = People / Cars;
RUN;
PROC PRINT DATA = averagetrain;
TITLE 'Average Number of People per Train Car';
FORMAT Time TIME5.;
RUN;

这样的结果就是增加了一个新的变量PeoplePerCar:

Average Number of People per Train Car
Obs Time Cars People PeoplePerCar
1 10:10 6 21 3.50000
2 12:15 10 56 5.60000
3 15:30 10 25 2.50000
4 11:30 8 34 4.25000
5 13:15 8 12 1.50000
6 10:45 6 13 2.16667
7 20:30 6 32 5.33333
8 23:15 6 12 2.00000

行合并

这里比较类似于R里面的rbind()函数,就是直接在尾部附上后面的数据。当SET指定了两个或多个数据集的时候,可以进行这样的操作。距离如下:

* Create a data set, both, combining northentrance and southentrance;
* Create a variable, AmountPaid, based on value of variable Age;
DATA both;
SET southentrance northentrance;
IF Age = . THEN AmountPaid = .;
ELSE IF Age < 3 THEN AmountPaid = 0;
ELSE IF Age < 65 THEN AmountPaid = 35;
ELSE AmountPaid = 27;
PROC PRINT DATA = both;
TITLE 'Both Entrances';
RUN;

然后结果输出为:

2013-12-09 16_03_41-The Little SAS Book(Fourth).PDF - Adobe Reader

这里很容易看出,对于第一个数据集没有的变量LOT,会自动添加缺失值。

SET还可以进一步结合BY对数据排序:

DATA interleave;
SET northentrance southentrance;
BY PassNumber;
PROC PRINT DATA = interleave;
TITLE 'Both Entrances, By Pass Number';
RUN;

这样返回的结果就是按照PassNumber排序的了:

2013-12-09 16_04_31-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS一对一合并数据集

类似于SQL的join和R的merge,SAS也可以合并数据集。先从最简单的一对一合并说起:

* Merge data sets by CodeNum;
DATA chocolates;
MERGE sales descriptions;
BY CodeNum;
PROC PRINT DATA = chocolates;
TITLE ”Today's Chocolate Sales”;
RUN;

这样就可以得到按照CodeNum来合并这两个数据集了,返回结果为:

2013-12-09 16_05_17-The Little SAS Book(Fourth).PDF - Adobe Reader

当然一对多也是可行的。

原数据为:

2013-12-09 16_06_42-The Little SAS Book(Fourth).PDF - Adobe Reader

然后代码为:

* Perform many-to-one match merge;
DATA prices;
MERGE regular discount;
BY ExerciseType;
NewPrice = ROUND(RegularPrice - (RegularPrice * Adjustment), .01);
PROC PRINT DATA = prices;
TITLE ’Price List for May’;
RUN;

最后得到的结果就是:

2013-12-09 16_07_15-The Little SAS Book(Fourth).PDF - Adobe Reader

有的时候我们还想把一些统计量也合并进来,比如PROC MEANS得到的那些,这样自然也是不怎么麻烦的。

DATA shoes;
INFILE ’c:\MyRawData\Shoesales.dat’;
INPUT Style $ 1-15 ExerciseType $ Sales;
PROC SORT DATA = shoes;
BY ExerciseType;
RUN;
* Summarize sales by ExerciseType and print;
PROC MEANS NOPRINT DATA = shoes;
VAR Sales;
BY ExerciseType;
OUTPUT OUT = summarydata SUM(Sales) = Total;
PROC PRINT DATA = summarydata;
TITLE ’Summary Data Set’;
RUN;
* Merge totals with the original data set;
DATA shoesummary;
MERGE shoes summarydata;
BY ExerciseType;
Percent = Sales / Total * 100;
PROC PRINT DATA = shoesummary;
BY ExerciseType;
ID ExerciseType;
VAR Style Sales Total Percent;
TITLE ’Sales Share by Type of Exercise’;
RUN;

这里用到了OUTPUT输出统计结果到SAS数据集,这样最后结果就是:
2013-12-09 16_08_12-The Little SAS Book(Fourth).PDF - Adobe Reader

2013-12-09 16_08_21-The Little SAS Book(Fourth).PDF - Adobe Reader

 

还有一些特定的情况,可以不用MERGE而是UPDATE,这个就得稍稍小心一点了...

* Update patient data with transactions;
DATA perm.patientmaster;
UPDATE perm.patientmaster transactions;
BY Account;
PROC PRINT DATA = perm.patientmaster;
FORMAT BirthDate LastUpdate MMDDYY10.;
TITLE 'Admissions Data';
RUN;

基本就是把patientmaster这个数据集用transactions里面有的数据覆盖掉相应的记录。

2013-12-09 16_09_06-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS里面拆分数据

在读入数据的时候,SAS还可以自动按照某些条件把其拆分为两个数据集,这里需要调用OUTPUT声明。

DATA morning afternoon;
INFILE 'c:\MyRawData\Zoo.dat';
INPUT Animal $ 1-9 Class $ 11-18 Enclosure $ FeedTime $;
IF FeedTime = 'am' THEN OUTPUT morning;
ELSE IF FeedTime = 'pm' THEN OUTPUT afternoon;
ELSE IF FeedTime = 'both' THEN OUTPUT;
RUN;
PROC PRINT DATA = morning;
TITLE 'Animals with Morning Feedings';
PROC PRINT DATA = afternoon;
TITLE 'Animals with Afternoon Feedings';
RUN;

得到的就是两个数据集(虽然我们读入的只有一个...你也可以理解为生成了两个原数据集的子集):

2013-12-09 16_09_53-The Little SAS Book(Fourth).PDF - Adobe Reader

这里就类似于R里面的split()函数了。

还有一些数据格式比较不稳定,比如一行多条记录:

Jan Varsity 56723 Downtown 69831 Super-6 70025
Feb Varsity 62137 Downtown 43901 Super-6 81534
Mar Varsity 49982 Downtown 55783 Super-6 69800

这个时候就可以利用OUTPUT的操作,来逐行读取并输出:

* Create three observations for each data line read
* using three OUTPUT statements;
DATA theaters;
INFILE 'c:\MyRawData\Movies.dat';
INPUT Month $ Location $ Tickets @;
OUTPUT;
INPUT Location $ Tickets @;
OUTPUT;
INPUT Location $ Tickets;
OUTPUT;
RUN;
PROC PRINT DATA = theaters;
TITLE 'Ticket Sales';
RUN;

最后得到的数据就相当规范了(我在想为啥SAS可以有这么多奇葩的数据输入...真折磨人啊):

2013-12-09 16_10_43-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS里面变量选取等参数

其实DATA里面的参数还是蛮多的,除了以前提到过的KEEP,DROP,还有可以重命名的RENAME等。还有一个比较有用的可能就是IN了:

DATA noorders;
MERGE customer orders (IN = Recent);
BY CustomerNumber;
IF Recent = 0;
PROC PRINT DATA = noorders;
TITLE ’Customers with No Orders in the Third Quarter’;
RUN;

这样可以增加一个新的变量Recent,来记录某条记录是否被合并。
2013-12-09 16_11_22-The Little SAS Book(Fourth).PDF - Adobe Reader

WHERE的用法也可以稍稍赘述一下:

*Input the data and create two subsets;
DATA tallpeaks (WHERE = (Height > 6000))
american (WHERE = (Continent CONTAINS ('America')));
INFILE 'c:\MyRawData\Mountains.dat';
INPUT Name $1-14 Continent $15-28 Height;
RUN;
PROC PRINT DATA = tallpeaks;
TITLE 'Members of the Seven Summits above 6,000 Meters';
PROC PRINT DATA = american;
TITLE 'Members of the Seven Summits in the Americas';
RUN;

这样得到的结果为:

2013-12-09 16_12_18-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS中数据的转置:TRANSPOSE

数据的转置有时候也是逃不掉的。这里就有些类似于R里面的reshape()函数了,但是肯定没有reshape2里面的melt and cast强大...我一度觉得reshape2的用法很麻烦,后来才发现原来这东西真的强大到一定程度了...

DATA baseball;
INFILE 'c:\MyRawData\Transpos.dat';
INPUT Team $ Player Type $ Entry;
PROC SORT DATA = baseball;
BY Team Player;
PROC PRINT DATA = baseball;
TITLE 'Baseball Data After Sorting and Before Transposing';
RUN;
* Transpose data so salary and batavg are variables;
PROC TRANSPOSE DATA = baseball OUT = flipped;
BY Team Player;
ID Type;
VAR Entry;
PROC PRINT DATA = flipped;
TITLE 'Baseball Data After Transposing';
RUN;

结果为:
2013-12-09 16_12_55-The Little SAS Book(Fourth).PDF - Adobe Reader

SAS里面自带的变量

SAS里面有些默认自带的变量,有时候用起来还是蛮方便的,类似于R会自带一个row.names这种变量。

比如_N_就会加上行号(当然有时候也不是,呃,准确的说应该是SAS执行的循环顺序,说了SAS是一行行操作数据的嘛):

DATA walkers;
INFILE 'c:\MyRawData\Walk.dat';
INPUT Entry AgeGroup $ Time @@;
PROC SORT DATA = walkers;
BY Time;
* Create a new variable, Place;
DATA ordered;
SET walkers;
Place = _N_;
PROC PRINT DATA = ordered;
TITLE 'Results of Walk';
PROC SORT DATA = ordered;
BY AgeGroup Time;
* Keep the first observation in each age group;
DATA winners;
SET ordered;
BY AgeGroup;
IF FIRST.AgeGroup = 1;
PROC PRINT DATA = winners;
TITLE 'Winners in Each Age Group';
RUN;

这样得到的结果就是排序后的次序了:

2013-12-09 16_13_36-The Little SAS Book(Fourth).PDF - Adobe Reader

类似的变量还有FIRST.variable和LST.variable,这里由于我们用到了 FIRST.AgeGroup,所以第二次输出的时候只有第一个AGE GROUP的结果。