BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
zhangda
Fluorite | Level 6

Hello,

 

I have a code below where a two-curve outlay on a red/blue bar chart. But I have two questions to ask. First, how to add new colors such as orange/purple on the two curves so that the curves could distinguish themselves from bar charts, which could also make the d_2015, d_2016 rows corresponding the curves under the graph distinguish those of bar chart. Second, is it possible to add gridded line on the fours d_2015, d_2016 rows and the row of 'Null, S_300, S_640,S_670....." Thank you so much!

 

data ds1;

input year $ mid $ resp1 resp2;

datalines;

null d_2016 0.45 0.64

null d_2015 0.35 0.783

s_300 d_2016 0.65 0.67

s_300 d_2015 0.55 0.75

s_640 d_2016 0.42 0.89

s_640 d_2015 0.65 0.87

s_670 d_2016 0.35 0.12

s_670 d_2015 0.75 0.09

s_700 d_2016 0.83 0.06

s_700 d_2015 0.47 0.07

s_730 d_2016 0.48 0.18

s_730 d_2015 0.58 0.21

s_760 d_2016 0.67 0.05

s_760 d_2015 0.69 0.045

;

run;

 

ods graphics / reset attrpriority=color width=5in height=3in imagename='Goodgraph';

title 'Score Distribution';

proc sgplot data=ds1 noborder noautolegend;

vbarparm category=year response=resp1 / group=mid groupdisplay=cluster

outlineattrs=(color=black) barwidth=0.8;

xaxistable resp1 / class=mid colorgroup=mid;

xaxis display=(nolabel);

yaxis display=(nolabel);

series x=year y=resp2 / group=mid smoothconnect

lineattrs=(thickness=2);

xaxistable resp2 / class=mid colorgroup=mid; styleattrs datacontrastcolors=(red blue);

xaxis display=(nolabel) label="Year";

yaxis label="Rate" tickvalueformat= percent7.0;

run;

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Jay54
Meteorite | Level 14

What you want is a bit more complex, but can be done using the Discrete Attributes Map.  This is like a format, but for line and bar colors.  You need two group columns, one for each response, and unique values for the groups.  I generated these by adding a "_2" to the other ones.  I used this way.  Alternatively, it may be preferable to have one response column, with 4 unique group values in "Mid".  You also need to define a DATTRMAP data set, setting the colors for each group value.

 

data ds1;
input year $ mid $ resp1 resp2;
mid2=cat(strip(mid), "_2");
datalines;
null d_2016 0.45 0.64
null d_2015 0.35 0.783
s_300 d_2016 0.65 0.67
s_300 d_2015 0.55 0.75
s_640 d_2016 0.42 0.89
s_640 d_2015 0.65 0.87
s_670 d_2016 0.35 0.12
s_670 d_2015 0.75 0.09
s_700 d_2016 0.83 0.06
s_700 d_2015 0.47 0.07
s_730 d_2016 0.48 0.18
s_730 d_2015 0.58 0.21
s_760 d_2016 0.67 0.05
s_760 d_2015 0.69 0.045
;
 
/*--Define Attr Map for groups--*/
data attrmap;
  length value FillColor LineColor TextColor $12;
  Id='X'; Value="d_2015"; FillStyleElement='graphdata1'; LineStyleElement='graphdata1'; TextStyleElement='graphdata1';output;
  Id='X'; Value="d_2016"; FillStyleElement='graphdata2'; LineStyleElement='graphdata2'; TextStyleElement='graphdata2';output;
  Id='X'; Value="d_2015_2"; FillStyleElement='graphdata3'; LineStyleElement='graphdata3'; TextStyleElement='graphdata3';output;
  Id='X'; Value="d_2016_2"; FillStyleElement='graphdata4'; LineStyleElement='graphdata4'; TextStyleElement='graphdata4';output;
run;

ods listing gpath='.' image_dpi=200;
ods graphics / reset attrpriority=color width=5in height=3in imagename='Goodgraph';
title 'Score Distribution';
proc sgplot data=ds1 noborder noautolegend cycleattrs dattrmap=attrmap;
vbarparm category=year response=resp1 / group=mid groupdisplay=cluster
         outlineattrs=(color=black) barwidth=0.8 attrid=X;
