| Return to SAS 9
|
This topic demonstrates some of the new features for Base SAS procedures in SAS 9.2.
The following code produces a PDF table without SPANROWS and the same table with SPANROWS:
%macro spanrows_demo(spanrows) ;
proc report data=sashelp.prdsale nowd &spanrows;
col region country division prodtype year product actual predict ;
define region / group;
define country / group;
define division / group;
define year / group;
define prodtype/ group;
define product /group;
run;
%mend;
ods listing close;
ods pdf file="no_spanrows.pdf";
%spanrows_demo();
ods pdf close;
ods pdf file="spanrows.pdf";
%spanrows_demo(spanrows);
ods listing;
ods pdf close;
This new feature responds to a SASWare ballot item. In SAS 9.2, you can specify variable name list shortcuts in the TABLE statement of PROC TABULATE. These shortcuts are already supported in the CLASS and VAR statements. Here is some example code:
data one(type=distance);
input (group x1-x10) (f2. 10*f3.);
cards;
1 0
1 96 0
1 53 42 0
1 2 25 95 0
1 12 10 45 80 0
1 37 74 87 49 4 0
1 48 70 60 14 53 11 0
1 31 6 74 79 98 70 98 0
1 44 4 75 89 69 50 64 3 0
1 17 89 55 9 79 15 11 56 65 0
2 0
2 25 0
2 33 15 0
2 53 65 56 0
2 11 97 90 55 0
2 98 71 30 46 5 0
2 96 98 57 40 44 89 0
2 7 89 97 47 60 13 11 0
2 35 41 6 7 84 40 94 78 0
2 47 73 8 54 1 21 59 52 20 0
3 0
3 95 0
3 1 34 0
3 34 10 23 0
3 51 99 3 40 0
3 90 35 42 17 70 0
3 8 1 69 79 84 70 0
3 31 93 9 94 86 77 50 0
3 59 35 90 8 2 4 60 9 0
3 84 17 51 8 14 20 77 2 96 0
;
run;
title 'Test x1-xn';
proc tabulate;
class x1-x10;
table x1-x10;
table (x10-x1);
table x1-x10*n;
table x1-x10,n;
table x1*pctn x2-x7*(n pctn);
table x:;
table x1:;
run;
The mode is the value that occurs most often in the data. This statistic is now available in the TABULATE and REPORT procedures. The procedure counts repetitions of the values of the analysis variables. If a tie occurs for the most frequent value, the procedure reports the lowest mode. When no repetitions occur in the data (as with truly continuous data), the procedure does not report the mode (i.e., sets it to missing).
The mode calculation is not performed if QMETHOD=P2 or if a WEIGHT variable is defined. In those cases the mode is set to missing.
Here is some example code:
data first;
input x;
datalines;
1
2
3
4
4
5
6
;
proc tabulate data=first;
var x;
table x*(q1 median q3 mode);
run;
The BLANKLINE option in the PRINT procedure enables you to insert a blank line after every n observations. Two forms of syntax are supported:
PROC PRINT BLANKLINE = n
PROC PRINT BLANKLINE = (COUNT = n <STYLE = [style-attribute-specification(s)] > )
The count of observations before inserting a blank line is reset at the beginning of each page and at the beginning of each new BYGROUP. This may result in less than n observations at the end of a page or BYGROUP. For example, if you specify n=10 and you have 52 observations on the page, then a blank line prints after observation 50, followed by 2 observations. The following page starts with the next 10 observations, followed by a blank line.
This option is valid for all destinations. However, the pagination for destinations such as RTF is done by the viewing application, not by PROC PRINT. In those cases, the count of observations before inserting a blank line is only reset at the beginning of a new BYGROUP, not at the beginning of each page.
Example 1: Insert a Blank Line Every Ten Observations
ods pdf file="blankline.pdf"; /* create a data set */ data a; do i=1 to 55; output; end; run; proc print blankline=10; run; ods pdf close;
Example 2: Insert a Blue Blank Line Every Four Observations
ods pdf file="blankline.pdf"; /* create a data set */ data a; do i=1 to 10; output; end; run; /* specify a destination other than Listing to see the style specification used */ proc print blankline=(count=4 style=[background=blue]); run; ods pdf close;
The SUMLABEL option in the PRINT procedure enables you to display the label of the BY variable on the summary line, if a label exists. The syntax is as follows:
PROC PRINT SUMLABEL;
When the SUMLABEL option is specified in conjunction with the SUM or SUMBY statements, the variable label of the BY variable is used on each summary line instead of the variable name, if a label exists.
Example 1: Using the SUMLABEL Option
/* create a data set */
data a;
do i=1 to 7;
do j=1 to 5;
output;
end;
end;
run;
proc print data=a sumlabel;
label i = "My Summing Variable";
by i;
sum j;
run;
Example 2: Using More Than One BY Variable
/* create a data set */
data exprev;
input Region $ State $ Month monyy5.
Expenses Revenues;
format month monyy5.;
datalines;
Southern GA JAN95 2000 8000
Southern GA FEB95 1200 6000
Southern FL FEB95 8500 11000
Northern NY FEB95 3000 4000
Northern NY MAR95 6000 5000
Southern FL MAR95 9800 13500
Northern MA MAR95 1500 1000
;
proc sort data=exprev;
by region state;
run;
proc print data=exprev noobs sumlabel
n='Number of observations for the state: '
'Number of observations for the data set: ';
sum expenses revenues;
by region state;
label region = "Regional Amount";
label state = "State Amount";
format revenues expenses comma10.;
title 'Revenue and Expense Totals for the #byval(region) Region';
run;
New for SAS 9.2 is a crosstabs template for the FREQ procedure. It is written in a dialect of the standard table template language that is both a subset (not everything in the table template language is supported) and a superset (you can do things in the crosstabs template that you can't do in other table templates).
The default template produces a table that is 99.9% identical to the current table. However, using the template you can perform these additional tasks:
Here is some example code. View output.
ods path (prepend) work.templat(write);
proc template;
define style white;
parent=styles.default;
style body /
background=white;
style systemtitle /
background=white
font_size=6
font_weight=bold
font_style=italic;
style systemfooter /
background=white
font_size=2
font_style=italic;
style proctitle /
background=white
foreground=#6078bf
font_weight=bold
font_style=italic;
end;
define crosstabs Base.Freq.CrossTabFreqs;
notes "Crosstabulation table";
define header TableOf;
text "Table of " _ROW_LABEL_ " by " _COL_LABEL_;
style=header {background=#BFCFFF foreground=#6078bf font_style=italic};
end;
define header ControllingFor;
/* To use labels in this header substitute `StrataVariableLabels' in the TEXT statement. */
dynamic StratNum StrataVariableNames StrataVariableLabels;
text "Controlling for" StrataVariableNames / StratNum > 0;
style=header;
end;
define header RowsHeader;
text _ROW_LABEL_ / _ROW_LABEL_ ^= '';
style=header {background=#BFCFFF foreground=#6078bf font_style=italic};
space=0;
end;
define header ColsHeader;
text _COL_LABEL_ / _COL_LABEL_ ^= '';
text _COL_NAME_;
style=header {background=#BFCFFF foreground=#6078bf font_style=italic};
space=1;
end;
define footer Missing;
dynamic FMissing;
text "Frequency Missing = " FMissing -12.99 / FMissing ^= 0;
style=header {background=#BFCFFF foreground=#6078bf font_style=italic};
space=1;
end;
define footer NoObs;
dynamic SampleSize;
text "Effective Sample Size = 0" / SampleSize = 0;
space=1;
style=header;
end;
define cellvalue Frequency;
header="";
label="Frequency Count";
format=BEST7. data_format_override=on print=on;
cellstyle _val_ < 10 as datastrong {foreground=green},
_val_ > 40 & _val_ < 50 as datastrong {foreground=orange},
_val_ >= 50 as datastrong {foreground=red};
end;
define cellvalue Expected;
header="";
label="Expected Frequency";
format=BEST6. data_format_override=on print=on;
end;
define cellvalue Deviation;
header="";
label="Deviation from Expected Frequency";
format=BEST6. data_format_override=on print=on;
end;
define cellvalue CellChiSquare;
header="";
label="Cell Chi-Square";
format=BEST6. print=on;
end;
define cellvalue TotalPercent;
header="";
label="Percent of Total Frequency";
format=6.2 print=on;
end;
define cellvalue Percent;
header="";
label="Percent of Two-Way Table Frequency";
format=6.2 print=on;
end;
define cellvalue RowPercent;
header="";
label="Percent of Row Frequency";
format=6.2 print=on;
end;
define cellvalue ColPercent;
header="";
label="Percent of Column Frequency";
format=6.2 print=on;
end;
define cellvalue CumColPercent;
header="";
label="Cumulative Percent of Column Frequency";
format=6.2 print=on;
end;
style=table {background=#BFCFFF}
cell_style=data {background=#FFFFF0}
row_var_style=rowheader {background=#BFCFFF foreground=rowfg.}
col_var_style=header {background=#BFCFFF foreground=colfg.}
row_total_style=data {background=#F0F0F0}
col_total_style=data {background=#F0F0F0}
grand_total_style=datastrong {background=#F0F0F0}
legend_style=header {background=#BFCFFF foreground=#6078bf font_style=italic};
rows_header=RowsHeader cols_header=ColsHeader;
label = "Frequency Counts and Percentages";
header /*TableOf*/ ControllingFor;
cellvalue
Frequency Expected Deviation
CellChiSquare TotalPercent Percent
RowPercent ColPercent CumColPercent;
footer NoObs Missing;
end;
run;
proc format;
Value Govtfmt -3='Council Manager'
0='Commission'
3='Mayor Council'
.N='Not Applicable'
.=' ?';
Value rowfg -3='red'
0='purple'
3='blue'
.N='green'
.='black'
other='black';
Value Robfmt 1='100 or Less'
2='101-200'
3='201-300'
4='Over 300'
.N='Not Known'
.=' ?';
Value colfg 1='yellow'
2='red'
3='blue'
4='purple'
.N='green'
.='black'
other='black';
ods html file=test style=white;
DATA ONE;
Label Citygovt='City Government Form'
Robgrp='Number of Citizens Robbed';
Input Citygovt Robgrp Weight; Missing N;
Format Citygovt Govtfmt. Robgrp Robfmt.;
LOOP: OUTPUT; WEIGHT=WEIGHT-1; IF WEIGHT>0 THEN GOTO LOOP;
DROP WEIGHT; CARDS;
0 1 6
0 3 3
0 2 7
0 4 5
N N 10
-3 1 47
-3 3 49
-3 2 63
-3 4 52
. 2 1
3 1 31
3 2 37
3 3 27
3 4 55
3 . 1
;
title "City Government Form by Number of Citizens Robbed";
footnote "Frequency";
footnote2 "Percent";
footnote3 "Row Percent";
footnote4 "Column Percent";
ods noproctitle;
proc freq;
tables citygovt*robgrp / missprint;
run;
ods html close;