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

I created a map using gmap. I need to apply colors to different regions using a standard color scale. I tried to convert the scales using both %rgb and %cmyk  macros to sas color scheme but I get totally different colors displayed. Any help?

 

here is the code for both macros:

%macro rgbconvert (r,g,b);

data _null_;
  r = &r;
  g = &g;
  b = &b;
  rgb="CX" || put(r,hex2.) || put(g,hex2.) || put(b,hex2.);
  put rgb;
run;
%mend rgbconvert;
%rgbconvert (190,27,27);
%rgbconvert (208,34,38);
%rgbconvert (222,54,60);
%rgbconvert (228,93,102);
%rgbconvert (231,111,119);
%rgbconvert (234,129,136);
%rgbconvert (237,147,153);
%rgbconvert (240,165,170);
%rgbconvert (243,183,187);
%rgbconvert (246,201,204);
%rgbconvert (249,219,221);
%rgbconvert (252,237,238);
%rgbconvert (228,241,234);
%rgbconvert (203,228,222);
%rgbconvert (178,215,210);
%rgbconvert (153,202,198);
%rgbconvert (128,189,186);
%rgbconvert (103,176,174);
%rgbconvert (78,163,162);
%rgbconvert (53,150,150);
%rgbconvert (28,137,138);
%rgbconvert (3,124,126);

Am suppose to get colors like deep green, light green, deep red, light red using the listed values. But am getting colors like brown, purple , blue and so on. Is there anything am doing wrong?

1 ACCEPTED SOLUTION

Accepted Solutions
GraphGuy
Meteorite | Level 14

Rather than letting the ranges of the user-defined-format control the legend color binning, I prefer to add a variable to the dataset, and specifically assign each observation to a bin (bucket), and then list all those buckets in gmap's midpoints= list (to make sure they all show up in the legend, even if there are no data values in a certain range/bucket). I then use a user-defined-format to make those buckets print in the legend as the range of values they represent. It's a little more manual work, but I think it provides more complete control.

 

Here's a modification of your code, using my technique:

 

%let name=map;
filename odsout '.';

goptions device=png;
goptions border;

ODS LISTING CLOSE;
ODS HTML path=odsout body="&name..htm" style=htmlblue;

goptions gunit=pct ftitle="albany amt/bold" ftext="albany amt" htitle=4.0 htext=2.5;
goptions ctext=gray33;

proc format;
value buckfmt
1 = '130.2 and more'
2 = '120.2 to 130.2'
3 = '105.8 to 120.2'
4 = '97.0  to 105.8'
5 = '80.9  to 97.0'
6 = '70.4  to 80.9'
7 = '60.6  to 70.4'
8 = '50.5  to 60.6'
9 = '48.0  to 50.5'
10 = '40.2  to 48.0'
11 = '34.0  to 40.2'
12 = '27.5  to 34.0'
13 = '21.6  to 27.5'
14 = '16.4  to 21.6'
15 = '12.8  to 16.4'
16 = ' 9.7  to 12.8'
17 = ' 5.8  to  9.7'
18 = ' 3.8  to  5.8'
19 = ' 1.8  to  3.8'
20 = ' 0.5  to  1.8'
21 = ' 0.1  to  0.5'
22 = ' 0.0  to  0.1'
;
run;

libname here '.';
data modhessen; set here.hessen; 
     if europianstandard>=130.2 then bucket=1;
else if europianstandard>=120.2 then bucket=2;
else if europianstandard>=105.8 then bucket=3;
else if europianstandard>=97.0 then bucket=4;
else if europianstandard>=80.9 then bucket=5;
else if europianstandard>=70.4 then bucket=6;
else if europianstandard>=60.6 then bucket=7;
else if europianstandard>=50.5 then bucket=8;
else if europianstandard>=48.0 then bucket=9;
else if europianstandard>=40.2 then bucket=10;
else if europianstandard>=34.0 then bucket=11;
else if europianstandard>=27.5 then bucket=12;
else if europianstandard>=21.6 then bucket=13;
else if europianstandard>=16.4 then bucket=14;
else if europianstandard>=12.8 then bucket=15;
else if europianstandard>=9.7 then bucket=16;
else if europianstandard>=5.8 then bucket=17;
else if europianstandard>=3.8 then bucket=18;
else if europianstandard>=1.8 then bucket=19;
else if europianstandard>=0.5 then bucket=20;
else if europianstandard>=0.1 then bucket=21;
else if europianstandard>=0.0 then bucket=22;
else bucket=.;
run;


