I have written the following query to extract a list of distinct military status from a SAS table.
proc sql;
create table mil_stat as
select distinct MILITARY_STAT_sERSS format $MILSTAT. as MILITARY_STATUS,
count(*) as TOTAL
from FPE
group by MILITARY_STAT_sERSS;
quit;
I need to add a summary row that shows the total count. I tried to do this in the proc sql statement, but could not figure out how to do it. So, I wrote the following proc report statement to provide the needed row in the report.
PROC REPORT DATA=work.mil_stat;
column MILITARY_STATUS TOTAL;
where MILITARY_STATUS ne '5';
define MILITARY_STATUS / group;
rbreak after / summarize style=[font_weight=bold];
compute MILITARY_STATUS;
if MILITARY_STATUS ne . then c_MILITARY_STATUS=MILITARY_STATUS;
else c_MILITARY_STATUS=' ';
if _break_ = '_RBREAK_' then MILITARY_STATUS = "Grand Total";
endcomp;
run;
The grand total row displays, but 'Grand Total' is truncated to a single character.
Any assistance to be able to display the 'Grand Total' string would be much appreciated.
Looks like MILITARY_STAT_sERSS is only one byte long. And also the format, $MILSTAT., that you are using with that variable does not have any decode for 'G'.
Try making MILITARY_STATUS long enough to store "Grand Total".
select MILITARY_STAT_sERSS as MILITARY_STATUS length=11 format=$MILSTAT.
...
Another solution would be to assign a value for the total ('G' is fine, or 'T', or whatever fits with your data) and then use that in the format. This would be my preferred solution, as it avoids having an unformatted value, and uses less space, but does require you to be able to adjust the format (or perhaps you can use a pass through format, if not).
proc format;
value $sex
'F' = 'Female'
'M' = 'Male'
'T' = 'Grand Total';
quit;
proc report data=sashelp.class;
columns sex height;
format sex $sex.;
define sex/group missing;
define height/analysis mean;
rbreak after/summarize;
compute sex;
if _break_='_RBREAK_' then sex='Total';
endcomp;
run;
I'm doing a simple count of occurrences of a by-variable within a class variable, but cannot find a way to rename the total count across class variables. At the moment, the output dataset includes counts for all cluster2 within each group as well as the total count across all groups (i.e. the class variable used). However, the counts within classes are named, while the total is shown by an empty string.
Code:
proc means data=seeds noprint;
class group;
by cluster2;
id label2;
output out=seeds_counts (drop= _type_ _freq_) n(id)=count;
run;
Example of output file:
cluster2 group label2 count
7 area 1 20
7 sa area 1 15
7 sb area 1 5
15 area 15 42
15 sa area 15 18
....
Naturally, renaming the emtpy string to "Total" could be accomplished in a separate datastep, but I would like to do it directly in the Proc Means-step. It should be simple and trivial, but I haven't found a way so far. Afterwards, I want to transpose the dataset, which means that the emtpy string has to be changed, or it will be dropped in the proc transpose.
I don't know of a way to do it directly, but you can sort-of-cheat: you can tell SAS to show "Total" instead of missing.
proc format;
value $MissTotalF
' ' = 'Total'
other = [$CHAR12.];
quit;
proc means data=sashelp.class noprint;
class sex;
id age;
output out=sex_counts (drop= _type_ _freq_) n(age)=count;
format sex $MissTotalF.;
run;
For example. I'd also recommend using PROC TABULATE instead of PROC MEANS if you're just going for counts, though in this case it doesn't really make much difference.
The problem here is that if the variable in the class statement is numeric, then the resultant column will be numeric, therefore you can't add the word Total (unless you use a format, similar to the answer from #Joe). This will be why the value is missing, as the class variable can be either numeric or character.
Here's an example of a numeric class variable.
proc sort data=sashelp.class out=class;
by sex;
run;
proc means data=class noprint;
class age;
by sex;
output out=class_counts (drop= _:) n=count;
run;
Using proc tabulate can display the result pretty much how you want it, however the output dataset will have the same missing values, so won't really help. Here's a couple of examples.
proc tabulate data=class out=class_tabulate1 (drop=_:);
class sex age;
table sex*(age all='Total'),n='';
run;
proc tabulate data=class out=class_tabulate2 (drop=_:);
class sex age;
table sex,age*n='' all='Total';
run;
I think the best option to achieve your final goal is to add the nway option to proc means, which will remove the subtotals, then transpose the data and finally write a data step that creates the Total column by summing each row. It's 3 steps, but doesn't involve much coding.
Here is one method you could use by taking advantage of the _TYPE_ variable so that you can process the totals and details separately. You will still have trouble with PROC TRANSPOSE if there is a class with missing values (separate from the overall summary record).
proc means data=sashelp.class noprint;
class sex;
id age;
output out=sex_counts (drop= _freq_ ) n(age)=count;
run;
proc transpose data=sex_counts out=transpose prefix=count_ ;
where _type_=1 ;
id sex ;
var count;
run;
data transpose ;
merge transpose sex_counts(where=(_type_=0) keep=_type_ count);
rename count=count_Total;
drop _type_;
run;
A sample SAS Proc report code is below. I want to change the color of the header background and foreground for one value of the across variable. I used a compute block to change the column background to light gray using the absolute column references c4 and c5. How do I change the header style attributes for c4 and c5 to background=gainboro and foreground=black?
data test;
length name $ 10 disease $ 10.;
infile datalines dsd;
input name $ disease cases rate;
datalines;
State,Fever,4847,25.16
State,Cold,25632,131.5
State,Flu,103825,535.82
Lincoln,Fever,3920,44.17
Lincoln,Cold,16913,190.18
Lincoln,Flu,62965,735.39
Washington,Fever,827,56.56
Washington,Cold,3609,234.26
Washington,Flu,16610,1078.8
Kings,Fever,1026,37.45
Kings,Cold,4984,181.85
Kings,Flu,18388,694.33
Sussex,Fever,1411,78.38
Sussex,Cold,5515,300.46
Sussex,Flu,13881,813.11
Queens,Fever,616,26.03
Queens,Cold,2496,107.75
Queens,Flu,12518,558.09
;
run;
proc report data=test nowd headline headskip
STYLE(Header)={background=charcoal foreground=white }
style(column)={background=gray foreground=black}
style(report)=[rules=rows bordercolor=white];
columns (name disease,(cases rate));
define name/group order=data 'County' style(column)={background=lighttgray} style(header)=[bordertopcolor=gainsboro background=gainsboro foreground=black];
define disease/across '' order=data ;
define cases/'Cases' format=comma9. ;
define rate/'Rate' format=comma12.1 ;
compute cases;
call define('_c4_','style','style={background=lighttgray}');
call define('_c5_','style','style={background=lighttgray}');
endcomp;
run;
quit;
run;
You can use formats to do something close to what you're asking, but I'm not sure it's possible to do what you're asking - maybe Cynthia Zender on communities.sas.com might?
data test;
length name $ 10 disease $ 10.;
infile datalines dsd;
input name $ disease cases rate;
datalines;
State,Fever,4847,25.16
State,Cold,25632,131.5
State,Flu,103825,535.82
Lincoln,Fever,3920,44.17
Lincoln,Cold,16913,190.18
Lincoln,Flu,62965,735.39
Washington,Fever,827,56.56
Washington,Cold,3609,234.26
Washington,Flu,16610,1078.8
Kings,Fever,1026,37.45
Kings,Cold,4984,181.85
Kings,Flu,18388,694.33
Sussex,Fever,1411,78.38
Sussex,Cold,5515,300.46
Sussex,Flu,13881,813.11
Queens,Fever,616,26.03
Queens,Cold,2496,107.75
Queens,Flu,12518,558.09
;
run;
proc format;
value $headerbackf
'Cold' = 'gainsboro'
other = 'charcoal';
value $headerforef
'Cold' = 'black'
other = 'white'
;
quit;
proc report data=test nowd headline headskip
STYLE(Header)={background=charcoal foreground=white }
style(column)={background=gray foreground=black}
style(report)=[rules=rows bordercolor=white];
columns (name disease,(cases rate));
define name/group order=data 'County' style(column)={background=lightgray} style(header)=[bordertopcolor=gainsboro background=gainsboro foreground=black];
define disease/across '' order=data style(header)={background=$HEADERBACKF. foreground=$HEADERFOREF.};
define cases/'Cases' format=comma9. style(header)=inherit;
define rate/'Rate' format=comma12.1 ;
compute cases;
call define('_c4_','style','style={background=lighttgray}');
call define('_c5_','style','style={background=lighttgray}');
endcomp;
run;
That gets that top row formatted, but, doesn't actually get the row you're asking for. I'm not sure it's possible to.
It's possible as #ChrisJ noted that you might be able to do this with CSS styles and nth child selection. It's also possible you can't, unfortunately, due to how SAS does things with PROC REPORT - in particular, in PROC REPORT everything gets shoved inside <tr>s including the header rows, so nth-child and sibling selectors are impossible due to the headers not being children or siblings of each other.
Here's an example of a kludgey version of this, using sashelp.cars as an example.
CSS: (save in a .css file on your drive somewhere, say "c:\temp\test.css"):
#import 'base.css';
/* Red the second (really third) column header value */
.table thead tr:nth-child(2) th:nth-child(3) {
color:red
}
/* Yellow background for the mpg headers under Europe */
.table thead tr:nth-child(3) th:nth-child(4),
.table thead tr:nth-child(3) th:nth-child(5)
{
background-color:yellow
}
/* Green the mpg-city values */
.table thead tr:nth-child(3) th:nth-child(even) {
color:green
}
SAS program: (assumes the above-saved CSS file)
ods html file='example.html' cssstyle='c:\temp\test.css'(html);
ods pdf file='example.pdf' cssstyle='c:\temp\test.css'(print);
proc sort data=sashelp.cars out=cars; by origin;
run;
proc report data=cars nowd;
columns type origin,(mpg_city mpg_highway);
define origin/across;
define type/group;
define mpg_City / analysis mean;
define mpg_highway / analysis mean;
run;
ods _all_ close;
This is partially based on Kevin Smith's Unveiling the power of Cascading Style Sheets (CSS) in ODS.
Unfortunately, we can't in any way identify a cell that has "MPG(City)" in it except by knowing they'll be even column numbers. We similarly can't identify a cell under a "Europe" except by knowing what cells those will be.
Try adding a dummy column _c to the end of your columns statement, and add a define & compute to go with it.
Also, ensure your colour names are actually valid, e.g. lighttgray is invalid and will not work.
columns ... _c ;
define _c / computed noprint ;
compute _c ;
call define('_c4_','style','style={background=lightgray}');
call define('_c5_','style','style={background=lightgray}');
endcomp ;
This is my first time using a programming related stack. So if this doesn't belong or should go somewhere please inform me and I will fix it.
I've just begun to use SAS Studio. I believe I have set up a title correctly, but I can't seem to get it only on the first page. It adds the title to every subsequent page I create. I've just begun watching tutorials on the SAS website, but I have yet to run across the answer to this particular question. Can anyone help point me in a correct direction?
Here is my code:
Data Question21;
Input Transfers Broken ##;
Datalines;
1 16 0 9 2 17 0 12 3 22 1 13 0 8 1 15 2 19 0 11
;
title color=red Bold underlin=3 "Assignment #1";
Proc Print;
run;
Proc sgplot;
scatter x=Transfers y=Broken;
run;
Proc reg;
model Broken=Transfers;
run;
and this is a sample of what happens when it runs:
TITLE is a global statement, and will take effect until you turn it off. So the simple answer is: after the PROC in which you want the title, and its RUN statement (or QUIT in those that use quit), enter
title;
Which will then clear all titles.
In a bit more detail:
Titles, and Footnotes, have a set of ten (each) that are in a sort of 'stack' (Setting one removes all higher ones). SAS stores them internally, and any time a PROC or anything else runs that supports a title, it will grab whatever is currently in the title and footnote stacks and show those titles and those footnotes.
It is important to remember that any PROC or DATA step doesn't submit fully until RUN or QUIT is reached, or else another PROC or DATA step is begun (called a "Step Boundary"). Since TITLE is a global statement, what'll happen is whatever is in the current title stack when the step boundary is reached will be shown. Notice what you actually see here...
title "One Title";
proc print data=sashelp.class;
title "Two Title";
run;
title "Three Title";
proc freq data=sashelp.class;
tables sex*age/list;
run;
title "Four";
A good habit is to always put TITLE statements in a consistent place - some disagree over where, but choose either:
Before the PROC/DATA statement
Immediately before RUN
and stick with it. Then, after every RUN, include a TITLE;, unless you intentionally have a common title.
For example, I might have an assignment that is to print SASHELP.CLASS, run some frequencies on it, and use PROC UNIVARIATE to look at the WEIGHT and HEIGHT variables.
title "SAS Class, Assignment One";
title2 "Written By Joe, 9/2/2015"; *these are global titles used for all printing;
title3 "Print of first 10 obs of SASHELP.CLASS";
proc print data=sashelp.class(obs=10);
run;
title3;
title3 "Freq of AGE, SEX in SASHELP.CLASS";
proc freq data=sashelp.class;
tables age sex;
run;
title3;
title3 "Univariate Examination of SASHELP.CLASS";
title4 "HEIGHT variable";
proc univariate data=sashelp.class;
var height;
run;
title4;
title4 "WEIGHT variable";
proc univariate data=sashelp.class;
var weight;
run;
title3; *notice 3 here - ending all of 3;
title3 "Plot of SASHELP.CLASS Height v Weight";
proc sgplot data=sashelp.class;
scatter x=weight y=height;
run;
title; *ends all titles!;
When I run the code below, it outputs a text file where the default hyphen for the headline option is replaced by the letter F. So I get a series of Fs dispayed across my report. Any idea what could be causing this? I've never run across this before and can't find any info about it...
proc printto print='c:\temp\test.txt';
run;
PROC REPORT DATA=SUM_2010 HEADLINE HEADSKIP MISSING nowd;
COLUMNS field1 field2;
DEFINE field1 / 'NUMBER OF things' FORMAT=COMMA20.0 WIDTH=25;
DEFINE filed2 / 'VALUE of things' FORMAT=DOLLAR28.2 WIDTH=30;
RBREAK AFTER/SKIP SUMMARIZE DOL;
TITLE1 "something";
TITLE2 "something something";
TITLE3 "more something";
TITLE4 "YEAR: 2010";
RUN;
quit;
Try the formchar option - this affects horizontal and vertical lines in proc tabulate and proc report. This should provide more appealing output => options formchar="|----||---|-/\<>*"; (run it before the proc report).