I am a beginner so my knowledge is lacking. I have a data set consisting of the following columns:
Subject
Age
Height
Weight
I wish to create a table such that for every 1 person i have three rows called Age, Height, Weight.
I have tried to use Proc Tabulate :
proc tabulate data=new;
class person;
var NEWCOLUMN;
table person,NEWCOLUMN;
run;
However i am getting an error because the new column is not the correct type.
You can pivot the data per person and REPORT or TABULATE the cell values.
Example:
proc transpose data=sashelp.class out=pivoted;
by name;
var age height weight;
where name <= 'C';
run;
ods html file='output.html' style=plateau;
options nodate nonumber nocenter;
title; footnote;
proc report data=pivoted;
column name _name_ col1;
define name / ' ' order order=data;
define _name_ / ' ';
define col1 / ' ';
run;
proc tabulate data=pivoted;
class name _name_ / order=data;
var col1;
table name*_name_='', col1=''*min='' / nocellmerge;
run;
ods html close;
Output
I'm using tagsets.excelxp in SAS to output dozens of two-way tables to an .xml file. Is there syntax that will suppress rows (frequencies and percents) if the frequency in that row is less than 10? I need to apply that in order to de-identify the results, and it would be ideal if I could automate the process rather than use conditional formatting in each of the outputted tables. Below is the syntax I'm using to create the tables.
ETA: I need those suppressed values to be included in the computation of column frequencies and percents, but I need them to be invisible in the final table (examples of options I have considered: gray out the entire row, turn the font white so it doesn't show for those cells, replace those values with an asterisk).
Any suggestions would be greatly appreciated!!!
Thanks!
dr j
%include 'C:\Users\Me\Documents\excltags.tpl';
ods tagsets.excelxp file = "C:\Users\Me\Documents\Participation_rdg_LSS_3-8.xml"
style = MonoChromePrinter
options(
convert_percentages = 'yes'
embedded_titles = 'yes'
);
title1 'Participation';
title2 'LSS-Level';
title3 'Grades 3-8';
title4 'Reading';
ods noproctitle;
proc sort data = part_rdg_3to8;
by flag_accomm flag_participation lss_nm;
run;
proc freq data = part_rdg_3to8;
by flag_accomm flag_participation;
tables lss_nm*grade_p / crosslist nopercent;
run;
ods tagsets.excelxp close;
D.Jay: Proc FREQ does not contain any options for conditionally masking cells of it's output. You can leverage the output data capture capability of the ODS system with a follow-up Proc REPORT to produce the desired masked output.
I am guessing on the roles of the lss and grade_p as to be a skill level and a student grade level respectively.
Generate some sample data
data have;
do student_id = 1 to 10000;
flag1 = ranuni(123) < 0.4;
flag2 = ranuni(123) < 0.6;
lss = byte(65+int(26*ranuni(123)));
grade = int(6*ranuni(123));
* at every third lss force data to have a low percent of grades < 3;
if mod(rank(lss),3)=0 then
do until (grade > 2 or _n_ < 0.15);
grade = int(6*ranuni(123));
_n_ = ranuni(123);
end;
else if mod(rank(lss),7)=0 then
do until (grade < 3 or _n_ < 0.15);
grade = int(6*ranuni(123));
_n_ = ranuni(123);
end;
output;
end;
run;
proc sort data=have;
by flag1 flag2;
*where lss in ('A' 'B') and flag1 and flag2; * remove comment to limit amount of output during 'learning the code' phase;
run;
Perform the Proc FREQ
Only capture the data corresponding to the output that would have been generated
ods _all_ close;
* ods trace on;
/* trace will log the Output names
* that a procedure creates, and thus can be captured
*/
ods output CrossList=crosslist;
proc freq data=have;
by flag1 flag2;
tables lss * grade / crosslist nopercent;
run;
ods output close;
ods trace off;
Now generate output to your target ODS destination (be it ExcelXP, html, pdf, etc)
Reference output of which needs to be produced an equivalent having masked values.
* regular output of FREQ, to be compare to masked output
* of some information via REPORT;
proc freq data=have;
by flag1 flag2;
tables lss * grade / crosslist nopercent;
run;
Proc REPORT has great features for producing conditional output. The compute block is used to select either a value or a masked value indicator for output.
options missing = ' ';
proc format;
value $lss_report ' '= 'A0'x'Total';
value grade_report . = 'Total';
value blankfrq .b = '*masked*' ._=' ' other=[best8.];
value blankpct .b = '*masked*' ._=' ' other=[6.2];
proc report data=CrossList;
by flag1 flag2;
columns
('Table of lss by grade'
lss grade
Frequency RowPercent ColPercent
FreqMask RowPMask ColPMask
)
;
define lss / order order=formatted format=$lss_report. missing;
define grade / display format=grade_report.;
define Frequency / display noprint;
define RowPercent / display noprint;
define ColPercent / display noprint;
define FreqMask / computed format=blankfrq. 'Frequency' ;
define RowPMask / computed format=blankpct. 'Row/Percent';
define ColPMask / computed format=blankpct. 'Column/Percent';
compute FreqMask;
if 0 <= RowPercent < 10
then FreqMask = .b;
else FreqMask = Frequency;
endcomp;
compute RowPMask;
if 0 <= RowPercent < 10
then RowPMask = .b;
else RowPMask = RowPercent;
endcomp;
compute ColPMask;
if 0 <= RowPercent < 10
then ColPMask = .b;
else ColPMask = ColPercent;
endcomp;
run;
ods html close;
If you have to produce lots of cross listings for different data sets, the code is easily macro-ized.
When I've done this in the past, I've first generated the frequency to a dataset, then filtered out the N, then re-printed the dataset (using tabulate usually).
If you can't recreate the frequency table perfectly from the freq output, you can do a simple frequency, check which IDs or variables or what have you to exclude, and then filter them out from the input dataset and rerun the whole frequency.
I don't believe that you can with PROC FREQ, but you can easily replicate your code with PROC TABULATE and you can use a custom format there to mask the numbers. This example sets it to M for missing and N for less than 5 and with one decimal place for the rest of the values. You could also replace the M/N with a space (single space) to have no values shown instead.
*Create a format to mask values less than 5;
proc format;
value mask_fmt
. = 'M' /*missing*/
low - < 5='N' /*less than 5 */
other = [8.1]; /*remaining values with one decimal place*/
run;
*sort data for demo;
proc sort data=sashelp.cars out=cars;
by origin;
run;
ods tagsets.excelxp file='/folders/myfolders/demo.xml';
*values partially masked;
proc tabulate data=cars;
where origin='Asia';
by origin;
class make cylinders;
table make, cylinders*n*f=mask_fmt. ;
run;
ods tagsets.excelxp close;
This was tested on SAS UE.
EDIT: Forgot the percentage piece, so this likely will not work for that, primarily because I don't think you'll get the percentages the same as in PROC FREQ (appearance) so it depends on how important that is to you. The other possibility to accomplish this would be to modify the PROC FREQ template to use the custom format as above. Unfortunately I do not have time to mock this up for you but maybe someone else can. I'll leave this here to help get you started and delete it later on.
Have a nice day to everyone here)
I hve number of gplot graphs. The output shows it "One after another".
Is is possible to output it nearby in a horizontal way? thank you!
%macro test;
%do i = 1 %to 2;
%_eg_conditional_dropds(WORK.SORTTempTableSorted&i.);
proc sql noprint;
select distinct name into: name from s&i.;quit;
PROC SORT
DATA=WORK.s&i.(KEEP=period SCORE RANGE_MID_2 RANGE_MID_1)
OUT=WORK.SORTTempTableSorted&i.
;BY period;
RUN;
SYMBOL1
INTERPOL=JOIN
HEIGHT=10pt
VALUE=NONE
LINE=1
WIDTH=2
CV = _STYLE_
;
SYMBOL2
INTERPOL=JOIN
HEIGHT=10pt
VALUE=NONE
LINE=1
WIDTH=2
CI=RED
CV = _STYLE_;
SYMBOL3
INTERPOL=JOIN
HEIGHT=10pt
VALUE=NONE
LINE=1
WIDTH=2
CI=YELLOW
CV = _STYLE_
;
Legend1
FRAME
;
Axis1
STYLE=1
WIDTH=1
MINOR=NONE
;
Axis2
STYLE=1
WIDTH=1
MINOR=NONE
;
TITLE;
TITLE1 "&_name";
FOOTNOTE;
PROC GPLOT DATA = WORK.SORTTempTableSorted&i.
;
PLOT SCORE * period RANGE_MID_2 * period RANGE_MID_1 * period /
OVERLAY
VAXIS=AXIS1
HAXIS=AXIS2
FRAME LEGEND=LEGEND1
RUN; QUIT;
%_eg_conditional_dropds(WORK.SORTTempTableSorted&i.);
TITLE; FOOTNOTE;
GOPTIONS RESET = SYMBOL;
%end;
%mend; %test;
This is am example when I generate 2 gplots. I did not make such reports before and do not know how to control the position of object.
You can have either an Absolute ODS Layout or a Gridded ODS Layout. I recommend the gridded layout since you have a generic macro that generates the code for you.
You will find these two documents very useful to get your layout correct, both documentations includes working code.
SAS ODS TipSheet and SAS ODS Paper.
Example from SAS Tipsheet:
ods pdf file='gridded.pdf';
/* You can change or add rows=2 */
ods layout gridded columns=2 width=5in column_gutter=.25in style={background=lightgray};
ods region style={background=lightblue};
/* Column One */
proc means data=sashelp.class mean; run;
ods region width=2in style={background=lightblue};
/* Column Two */
proc print data=sashelp.class(obs=5 keep=name age); run;
ods layout end;
ods pdf close;
I am trying to generate the ODS pdf file after running the proc report syntex.
ods pdf file = "D:\New folder (2)\Assignment\Case_Study_1\Summary.pdf";
proc report data = Cs1.olympics headline;
column Probability Stage (n) Total_Media_Value Tot_Forecast;
where Probability > 0;
define Probability/group Descending 'Probability';
define Stage/group noprint;
define n / format = comma6. 'Nbr_of_Optys';
define Total_Media_Value/analysis format = dollar25. 'Tot_Budget';
define Tot_Forecast/computed format = dollar25.;
compute Tot_Forecast;
if upcase (_BREAK_) = ' ' then do;
Tot_Forecast = (Total_Media_Value.sum*Probability)/100;
Tot_Forecast_Summer=sum(Tot_Forecast_Summer,Tot_Forecast);
end;
else do;
Tot_Forecast=Tot_Forecast_Summer;
end;
endcomp;
rbreak after / summarize ol ul;
run;
ods pdf close;
I am not able to generate the pdf. Can you please help me out.
Thanks is advance.
So here, I am losing the TagAttr on the highlighted "All" row. What I want is the Total row to be highlighted and to also maintain the TagAttr on the output.
ods tagsets.excelxp
file= "c:\Sheet1.xml"
proc tabulate data=sashelp.class missing;
class sex age;
var height;
table (sex='' all='Total')*
(age=''
all={label='Total NCO' s={background=yellow font_weight=bold}} *{s={font_weight=bold background=yellow }}),
(height='Height'*mean=' ' *[s=[tagattr='#,##0;[Red](#,##0);"-"']]
height='%height'*pctsum=''*[s=[tagattr='0.00%;[Red]0.00%;"-";"-"']])
/ box=_page_ style_precedence=row;
run;
ods tagsets.excelxp close;