pattern1 value=solid color='CXBF1C1C'; ****red0 redbrown****;
pattern2 value=solid color='CXD02226'; ****red1****;
pattern3 value=solid color='CXDE363C'; ****red2****;
pattern4 value=solid color='CXE45D66'; ****red3****;
pattern5 value=solid color='CXE76F77'; ****red4****;
pattern6 value=solid color='CXEA8188'; ****red5****;
pattern7 value=solid color='CXED9399'; ****red6****;
pattern8 value=solid color='CXF0A5AA'; ****red7****;
pattern9 value=solid color='CXF3B7BB'; ****lightred8****;
pattern10 value=solid color='CXF6C9CC'; ****lightred9****;
pattern11 value=solid color='CXF9DBDD'; ****lightred10****;
pattern12 value=solid color='CXFCEDEE'; ****palered11****;
pattern13 value=solid color='CXE4F1EA'; ****palegreen10****;
pattern14 value=solid color='CXCBE4DE'; ****lightgreen9****;
pattern15 value=solid color='CXB2D7D2'; ****lightgreen8****;
pattern16 value=solid color='CX99C9C7'; ****green7****;
pattern17 value=solid color='CX80BDBA'; ****green6****;
pattern18 value=solid color='CX67B0AE'; ****green5****;
pattern19 value=solid color='CX4EA3A2'; ****green4****;
pattern20 value=solid color='CX359696'; ****green3****;
pattern21 value=solid color='CX1C898A'; ****green2****;
pattern22 value=solid color='CX037C7E'; ****green1****;

title1 ls=1.5 "GMap, with custom legend binning";

legend1 label =(f="albany amt/bold" position=top j=c h=12pt "Inzidenzrate")
 value=(f="albany amt" h=10pt c=black tick=3)
 across=1
 position=(right middle) 
 offset=(-2,3)
 space=1
 mode=reserve
 shape=bar(.15in,.15in)
 ;

proc gmap map=here.test data=modhessen all;
format bucket buckfmt.;
ID id;
choro bucket/ discrete midpoints = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 /* Annotate=maplabelhessen */
 legend=legend1
 coutline=black
 cdefault=cxfcfad2 /* areas with no data are light yellow */
 name="mychart";
run; 

quit;
ODS HTML CLOSE;
ODS LISTING;

 

binned_map.png 

View solution in original post

13 REPLIES 13
PaigeMiller
Diamond | Level 26

Since you don't say where the colors will be applied, let me just point out that if you want the geographic regions (like a state) to have a certain color, you need to produce PATTERN statements that contains the colors you want. An example is here:

http://documentation.sas.com/?cdcId=pgmmvacdc&cdcVersion=9.4&docsetId=grmapref&docsetTarget=p11sce4o...

 

If you want colors that are not a specific color name in SAS (like "green" is a specific color name in SAS), you can specify the colors in the RGB hexadecimal scale as

 

PATTERN COLOR=CXBB5592;

PATTERN2 COLOR=CXAA7700;

etc

 

