Three ways to specify colors in SAS statistical graphics procedures

14

What's in a name? As Shakespeare's Juliet said, "That which we call a rose / By any other name would smell as sweet." A similar statement holds true for the names of colors in SAS: "Rose" by any other name would look as red!

SAS enables you to specify a color in several ways. This article shows how to use color names and RGB colors to specify colors in the SAS statistical graphics procedures, such as PROC SGPLOT. It gathers together color resources in a single location so you might want to bookmark this article for future reference.

Pre-defined SAS color names

SAS knows dozens of names of colors. There are "red" and "brown," of course, but also designer colors such as "aquamarine," "chartreuse," "khaki," and "teal." The following call to the SGPLOT procedure creates a scatter plot for which the marker color is set to "rose":

proc sgplot data=sashelp.class;
scatter x=height y=weight / markerattrs=(size=14 symbol=CircleFilled
                            color="Rose" );
run;

If you want to see some of the color names that SAS recognizes, run the following statements, which will print a list of colors to the SAS log:

proc registry list startat="COLORNAMES";
run;

The SAS color-naming convention

Some of the more "imaginative" names that SAS supports (such as "Peru," "Thistle," and "Gainsboro") might be unfamiliar. Fortunately, SAS has a color-naming scheme that enables you to specify a descriptive name for many colors, such as "Red," "Light Gray," or "Dark Green." To use the color-naming scheme, choose one value from each of the following categories:

  1. Lightness: Black (*), Very Dark, Dark, Medium (default), Light, Very Light, or White (*)
  2. Saturation: Gray (*), Grayish, Moderate, Strong, Vivid (default)
  3. Hue: Blue, Purple, Red, Orange or Brown, Yellow, Green

So, for example, valid names for colors include the following:

  • "Very Dark Grayish Blue"
  • "Dark Moderate Purple"
  • "Strong Red" (default value for Lightness)
  • "Light Brown" (default value for Saturation)

A few exceptions to the "choose one from each category" rule are indicated by asterisks. If you use Black or White, you cannot specify Saturation or Hue. Similarly, if you specify Gray, you cannot specify a Hue.

You can also specify a mixture of hues by specifying two adjacent hues in the list. Optionally, you can use the -ish suffix to diminish a hue, as in the following examples:

  • "Medium Strong Red Orange"
  • "Light Yellowish Green"
  • "Light Strong Brownish Orange"

For example, the following scatter plot sets the color of markers by using the SAS color-naming scheme:

proc sgplot data=sashelp.class;
scatter x=height y=weight / markerattrs=(size=14 symbol=CircleFilled
                            color="Light Strong Brownish Orange" );
run;

Representing colors by their RGB values

SAS also enables you to specify a color by using the red-green-blue (RGB) color model. The RGB color model is an additive model in which a color is specified in terms of red, green, and blue components. Each component ranges from 0 (which indicates the absence of a component) to 255 (which indicates the full presence of a component). A color is therefore a triplet of values that indicates the relative proportions of red, green, and blue. For example, the RGB triplet (255, 96, 96) represents a color that has a maximum amount of red and a small amount of green and blue.

The drawback of the RGB model is readability. If I write a program and specify a color as the RGB triplet (255, 96, 96), it is difficult to know what color is going to be produced. It turns out that this color is exactly "Rose," but you might have had a hard time predicting that in advance.

Most of the time, RGB triplets are compactly represented by a hexadecimal integer. The prefix CX tells SAS to interpret the integer as a color. You can find the hexadecimal representation of a color such as "Rose" by using the handy reference chart that lists SAS colors and their hexadecimal values.

The chart says that the RGB color for "Rose" is CXFF6060. This value is read two digits at a time:

  • CX means that the value is a color
  • FF is the hexadecimal (base-16) value for 16*15 + 15 = 255, which is the red component
  • 60 is the hexadecimal value for 16*6 + 0 = 96, which is the green component
  • 60 is the blue component

Consequently, the following statements reproduce the first image in this article:

/* "Rose" = RGB(255,96,96) = cxFF6060 */
proc sgplot data=sashelp.class;
scatter x=height y=weight / markerattrs=(size=14 symbol=CircleFilled
                            color=cxFF6060 );
run;

If you are a hard-core programmer, you're probably already thinking about how to write a SAS macro that converts a triplet of RGB values into a hexadecimal color. If you want to try to construct the macro yourself, stop reading now!

You can use the following SAS macro to create a hexadecimal value from a triplet of RGB colors. It's easy to use the PUT function to construct the hexadecimal value inside of a DATA step, but it is slightly more challenging to use the macro language to construct an "in-line" string that can be used outside of the DATA step. You can use the following macro to specify the COLOR= option for a statement in the SGPLOT procedure:

