Make the output of proc tabulate to vertical? - sas

My SAS code is as follow:
DATA CLASS;
INPUT NAME $ SEX $ AGE HEIGHT WEIGHT;
CARDS;
ALFRED M 14 69.0 112.5
ALICE F 13 56.5 84.0
BARBARA F 13 65.3 98.0
CAROL F 14 62.8 102.5
HENRY M 14 63.5 102.5
RUN;
PROC PRINT;
TITLE 'DATA';
RUN;
proc print data=CLASS;run;
proc tabulate data=CLASS;
var AGE HEIGHT WEIGHT;
table (AGE HEIGHT WEIGHT)*(MEAN STD MEDIAN Q1 Q3 MIN MAX n NMISS);
title 'summary';
run;
The out put looks like
How can make the output list in the vertical direction?

A TABLE statement without a comma (,) is specifying only a column expression.
Use a comma in your table statement
table <row-expression> , <column-expression> ;
Example:
DATA CLASS;
INPUT NAME $ SEX $ AGE HEIGHT WEIGHT;
CARDS;
ALFRED M 14 69.0 112.5
ALICE F 13 56.5 84.0
BARBARA F 13 65.3 98.0
CAROL F 14 62.8 102.5
HENRY M 14 63.5 102.5
;
ods html file='tabulate.html' style=plateau;
TITLE 'DATA';
proc print data=CLASS;
run;
proc tabulate data=CLASS;
var AGE HEIGHT WEIGHT;
table (AGE HEIGHT WEIGHT)*(MEAN STD MEDIAN Q1 Q3 MIN MAX n NMISS);
* comma being used;
table (AGE HEIGHT WEIGHT),(MEAN STD MEDIAN Q1 Q3 MIN MAX n NMISS);
* comma being used, swapping row and column expressions;
table (MEAN STD MEDIAN Q1 Q3 MIN MAX n NMISS),(AGE HEIGHT WEIGHT);
title 'summary';
run;

Related

Is it possible to get specified values in the stat variable of proc means output?

So I am working on generating summary dataset. I need to print only the values of N,MIN,MEDIAN,MAX,STD. It will be convenient for me to get the result as the statistics in a single variable stat. But if I use proc means without specifying the stats after output statement, I just get the default stats. Is there any way of doing this? This is what I tried.
PROC MEANS DATA=sashelp.class NWAY N MIN MAX MEDIAN STD;
CLASS name;
VAR height weight;
OUTPUT OUT=output (DROP=_type_ _freq_ RENAME=(_stat_=stat)) ;
RUN;
It only shows the default stats.
Anyway, I can specify the stats in output option, but I want the output like from the code I have provided.
Thanks in advance for helping.
No.
Generate them in "wide" format and then transpose to "tall" if you want.
PROC SUMMARY DATA=sashelp.class NWAY N MIN MAX MEDIAN STD;
CLASS name;
VAR height weight;
OUTPUT OUT=wide n= min= max= median= std= /autoname ;
RUN;
proc transpose data=wide(drop=_type_ _freq_) out=tall ;
by name ;
run;
data tall ;
set tall ;
length Stat $32 ;
stat = scan(_name_,-1,'_');
_name_=substr(_name_,1,length(_name_)-length(stat)-1);
run;
proc transpose data=tall out=want(drop=_name_);
by name stat notsorted;
id _name_;
var col1 ;
run;
Results:
Obs Name Stat Height Weight
1 Alfred N 1.0 1.0
2 Alfred Min 69.0 112.5
3 Alfred Max 69.0 112.5
4 Alfred Median 69.0 112.5
5 Alfred StdDev . .
6 Alice N 1.0 1.0
7 Alice Min 56.5 84.0
8 Alice Max 56.5 84.0
9 Alice Median 56.5 84.0
10 Alice StdDev . .
...

compute variable after datalines

I have the following dataset (fictional data).
DATA test;
INPUT name $ age height weight;
DATALINES;
Peter 20 1.70 80
Hans 30 1.72 75
Tina 25 1.67 65
Luisa 10 1.20 50
;
RUN;
How can I compute a new variable "bmi" (weight / height^2) directly after the end of the DATALINE-command? Unfortunately in my SAS-book all the examples are with DATA ... INFILE= instead of using DATALINES.
PROC PRINT
DATA = test;
TITLE 'Fictional Data';
RUN;
Datalines appears at the end of the data step. Your computation statements should be placed before datalines, after the input
INPUT name $ age height weight;
bmi = weight / height**2;
DATALINES;
…

SAS, transpose a table

I want to transform my SAS table from data Have to data want.
I feel I need to use Proc transpose but could not figure it out how to do it.
data Have;
input Stat$ variable_1 variable_2 variable_3 variable_4;
datalines;
MAX 6 7 11 23
MIN 0 1 3 5
SUM 29 87 30 100
;
data Want;
input Variable $11.0 MAX MIN SUM;
datalines;
Variable_1 6 0 29
Variable_2 7 1 87
Variable_3 11 3 87
Variable_4 23 5 100
;
You are right, proc transpose is the solution
data Have;
input Stat$ variable_1 variable_2 variable_3 variable_4;
datalines;
MAX 6 7 11 23
MIN 0 1 3 5
SUM 29 87 30 100
;
/*sort it by the stat var*/
proc sort data=Have; by Stat; run;
/*id statement will keep the column names*/
proc transpose data=have out=want name=Variable;
id stat;
run;
proc print data=want; run;

Create table with frequency buckets in Base SAS