So you would have to convert the RGB values to the CX scale in SAS, which you seem to be doing in your code (I didn't test it to determine if your code was doing it correctly)

 

Also, if you want a smooth gradient of colors, there is the %COLORSCALE macro to produce this gradient

http://support.sas.com/kb/48/480.html

--
Paige Miller
Anita_n
Pyrite | Level 9

Thanks for your reply, I could solve the issue myself. It was a mistake I made by placing the goptions reset=all below the Pattern statement. This was always resetting the color to the default color, that was why it wasn't worrking.

 

My next problem now is how do I assign ranges for each of this patterns, like pattern 1 v=s c=green; for ranges between 10.5 and 17.6

I used format to assign them but it seems not to work properly

PaigeMiller
Diamond | Level 26

I used format to assign them but it seems not to work properly

 

You can't say things like "not to work properly" without giving details, because if that's all you say, we can't help. Show us the SASLOG. Explain why it didn't work.

--
Paige Miller
Anita_n
Pyrite | Level 9

Hi, here is a sample data. I wish to assign the following formats to the colors listed in the pattern statements. But if I run my program  the values are assigned wrongly. Is there any thing I need to add to my code?

 

proc format;
value class

                        130.2 - high= '130.2 and more'
				120.2 - 130.2= '120.2 to 130.2'
				105.8 - 120.2= '105.8 to 120.2'
				 97.0 - 105.8= '97.0  to 105.8'
				 80.9 - 97.0 = '80.9  to 97.0'
				 70.4 -  80.9= '70.4  to 80.9'
				 60.6 -  70.4= '60.6  to 70.4'
				 50.5 -  60.6= '50.5  to 60.6'
				 48.0 -  50.5= '48.0  to 50.5'
				 40.2 -  48.0= '40.2  to 48.0'
				 34.0 -  40.2= '34.0  to 40.2'
				 27.5 -  34.0= '27.5  to 34.0'
				 21.6 -  27.5= '21.6  to 27.5'
				 16.4 -  21.6= '16.4  to 21.6'
				 12.8 -  16.4= '12.8  to 16.4'
				  9.7 -  12.8= ' 9.7  to 12.8'
				  5.8 -   9.7= ' 5.8  to  9.7'
				  3.8 -   5.8= ' 3.8  to  5.8'
				  1.8 -   3.8= ' 1.8  to  3.8'
				  0.5 -   1.8= ' 0.5  to  1.8'
				  0.1 -   0.5= ' 0.1  to  0.5'
				  0.0 -   0.1= ' 0.0  to  0.1'
				 

				  ;
run;



pattern1 value=solid color='CXBF1C1C'; ****red0 redbrown****;
pattern2 value=solid color='CXD02226'; ****red1****;
pattern3 value=solid color='CXDE363C'; ****red2****;
pattern4 value=solid color='CXE45D66'; ****red3****;
pattern5 value=solid color='CXE76F77'; ****red4****;
pattern6 value=solid color='CXEA8188'; ****red5****;
pattern7 value=solid color='CXED9399'; ****red6****;
pattern8 value=solid color='CXF0A5AA'; ****red7****;
pattern9 value=solid color='CXF3B7BB'; ****lightred8****;
pattern10 value=solid color='CXF6C9CC'; ****lightred9****;
pattern11 value=solid color='CXF9DBDD'; ****lightred10****;
pattern12 value=solid color='CXFCEDEE'; ****palered11****;
pattern13 value=solid color='CXE4F1EA'; ****palegreen10****;
pattern14 value=solid color='CXCBE4DE'; ****lightgreen9****;
pattern15 value=solid color='CXB2D7D2'; ****lightgreen8****;
pattern16 value=solid color='CX99C9C7'; ****green7****;
pattern17 value=solid color='CX80BDBA'; ****green6****;
pattern18 value=solid color='CX67B0AE'; ****green5****;
pattern19 value=solid color='CX4EA3A2'; ****green4****;
pattern20 value=solid color='CX359696'; ****green3****;
pattern21 value=solid color='CX1C898A'; ****green2****;
pattern22 value=solid color='CX037C7E'; ****green1****;



legend1 label =("Inzidenzrate" position=top h=12pt)
        value=(h=10pt c=black tick=3 f=Arial)
		across=1
		position= (right middle) 
		offset=(-2,2.5)cm
		space=1
		mode=reserve
		;


proc gmap map=test
data=hessen gout=gfout;
ID id ;
format europianstandard class.;
choro europianstandard/ discrete
                      name="mychart"
                      Annotate=maplabelhessen
					  legend= legend1
					  coutline= black
					  xsize=7.4 cm
					  ysize=10 cm
					  ;
run; 
title "";
quit;

 

PaigeMiller
Diamond | Level 26

 the values are assigned wrongly.


Details are needed. What is wrong? State clearly what you think should happen, and what does happen.

--
Paige Miller
PaigeMiller
Diamond | Level 26

What happens if you take DISCRETE out of the CHORO statement?

--
Paige Miller
Anita_n
Pyrite | Level 9

Hello PaigeMiller,

Thanks for your reply, there is a column called europeanstandard in the dataset I sent with some values. The map regions should be coloured depending on this values. This ranges is what I have defined in the proc format. The corresponding colors to be assigned are what I defined in the pattern Statement, that means : pattern1 should be assigned color CXBF1C1C when the range of europeanstandard is between "130.2 - high" and this should be labelled as "130.2 and more" on legend 1 etc.

If I run the program it assigns just red colors although some values which are in the dataset lie in the range where the color should be green. I dont understand why.

Is there any way to find out which format is been assign which color?

I hope you now understand what I mean

 

pattern1='130.2 and more'
pattern2='120.2 to 130.2'
pattern3='105.8 to 120.2'
pattern4='97.0  to 105.8' 
pattern5='80.9  to 97.0'
pattern6='70.4  to 80.9'
and so on

 

PaigeMiller
Diamond | Level 26

Since I can't download your SAS data sets (my company doesn't allow that), it's not clear to me what the problem is.

 

