I am using SGPLOT (in SAS 9.4 1M4) to create a stacked bar chart. Each subject has 5 visits (Visit 1,2,3,4,5) and a dose at each visit. They have a total dose at each visit. My Y-axis is the total dose. The X-axis is each subject. Each stacked bar shows the total dose split up by visit.
proc sgplot data=test;
vbar subject / response=tot /* Total Dose at each visit by subject. So each subject has 5 records to capture total dose at a visit*/
group=visit /*Numeric 1,2,3,4,5*/
categoryorder=respasc /*Displays totals by ascending oder*/
/* grouporder=ascending ***This accomplishes the requirement to keep the visits in order. If I try to use both categoryorder and grouporder options together it does not work*/;
xaxis label='Subject';
yaxis label='Total Dose';
run;
Now in each stacked bar, I need to keep the visits in the same visit order (1,2,3,4,5) instead of their dose at each visit. So right now, if visit 4 has a smaller dose than visit 1, it shows up before (bottom of the stack) the visit 1 dose in the stack. I want the stack to always display visit 1 before visit 2 and so on for each subject while still displaying the stacks in ascending order of TOTAL DOSE. How can I accomplish this?
Thanks,
Vamsi
Dan,
Thank you so much. The issue was to sort it by only the tot_height and then it works.
Thanks,
Vamsi
@Vamsi_77 wrote:
I am using SGPLOT (in SAS 9.4 1M4) to create a stacked bar chart. Each subject has 5 visits (Visit 1,2,3,4,5) and a dose at each visit. They have a total dose at each visit. My Y-axis is the total dose. The X-axis is each subject. Each stacked bar shows the total dose split up by visit.
proc sgplot data=test;
vbar subject / response=tot /* Total Dose at each visit by subject. So each subject has 5 records to capture total dose at a visit*/group=visit /*Numeric 1,2,3,4,5*/
categoryorder=respasc /*Displays totals by ascending oder*/
/* grouporder=ascending ***This accomplishes the requirement to keep the visits in order. If I try to use both categoryorder and grouporder options together it does not work*/;
xaxis label='Subject';
yaxis label='Total Dose';
run;
Now in each stacked bar, I need to keep the visits in the same visit order (1,2,3,4,5) instead of their dose at each visit. So right now, if visit 4 has a smaller dose than visit 1, it shows up before (bottom of the stack) the visit 1 dose in the stack. I want the stack to always display visit 1 before visit 2 and so on for each subject while still displaying the stacks in ascending order of TOTAL DOSE. How can I accomplish this?
Thanks,
Vamsi
From the documentation on CATEGORYORDER
Interactions | When a group variable is used with the CATEGORYORDER= option, the response values for each group segment become the sorting key. CATEGORYORDER sorts first by the response statistic and then displays the GROUP values sorted within each category. |
So, do not use the categoryorder option.
Try using the GROUPORDER=ASCENDING option to use the group variable to control order of the segments.
Yes, I already did that but then I would not be able to sort by ascending order of total dose. I need to combine the functionality of the category order and group order.
Here's how you can do it:
1. Using PROC SUMMARY or PROC MEANS, compute the bar height MINUS THE GROUP. Some like:
proc summary data=whatever nway;
class subject;
var tot;
output out=barheight sum=height;
run;
2. Match merge the "barheight" data with the "whatever" data by SUBJECT.
3. PROC SORT the merged dataset by HEIGHT and VISIT.
4. Use VBARPARM instead of VBAR to render the chart. Be sure to set DISCRETEORDER=DATA on the XAXIS statement.
Hope this helps!
Dan
Thanks, Dan. I am at the 4th step and this is the code I am using:
proc sgplot data=whatever;
vbarparm category=subjid response=tot / group=Visit;
xaxis discreteorder=data label='Subject';
yaxis label='Total Dose';
run;
I am getting a graph similar to using the grouporder option that I was using previously. Can you please let me know what I am missing?
Thanks,
Vamsi
Can you PROC PRINT your data and verify that the groups within each bar are in order? You might need to specify GROUPORDER=ASCENDING on the VBARPARM as well. Let me know what you find.
Thanks!
Dan
The PROC PRINT shows the data are in the correct order. The grouporder=ascending does not add anything.
Thanks,
Vamsi
Since your data is in the correct order, try GROUPORDER=DATA and see if that works for you.
Dan,
Thank you so much. The issue was to sort it by only the tot_height and then it works.
Thanks,
Vamsi
Dan,
How can I add a data label on top of a few stacked bars. For example, I want to add a label above all 'male' subjects.
data dlabel;
set test;
if male='Y' then dlabel="*";
else dlabel=" ";
run;
I tried using the datalabel=dlabel option in my vbarparm statement as you suggested in another post.
It does not work for me. I would appreciate any help.
Thanks,
Vamsi
That example also needed GROUPDISPLAY=CLUSTER. I have now corrected that example. Thanks for bringing it to my attention. Since you need this for stacked bars, you can use a TEXT plot overlay on your VBARPARM to add the labels at the top. Here is a simple example:
/* The standard bar calculations using the group variable*/
proc summary data=sashelp.class nway;
class age sex;
var weight;
output out=temp sum=sumwgt;
run;
/* Find the top of the bars */
proc summary data=sashelp.class nway;
class age;
var weight;
output out=labelpos sum=pos;
run;
/* merge what is needed, and add your labels */
data class;
merge temp labelpos (keep=age pos);
by age;
if age < 14 then label="Young";
else label="Old";
run;
proc sgplot data=class;
vbarparm category=age response=sumwgt / group=sex;
text x=age y=pos text=label / position=top;
run;
Hope this helps!
Dan
I already have a group. So my code looks like this:
proc sgplot data=test;
vbarparm category=subjid repsonse=tot /*total dose at each visit*/
/ group=visit grouporder=ascending datalabel=dlabel;
xaxis discreteorder=data label='Subject';
yaxis label = 'Total Dose' values=(0 to 5000 by 1000) offsetmin=0;
run;
Thanks,
Vamsi
It worked. I did not notice the y=bar_ht in the text statement. Thank you.
Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9. Sign up by March 14 for just $795.
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.