-->
In the sgplot below, I am trying to create a graph that draws attention to "North America" and coding it so that when I update the data next year, even if the order by "growth_rate" (which is defined by proc sort) changes (i.e., North America is no longer the region with the worst growth rate in 2025), every time the horizontal bars are created for North America they will have the respective reddish colors chosen in the data step "have3" and all other regions will have the bluish colors chosen in the data step "have3".
Could someone help me understand why SAS is not correctly applying the colors defined for the variable color (and instead is using shades of gray that I have not indicated)?
Also how to make my code works as I intend? In other words, I am trying to create a graph that always draws attention to North America by assigning it a unique colors. Any insight is welcome!
Here is my code:
data have;
input code region &$20. growth_rate year;
datalines;
0 North America -5.92 2020
0 North America -2.18 2021
0 North America -7.47 2022
0 North America -2.17 2023
0 North America -9.64 2024
1 South America 0.36 2020
1 South America 2.69 2021
1 South America -8.13 2022
1 South America 1.22 2023
1 South America -1.34 2024
2 Asia -1.53 2020
2 Asia 2.18 2021
2 Asia 5.64 2022
2 Asia 6.80 2023
2 Asia 8.70 2024
3 Europe -9.68 2020
3 Europe 3.91 2021
3 Europe 5.48 2022
3 Europe 3.52 2023
3 Europe 3.69 2024
4 Africa 3.29 2020
4 Africa 7.97 2021
4 Africa 2.48 2022
4 Africa 7.36 2023
4 Africa 1.31 2024
5 Oceania 8.00 2020
5 Oceania -6.05 2021
5 Oceania 6.91 2022
5 Oceania -1.09 2023
5 Oceania -7.46 2024
;
run;
proc sort data=have(where=(year=2024)) out=temp;
by descending growth_rate ;
run;
data fmt;
set temp(rename=(region=start));
retain fmtname 'fmt' type 'c';
length label $ 80;
label=repeat(' ',_n_)||strip(start);
keep fmtname type start label;
run;
proc format cntlin=fmt;
run;
data have2;
set have;
_region=put(region,$fmt32.);
if region="North America" then call symput('NorthAmerica',_region);
run;
data have3;
set have2;
if _region="North America" then do;
if year=2020 then color="#f7ebde";
else if year=2021 then color="#efdbc6";
else if year=2022 then color="#e1ca9e";
else if year=2023 then color="#d6ae6b";
else if year=2024 then color="#b4771f";
end;
if _region NE "North America" then do;
if year=2020 then color="#deebf7";
else if year=2021 then color="#c6dbef";
else if year=2022 then color="#9ecae1";
else if year=2023 then color="#6baed6";
else if year=2024 then color="#1f77b4";
end;
run;
%sganno
data sganno;
%SGTEXT(LABEL="North America",TEXTWEIGHT="BOLD",TEXTCOLOR="RED",TEXTSIZE=10, FILLCOLOR="white",FILLTRANSPARENCY=0,WIDTH=40,Y1SPACE="DATAVALUE",X1SPACE="LAYOUTPERCENT",YC1="&NorthAmerica.",X1=6 )
run;
proc sgplot data=have3 sganno=sganno;
title "Growth rate";
styleattrs datacolors=(color);
hbar _region / response=growth_rate group=year
groupdisplay=cluster
clusterwidth=0.9
datalabel DATALABELFITPOLICY=NONE
datalabelattrs=(size=8pt)
barwidth=1 nooutline
transparency=0 dataskin=none;
xaxis display=(nolabel) min=-12 max=12;
yaxis display=(nolabel) colorbands=even ;
run;
I think the easiest way for this case here is to use a range attributes map. The key is mapping the region/year combinations into a single numeric value that you can use in the attributes map.
data have;
input code region $ 3-16 growth_rate year;
datalines;
0 North America -5.92 2020
0 North America -2.18 2021
0 North America -7.47 2022
0 North America -2.17 2023
0 North America -9.64 2024
1 South America 0.36 2020
1 South America 2.69 2021
1 South America -8.13 2022
1 South America 1.22 2023
1 South America -1.34 2024
2 Asia -1.53 2020
2 Asia 2.18 2021
2 Asia 5.64 2022
2 Asia 6.80 2023
2 Asia 8.70 2024
3 Europe -9.68 2020
3 Europe 3.91 2021
3 Europe 5.48 2022
3 Europe 3.52 2023
3 Europe 3.69 2024
4 Africa 3.29 2020
4 Africa 7.97 2021
4 Africa 2.48 2022
4 Africa 7.36 2023
4 Africa 1.31 2024
5 Oceania 8.00 2020
5 Oceania -6.05 2021
5 Oceania 6.91 2022
5 Oceania -1.09 2023
5 Oceania -7.46 2024
;
run;
proc sort data=have(where=(year=2024)) out=temp;
by descending growth_rate ;
run;
data fmt;
set temp(rename=(region=start));
retain fmtname 'fmt' type 'c';
length label $ 80;
label=repeat(' ',_n_)||strip(start);
keep fmtname type start label;
run;
proc format cntlin=fmt;
run;
data have2;
set have;
_region=put(region,$fmt32.);
if region="North America" then call symput('NorthAmerica',_region);
run;
data have3;
set have2;
if region="North America" then do;
if year=2020 then color=1;
else if year=2021 then color=2;
else if year=2022 then color=3;
else if year=2023 then color=4;
else if year=2024 then color=5;
end;
if region NE "North America" then do;
if year=2020 then color=6;
else if year=2021 then color=7;
else if year=2022 then color=8;
else if year=2023 then color=9;
else if year=2024 then color=10;
end;
run;
data attrmap;
retain ID "barcolors" altcolor "black";
input min $ max $ color $;
datalines;
1 1 cxf7ebde
2 2 cxefdbc6
3 3 cxe1ca9e
4 4 cxd6ae6b
5 5 cxb4771f
6 6 cxdeebf7
7 7 cxc6dbef
8 8 cx9ecae1
9 9 cx6baed6
10 10 cx1f77b4
;
run;
data sganno;
%sganno
%SGTEXT(LABEL="North America",TEXTWEIGHT="BOLD",TEXTCOLOR="RED",TEXTSIZE=10, FILLCOLOR="white",FILLTRANSPARENCY=0,WIDTH=40,Y1SPACE="DATAVALUE",X1SPACE="LAYOUTPERCENT",YC1="&NorthAmerica.",X1=6 )
run;
proc sgplot data=have3 sganno=sganno rattrmap=attrmap noautolegend;
title "Growth rate";
hbar _region / response=growth_rate group=year colorresponse=color rattrid=barcolors
groupdisplay=cluster
clusterwidth=0.9
datalabel DATALABELFITPOLICY=NONE
datalabelattrs=(size=8pt)
barwidth=1 nooutline
transparency=0 dataskin=none;
xaxis display=(nolabel) min=-12 max=12;
yaxis display=(nolabel) colorbands=even ;
run;
Please follow these instructions and example
I think the easiest way for this case here is to use a range attributes map. The key is mapping the region/year combinations into a single numeric value that you can use in the attributes map.
data have;
input code region $ 3-16 growth_rate year;
datalines;
0 North America -5.92 2020
0 North America -2.18 2021
0 North America -7.47 2022
0 North America -2.17 2023
0 North America -9.64 2024
1 South America 0.36 2020
1 South America 2.69 2021
1 South America -8.13 2022
1 South America 1.22 2023
1 South America -1.34 2024
2 Asia -1.53 2020
2 Asia 2.18 2021
2 Asia 5.64 2022
2 Asia 6.80 2023
2 Asia 8.70 2024
3 Europe -9.68 2020
3 Europe 3.91 2021
3 Europe 5.48 2022
3 Europe 3.52 2023
3 Europe 3.69 2024
4 Africa 3.29 2020
4 Africa 7.97 2021
4 Africa 2.48 2022
4 Africa 7.36 2023
4 Africa 1.31 2024
5 Oceania 8.00 2020
5 Oceania -6.05 2021
5 Oceania 6.91 2022
5 Oceania -1.09 2023
5 Oceania -7.46 2024
;
run;
proc sort data=have(where=(year=2024)) out=temp;
by descending growth_rate ;
run;
data fmt;
set temp(rename=(region=start));
retain fmtname 'fmt' type 'c';
length label $ 80;
label=repeat(' ',_n_)||strip(start);
keep fmtname type start label;
run;
proc format cntlin=fmt;
run;
data have2;
set have;
_region=put(region,$fmt32.);
if region="North America" then call symput('NorthAmerica',_region);
run;
data have3;
set have2;
if region="North America" then do;
if year=2020 then color=1;
else if year=2021 then color=2;
else if year=2022 then color=3;
else if year=2023 then color=4;
else if year=2024 then color=5;
end;
if region NE "North America" then do;
if year=2020 then color=6;
else if year=2021 then color=7;
else if year=2022 then color=8;
else if year=2023 then color=9;
else if year=2024 then color=10;
end;
run;
data attrmap;
retain ID "barcolors" altcolor "black";
input min $ max $ color $;
datalines;
1 1 cxf7ebde
2 2 cxefdbc6
3 3 cxe1ca9e
4 4 cxd6ae6b
5 5 cxb4771f
6 6 cxdeebf7
7 7 cxc6dbef
8 8 cx9ecae1
9 9 cx6baed6
10 10 cx1f77b4
;
run;
data sganno;
%sganno
%SGTEXT(LABEL="North America",TEXTWEIGHT="BOLD",TEXTCOLOR="RED",TEXTSIZE=10, FILLCOLOR="white",FILLTRANSPARENCY=0,WIDTH=40,Y1SPACE="DATAVALUE",X1SPACE="LAYOUTPERCENT",YC1="&NorthAmerica.",X1=6 )
run;
proc sgplot data=have3 sganno=sganno rattrmap=attrmap noautolegend;
title "Growth rate";
hbar _region / response=growth_rate group=year colorresponse=color rattrid=barcolors
groupdisplay=cluster
clusterwidth=0.9
datalabel DATALABELFITPOLICY=NONE
datalabelattrs=(size=8pt)
barwidth=1 nooutline
transparency=0 dataskin=none;
xaxis display=(nolabel) min=-12 max=12;
yaxis display=(nolabel) colorbands=even ;
run;
Oh, I forgot to add the NOAUTOLEGEND option to the SGPLOT statement. You'll want that to get rid of the gradient legend on the right.
Nevermind, I was able to edit the post 🙂
1)
Same as Danh_sas 's code, other than him ,I used DATTRMAP= option:
data have; input code region &$20. growth_rate year; datalines; 0 North America -5.92 2020 0 North America -2.18 2021 0 North America -7.47 2022 0 North America -2.17 2023 0 North America -9.64 2024 1 South America 0.36 2020 1 South America 2.69 2021 1 South America -8.13 2022 1 South America 1.22 2023 1 South America -1.34 2024 2 Asia -1.53 2020 2 Asia 2.18 2021 2 Asia 5.64 2022 2 Asia 6.80 2023 2 Asia 8.70 2024 3 Europe -9.68 2020 3 Europe 3.91 2021 3 Europe 5.48 2022 3 Europe 3.52 2023 3 Europe 3.69 2024 4 Africa 3.29 2020 4 Africa 7.97 2021 4 Africa 2.48 2022 4 Africa 7.36 2023 4 Africa 1.31 2024 5 Oceania 8.00 2020 5 Oceania -6.05 2021 5 Oceania 6.91 2022 5 Oceania -1.09 2023 5 Oceania -7.46 2024 ; run; proc sort data=have(where=(year=2024)) out=temp; by descending growth_rate ; run; data fmt; set temp(rename=(region=start)); retain fmtname 'fmt' type 'c'; length label $ 80; label=repeat(' ',_n_)||strip(start); keep fmtname type start label; run; proc format cntlin=fmt; run; data have2; set have; _region=put(region,$fmt32.); if region="North America" then call symput('NorthAmerica',_region); run; data have3; set have2; if strip(_region)="North America" then year=10*year ; run; data dattramp; input id $ value fillcolor $; cards; x 20200 #f7ebde x 20210 #efdbc6 x 20220 #e1ca9e x 20230 #d6ae6b x 20240 #b4771f x 2020 #deebf7 x 2021 #c6dbef x 2022 #9ecae1 x 2023 #6baed6 x 2024 #1f77b4 ; %sganno data sganno; %SGTEXT(LABEL="North America",TEXTWEIGHT="BOLD",TEXTCOLOR="RED",TEXTSIZE=10, FILLCOLOR="white",FILLTRANSPARENCY=0,WIDTH=40,Y1SPACE="DATAVALUE",X1SPACE="LAYOUTPERCENT",YC1="&NorthAmerica.",X1=6 ) run; proc sgplot data=have3 sganno=sganno dattrmap=dattramp noautolegend; title "Growth rate"; *styleattrs datacolors=(color); hbar _region / response=growth_rate group=year attrid=x groupdisplay=cluster clusterwidth=0.9 datalabel DATALABELFITPOLICY=NONE datalabelattrs=(size=8pt) barwidth=1 nooutline transparency=0 dataskin=none; xaxis display=(nolabel) min=-12 max=12; yaxis display=(nolabel) colorbands=even colorbandsattrs=(transparency=0.8 color=grey) ; run;
2)And if your dataset has been sorted as you did, you can code it as simple as this:
data have; input code region &$20. growth_rate year; datalines; 0 North America -5.92 2020 0 North America -2.18 2021 0 North America -7.47 2022 0 North America -2.17 2023 0 North America -9.64 2024 1 South America 0.36 2020 1 South America 2.69 2021 1 South America -8.13 2022 1 South America 1.22 2023 1 South America -1.34 2024 2 Asia -1.53 2020 2 Asia 2.18 2021 2 Asia 5.64 2022 2 Asia 6.80 2023 2 Asia 8.70 2024 3 Europe -9.68 2020 3 Europe 3.91 2021 3 Europe 5.48 2022 3 Europe 3.52 2023 3 Europe 3.69 2024 4 Africa 3.29 2020 4 Africa 7.97 2021 4 Africa 2.48 2022 4 Africa 7.36 2023 4 Africa 1.31 2024 5 Oceania 8.00 2020 5 Oceania -6.05 2021 5 Oceania 6.91 2022 5 Oceania -1.09 2023 5 Oceania -7.46 2024 ; run; proc sort data=have(where=(year=2024)) out=temp; by descending growth_rate ; run; data fmt; set temp(rename=(region=start)); retain fmtname 'fmt' type 'c'; length label $ 80; label=repeat(' ',_n_)||strip(start); keep fmtname type start label; run; proc format cntlin=fmt; run; data have2; set have; _region=put(region,$fmt32.); if region="North America" then call symput('NorthAmerica',_region); run; data have3; set have2; if strip(_region)="North America" then year=10*year ; run; %sganno data sganno; %SGTEXT(LABEL="North America",TEXTWEIGHT="BOLD",TEXTCOLOR="RED",TEXTSIZE=10, FILLCOLOR="white",FILLTRANSPARENCY=0,WIDTH=40,Y1SPACE="DATAVALUE",X1SPACE="LAYOUTPERCENT",YC1="&NorthAmerica.",X1=6 ) run; proc sgplot data=have3 sganno=sganno noautolegend; title "Growth rate"; styleattrs datacolors=( cxf7ebde cxefdbc6 cxe1ca9e cxd6ae6b cxb4771f cxdeebf7 cxc6dbef cx9ecae1 cx6baed6 cx1f77b4 ); hbar _region / response=growth_rate group=year groupdisplay=cluster clusterwidth=0.9 datalabel DATALABELFITPOLICY=NONE datalabelattrs=(size=8pt) barwidth=1 nooutline transparency=0 dataskin=none; xaxis display=(nolabel) min=-12 max=12; yaxis display=(nolabel) colorbands=even colorbandsattrs=(transparency=0.8 color=grey) ; run;
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.