{"id":931,"date":"2017-06-17T09:32:59","date_gmt":"2017-06-17T14:32:59","guid":{"rendered":"http:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/?p=931"},"modified":"2017-08-23T21:50:57","modified_gmt":"2017-08-24T02:50:57","slug":"stata-code-for-designing-custom-graph-colors","status":"publish","type":"post","link":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/2017\/06\/17\/stata-code-for-designing-custom-graph-colors\/","title":{"rendered":"Stata code for designing custom graph colors"},"content":{"rendered":"<p>A few readers may be interested in how I used Stata to create the color scheme for the offenses in the graphs I&#8217;ve posted recently. This is a &#8220;stats nerd&#8221; post that assumes the reader uses Stata, a statistical package. Everybody else may wish to give it a pass. Some preliminary tricks, then the code. <em>UPDATED 8\/6\/2017 to include RGB values in the color palette and to give the formulas for calculating them from intensities.<\/em><\/p>\n<p>Trick 1 that I have learned is to generate self-labeling lines by creating a variable that has the label only in the last value of the x-axis variable, year in my case. E.g. gen xvalue15=Label if xvalue==15. Or self-labeling scatterplots by having a label for all values.<\/p>\n<p>Trick 2 is to use Stata macros to generate the lines of a plot. The general scheme is:<\/p>\n<pre>local plotlist \"\"\r\nforeach val in `list of values' {\r\n    local plotlist \"`plotlist' (code_for_one_line )\"\r\n    }\r\ntwoway `plotlist', [code for graph as a whole]<\/pre>\n<p>In this code, each line gets added to the macro plotlist. Pro tip: remember to reset the plot macro to &#8221; &#8221; (empty) (or use a new macro name each time) or you will get unpleasant\u00a0results with repeated graphs.<\/p>\n<h2>Color Swatch Generator<\/h2>\n<p>Although Stata can generate colors using any set of RGB values, for a variety of reasons* I found it easiest to work with the built-in named colors. Named colors can be modified with the syntax &#8220;color*##. Numbers less than 1 lighten the color and numbers greater than 1 darken the color. The ado file <em>full_palette<\/em> \u00a0generates a swatch of the 66 named colors in Stata, with their RGB values (you can access this by typing help full_palette and installing the ado), and the built-in ado <em>palette color<\/em>\u00a0 will show color samples and the RGB values for two colors (type help palette color to see the syntax of the command). But I wanted to see ranges of colors using the intensity values across several different named colors. I also tested creating my own color (uwred) and saving it in a .style file. **<\/p>\n<p><a href=\"http:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-content\/uploads\/2017\/06\/test_today_color_swatch_RGB2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1153\" src=\"http:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-content\/uploads\/2017\/06\/test_today_color_swatch_RGB2.png\" alt=\"\" width=\"600\" height=\"450\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<pre>* Stata program to generate color swatches\r\n* Pamela Oliver 5\/29\/2017, updated 6\/18\/2017 and 8\/6\/2017 \r\n* now locates .style file for named color and identifies RGB code\r\n* calculates and prints RGB values as well as color names\r\n* uses syntax \"scatter y1 y2 x\" to  print two-line labels\r\n* edits code so colors now print in the order of colorlist \r\n     * instead of alphabetical\r\n* uwred is a color I created and saved in my personal ado file\r\nversion 14.2 \r\nlocal colorlist \"ebblue eltblue orange orange_red red uwred purple\"\r\nlocal intenlist \".8 1 1.3 1.5 1.8 2\"\r\nlocal intnumlist=subinstr(\"`intenlist'\",\" \",\", \",.) \/\/ a numlist with commas\r\ndisp \"`intnumlist'\"\r\n** This code to get a decent intensity range in the graph regardless of entries\r\nlocal maxint=max(`intnumlist')\r\nlocal minint=min(`intnumlist')\r\ndisp `maxint' `minint'\r\nlocal range=`maxint'-`minint'\r\nlocal edgegap=round(`range'*.2,.01)\r\nlocal labgap=`edgegap'\/8\r\nlocal lowint=`minint'-`edgegap'\r\nlocal yrange \"`lowint' (`edgegap') `maxint'\"\r\n** This code generates the data for the plots\r\nlocal ncolor=wordcount(\"`colorlist'\")\r\nlocal ninten=wordcount(\"`intenlist'\")\r\nlocal ncases=`ncolor'*`ninten'\r\ndisp \"ncolor `ncolor' ninten `ninten' ncases `ncases'\"\r\nset more off\r\nclear\r\nset obs `ncases'\r\ngen case=_n\r\ngen ncases=_N\r\ngen color=\"\"\r\ngen intenS=\"\"\r\ngen colorname=\"\"\r\n** fill in the strings with colors and intensities\r\nlocal ii=1\r\nforval color= 1\/`ncolor' {\r\nforval inten= 1\/`ninten' {\r\n     replace basecolor=word(\"`colorlist'\",`color') if case==`ii'\r\n     replace colornum=<code>color' if case==<\/code>ii' \r\n replace intenS=word(\"`intenlist'\",`inten') if case==`ii' \r\n replace colorname=color+\"*\"+intenS \r\n replace col_int_num=<code>ii' if case==<\/code>ii' local ii=`ii'+1 } } \r\n*** the num variables are sequential \r\n** uses the string variables as value labels for the numerical variables \r\nlabmask colornum, values(basecolor) \r\nlabmask col_int_num, values(colorname) \r\n** create numeric version of intensity \r\nencode intenS, gen(intennum) \r\ngen inten=real(intenS) \/\/ this is the actual numeric value of intensity \r\ngen RGB_base=\"\" \r\ngen RGB_base=\"\" \r\n** this code snippet taken from full_palette.ado with modifications \r\n** it finds and reads the color style file for each named color \r\n** and extracts the RGB values for that color and puts it in a variable RGB_base \r\n** I did not copy all the error code returns \r\nforeach base in `colorlist' { \r\n tempname hdl`base' \u00a0\/\/ assigns a tempfile name \r\n findfile color-`base'.style \/\/ this command searches all ado directories \r\n local colorfile=r(fn) \u00a0\/\/ findfile returns the file location \r\n file open `hdl`base'' using \"`colorfile'\", read text \r\n file read `hdl`base'' line \r\n while r(eof)==0 { \r\n tokenize `\"`line'\"' \r\n if \"`1'\"==\"set\" &amp; \"`2'\"==\"rgb\" { \r\n *qui replace lab=`\"\"`3'`basemod'\"\"' in `i' \u00a0\/\/ the code from full_palette.ado \r\n qui replace RGB_base=\"`3'\" if basecolor==\"`base'\" \r\n file close `hdl`base'' continue, break \r\n } \r\n file read `hdl`base'' line \r\n } \r\n } \r\n*** parse the original RGB codes \r\ngen Ro=real(word(RGB_base,1)) \r\ngen Go=real(word(RGB_base,2)) \r\ngen Bo=real(word(RGB_base,3)) \r\nforeach CC in R G B { \r\n gen `CC'x=`CC'o if inten==1 \r\n replace `CC'x=round(`CC'o\/inten,1) if inten&gt;1 \r\n replace `CC'x=`CC'o + round((1-inten)*(255-`CC'o)) if inten&lt;1 \r\n } \r\ngen RGB_derived=string(Rx)+\" \"+string(Gx)+\" \"+string(Bx) \r\n** gen a value of inten just a little lower to carry the second label \r\ngen int2=inten-`labgap' \u00a0\/\/ slightly lower value on vertical axis \r\nset scheme s1color \r\nlocal plot \"\" \r\nlocal plot2 \"\" \r\nsumm col_int_num \r\nlocal nplots=r(max) \r\nforval point=1\/`nplots' { \r\n **get the values for each point in the plot \r\n qui summ col_int_num if col_int_num==`point' \r\n local labelnum=r(mean) \r\n local colorname: label col_int_num `labelnum' \r\n qui summ colornum if col_int_num==`point' \r\n local colnum=r(mean) \r\n local color: label colornum `colnum' \r\n qui summ intennum if col_int_num==`point' \r\n local intnum=r(mean) \r\n local inten: label intennum `intnum' \r\n** collect the plots for each point in locals named plot and plot2 \r\n local plot \"`plot' (scatter inten colornum if col_int_num==`point', mcolor(`colorname') msize(huge) mlab(colorname) mlabc(`colorname') mlabsize(tiny) mlabpos(6))\" \r\n local plot2 \"`plot2' (scatter inten int2 colornum if col_int_num==`point', ms(S none) mcolor(`colorname' `colorname') msize(*3 *3) mlab( RGB_derived colorname) mlabc(`colorname' `colorname') mlabsize(vsmall vsmall) mlabpos(6 6))\" \r\n } \/\/ end of the loop defining the plots \r\n*disp \"`plot'\" \/\/ in case you need to check whether it worked \r\nlocal xmax=`ncolor'+1 \/\/ put an extra column of padding in the table \r\nlocal testname \"test_today\" \/\/ give a unique name to the output file \r\n** plot with just the colornames and round swatches \r\ntwoway `plot' , legend(off) ylab(.25 (.25) 2) xlab(0 (1) `xmax', val) xtitle(color) ytitle(intensity) \r\ngraph export `testname'_sample_color_swatch.png, replace \r\n**plot with two labels and square swatches \r\ntwoway `plot2' , legend(off) ylab(`yrange') xlab(0 (1) `xmax', val) xtitle(color) ytitle(intensity) \r\ngraph export `testname'_color_swatch_RGB2.png, replace width(800) height(600) exit<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2>Color Line Generator<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-876\" src=\"https:\/\/sociologicalconfessions.files.wordpress.com\/2017\/06\/color_lines_sample3.png\" alt=\"color_lines_sample\" width=\"478\" height=\"347\" \/><\/p>\n<p>My application has too many values to use just color (or so I judged) so I also used line type. Thus the code to generate sample lines.<\/p>\n<pre>stata 14.2\r\n* insert colors, intensities, patterns in the lists as desired\r\n\r\nlocal colorlist \"orange_red ebblue\"\r\nlocal intenlist \".5 \u00a01 1.75 \"\r\nlocal lplist \"solid dash shortdash\"\r\nlocal ncolor=wordcount(\"`colorlist'\")\r\nlocal ninten=wordcount(\"`intenlist'\")\r\nlocal nlp = wordcount(\"`lplist'\")\r\nlocal ncases=`ncolor'*`ninten'*`nlp'\r\nclear\r\nset obs `ncases'\r\ngen case=_n\r\ngen Ncases=_N\r\ngen hue=\"\"\r\ngen inten=\"\"\r\ngen linepat=\"\"\r\nset more off\r\nset scheme s1color \u00a0\/\/ white background\r\n*** fill in the color values, text variables\r\nlocal xx=1\r\nforval col=1\/`ncolor' {\r\n     forval int=1\/`ninten' {\r\n       forval lpat=1\/`nlp' { \r\n          replace hue=word(\"`colorlist'\", `col') if case==`xx' \r\n          replace inten=word(\"`intenlist'\", `int') if case==`xx'\r\n          replace linepat=word(\"`lplist'\", `lpat') if case==`xx' \r\n       local xx=`xx'+1 \r\n       } \r\n       } \r\n       } \r\n** CREATE 16 values for the X axis ****** \r\nDuplicate observations\r\nexpand 2, gen(copy1)\r\nexpand 2, gen(copy2)\r\nexpand 2, gen(copy3)\r\nexpand 2, gen(copy4)\r\ngen xvalue=copy1 + 2*copy2 + 4*copy3 + 8*copy4\r\n\r\n* generate text from other text\r\ngen color=hue+\"*\"+inten\r\ngen definition=hue+\"*\"+inten+\" \"+linepat\r\ngen def15=definition if xvalue==15\r\n* create numeric variables with the strings as values\r\nencode color, gen(colornum)\r\nencode linepat, gen(lpnum)\r\nqui sum colornum\r\nlocal ncol=r(max)\r\nforval colnum=1\/`ncol' { \r\n    local col`colnum' = `colnum' \r\n    }\r\nforval lpnum=1\/`nlp' { \r\n     local lp`lpnum'=`lpnum' \r\n    }\r\n\r\nlocal plotlist \"\"\r\ndisp \"ncases `ncases'\"\r\nforval case=1\/`ncases' { \r\n\r\n    qui summ colornum if case==`case' \r\n    local cn=r(mean) \r\n    local color: label colornum `cn' \r\n\r\n    qui summ lpnum if case==`case' \r\n    local ln=r(mean) \r\n    local lpat: label lpnum `ln' \r\n\r\n    local plotlist \"`plotlist' (connected case xvalue if case==`case', msym(i) mlab(def15) lc(`color') mlabc(`color'') lp(`lpat'))\" \r\n    }\r\ntwoway `plotlist', legend(off) xlab(0 (2) 22)\r\ngraph export color_lines_sample.png, replace<\/pre>\n<h2>Offense line palette<\/h2>\n<p>This is the problem that started me on this path. I have 17 offenses for which I want to graph imprisonment over \u00a0time. Letting Stata choose the colors generates an unreadable hash. And brewscheme won&#8217;t help because I want to assign particular markers\/colors to particular offenses, not create a general order of colors. After working on this problem a while, I realized the graph could be more meaningful if similar offenses had related colors. Generating a variable-specific palette is easy using the skills developed above.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-881\" src=\"https:\/\/sociologicalconfessions.files.wordpress.com\/2017\/06\/offense_lines_2017-6-1set1.png\" alt=\"offense_lines_2017-6-1set1\" width=\"478\" height=\"347\" \/><\/p>\n<p>Step 1: Create a spreadsheet with the variable names and labels plus columns for variable groups, color name (hue), intensity, line type, and the order in which I wanted the graphs to appear in my sample. This last is to put the colors that might be difficult to distinguish next to each other in the sample. In my spreadsheet, I put different possible color schemes in different tabs. Here is one sample.<\/p>\n<table border=\"0\" width=\"448\" cellspacing=\"0\" cellpadding=\"0\">\n<colgroup>\n<col span=\"7\" width=\"64\" \/> <\/colgroup>\n<tbody>\n<tr>\n<td width=\"64\" height=\"20\">OffLab<\/td>\n<td width=\"64\">offdetail<\/td>\n<td width=\"64\">group<\/td>\n<td width=\"64\">hue<\/td>\n<td width=\"64\">intensity<\/td>\n<td width=\"64\">line<\/td>\n<td width=\"64\">order<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Drugs<\/td>\n<td align=\"right\">12<\/td>\n<td>drugdwi<\/td>\n<td>navy<\/td>\n<td align=\"right\">2<\/td>\n<td>solid<\/td>\n<td align=\"right\">10<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">DWI<\/td>\n<td align=\"right\">20<\/td>\n<td>drugdwi<\/td>\n<td>navy<\/td>\n<td align=\"right\">2<\/td>\n<td>dash<\/td>\n<td align=\"right\">11<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Escape_etc<\/td>\n<td align=\"right\">21<\/td>\n<td>misc<\/td>\n<td>ebblue<\/td>\n<td align=\"right\">0.5<\/td>\n<td>solid<\/td>\n<td align=\"right\">16<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Family<\/td>\n<td align=\"right\">22<\/td>\n<td>misc<\/td>\n<td>ebblue<\/td>\n<td align=\"right\">0.5<\/td>\n<td>shortdash<\/td>\n<td align=\"right\">17<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Larceny<\/td>\n<td align=\"right\">8<\/td>\n<td>property<\/td>\n<td>ebblue<\/td>\n<td align=\"right\">1.5<\/td>\n<td>dash<\/td>\n<td align=\"right\">12<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">MVTheft<\/td>\n<td align=\"right\">9<\/td>\n<td>property<\/td>\n<td>ebblue<\/td>\n<td align=\"right\">1.5<\/td>\n<td>solid<\/td>\n<td align=\"right\">13<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Fraud<\/td>\n<td align=\"right\">10<\/td>\n<td>property<\/td>\n<td>ebblue<\/td>\n<td align=\"right\">1<\/td>\n<td>shortdash<\/td>\n<td align=\"right\">14<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">OthProp<\/td>\n<td align=\"right\">11<\/td>\n<td>property<\/td>\n<td>ebblue<\/td>\n<td align=\"right\">1<\/td>\n<td>solid<\/td>\n<td align=\"right\">15<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Robbery<\/td>\n<td align=\"right\">4<\/td>\n<td>robbur<\/td>\n<td>purple<\/td>\n<td align=\"right\">1<\/td>\n<td>solid<\/td>\n<td align=\"right\">9<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Burglary<\/td>\n<td align=\"right\">7<\/td>\n<td>robbur<\/td>\n<td>purple<\/td>\n<td align=\"right\">1<\/td>\n<td>dash<\/td>\n<td align=\"right\">8<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Murder<\/td>\n<td align=\"right\">1<\/td>\n<td>violent<\/td>\n<td>orange_red<\/td>\n<td align=\"right\">1.75<\/td>\n<td>solid<\/td>\n<td align=\"right\">7<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">NegMansl<\/td>\n<td align=\"right\">2<\/td>\n<td>violent<\/td>\n<td>orange_red<\/td>\n<td align=\"right\">1.75<\/td>\n<td>shortdash<\/td>\n<td align=\"right\">6<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Rape<\/td>\n<td align=\"right\">3<\/td>\n<td>violent<\/td>\n<td>orange_red<\/td>\n<td align=\"right\">1.75<\/td>\n<td>dash<\/td>\n<td align=\"right\">5<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Assault<\/td>\n<td align=\"right\">5<\/td>\n<td>violent<\/td>\n<td>orange_red<\/td>\n<td align=\"right\">1<\/td>\n<td>dash<\/td>\n<td align=\"right\">4<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">OthViolent<\/td>\n<td align=\"right\">6<\/td>\n<td>violent<\/td>\n<td>orange_red<\/td>\n<td align=\"right\">1<\/td>\n<td>solid<\/td>\n<td align=\"right\">3<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">Weapon<\/td>\n<td align=\"right\">23<\/td>\n<td>violent<\/td>\n<td>orange_red<\/td>\n<td align=\"right\">0.5<\/td>\n<td>solid<\/td>\n<td align=\"right\">2<\/td>\n<\/tr>\n<tr>\n<td height=\"20\">PubOrd<\/td>\n<td align=\"right\">13<\/td>\n<td>violent<\/td>\n<td>orange_red<\/td>\n<td align=\"right\">0.5<\/td>\n<td>dash<\/td>\n<td align=\"right\">1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The do file reads the spreadsheet (with a local parameter that selects the tab) and generates a sample plot.<\/p>\n<pre>stata 14.2\r\nlocal group set1\r\nimport excel \"offense_colors_lines.xlsx\", sheet(\"`group'\") firstrow allstring clear\r\ngen color=hue+\"*\"+intensity\r\nencode color, gen(colornum)\r\nencode line, gen(linenum)\r\ndestring offdetail, replace\r\ndestring order, replace\r\n\r\n** I save this as a Stata file so I can merge it into the data file for production runs\r\n\r\nsave \"offense_lines_2017-6-1`group'.dta\", replace\r\n\r\nlevelsof offdetail, local(offlist) clean\r\nforeach off in `offlist' {\r\n    qui summ colornum if offdetail==`off'\r\n    local cnum=r(mean)\r\n    local col`off': label colornum `cnum'\r\n    qui summ linenum if offdetail==`off'\r\n    local lnum=r(mean)\r\n    local line`off': label linenum `lnum'\r\n    }\r\n** creates values for an X axis\r\nexpand 2, gen(copy1)\r\nexpand 2, gen(copy2)\r\nexpand 2, gen(copy3)\r\nexpand 2, gen(copy4)\r\ngen xvalue=copy1 + 2*copy2 + 4* copy3 + 8*copy4\r\ngen OffLab15=OffLab if xvalue==15\r\n\r\n\r\nlocal plotlist \"\"\r\nforval xx=1\/17 {\r\n   qui summ offdetail if order==`xx'\r\n   local off=r(mean)\r\n   local plotlist \"`plotlist' (connected order xvalue if offdetail==`off', ml(OffLab15) ms(i) lc(`col`off'') mlabc(`col`off'') lp(`line`off''))\"\r\n    }\r\ndisp \"`plotlist'\" \r\ntwoway `plotlist', legend(off) xlab(0 (3) 20)\r\ngraph export \"offense_lines_2017-6-1`group'.png\", replace<\/pre>\n<p>Using this scheme in my production graphs involves this code:<\/p>\n<pre>use [data file]\r\n\r\nmerge m:1 offdetail using offense_lines_2017-6-1set1.dta\r\n\r\nlevelsof offdetail, local(offlist) clean\r\nforeach off in `offlist' {\r\n\u00a0 \u00a0 \u00a0qui summ colornum if offdetail==`off'\r\n\u00a0 \u00a0 \u00a0local cnum=r(mean)\r\n\u00a0 \u00a0 \u00a0local col`off': label colornum `cnum'\r\n\u00a0 \u00a0 \u00a0qui summ linenum if offdetail==`off'\r\n\u00a0 \u00a0 \u00a0local lnum=r(mean)\r\n\u00a0 \u00a0 \u00a0local line`off': label linenum `lnum'\r\n\u00a0 \u00a0 \u00a0}\r\n\r\n<\/pre>\n<p>These local macros can then be used in the production graphs with the same code logic as was used to generate the samples.<\/p>\n<p>Notes<br \/>\nOriginally blogged at:<br \/>\n<a href=\"https:\/\/sociologicalconfessions.wordpress.com\/2017\/06\/02\/stata-roll-your-own-color-palettes\/\">Stata: roll your own color&nbsp;palettes<\/a><\/p>\n<p>* I originally tried to use the RGB values from specific palettes I found on line, but passing RGB values in a macro the way I do with my offense colors did not work. I think the problem is a subtle Stata bug\/behavior about parsing quotes within quotes within quotes in macros referring to macros and\/or the parsing of a list of numbers separated only by spaces. When I used the most straightforward syntax, Stata eliminated the spaces between the numbers (a very odd behavior!), and when I added the Stata special double quotes `&#8221; and &#8220;&#8216; , that problem was solved but the resulting code generated an error. However, if you use ado files you can find on line to create and save new colors with names, those new colors should work fine with this routine. You create a new color by creating a file named color-COLORNAME.style in your personal ado path (I put it in a style folder that had previously been created but anywhere works); the content of this file must be<\/p>\n<pre>set rgb \"255 255 255\"<\/pre>\n<p>where you replace the 255&#8217;s with the RGB codes for the color you want to name. If you examine the color-NAME.style files in your system files (which you can find by typing &#8220;findfile color-red.style&#8221; in a Stata session \u00a0and reading the resulting path) you will see that you can also include comments labels and other commands that don&#8217;t get in the way of this core command, but this is the one you need.<\/p>\n<p>** I spent some time studying the code for the ado files palette.ado and full_palette.ado trying to figure out how the RGB values were generated \u00a0from the color and intensity values so I could put them in my palette as well, but finally gave up. Both ado files read the RGB code for the base color from the color .style file, but I could not find the code in palette.ado that computes the derived RGB when there is an intensity factor. It must not look the way I&#8217;m expecting it to look.<\/p>\n<p>By experimentation with putting values into <em>palette color<\/em>, I learned that an intensity greater than 1 consistently divides the RGB values by that number (e.g. ebblue is RGB 0 139 188 and ebblue*2 is 0 70 94). Lower RGB values are darker with black being 0 0 0). An intensity less than 1 increases the values of all three RGB values and pulls it toward white, which has RGB 255 255 255. So for example, red is 255 0 0 , red*5 is 255 128 128, red*.2 is 255 204 204, ebblue is 0 139 188, ebblue*.5 is 128 197 222, teal is 110 142 132, teal*.5 is 183 199 194, teal*.2 is 226 232 230. If the color is pure and fully saturated, the intensity factor adds (1-int)*255 to the other colors. <del>I am sure I could empirically work out the formula for intensities less than 1 for the more complex cases if I spend more time on it, but it is not immediately obvious to me. \u00a0If you know the formula and put it in the comments, I would be grateful. I&#8217;m not sure it matters except to my curiosity.<\/del> EDIT: \u00a0The correct general formula for intensity&lt;1 is: \u00a0orig_RGBnum + (1-intensity)(255-orig_RGBnum) for each of the three original RGB numbers. I still have not found the actual code that implements these formulas in the palette.ado file. But I was able to implement the formula in my own program.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few readers may be interested in how I used Stata to create the color scheme for the offenses in the graphs I&#8217;ve posted recently. This is a &#8220;stats nerd&#8221; post that assumes the reader uses Stata, a statistical package. Everybody else may wish to give it a pass. Some<\/p>\n","protected":false},"author":3,"featured_media":936,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"sfsi_plus_gutenberg_text_before_share":"","sfsi_plus_gutenberg_show_text_before_share":"","sfsi_plus_gutenberg_icon_type":"","sfsi_plus_gutenberg_icon_alignemt":"","sfsi_plus_gutenburg_max_per_row":"","footnotes":""},"categories":[92],"tags":[94,93],"class_list":["post-931","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-research-methods","tag-color-palette","tag-stata"],"_links":{"self":[{"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/posts\/931","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/comments?post=931"}],"version-history":[{"count":18,"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/posts\/931\/revisions"}],"predecessor-version":[{"id":1224,"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/posts\/931\/revisions\/1224"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/media\/936"}],"wp:attachment":[{"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/media?parent=931"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/categories?post=931"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ssc.wisc.edu\/soc\/racepoliticsjustice\/wp-json\/wp\/v2\/tags?post=931"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}