series x=year y=resp2 / group=mid2 smoothconnect attrid=X
         lineattrs=(thickness=3);
xaxistable resp1 / class=mid colorgroup=mid attrid=X;
xaxistable resp2 / class=mid2 colorgroup=mid2 attrid=X; 
xaxis display=(nolabel) label="Year";
yaxis offsetmin=0 label="Rate" tickvalueformat= percent7.0;
run;

Goodgraph.png

 

View solution in original post

8 REPLIES 8
Jay54
Meteorite | Level 14

What you want is a bit more complex, but can be done using the Discrete Attributes Map.  This is like a format, but for line and bar colors.  You need two group columns, one for each response, and unique values for the groups.  I generated these by adding a "_2" to the other ones.  I used this way.  Alternatively, it may be preferable to have one response column, with 4 unique group values in "Mid".  You also need to define a DATTRMAP data set, setting the colors for each group value.

 

data ds1;
input year $ mid $ resp1 resp2;
mid2=cat(strip(mid), "_2");
datalines;
null d_2016 0.45 0.64
null d_2015 0.35 0.783
s_300 d_2016 0.65 0.67
s_300 d_2015 0.55 0.75
s_640 d_2016 0.42 0.89
s_640 d_2015 0.65 0.87
s_670 d_2016 0.35 0.12
s_670 d_2015 0.75 0.09
s_700 d_2016 0.83 0.06
s_700 d_2015 0.47 0.07
s_730 d_2016 0.48 0.18
s_730 d_2015 0.58 0.21
s_760 d_2016 0.67 0.05
s_760 d_2015 0.69 0.045
;
 
/*--Define Attr Map for groups--*/
data attrmap;
  length value FillColor LineColor TextColor $12;
  Id='X'; Value="d_2015"; FillStyleElement='graphdata1'; LineStyleElement='graphdata1'; TextStyleElement='graphdata1';output;
  Id='X'; Value="d_2016"; FillStyleElement='graphdata2'; LineStyleElement='graphdata2'; TextStyleElement='graphdata2';output;
  Id='X'; Value="d_2015_2"; FillStyleElement='graphdata3'; LineStyleElement='graphdata3'; TextStyleElement='graphdata3';output;
  Id='X'; Value="d_2016_2"; FillStyleElement='graphdata4'; LineStyleElement='graphdata4'; TextStyleElement='graphdata4';output;
run;

ods listing gpath='.' image_dpi=200;
ods graphics / reset attrpriority=color width=5in height=3in imagename='Goodgraph';
title 'Score Distribution';
proc sgplot data=ds1 noborder noautolegend cycleattrs dattrmap=attrmap;
vbarparm category=year response=resp1 / group=mid groupdisplay=cluster
         outlineattrs=(color=black) barwidth=0.8 attrid=X;
series x=year y=resp2 / group=mid2 smoothconnect attrid=X
         lineattrs=(thickness=3);
xaxistable resp1 / class=mid colorgroup=mid attrid=X;
xaxistable resp2 / class=mid2 colorgroup=mid2 attrid=X; 
xaxis display=(nolabel) label="Year";
yaxis offsetmin=0 label="Rate" tickvalueformat= percent7.0;
run;

Goodgraph.png

 

zhangda
Fluorite | Level 6

Hi Sanjay,

 

Is it possible that another parallel vertical line is added to the right side of the graph below, where 0%,20%,40%,60%,80% are labelled respectively as the vertical line on the left side the graph showed. Thanks!

Jay54
Meteorite | Level 14

Yes.  You can use the REFTICKS option to repeat the same axis on the other side.  

Or, you can display a 2nd independent axis (Y2) by setting some plots to Y2AXIS.

http://blogs.sas.com/content/graphicallyspeaking/2016/07/24/stock-plots/

zhangda
Fluorite | Level 6

Hi Sanjay,

 

