I have a table parms that looks like this:
parameter split test1 test2 test3... test10 gini 1 gini 2 gini 3 mse 1 mse 2 mse 3
I need to create a macro that would take this table and create a pdf report of 3 pages (a page for each split), each page containing 2 graphs (gini & mse), each graph plotting the values of the tests (10 points). Thank you for your help!
Before you convert code to a macro you need working code, do you have code that creates the report you'd like?
I would recommend first doing that. I suspect it'll be easier if you restructure your data as well, to a long format. You can use PROC TRANSPOSE for that.
Transposing data tutorials:
Wide to Long:
https://stats.idre.ucla.edu/sas/modules/how-to-reshape-data-wide-to-long-using-proc-transpose/
https://stats.idre.ucla.edu/sas/modules/reshaping-data-wide-to-long-using-a-data-step/
Then create your base report which would be pretty straightforward IME.
Not exactly sure what the macro part would be since all the data is represented in a report, you could probably just repeat it three times much faster.
proc sgplot data=have;
where parameter="gini" and split="1";
series x= testNumber y = testValue;
run;
proc sgplot data=have;
where parameter="mse" and split="1";
series x= testNumber y = testValue;
run;
Here are some macro references to get you started if you really want a macro for some reason.
UCLA introductory tutorial on macro variables and macros
https://stats.idre.ucla.edu/sas/seminars/sas-macros-introduction/
Tutorial on converting a working program to a macro
This method is pretty robust and helps prevent errors and makes it much easier to debug your code. Obviously biased, because I wrote it 🙂 https://github.com/statgeek/SAS-Tutorials/blob/master/Turning%20a%20program%20into%20a%20macro.md
Examples of common macro usage
https://communities.sas.com/t5/SAS-Communities-Library/SAS-9-4-Macro-Language-Reference-Has-a-New-Ap...
@asasha wrote:
I have a table parms that looks like this:
parameter split test1 test2 test3... test10 gini 1 gini 2 gini 3 mse 1 mse 2 mse 3I need to create a macro that would take this table and create a pdf report of 3 pages (a page for each split), each page containing 2 graphs (gini & mse), each graph plotting the values of the tests (10 points). Thank you for your help!
Actual data would help.
The SAS graphing procedure will work a lot better with data in the form of
Parameter split test_number test_value
gini 1 1 123
gini 1 2 128
gini 1 3 121
and so forth.
Proc transpose can help get it in that form.
Proc SGPANEL will make a separate graph for each level of a BY variable, such as Split and
separate panels for values of Parameter on a Panelby statement.
Why type of plot do you want? Scatter, series, bar, needle, regression? Is the test number supposed to be the xaxis value?
Do you want the two parameter graphs side-by-side , one above the other, or possibly superimposed (both in one graph with two colors to differentiate the parameter)?
I would like a simple line graph. The test numbers would be the x axis. Two separate graphs are good (i.e. one above the other). I have no SAS experience. Transpose makes sense! I need it to be a macro that creates one report, as the number of tests could be more (i.e. 50) and the number of splits could be more as well. Each page would represent one split and contain both graphs.
Likely no macro needed.
You should be able to copy and run this code:
data have; do parameter='gini','mse'; do split=1 to 3; array test{10}; do i=1 to dim(test); test[i] = 100*rand('uniform'); end; output; end; end; run; proc sort data=have; by split parameter; run; proc transpose data=have out=trans; by split parameter; var test: ;/* the : immediately after the test tells SAS to use all variables starting with "test"*/ run; data forplot; set trans; Testnumber = input(substr(_name_,5),best.); run; proc sgpanel data=forplot; by split; panelby parameter /rows=2; series x=testnumber y=col1; run; /* or */ proc sgplot data=forplot; by split; series x=testnumber y=col1 / group=parameter; run;
The first data step just makes a data set with some values. Since the test variable values are random the likely do not look like your data.
Sort to get order needed to Transpose.
Then transpose the data.
If your data doesn't have any surprises, like duplicate Parameter/split pairs of values the data will have one output variable named Col1 with the values of the test numbers.
The second data step is to get the test number as a numeric value. Not needed but easier to control axis values with numbers than text if needed.
Then two different approaches to plotting the data as series.
Note, if the input data set has different numbers of tests it still works (change the size of the TEST array in the first data set, splits change the split = 1 to <some other integer>, or parameter, add other parameters in the list quoted and separated by commas. Warning: if you add parameters for testing the LONGEST name needs to be the first one in the list because of the way SAS creates text variables if you do not declare them with a LENGTH statement prior to the first use.
To create a PDF of the results the graph code would be placed in an "ods destination sandwich". That is a statement that tells say to start sending data to a file of the specified type and to stop surrounding the output. that generically would look like:
ods pdf file="C:\folder\otherfolder\filenameyouwant.pdf"; <any SAS procedures that create output, Proc Print, the graph procedure, other procedures > ods pdf close; /* stop sending output to the pdf file*/
I tried this and it worked! The only problem I have is the axes range. Both graphs are showing from 0 to 20, so I am getting two straight lines. I need the axis to be in 0.1 - 0.01 increments or so around its average value to see the shape for each metric.
You can control the displayed axis ranges by using a values statement.
You didn't mention the actual needed range but
rowaxis values =( 0 to 1 by 0.1)
would create 0, 0.1, 0.2 ... 1 axis tick marks on the vertical axis.
If you need to have different ranges for the yaxis you might try UNISCALE=Column in the PANELBY statement. That will allow rows to have different scales but you would not want to use the Values in a rowaxis statement. The rowaxis would set the axis for each row to the specified list. It isn't quite clear which you may need.
Generally SAS is pretty good about guesstimating ranges. I would expect one of the values to have a range close to 20, may be above 16.
If you really need to control lots of axis values then that is going to run a lot more programming
Uniscale did the trick, thank you!
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Learn how use the CAT functions in SAS to join values from multiple variables into a single value.
Find more tutorials on the SAS Users YouTube channel.
Ready to level-up your skills? Choose your own adventure.