When the color you want is the data

It sounds silly, but three hours have been taken up trying to solve this one problem.

I have a data set that holds the colors of a set of M&Ms candies (data tabledput at end of message). You'll note that the data in the table are colors (rather than, say numbers that are coded values of colors). I'd like to make a bar chart of these data with the color of the bar matching the color of the data it reflects. I thought this would be a relatively simple thing to do since I spent a good bit of time yesterday making sure I could harvest a list of these colors in vector format (in my case, using the levels()command).

I didn't keep a running list of the things I tried. I did try associating the color list the color list

library(ggplot2)
ggplot(data = Candies) + geom_bar(mapping = aes(x = MMs))
ggplot(data = Candies, fill=levels(Candies$MMs)) + geom_bar(mapping = aes(x = MMs))
ggplot(data = Candies) + geom_bar(mapping = aes(x = MMs, fill=levels(Candies$MMs)))
ggplot(data = Candies) + geom_bar(mapping = aes(x = MMs)) + scale_fill_identity()
ggplot(data = Candies) + geom_bar(mapping = aes(x = MMs), fill=Candies$MMs) + scale_fill_identity()
ggplot(data = Candies) + geom_bar(mapping = aes(x = MMs)) +scale_color_identity(mapping=aes(fill))

There's an article at r-bloggers who deceivingly appears to address this problem, but the color is assigned as the data.frame is constructed. I think I need to construct a color pallete myself (and that r-bloggers article even has the exact M&Ms color values!)

I made a custom color tibble...

myColors <- tibble(color_name=c("Red", "Orange", "Yellow", "Green", "Blue", "Brown"), official_color = c("#cb1634", "#eb6624", "#fff10a", "#37b252", "#009edd", "#562f14"))
> myColors
# A tibble: 6 x 2
  color_name official_color
  <chr>      <chr>         
1 Red        #cb1634       
2 Orange     #eb6624       
3 Yellow     #fff10a       
4 Green      #37b252       
5 Blue       #009edd       
6 Brown      #562f14   

...which didn't get me anywhere. Errors like the ones above. There's an article here about making and using a corporate color scheme, but his needs and skill level are quite a bit splashier than mine are. Somewhere in creating all those functions and function calls I got lost.

If changing the axis on the plots from counts to percentages is this hard I'm going to smack my head against the wall. And if I start wondering if I've got a tibble of candies or a tibble of candies or a tibble of candy, I'm going look for a harakiri sword on ebay.

