I have a series of plots using sgplot. The values on the y-axis vary. For some, the values only have 1 digits (e.g. 1 to 8). For others, there's a decimal place (e.g. 0 to 0.5). For others, there's 3 digits (e.g. 0 to 300). Because of the different amount of space needed to fit these values, my y-axis keeps moving around. It's furthest to the left for those with 1 digit and starts migrating rightwards the more space the values need.
We would like to freeze the y-axis in one place for all graphs. E.g. Fix the y axis to be some distance from the left of the graphic, unmoving from page to page, regardless of what values are being displayed. Even if space for only 1 digit is needed, we'd like the yaxis to be moved over to accomodate space for 3. Is there anyway to do this? The closest I have come is setting valuesFormat = z5.1 for each graph. Of course, the issue with that is that now I have leading zeros I don't want and a decimal place on graphs that don't need a decimal place. Is there way to tell SAS to draw the yaxis at 10% of the graphing space regardless of values or something similar?
Please show the code you are using now.
Likely you need to provide a YAXIS statement with a VALUES option to show the range of values to display.
It would help if you tell us the actual range of values you want included.
Since you say "series of plots" using SGPLOT it may be that SGPANEL would be an appropriate choice as well. You can get a separate graph for each level of a variable with the PANELBY statement. By default all of the graphs generated would have the same x and y axis.
Sure. Here's the code.
%macro plotMedian(title = , test = , yAxisValues = , Units = ); title font = 'Times New Roman' height = 11pt bold &title ' (' &units ')'; proc sgplot data = Section_8_30_YForSampleSizeAdded (where = (strip(upCase(test)) = strip(upCase(&test)))); band x = Window_Label lower = P05 upper = P10 / name = 'P05_P10' transparency = 0.8 fillAttrs = (color = cx79AFE7) legendLabel = '5th-95th Percentiles'; band x = Window_Label lower = P10 upper = Q1 / name = 'P10_Q1' transparency = 0.5 fillAttrs = (color = cx79AFE7) legendLabel = '10th-90th Percentiles'; band x = Window_Label lower = Q1 upper = Q3 / name = 'Q1_Q3' transparency = 0.5 fillAttrs = (color = cxFFCFA4) legendlabel = '25th-75th Percentiles'; band x = Window_Label lower = Q3 upper = P90 / name = 'Q3_P90' transparency = 0.5 fillAttrs = (color = cx79AFE7); band x = Window_Label lower = P90 upper = P95 / name = 'P90_P95' transparency = 0.8 fillAttrs = (color = cx79AFE7); series x = Window_Label y = Mean / name = 'Mean' lineAttrs = (pattern = dash color = purple) legendLabel = 'Mean'; series x = Window_Label y = Median / name = 'Median' lineAttrs = (pattern = solid color = blue) legendLabel = 'Median'; scatter x = Window_Label y = y / markerChar = n markerCharAttrs = (family = 'Times New Roman' size = 10pt); yaxis offSetMin = 0.045 offSetMax = 0.00 grid label = &Units labelAttrs = (family = 'Times New Roman' size = 10pt weight = bold) values = &yAxisValues /*valuesFormat = yaxis.*/; xaxis offSetMin = 0.03 offSetMax = 0.03 grid display = (noLabel) valueAttrs = (family = 'Times New Roman' size = 10pt ) fitPolicy = rotate values = ('Jul 2002 – Dec 2003' 'Jul 2003 – Dec 2004' 'Jul 2004 – Dec 2005' 'Jul 2005 – Dec 2006' 'Jul 2006 – Dec 2007' 'Jul 2007 – Dec 2008' 'Jul 2008 – Dec 2009' 'Jul 2009 – Dec 2010' 'Jul 2010 – Dec 2011' 'Jul 2011 – Dec 2012' 'Jul 2012 – Dec 2013' 'Jul 2013 – Dec 2014' 'Jul 2014 – Dec 2015' 'Jul 2015 – Dec 2016' 'Jul 2016 – Dec 2017' 'Jul 2017 – Dec 2018' 'Jul 2018 – Dec 2019'); * These must be listed, because HDL and LDL have no results before 2011. *; keylegend 'Median' 'Mean' 'Q1_Q3' 'P10_Q1' 'P05_P10' / position = bottom valueAttrs = (family = 'Times New Roman' size = 10pt); format n comma.; run; title; %mEnd plotMedian; ods rtf file = "&outFolder\8. Clinical Chemistry\Clinical Chemistry Lab Plots Median with Percentiles and Mean.doc" startPage = no image_dpi = 600; ods escapeChar = '`'; %plotMedian(title = 'Alanine aminotransferase (ALT)' , test = 'ALT' , yAxisValues = (0 to 80 by 5 ), Units = 'U/L' ); %plotMedian(title = 'Aspartate aminotransferase (AST)', test = 'AST' , yAxisValues = (0 to 80 by 5 ), Units = 'U/L' ); %plotMedian(title = 'Cholesterol: Total' , test = 'Cholesterol' , yAxisValues = (0 to 300 by 20 ), Units = 'mg/dL' ); %plotMedian(title = 'Cholesterol: HDL' , test = 'HDL cholesterol', yAxisValues = (0 to 300 by 20 ), Units = 'mg/dL' ); %plotMedian(title = 'Cholesterol: LDL' , test = 'LDL cholesterol', yAxisValues = (0 to 300 by 20 ), Units = 'mg/dL' ); %plotMedian(title = 'Creatinine' , test = 'Creatinine' , yAxisValues = (0 to 2 by 0.2), Units = 'mg/dL' ); %plotMedian(title = 'Eosinophils, %' , test = 'Eosinophil %' , yAxisValues = (0 to 8 by 1 ), Units = '%' ); %plotMedian(title = 'Glucose' , test = 'Glucose' , yAxisValues = (0 to 200 by 20 ), Units = 'mg/dL' ); %plotMedian(title = 'Hemoglobin' , test = 'Hemoglobin' , yAxisValues = (0 to 20 by 2 ), Units = 'g/dL' ); %plotMedian(title = 'White Blood Cell (WBC) Count' , test = 'WBC Count' , yAxisValues = (0 to 12 by 1 ), Units = '·10^3/µL'); ods rtf close;
It appears that your axis moving around is because each call to your macro has a different value for the yaxisvalues.
Any graphs that you want to display with the same yaxsis appearance will require having the same yaxisvalues set in your macro as you are currently coding things.
Thanks for the help. Yes, you are correct. It's moving around because there is a different amount of space needed for each graph depending on the yaxis values. I'm looking for a way to override this and specify exactly where I want the yaxis, regardless of what values are displayed.
E.g. if the graph is 6 inches wide, I would like to specify that the yaxis always be drawn 1 inch from the left edge.
I think one way to do this is to use SGPANEL procedure with:
PANELBY test / LAYOUT=ROWLATTICE ROWS=1;
One column of cells will be created, with each cell containing the graph per "test". SGPANEL will automatically align the offset of all the y axes in each cell the the maximum needed for all cells. Setting ROWS=1 will output one cell of the column per output image. Other customizations may be needed.
I don't have a way to test this out, maybe DanH_SAS can verify.
@Jay54 's trick will work great, with the addition of a couple of options:
PANELBY test / LAYOUT=ROWLATTICE ROWS=1 UNISCALE=COLUMN NOHEADER;
This big issue with using SGPANEL here is your dynamic title. It is possible to incorporate your title into your data and doing something like this:
PANELBY title / ROWS=1 COLUMNS=1 UNISCALE=COLUMN;
This would put the title in the cell header for each plot.
For title, you could remove the header (NOHEADER), and add the title using the TEXT plot statement. Add the title to a column in the data called 'Title'. For each value of 'Test', populate this title column with the title, for other obs of same test value, leave it blank. Add two columns xTitle=(mid value of the x range) and yTitle =max value for each test case. Then, use:
TEXT x=xTitle y=yTitle text=Title / Position=TOP;
This will place the title inside each graph in the center at the top.
Registration is open! SAS is returning to Vegas for an AI and analytics experience like no other! Whether you're an executive, manager, end user or SAS partner, SAS Innovate is designed for everyone on your team. Register for just $495 by 12/31/2023.
If you are interested in speaking, there is still time to submit a session idea. More details are posted on the website.
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.