Thank you so much for your guidance, but I still have a couple of questions.

1. How can I put the vertical axis the percentage data ranging from 0% to 100% instead of '0% to 80%'?

2. I added reftick option as the code below, but why there is no '0% ,20%, 40%, 60%, 80%', just a naked parallel vertical axis.

3.  I also added a label beside it as ' Second rate', as the axis on the left side shows , but why  the ' Second rate' does not show off ?

4.  I remove the noautolegend option, but why I can only have two small blocks showing 2 colors, for which I am supposed to have four blocks showing 4 colors instead,

5. Apart from color reminder, can I add a piece of block and a piece of line also, to remind readers that what color and what shape represents what color?

6. How can I move the legend showing 4 colors and 4 shapes down and put it ahead of 'd_2015','d_2015','d_2015_2', 'd_2016_2' respectively so that the readers can figure out what color adn what shape represents what data at first sight.

 

Thank you so much!

 

data ds1;
input year $ mid $ resp1 resp2;
mid2=cat(strip(mid), "_2");
datalines;
null d_2016 0.45 0.64
null d_2015 0.35 0.783
s_300 d_2016 0.65 0.67
s_300 d_2015 0.55 0.75
s_640 d_2016 0.42 0.89
s_640 d_2015 0.65 0.87
s_670 d_2016 0.35 0.12
s_670 d_2015 0.75 0.09
s_700 d_2016 0.83 0.06
s_700 d_2015 0.47 0.07
s_730 d_2016 0.48 0.18
s_730 d_2015 0.58 0.21
s_760 d_2016 0.67 0.05
s_760 d_2015 0.69 0.045
; run;

data attrmap;
length value FillColor LineColor TextColor $12;
Id='X'; Value="d_2015"; FillStyleElement='graphdata1'; LineStyleElement='graphdata1'; TextStyleElement='graphdata1';output;
Id='X'; Value="d_2016"; FillStyleElement='graphdata2'; LineStyleElement='graphdata2'; TextStyleElement='graphdata2';output;
Id='X'; Value="d_2015_2"; FillStyleElement='graphdata3'; LineStyleElement='graphdata3'; TextStyleElement='graphdata3';output;
Id='X'; Value="d_2016_2"; FillStyleElement='graphdata4'; LineStyleElement='graphdata4'; TextStyleElement='graphdata4';output;
run;

ods listing gpath='.' image_dpi=200;
ods graphics / reset attrpriority=color width=5in height=3in imagename='Goodgraph';
title 'Score Distribution';
proc sgplot data=ds1 noborder cycleattrs dattrmap=attrmap;
vbarparm category=year response=resp1 / group=mid groupdisplay=cluster
outlineattrs=(color=black) barwidth=0.8 attrid=X;
series x=year y=resp2 / group=mid2 smoothconnect attrid=X
lineattrs=(thickness=3);
xaxistable resp1 / class=mid colorgroup=mid attrid=X;
xaxistable resp2 / class=mid2 colorgroup=mid2 attrid=X;
xaxis display=(nolabel) label="Year";
yaxis offsetmin=0 label="Rate" tickvalueformat= percent7.0
REFTICKS label="Second Rate" tickvalueformat= percent7.0;
run;

Jay54
Meteorite | Level 14

REFTICKS=(label values) 

Rick_SAS
SAS Super FREQ

IMHO, you should get rid of the SMOOTHCONNECT option.  The X axis is categorical, so a smooth curve is misleading and doesn't make sense.

zhangda
Fluorite | Level 6

Hi Rick,

 

Thank you for your reply, but you know what, to make the curve smooth is the basic requirement from the team leader.

Rick_SAS
SAS Super FREQ

Does the X axis represent time values such as 0, 300, 640,... days?  If so, then a smooth curve would make sense. However, if the axis represents time points then you should space out the axis in a linear fashion, so that the distance betwee 300 and 640 is not the same as the distance between 640 and 670.

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

How to Concatenate Values

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 8 replies
  • 1967 views
  • 1 like
  • 3 in conversation