Below is a sample of my dataset:
City Days
Atlanta 10
Tampa 95
Atlanta 100
Charlotte 20
Charlotte 31
Tampa 185
I would like to break down "Days" into buckets of 0-30, 30-90, 90-180, 180+, such that the "buckets" are along the x-axis of the table, and the cities are along the y-axis.
I tried using PROC FREQ, but I don't have SAS/STAT. Is there any way to do this in base SAS?
I believe this is what you want. This is most certainly a "brute force" approach, but I think its outlines the concept correctly.
data have;
length city $9;
input city dayscount;
cards;
Atlanta 10
Tampa 95
Atlanta 100
Charlotte 20
Charlotte 31
Tampa 185
;
run;
data want;
set have;
if dayscount >= 0 and dayscount <=30 then '0-30'n = dayscount;
if dayscount >= 30 and dayscount <=90 then '30-90'n = dayscount;
if dayscount >= 90 and dayscount <=180 then '90-180'n = dayscount;
if dayscount > 180 then '180+'n = dayscount;
drop dayscount;
run;
One of the ways for solving this problem is by using Proc Format for assigning the value bucket and then using Proc Transpose for the desired result:
data city_day_split;
length city $12.;
input city dayscount;
cards;
atlanta 10
tampa 95
atlanta 100
charlotte 20
charlotte 31
tampa 185
;
run;
/****Assigning the buckets****/
proc format;
value buckets
0 - <30 = '0-30'
30 - <90 = '30-90'
90 - <180 = '90-180'
180 - high = 'gte180'
;
run;
data city_day_split;
set city_day_split;
day_bucket = put(dayscount,buckets.);
run;
proc sort data=city_day_split out=city_day_split;
by city;
run;
/****Making the Buckets as columns, City as rows and daycount as Value****/
proc transpose data=city_day_split out=city_day_split_1(drop=_name_);
by city;
id day_bucket;
var dayscount;
run;
My Output:
> **city |0-30 |90-180 |30-90 |GTE180**
> Atlanta |10 |100 |. |.
> Charlotte |20 |. |31 |.
> Tampa |. |95 |. |185

combine and merge rows in SAS

I have a SAS Table like:
DATA test;
INPUT id sex $ age inc r1 r2 Zaehler work $;
DATALINES;
1 F 35 17 7 2 1 w
17 M 40 14 5 5 1 w
33 F 35 6 7 2 1 w
49 M 24 14 7 5 1 w
65 F 52 9 4 7 1 w
81 M 44 11 7 7 1 w
2 F 35 17 6 5 1 n
18 M 40 14 7 5 1 n
34 F 47 6 6 5 1 n
50 M 35 17 5 7 1 w
;
PROC PRINT; RUN;
proc sort data=have;
by county;
run;
I want compare rows if sex and age is equal and build sum over Zaehler. For example:
1 F 35 17 7 2 1 w
and
33 F 35 6 7 2 1 w
sex=f and age=35 are equale so i want to merge them like:
id sex age inc r1 r2 Zaehler work
1 F 35 17 7 2 2 w
I thought i can do it with proc sql but i can't use sum in proc sql. Can someone help me out?
PROC SUMMARY is the normal way to compute statistics.
proc summary data=test nway ;
class sex age ;
var Zaehler;
output out=want sum= ;
run;
Why would you want to include variables other than SEX, AGE and Zaehler in the output?
Your requirement is not difficult to understand or to satisfy, however, I am not sure what is your underline reason for doing this. Explain more on your purpose may help to facilitate better answers that work from the root of your project. Although I have a feeling the PROC MEAN may give you better matrix, here is a one step PROC SQL solution to get you the summary as well as retaining "the value of first row":
proc sql;
create table want as
select id, sex , age, inc, r1, r2, sum(Zaehler) as Zaehler, work
from test
group by sex, age
having id = min(id) /*This is tell SAS only to keep the row with the smallest id within the same sex,age group*/
;
quit;
You can use proc sql to sum over sex and age
proc sql;
create table sum as
select
sex
,age
,sum(Zaehler) as Zaehler_sum
from test
group by
sex
,age;
quit;
You can than join it back to the main table if you want to include all the variables
proc sql;
create table test_With_Sum as
select
t.*
,s.Zaehler_sum
from test t
inner join sum s on t.sex = s.sex
and t.age = s.age
order by
t.sex
,t.age
;
quit;
You can write it all as one proc sql query if you wish and the order by is not needed, only added for a better visibility of summarised results
Not a good solution. But it should give you some ideas.
DATA test;
INPUT id sex $ age inc r1 r2 Zaehler work $;
DATALINES;
1 F 35 17 7 2 1 w
17 M 40 14 5 5 1 w
33 F 35 6 7 2 1 w
49 M 24 14 7 5 1 w
65 F 52 9 4 7 1 w
81 M 44 11 7 7 1 w
2 F 35 17 6 5 1 n
18 M 40 14 7 5 1 n
34 F 47 6 6 5 1 n
50 M 35 17 5 7 1 w
;
run;
data t2;
set test;
nobs = _n_;
run;
proc sort data=t2;by descending sex descending age descending nobs;run;
data t3;
set t2;
by descending sex descending age;
if first.age then count = 0;
count + 1;
zaehler = count;
if last.age then output;
run;
proc sort data=t3 out=want(drop=nobs count);by nobs sex age;run;
thanks for your help. Here is my final code.
proc sql;
create table sum as
select distinct
sex
,age
,sum(Zaehler) as Zaehler
from test
WHERE work = 'w'
group by
sex
,age
;
PROC PRINT;quit;
I just modify the code a little bit. I filtered the w and i merg the Columns with the same value.
It was just an example the real Data is much bigger and has more Columns and rows.