What is one of the values that is assigned to red when it should be green?

 

UPDATE: Disregard this request, I think the answer is in my next post

If your data sets are not too big, you can post them as SAS code, where a datastep reads in the values.

--
Paige Miller
Anita_n
Pyrite | Level 9

I mean I need something similar to attrmap in sg plot to assign formats and colors to regions in my map (using proc gmap)

GraphGuy
Meteorite | Level 14

Rather than letting the ranges of the user-defined-format control the legend color binning, I prefer to add a variable to the dataset, and specifically assign each observation to a bin (bucket), and then list all those buckets in gmap's midpoints= list (to make sure they all show up in the legend, even if there are no data values in a certain range/bucket). I then use a user-defined-format to make those buckets print in the legend as the range of values they represent. It's a little more manual work, but I think it provides more complete control.

 

Here's a modification of your code, using my technique:

 

%let name=map;
filename odsout '.';

goptions device=png;
goptions border;

ODS LISTING CLOSE;
ODS HTML path=odsout body="&name..htm" style=htmlblue;

goptions gunit=pct ftitle="albany amt/bold" ftext="albany amt" htitle=4.0 htext=2.5;
goptions ctext=gray33;

proc format;
value buckfmt
1 = '130.2 and more'
2 = '120.2 to 130.2'
3 = '105.8 to 120.2'
4 = '97.0  to 105.8'
5 = '80.9  to 97.0'
6 = '70.4  to 80.9'
7 = '60.6  to 70.4'
8 = '50.5  to 60.6'
9 = '48.0  to 50.5'
10 = '40.2  to 48.0'
11 = '34.0  to 40.2'
12 = '27.5  to 34.0'
13 = '21.6  to 27.5'
14 = '16.4  to 21.6'
15 = '12.8  to 16.4'
16 = ' 9.7  to 12.8'
17 = ' 5.8  to  9.7'
18 = ' 3.8  to  5.8'
19 = ' 1.8  to  3.8'
20 = ' 0.5  to  1.8'
21 = ' 0.1  to  0.5'
22 = ' 0.0  to  0.1'
;
run;

libname here '.';
data modhessen; set here.hessen; 
     if europianstandard>=130.2 then bucket=1;
