SAS编程技巧--频数统计
(2012-12-27 18:25:32)
标签:
杂谈 |
分类: SAS_Quick_Tips |
这篇算是《SAS编程技巧--数据汇总》的姐妹篇,在数据汇总那篇文章中我们用 SUMMARY 过程计算了所有数值型变量的频数以及各种统计量,今天我们看看如何用 SAS 对分类变量进行频数分析。这篇文章纯粹是编程方面的讨论,比较枯燥,但是编程中遇到的问题及其解决办法个人认为很是有趣,而且我建议大家下去试试有没有更好的解决办法。
假设我们现在需要对数据集中所有分类变量进行频数分析,并将结果保存至 SAS 数据集,期望的结果如下:
varname | level | Frequency | Percent | CumFrequency | CumPercent |
---|---|---|---|---|---|
sex | M | 10 | 52.63 | 10 | 52.63 |
sex | F | 9 | 47.37 | 19 | 100.00 |
age | 12 | 5 | 26.32 | 5 | 26.32 |
age | 14 | 4 | 21.05 | 9 | 47.37 |
age | 15 | 4 | 21.05 | 13 | 68.42 |
age | 13 | 3 | 15.79 | 16 | 84.21 |
age | 11 | 2 | 10.53 | 18 | 94.74 |
age | 16 | 1 | 5.26 | 19 | 100.00 |
我们先从最简单的情况入手,即只有字符型的变量才是分类变量,不考虑数值型变量,也不考虑字符型客户号码等极端情况。看到这个题目,大家基本上都会选择
FREQ 过程步的
proc freq data=sashelp.class order=freq noprint;
run;quit;
输出结果(表 1):
Sex | COUNT | PERCENT |
---|---|---|
M | 10 | 52.6316 |
F | 9 | 47.3684 |
从表 1 我们可以看到只有最后一个变量的结果保存到数据集中,其他变量的结果没有保存。为了解决这个问题,我们使用 ODS OUTPUT 语句。
ods output onewayfreqs=onewayfreqs;
proc freq data=sashelp.class order=freq;
run;quit;
输出结果(表 2):
Table | F_Name | Name | Frequency | Percent | CumFrequency | CumPercent | F_Sex | Sex |
---|---|---|---|---|---|---|---|---|
Table Name | Alfred | Alfred | 1 | 5.26 | 1 | 5.26 | ||
Table Name | Alice | Alice | 1 | 5.26 | 2 | 10.53 | ||
Table Name | Barbara | Barbara | 1 | 5.26 | 3 | 15.79 | ||
Table Name | Carol | Carol | 1 | 5.26 | 4 | 21.05 | ||
Table Name | Henry | Henry | 1 | 5.26 | 5 | 26.32 | ||
Table Name | James | James | 1 | 5.26 | 6 | 31.58 | ||
Table Name | Jane | Jane | 1 | 5.26 | 7 | 36.84 | ||
Table Name | Janet | Janet | 1 | 5.26 | 8 | 42.11 | ||
Table Name | Jeffrey | Jeffrey | 1 | 5.26 | 9 | 47.37 | ||
Table Name | John | John | 1 | 5.26 | 10 | 52.63 | ||
Table Name | Joyce | Joyce | 1 | 5.26 | 11 | 57.89 | ||
Table Name | Judy | Judy | 1 | 5.26 | 12 | 63.16 | ||
Table Name | Louise | Louise | 1 | 5.26 | 13 | 68.42 | ||
Table Name | Mary | Mary | 1 | 5.26 | 14 | 73.68 | ||
Table Name | Philip | Philip | 1 | 5.26 | 15 | 78.95 | ||
Table Name | Robert | Robert | 1 | 5.26 | 16 | 84.21 | ||
Table Name | Ronald | Ronald | 1 | 5.26 | 17 | 89.47 | ||
Table Name | Thomas | Thomas | 1 | 5.26 | 18 | 94.74 | ||
Table Name | William | William | 1 | 5.26 | 19 | 100.00 | ||
Table Sex | 10 | 52.63 | 10 | 52.63 | M | M | ||
Table Sex | 9 | 47.37 | 19 | 100.00 | F | F |
表 2 中包含了所有变量的频数统计结果,但是这并不是我们想要的表结构,我们希望对表 2 进一步处理,生成最后的结果。
%let data=sashelp.class;
%let vars =name sex;
ods output onewayfreqs=onewayfreqs;
proc freq data=&data order=freq;
run;quit;
data freq_out;
run;
输出结果(表 3):
varname | level | Frequency | Percent | CumFrequency | CumPercent |
---|---|---|---|---|---|
name | Alfred | 1 | 5.26 | 1 | 5.26 |
name | Alice | 1 | 5.26 | 2 | 10.53 |
name | Barbara | 1 | 5.26 | 3 | 15.79 |
name | Carol | 1 | 5.26 | 4 | 21.05 |
name | Henry | 1 | 5.26 | 5 | 26.32 |
name | James | 1 | 5.26 | 6 | 31.58 |
name | Jane | 1 | 5.26 | 7 | 36.84 |
name | Janet | 1 | 5.26 | 8 | 42.11 |
name | Jeffrey | 1 | 5.26 | 9 | 47.37 |
name | John | 1 | 5.26 | 10 | 52.63 |
name | Joyce | 1 | 5.26 | 11 | 57.89 |
name | Judy | 1 | 5.26 | 12 | 63.16 |
name | Louise | 1 | 5.26 | 13 | 68.42 |
name | Mary | 1 | 5.26 | 14 | 73.68 |
name | Philip | 1 | 5.26 | 15 | 78.95 |
name | Robert | 1 | 5.26 | 16 | 84.21 |
name | Ronald | 1 | 5.26 | 17 | 89.47 |
name | Thomas | 1 | 5.26 | 18 | 94.74 |
name | William | 1 | 5.26 | 19 | 100.00 |
sex | M | 10 | 52.63 | 10 | 52.63 |
sex | F | 9 | 47.37 | 19 | 100.00 |
有时候我们不能简单地根据变量的类型来决定变量的测量水平,因为有些数值型变量也可能是分类变量,例如:客户类型既可以用字符表示,也可以用数值表示。上面的代码只能处理字符型分类变量,因为我们使用了数组
array varlist{*} $100
&vars;,而数组要求所有元素的类型与其类型都是一致的。有人可能会说表 2 中所有 F_
开头的变量都是字符型的,恰好没有这个限制,但是使用 F_ 开头的变量会令你的代码变得相当复杂,因为有很多情况需要考虑,包括 SAS
软件本身的限制(变量名长度不能多于 32
个字符)。对于一些极端的情况,比如恰巧有两个变量,分别取名为:longagenaaaaaaaaaaaaaaaa
对于数值型、字符型混合的情况,我们需要重新编码,克服上述所有问题。其中,用到了 MISSING 选项,这个我在《SAS编程技巧--巧用MISSING选项》里面有介绍。
%let data=sashelp.class;
%let vars =sex age;
ods output onewayfreqs=onewayfreqs;
proc freq data=&data order=freq;
run;quit;
options missing='';
data freq_out;
run;
options missing=.;
输出结果(表 4):
varname | level | Frequency | Percent | CumFrequency | CumPercent |
---|---|---|---|---|---|
sex | M | 10 | 52.63 | 10 | 52.63 |
sex | F | 9 | 47.37 | 19 | 100.00 |
age | 12 | 5 | 26.32 | 5 | 26.32 |
age | 14 | 4 | 21.05 | 9 | 47.37 |
age | 15 | 4 | 21.05 | 13 | 68.42 |
age | 13 | 3 | 15.79 | 16 | 84.21 |
age | 11 | 2 | 10.53 | 18 | 94.74 |
age | 16 | 1 | 5.26 | 19 | 100.00 |