Difference between table and tables in proc freq in sas - sas

Could anyone please tell the difference between table and tables in Proc freq with an example?
proc freq data= want;
table variable;
run;
proc freq data= want;
tables variable;
run;`

There is no difference. The statement is the TABLES statement, but SAS will silently accept TABLE as a synonym without issuing any warning or note. Some miss spellings will generate just a warning while others will cause an error.
1668 proc freq data= sashelp.class;
1669 tablex age name;
------
1
WARNING 1-322: Assuming the symbol TABLE was misspelled as tablex.
1670 run;
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
1671
1672 proc freq data= sashelp.class;
1673 tabl age name;
----
1
WARNING 1-322: Assuming the symbol TABLE was misspelled as tabl.
1674 run;
NOTE: There were 19 observations read from the data set SASHELP.CLASS.
1675
1676 proc freq data= sashelp.class;
1677 tab age name;
---
180
ERROR 180-322: Statement is not valid or it is used out of proper order.
1678 run;
NOTE: The SAS System stopped processing this step because of errors.

Related

Formating proc freq output table in SAS

I have the following data
DATA HAVE;
input year dz area;
cards;
2000 1 08
2000 1 06
2000 1 06
;
run;
proc freq data=have;
table area*dz / norow nocol;
run;
I get the following output
I would like to format it to put frequency in one column and percent in another column and I don't want the total column. Is there a way to do it?
Thank you!
Try adding the LIST option to get a different layout:
proc freq data=have;
table area*dz / norow nocol LIST;
run;
Pipe it to a data set and format as desired:
proc freq data=have;
table area*dz / norow nocol LIST out=want;
run;
proc print data=want;run;
Use PROC TABULATE instead (not shown), which allows you more control over your layout and formats.

SAS Array creation

I am trying to create array that hold a value.
proc sql noprint;
select count(*) into :dscnt from study;
select libname into :libname1 - :libname&dscnt from study;
quit;
I think the syntax is correct but i keep getting this following error message in in SAS studio.
***NOTE: PROC SQL set option NOEXEC and will continue to check the syntax of statements.
NOTE: Line generated by the macro variable "DSCNT".
79 libname 4
_
22
200
ERROR 22-322: Syntax error, expecting one of the following: ',', FROM, NOTRIM.
ERROR 200-322: The symbol is not recognized and will be ignored.***
Can someone explain to me what i am doing wrong?
Thanks
You do not need to know the number of items ahead of time, if you leave it blank, SAS will automatically create the correct number of macro variables.
If you do want to use that number elsewhere you can create it using the TRIMMED option to remove any extra spaces. See the second example below.
proc sql noprint;
select name into :name1- from sashelp.class;
quit;
%put &name1;
%put &name19.;
proc sql noprint;
select count(distinct name) into :name_count TRIMMED from sashelp.class;
quit;
%put &name_count;
Results:
3068 proc sql noprint;
3069 select name into :name1- from sashelp.class;
3070 quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.00 seconds
cpu time 0.01 seconds
3071
3072 %put &name1;
Alfred
3073 %put &name19.;
William
3074
3075 proc sql noprint;
3076 select count(distinct name) into :name_count TRIMMED from
3076! sashelp.class;
3077 quit;
NOTE: PROCEDURE SQL used (Total process time):
real time 0.01 seconds
cpu time 0.00 seconds
3078
3079 %put &name_count;
19
The into syntax in proc sql stores formatted values into macro variables. For example if you run this code:
proc sql noprint;
select count(*) into :dscnt from sashelp.class;
quit;
%put #&dscnt#;
You will see the output is:
# 19#
In otherwords the result is left padded with spaces. This means in your example, the code is resolving to something like:
select libname into :libname1 - :libname 19 from study;
^ Which is obviously invalid syntax. To fix this, you can simply add the TRIMMED keyword to your SQL statement:
select count(*) into :dscnt TRIMMED from study;
Thanks to Reeza for the TRIMMED keyword.
do something like below
proc sql noprint;
select count(*) into :dscnt from sashelp.class;
select name into :name1 - :name%left(&dscnt) from sashelp.class;
quit;

How do I put conditions around Proc Freq statements in SAS?

I have the following statement
Proc Freq data =test;
tables gender;
run;
I want this to generate an output based on a condition applied to the gender variable. For example - if count of gender greater than 2 then output.
How can I do this in SAS?
Thanks
If you mean an output dataset, you can put a where clause directly in the output dataset options.
Proc Freq data =sashelp.class;
tables sex/out=sex_freq(where=(count>9));
run;
I'm not aware of how you can accomplish this only using proc freq but you can redirect the output to a data set and then print the results.
proc freq data=test;
tables gender / noprint out=tmp;
run;
proc print data=tmp;
where count > 2;
run;
Alternatively you could use proc summary, but this still requires two steps.
proc summary data=test nway;
class gender;
output out=tmp(where=(_freq_ > 2));
run;
proc print data=tmp;
run;

proc contents is truncating the values in out put dataset.How to get full values in out put dataset?

I'm trying to get all dataset names in a library in to a data set.
proc datasets library=LIB1 memtype=data ;
contents data=_all_ noprint out=Datasets_in_Lib1(keep=memname) ;
run;
The final data set (Datasets_in_Lib1) is having all the data set names that are in LIB1, but names are truncated to 6 characters.Is there any way to get full names of the datasets with out truncation.
Ex: If dataset name is x123456789, the Datasets_in_Lib1 will have x12345 only.
Thanks in advance,
Sam.
Agree with the comment, in 9.3 memname is $32. I don't think there was a version of SAS where data set names were limited to 6 characters. They went from 8 characters to 32 characters in v7 (I think).
Here's a log from running your code, showing it works as you want in 9.3
51 data work.x123456789;
52 x=1;
53 run;
NOTE: The data set WORK.X123456789 has 1 observations and 1 variables.
54
55 proc datasets library=work memtype=data nolist;
56 contents data=_all_ noprint out=Datasets_in_Lib1(keep=memname) ;
57 run;
NOTE: The data set WORK.DATASETS_IN_LIB1 has 1 observations and 1 variables.
58
59 data _null_;
60 set Datasets_in_Lib1;
61 put _all_;
62 run;
MEMNAME=X123456789 _ERROR_=0 _N_=1
NOTE: There were 1 observations read from the data set WORK.DATASETS_IN_LIB1.
You can also query the sashelp.vtable to obtain the list of datasets:
proc sql;
create table mem_list as
select memname
from sashelp.vtable
where libname='LIB1' and memtype='DATA';
quit;

How do I tell PROC FREQ to only display the tables which have missing values?

I have a data set with many variables - many of which are character valued. I have the following code to count the number of missing values for each variable:
proc format;
value $missfmt ' '='Missing' other='Not Missing';
value missfmt . ='Missing' other='Not Missing';
run;
proc freq data=dataname;
format _CHAR_ $missfmt.; /* apply format for the duration of this PROC */
tables _CHAR_ / missing missprint nocum nopercent;
format _NUMERIC_ missfmt.;
tables _NUMERIC_ / missing missprint nocum nopercent;
run;
However, this results in a huge output (300 page pdf if I print to pdf) with 90% of the variables having no missing values. How do I tell PROC FREQ to only display the tables which have missing values?
You can identify which variables have a missing value from the NLEVELS option in PROC FREQ. So my process would be to create a dataset that just held the variables with missing values, then store them in a macro variable so the following PROC FREQ can be run against them only.
Here is the code to do that.
/* set up dummy dataset */
data have;
set sashelp.class;
if _n_ in (10,13) then call missing(age,sex);
run;
/* create dataset that holds variables with missing values */
ods select nlevels;
ods output nlevels=miss_vars (where=(nmisslevels>0));
ods noresults;
proc freq data=have nlevels;
run;
ods results;
/* store names in a macro variable */
proc sql noprint;
select tablevar into :missvar separated by ' '
from miss_vars;
quit;
proc format;
value $missfmt ' '='Missing' other='Not Missing';
value missfmt . ='Missing' other='Not Missing';
run;
proc freq data=have (keep=&missvar.);
format _CHAR_ $missfmt.; /* apply format for the duration of this PROC */
tables _CHAR_ / missing missprint nocum nopercent;
format _NUMERIC_ missfmt.;
tables _NUMERIC_ / missing missprint nocum nopercent;
run;
This one removes all blank columns:
%macro removeblanks(dataset,output);
/* create dataset that holds variables with missing values */
ods select nlevels;
ods output nlevels=miss_vars (where=(nmisslevels>0 and nnonmisslevels=0));
ods noresults;
proc freq data=&dataset. nlevels;
run;
/* store names in a macro variable */
proc sql noprint;
select tablevar into :missvar separated by ' '
from miss_vars;
quit;
data &output.;
set &dataset.(drop=&missvar.);
run;
%mend removeblanks;`