else if europianstandard>=120.2 then bucket=2;
else if europianstandard>=105.8 then bucket=3;
else if europianstandard>=97.0 then bucket=4;
else if europianstandard>=80.9 then bucket=5;
else if europianstandard>=70.4 then bucket=6;
else if europianstandard>=60.6 then bucket=7;
else if europianstandard>=50.5 then bucket=8;
else if europianstandard>=48.0 then bucket=9;
else if europianstandard>=40.2 then bucket=10;
else if europianstandard>=34.0 then bucket=11;
else if europianstandard>=27.5 then bucket=12;
else if europianstandard>=21.6 then bucket=13;
else if europianstandard>=16.4 then bucket=14;
else if europianstandard>=12.8 then bucket=15;
else if europianstandard>=9.7 then bucket=16;
else if europianstandard>=5.8 then bucket=17;
else if europianstandard>=3.8 then bucket=18;
else if europianstandard>=1.8 then bucket=19;
else if europianstandard>=0.5 then bucket=20;
else if europianstandard>=0.1 then bucket=21;
else if europianstandard>=0.0 then bucket=22;
else bucket=.;
run;


pattern1 value=solid color='CXBF1C1C'; ****red0 redbrown****;
pattern2 value=solid color='CXD02226'; ****red1****;
pattern3 value=solid color='CXDE363C'; ****red2****;
pattern4 value=solid color='CXE45D66'; ****red3****;
pattern5 value=solid color='CXE76F77'; ****red4****;
pattern6 value=solid color='CXEA8188'; ****red5****;
pattern7 value=solid color='CXED9399'; ****red6****;
pattern8 value=solid color='CXF0A5AA'; ****red7****;
pattern9 value=solid color='CXF3B7BB'; ****lightred8****;
pattern10 value=solid color='CXF6C9CC'; ****lightred9****;
pattern11 value=solid color='CXF9DBDD'; ****lightred10****;
pattern12 value=solid color='CXFCEDEE'; ****palered11****;
pattern13 value=solid color='CXE4F1EA'; ****palegreen10****;
pattern14 value=solid color='CXCBE4DE'; ****lightgreen9****;
pattern15 value=solid color='CXB2D7D2'; ****lightgreen8****;
pattern16 value=solid color='CX99C9C7'; ****green7****;
pattern17 value=solid color='CX80BDBA'; ****green6****;
pattern18 value=solid color='CX67B0AE'; ****green5****;
pattern19 value=solid color='CX4EA3A2'; ****green4****;
pattern20 value=solid color='CX359696'; ****green3****;
pattern21 value=solid color='CX1C898A'; ****green2****;
pattern22 value=solid color='CX037C7E'; ****green1****;

title1 ls=1.5 "GMap, with custom legend binning";

legend1 label =(f="albany amt/bold" position=top j=c h=12pt "Inzidenzrate")
 value=(f="albany amt" h=10pt c=black tick=3)
 across=1
 position=(right middle) 
 offset=(-2,3)
 space=1
 mode=reserve
 shape=bar(.15in,.15in)
 ;

proc gmap map=here.test data=modhessen all;
format bucket buckfmt.;
ID id;
choro bucket/ discrete midpoints = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 /* Annotate=maplabelhessen */
 legend=legend1
 coutline=black
 cdefault=cxfcfad2 /* areas with no data are light yellow */
 name="mychart";
run; 

quit;
ODS HTML CLOSE;
ODS LISTING;

 

binned_map.png 

Anita_n
Pyrite | Level 9

Hello Robert,

Thanks a lot for the help and detailed explanation. I am very grateful for that. Since am out of office. I will try that on Monday morning and give you a feedback.

Anita_n
Pyrite | Level 9

Hi Robert,

once again thanks for the help. I tried the code this morning. It worked fine with the colors. My only problem is that the legend can not be displayed. The warning says : There is no enough room for legend to be displayed. The legend has been suppressed. I tried to reduce the font sizes but without any success. Is there any thing I can do here?

Anita_n
Pyrite | Level 9

Hi Rober,

I could solve the problem myself by adding origin=(78,18) to my legend statement. It works perfectly. Am very grateful

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
  • 13 replies
  • 6241 views
  • 2 likes
  • 3 in conversation