structure(list(MMs = c("brown", "red", "red", "blue", "green", 
"red", "red", "orange", "green", "orange", "brown", "green", 
"yellow", "green", "blue", "yellow", "brown", "yellow", "red", 
"green", "brown", "yellow", "yellow", "green", "yellow", "brown", 
"brown", "blue", "blue", "brown", "blue", "yellow", "yellow", 
"blue", "brown", "yellow", "blue", "orange", "yellow", "blue", 
"red", "red", "red", "red", "blue", "yellow", "blue", "blue", 
"brown", "yellow", "red", "red", "orange", "brown", "brown", 
"orange", "brown", "brown", "yellow", "yellow", "red", "red", 
"brown", "red", "blue", "red", "yellow", "brown", "orange", "red", 
"red", "orange", "brown", "red", "yellow", "green", "brown", 
"blue", "red", "brown", "brown", "brown", "red", "yellow", "brown", 
"brown", "brown", "brown", "red", "blue", "brown", "red", "orange", 
"brown", "brown", "blue", "brown", "green", "green", "brown", 
"red", "brown", "brown", "red", "green", "red", "brown", "yellow", 
"yellow", "yellow", "yellow", "brown", "red", "red", "orange", 
"red", "brown", "red", "brown", "green", "blue", "yellow", "red", 
"blue", "red", "red", "green", "red", "orange", "red", "brown", 
"green", "orange", "red", "orange", "red", "yellow", "brown", 
"yellow", "yellow", "blue", "brown", "brown", "yellow", "green", 
"brown", "red", "brown", "yellow", "orange", "red", "red", "brown", 
"green", "green", "brown", "brown", "yellow", "orange", "red", 
"red", "yellow", "green", "yellow", "green", "red", "red", "brown", 
"brown", "yellow", "green", "orange", "orange", "red", "blue", 
"brown", "brown", "yellow", "blue", "yellow", "red", "brown", 
"red", "red", "brown", "blue", "red", "yellow", "blue", "blue", 
"yellow", "yellow", "brown", "yellow", "brown", "yellow", "brown", 
"yellow", "brown", "blue", "blue", "orange", "green", "red", 
"red", "red", "brown", "red", "red", "green", "yellow", "green", 
"red", "red", "blue", "green", "blue", "brown", "green", "green", 
"red", "red", "red", "yellow", "brown", "green", "yellow", "blue", 
"red", "red", "yellow", "green", "brown", "yellow", "yellow", 
"yellow", "yellow", "red", "blue", "green", "brown", "orange", 
"yellow", "orange", "yellow", "brown", "orange", "red", "yellow", 
"red"), BrandX = c("yellow", "red", "orange", "blue", "orange", 
"green", "red", "yellow", "blue", "blue", "red", "red", "yellow", 
"blue", "yellow", "orange", "red", "green", "brown", "brown", 
"red", "red", "yellow", "yellow", "brown", "red", "blue", "orange", 
"red", "red", "yellow", "orange", "yellow", "orange", "brown", 
"blue", "blue", "green", "red", "orange", "brown", "orange", 
"red", "red", "brown", "red", "yellow", "yellow", "brown", "orange", 
"blue", "brown", "yellow", "red", "red", "brown", "brown", "yellow", 
"brown", "blue", "orange", "orange", "brown", "orange", "yellow", 
"orange", "red", "red", "blue", "red", "blue", "red", "blue", 
"orange", "red", "orange", "red", "red", "brown", "brown", "brown", 
"red", "yellow", "red", "blue", "yellow", "blue", "brown", "orange", 
"yellow", "red", "orange", "green", "brown", "red", "orange", 
"yellow", "red", "brown", "orange", "yellow", "orange", "yellow", 
"brown", "blue", "brown", "red", "yellow", "yellow", "red", "brown", 
"yellow", "brown", "orange", "brown", "blue", "red", "orange", 
"yellow", "orange", "blue", "red", "blue", "red", "orange", "red", 
"red", "green", "brown", "brown", "red", "brown", "red", "brown", 
"yellow", "brown", "orange", "yellow", "brown", "orange", "red", 
"red", "red", "red", "orange", "green", "brown", "yellow", "red", 
"brown", "brown", "red", "yellow", "orange", "red", "blue", "blue", 
"yellow", "brown", "yellow", "blue", "brown", "red", "orange", 
"brown", "brown", "green", "brown", "blue", "red", "brown", "brown", 
"brown", "blue", "yellow", "orange", "yellow", "yellow", "yellow", 
"orange", "orange", "brown", "red", "brown", "orange", "yellow", 
"red", "red", "yellow", "blue", "red", "green", "brown", "orange", 
"red", "brown", "orange", "yellow", "yellow", "brown", "brown", 
"red", "blue", "yellow", "red", "brown", "blue", "brown", "red", 
"green", "yellow", "yellow", "red", "orange", "brown", "red", 
"orange", "red", "red", "red", "brown", "blue", "yellow", "red", 
"red", "brown", "red", "brown", "blue", "orange", "orange", "yellow", 
"red", "red", "brown", "brown", "yellow", "orange", "brown", 
"orange", "brown", "red", "yellow", "orange", "red", "brown", 
"red", "orange", "yellow", "red")), class = c("tbl_df", "tbl", 
"data.frame"), row.names = c(NA, -250L), spec = structure(list(
    cols = list(MMs = structure(list(), class = c("collector_character", 
    "collector")), BrandX = structure(list(), class = c("collector_character", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector"))), class = "col_spec"))
#>        MMs BrandX
#> 1    brown yellow
#> 2      red    red
#> 3      red orange
#> 4     blue   blue
#> 5    green orange
#> 6      red  green
#> 7      red    red
#> 8   orange yellow
#> 9    green   blue
#> 10  orange   blue
#> 11   brown    red
#> 12   green    red
#> 13  yellow yellow
#> 14   green   blue
#> 15    blue yellow
#> 16  yellow orange
#> 17   brown    red
#> 18  yellow  green
#> 19     red  brown
#> 20   green  brown
#> 21   brown    red
#> 22  yellow    red
#> 23  yellow yellow
#> 24   green yellow
#> 25  yellow  brown
#> 26   brown    red
#> 27   brown   blue
#> 28    blue orange
#> 29    blue    red
#> 30   brown    red
#> 31    blue yellow
#> 32  yellow orange
#> 33  yellow yellow
#> 34    blue orange
#> 35   brown  brown
#> 36  yellow   blue
#> 37    blue   blue
#> 38  orange  green
#> 39  yellow    red
#> 40    blue orange
#> 41     red  brown
#> 42     red orange
#> 43     red    red
#> 44     red    red
#> 45    blue  brown
#> 46  yellow    red
#> 47    blue yellow
#> 48    blue yellow
#> 49   brown  brown
#> 50  yellow orange
#> 51     red   blue
#> 52     red  brown
#> 53  orange yellow
#> 54   brown    red
#> 55   brown    red
#> 56  orange  brown
#> 57   brown  brown
#> 58   brown yellow
#> 59  yellow  brown
#> 60  yellow   blue
#> 61     red orange
#> 62     red orange
#> 63   brown  brown
#> 64     red orange
#> 65    blue yellow
#> 66     red orange
#> 67  yellow    red
#> 68   brown    red
#> 69  orange   blue
#> 70     red    red
#> 71     red   blue
#> 72  orange    red
#> 73   brown   blue
#> 74     red orange
#> 75  yellow    red
#> 76   green orange
#> 77   brown    red
#> 78    blue    red
#> 79     red  brown
#> 80   brown  brown
#> 81   brown  brown
#> 82   brown    red
#> 83     red yellow
#> 84  yellow    red
#> 85   brown   blue
#> 86   brown yellow
#> 87   brown   blue
#> 88   brown  brown
#> 89     red orange
#> 90    blue yellow
#> 91   brown    red
#> 92     red orange
#> 93  orange  green
#> 94   brown  brown
#> 95   brown    red
#> 96    blue orange
#> 97   brown yellow
#> 98   green    red
#> 99   green  brown
#> 100  brown orange
#> 101    red yellow
#> 102  brown orange
#> 103  brown yellow
#> 104    red  brown
#> 105  green   blue
#> 106    red  brown
#> 107  brown    red
#> 108 yellow yellow
#> 109 yellow yellow
#> 110 yellow    red
#> 111 yellow  brown
#> 112  brown yellow
#> 113    red  brown
#> 114    red orange
#> 115 orange  brown
#> 116    red   blue
#> 117  brown    red
#> 118    red orange
#> 119  brown yellow
#> 120  green orange
#> 121   blue   blue
#> 122 yellow    red
#> 123    red   blue
#> 124   blue    red
#> 125    red orange
#> 126    red    red
#> 127  green    red
#> 128    red  green
#> 129 orange  brown
#> 130    red  brown
#> 131  brown    red
#> 132  green  brown
#> 133 orange    red
#> 134    red  brown
#> 135 orange yellow
#> 136    red  brown
#> 137 yellow orange
#> 138  brown yellow
#> 139 yellow  brown
#> 140 yellow orange
#> 141   blue    red
#> 142  brown    red
#> 143  brown    red
#> 144 yellow    red
#> 145  green orange
#> 146  brown  green
#> 147    red  brown
#> 148  brown yellow
#> 149 yellow    red
#> 150 orange  brown
#> 151    red  brown
#> 152    red    red
#> 153  brown yellow
#> 154  green orange
#> 155  green    red
#> 156  brown   blue
#> 157  brown   blue
#> 158 yellow yellow
#> 159 orange  brown
#> 160    red yellow
#> 161    red   blue
#> 162 yellow  brown
#> 163  green    red
#> 164 yellow orange
#> 165  green  brown
#> 166    red  brown
#> 167    red  green
#> 168  brown  brown
#> 169  brown   blue
#> 170 yellow    red
#> 171  green  brown
#> 172 orange  brown
#> 173 orange  brown
#> 174    red   blue
#> 175   blue yellow
#> 176  brown orange
#> 177  brown yellow
#> 178 yellow yellow
#> 179   blue yellow
#> 180 yellow orange
#> 181    red orange
#> 182  brown  brown
#> 183    red    red
#> 184    red  brown
#> 185  brown orange
#> 186   blue yellow
#> 187    red    red
#> 188 yellow    red
#> 189   blue yellow
#> 190   blue   blue
#> 191 yellow    red
#> 192 yellow  green
#> 193  brown  brown
#> 194 yellow orange
#> 195  brown    red
#> 196 yellow  brown
#> 197  brown orange
#> 198 yellow yellow
#> 199  brown yellow
#> 200   blue  brown
#> 201   blue  brown
#> 202 orange    red
#> 203  green   blue
#> 204    red yellow
#> 205    red    red
#> 206    red  brown
#> 207  brown   blue
#> 208    red  brown
#> 209    red    red
#> 210  green  green
#> 211 yellow yellow
#> 212  green yellow
#> 213    red    red
#> 214    red orange
#> 215   blue  brown
#> 216  green    red
#> 217   blue orange
#> 218  brown    red
#> 219  green    red
#> 220  green    red
#> 221    red  brown
#> 222    red   blue
#> 223    red yellow
#> 224 yellow    red
#> 225  brown    red
#> 226  green  brown
#> 227 yellow    red
#> 228   blue  brown
#> 229    red   blue
#> 230    red orange
#> 231 yellow orange
#> 232  green yellow
#> 233  brown    red
#> 234 yellow    red
#> 235 yellow  brown
#> 236 yellow  brown
#> 237 yellow yellow
#> 238    red orange
#> 239   blue  brown
#> 240  green orange
#> 241  brown  brown
#> 242 orange    red
#> 243 yellow yellow
#> 244 orange orange
#> 245 yellow    red
#> 246  brown  brown
#> 247 orange    red
#> 248    red orange
#> 249 yellow yellow
#> 250    red    red

Created on 2019-02-15 by the reprex package (v0.2.1)

1 Like

I think this is what you're looking for:

library(ggplot2)

ggplot(data = Candies) + 
  geom_bar(aes(x = MMs, fill=MMs)) +
  scale_fill_identity()

The column that has the color names (or hexadecimal values) needs to be mapped to the fill aesthetic, then scale_fill_identity() uses those color names (or hexadecimal values) as is for the fill colors.

To ensure that you live to plot another day, here's a way to show percentages. In this case, we pre-summarize the data before feeding it to ggplot:

library(tidyverse)
library(scales)

Candies %>% 
  group_by(MMs) %>% 
  tally %>% 
  mutate(pct=n/sum(n)) %>% 
  ggplot() + 
    geom_col(aes(x = MMs, y = pct, fill=MMs)) +
    scale_fill_identity() +
    scale_y_continuous(labels=percent_format(accuracy=1))

I thought it would be possible to plot proportions using the internally calculated ..prop.. variable with group=1, but this seems to override the fill aesthetic, resulting in all gray bars.

ggplot(Candies) + 
  geom_bar(aes(x = MMs, y=..prop.., fill=MMs, group=1)) +
  scale_fill_identity() +
  scale_colour_identity()

Ah, here's the way to plot proportions without pre-summarizing and with a working fill aesthetic:

ggplot(Candies) + 
  geom_bar(aes(x = MMs, y=..count../sum(..count..), fill=MMs)) +
  scale_fill_identity() +
  scale_y_continuous(labels=percent_format(accuracy=1))
4 Likes

Uff da. I've got no idea how I'm going to explain this in a simple way while my editor continues to tell me that I am teaching statistics using R and not teaching R itself. (The theoretical reader has "some familiarity" with R, but I'm guessing dplyr and ggplot2 aren't there.)

Re: the group=1 approach

I've been through that myself, finding it on a lot of web pages.

My heart sank a little when my searching found this page, which does not give you confidence nor very much guidance.

I don't know if it's any better for your students/readers, but I've updated my answer to plot proportions without pre-summarizing.

1 Like

The ..count.. type expression may now be replaced with stat(), which is more intuitive:

1 Like

Meta comment: Which multiverse do I have to find a wormhole for is R spoken in a dialect that includes look-up tables in tidy?

Both scales and ggplot2 have had major releases in the time since then that address some of these issues, so I definitely recommend taking a look at some of the updated documentation.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.