/* convert integer 0--255 to 2 digit hex 00-FF */
%macro hex2(n);
  %local digits n1 n2;
  %let digits = 0123456789ABCDEF;
  %let n1 = %substr(&digits, &n / 16 + 1, 1);
  %let n2 = %substr(&digits, &n - &n / 16 * 16 + 1, 1);
  &n1&n2
%mend hex2;
 
/* convert RGB triplet (r,g,b) to SAS color in hexadecimal. 
   The r, g, and b parameters are integers in the range 0--255 */
%macro RGB(r,g,b);
  %cmpres(CX%hex2(&r)%hex2(&g)%hex2(&b))
%mend RGB;
 
data A;
put "Rose = %RGB(255,96,96)";
run;
 
proc sgplot data=sashelp.class;
scatter x=height y=weight / markerattrs=(size=14 symbol=CircleFilled
                            color=%RGB(255,96,96) );
run;

Because (255, 96, 96) specifies the same color as "rose," the image is identical to the first graph in this article.

So what's in a name? A lot of information! But in SAS, "rose" by the name of CXFF6060 looks just as sweet!

Share

About Author

Rick Wicklin

Distinguished Researcher in Computational Statistics

Rick Wicklin, PhD, is a distinguished researcher in computational statistics at SAS and is a principal developer of SAS/IML software. His areas of expertise include computational statistics, simulation, statistical graphics, and modern methods in statistical data analysis. Rick is author of the books Statistical Programming with SAS/IML Software and Simulating Data with SAS.

14 Comments

  1. Hi Rick

    Finally someone who made the SAS color naming convention clear to me.

    I thought it would be simple to make a one-line version of %rgb above, but it actually gave me some trouble. But I succeeded. The trick for me was to use round... Perhaps there is a nicer way?

    %macro RGB(r,g,b);
    CX%sysfunc(round(&r.,1),hex2.)%sysfunc(round(&g.,1),hex2.)%sysfunc(round(&b.,1),hex2.)
    %mend RGB;

    /Rune

    • %macro RGB2CX(r,g,b);
      CX%sysfunc(putn(&r.,hex2.))%sysfunc(
                 putn(&g.,hex2.))%sysfunc(putn(&b.,hex2.))
      %mend;
      

      does the trick.

  2. Pingback: Debating colors, admin needs and IT’s role with analytics - SAS Voices

  3. Howard Houston on

    You do not need to write your own macros. There autocall maros that will generate the CX color names from percentage values and various color spaces.
    The following will give display what is available;
    %colormac;
    %helpclr(all);

    Also, in the 9.3 release there are RGBA and CMYK color names. The RGBA color specification allows you to cintrol the opacity of a color on those output formats that support it, such as PNG.

    RGBAff000080 or Aff000080 a red that is 50% translucent.

    • Rick Wicklin

      The macros that Howard mentions are described in the SAS/GRAPH documentation. I don't use them because they take RGB inputs in the range 0--100. They enable you to approximately specify a color, but I find them unwieldy when I want to exactly specify an 8-bit RGB triplet where each component is in the range 0-255.

      The SG procedures do not support the alpha-transparency channel that is supported by SAS/GRAPH procedures. Instead, the SG procedures support a TRANSPARENCY= option that ranges from 0 (opaque) to 1 (completely transparent). If you specify an RGBA color to an SG procedure, the alpha channel is ignored.

  4. Pingback: Convert hexadecimal colors to RGB - The DO Loop

  5. Pingback: Color markers in a scatter plot by a third variable in SAS - The DO Loop

  6. Pingback: What colors does PROC SGPLOT use for markers? - The DO Loop

  7. More of a processing question, but is there a way to output these to a data set instead of a log? Thank you!
    I have a list of 6-digit codes that I'd like to convert to codes with a CX prefix, so that I can move them to an attribute map. Copying them from the log is not practical.
    Thank you!

    • Rick Wicklin

      You can ask SAS programming questions at the SAS Support Communities. For this question, get rid of the PUT statement and make an assignment:

      data A;
      Rose = "%RGB(255,96,96)";
      run;
      

      Or if you need to translate many RBG codes, use this:

      data HexColors;
      input R G B;
      Hex = cat("CX", 
                put(R,hex2.),
                put(G,hex2.),
                put(B,hex2.));
      datalines;
      255  96   96
      105   0   56
      200   0  220
      ;
      

Leave A Reply

Back to Top