3

When using a named vector to set colours in a manual scale in ggplot2, if you use a variable as one of the names, the colour will not appear in the final plot.

library(ggplot2)

first_species <- 'setosa'
colours <- c(first_species = 'black',
             'versicolor'  = 'cadetblue',
             'virginica'   = 'hotpink')

ggplot(iris) +
  aes(x = Petal.Length, y = Petal.Width, colour = Species) +
  geom_point() +
  scale_colour_manual(values = colours)

Missing a colour

However, if I create the named vector using names, the plot appears as expected:

colours <- c('black', 'cadetblue', 'hotpink')
names(colours) <- c(first_species, 'versicolor', 'virginica')

ggplot(iris) +
  aes(x = Petal.Length, y = Petal.Width, colour = Species) +
  geom_point() +
  scale_colour_manual(values = colours)

Correct plot

Can anyone explain this behaviour to me? I suspect it is related to non-standard evaluation (ggplot2 is using the name rather than the value?).

Suggestions the best way to use a variable in the manual scale setting functions, would be appreciated!

Mhairi McNeill
  • 1,951
  • 11
  • 20
  • 3
    in the first example, after colours <- c(first_species = 'black', versicolor' = 'cadetblue', 'virginica' = 'hotpink') , if you check the names(colours) , you will find that first name is set to "first_species" instead of "setosa". This is the reason why while plotting ggplot() is unable to find "first_species" in the data and so doesn't plot. – joel.wilson Nov 04 '16 at 15:49
  • 2
    If you want a single line of code for setting names instead of using two lines with `names` you can use `setNames`, which is a convenience function for that situation. – aosmith Nov 04 '16 at 15:58

2 Answers2

3

When you do something like:

c(n=1)

Its like doing:

runif(n=10)

The n is a name here, and isn't evaluated like it was a variable. Its a named argument. That you can quote names like runif("n"=10) is a feature of the parser that lets you put otherwise unparsable names as arguments:

list("this has spaces" = 99) # works, list(this has spaces=99) fails
Spacedman
  • 92,590
  • 12
  • 140
  • 224
  • Okay, this makes sense. To confirm: the names in a named vector are something different from just characters? – Mhairi McNeill Nov 04 '16 at 16:07
  • I think part of my confusion is that `is.character(names(colours))` is true. But I assume the names function converts to character. – Mhairi McNeill Nov 04 '16 at 16:09
  • Ah, I didn't realise that you can do this: `c(is = 4, a = 5, thing = 8)`. I guess I thought that `c()` worked differently from other functions that take named arguments. Okay this makes sense! – Mhairi McNeill Nov 04 '16 at 16:13
2

As others have mentioned, if you look at the named vector colours you created, you will see that it didn't evaluate first_species, it simply assigned it as the name.

first_species <- 'setosa'
colours <- c(first_species = 'black',
             'versicolor'  = 'cadetblue',
             'virginica'   = 'hotpink')

colours
# first_species    versicolor     virginica 
#       "black"   "cadetblue"     "hotpink"

You can get R to evaluate that variable by calling it using setNames:

colours <- setNames(c("black", "cadetblue", "hotpink" ), 
                    c(first_species, "versicolor", "virginica"))

colours
#      setosa  versicolor   virginica 
#     "black" "cadetblue"   "hotpink" 

Now you get the desired plot:

ggplot(iris) +
  aes(x = Petal.Length, y = Petal.Width, colour = Species) +
  geom_point() +
  scale_colour_manual(values = colours)

plot output

Dan Adams
  • 4,971
  • 9
  • 28