Robin Kohrs
Robin Kohrs

Reputation: 697

Consistent mapping from value to color in ggplot

I think I'm missing something very easy here, but I just can't figure it out at the moment: I would like to consistently assign colors to certain values from a column across multiple plots. So I have this tibble (sl):

# A tibble: 15 x 3
   class                           hex         x
   <chr>                           <chr>   <int>
 1 translational slide             #c23b22     1
 2 rotational slide                #AFC6CE     2
 3 fast flow-type                  #b7bf5e     3
 4 complex                         #A6CEE3     4
 5 area subject to rockfall/topple #1F78B4     5
 6 fall-type                       #B2DF8A     6
 7 n.d.                            #33A02C     7
 8 NA                              #FB9A99     8
 9 area subject to shallow-slides  #E31A1C     9
10 slow flow-type                  #FDBF6F    10
11 topple                          #FF7F00    11
12 deep-seated movement            #CAB2D6    12
13 subsidence                      #6A3D9A    13
14 areas subject to subsidence     #FFFF99    14
15 area of expansion               #B15928    15

This should recreate it:

structure(list(class = c("translational slide", "rotational slide", 
"fast flow-type", "complex", "area subject to rockfall/topple", 
"fall-type", "n.d.", NA, "area subject to shallow-slides", "slow flow-type", 
"topple", "deep-seated movement", "subsidence", "areas subject to subsidence", 
"area of expansion"), hex = c("#c23b22", "#AFC6CE", "#b7bf5e", 
"#A6CEE3", "#1F78B4", "#B2DF8A", "#33A02C", "#FB9A99", "#E31A1C", 
"#FDBF6F", "#FF7F00", "#CAB2D6", "#6A3D9A", "#FFFF99", "#B15928"
), x = 1:15), row.names = c(NA, -15L), class = c("tbl_df", "tbl", 
"data.frame"))

Now I would like to plot each class with a bar in the color if its hex-code (for now just for visualization purposes). So I did:

ggplot(sl) +
  geom_col(aes(x = x,
               y = 1,
               fill = class)) +
  scale_fill_manual(values = sl$hex) +
  geom_text(aes(x = x,
                y = 0.5,
                label = class),
            angle = 90)

But these are not the colors as they are in the tibble. So I tried to follow this guide: How to assign colors to categorical variables in ggplot2 that have stable mapping? and created this:

# create the color palette
mycols = sl$hex 
names(mycols) = sl$class

and then plotted it with

ggplot(sl) +
  geom_col(aes(x = x,
               y = 1,
               fill = class)) +
  scale_fill_manual(values = mycols) +
  geom_text(aes(x = x,
                y = 0.5,
                label = class),
            angle = 90)

But the results is the same. It's this:

enter image description here

For example the translational slide has the hex code: "#c23b22" and should be a pastell darkish red. Anyone might have an idea what I'm missing here?

Upvotes: 2

Views: 1247

Answers (3)

PKumar
PKumar

Reputation: 11128

You need to provide correct order to colors as per your column, since there is already one called 'x' I have used it as well. Also I replaced NA with character 'NA'. I have checked few of them, Please let me know if this is not the desired output. Thanks

#Assuming df is your dataframe:

df[is.na(df$class), 'class'] <- 'NA'

ggplot(df) +
geom_col(aes(x = x,
           y = 1,
           fill = factor(x))) +
scale_fill_manual(values = df$hex, labels=df$class) +
geom_text(aes(x = x,
            y = 0.5,
            label = class),
        angle = 90)

Output:

enter image description here

Upvotes: 2

Sirius
Sirius

Reputation: 5429

Consider this:


sl <- structure(list(class = c("translational slide", "rotational slide",
"fast flow-type", "complex", "area subject to rockfall/topple",
"fall-type", "n.d.", NA, "area subject to shallow-slides", "slow flow-type",
"topple", "deep-seated movement", "subsidence", "areas subject to subsidence",
"area of expansion"), hex = c("#c23b22", "#AFC6CE", "#b7bf5e",
"#A6CEE3", "#1F78B4", "#B2DF8A", "#33A02C", "#FB9A99", "#E31A1C",
"#FDBF6F", "#FF7F00", "#CAB2D6", "#6A3D9A", "#FFFF99", "#B15928"
), x = 1:15), row.names = c(NA, -15L), class = c("tbl_df", "tbl",
"data.frame"))

sl$class <- factor( sl$class, levels=unique(sl$class) )

cl <- sl$hex
names(cl) <- paste( sl$class )

ggplot(sl) +
    geom_col(aes(x = x,
                 y = 1,
                 fill = class)) +
    scale_fill_manual( values = cl, na.value = cl["NA"] ) +
    geom_text(aes(x = x,
                  y = 0.5,
                  label = class),
              angle = 90)

By changing class to a factor and setting levels to it, and using a named vector for your values in scale_fill_manual, and using na.value in there properly, yo might get something that looks more as expected.

enter image description here

Upvotes: 2

Limey
Limey

Reputation: 12585

I think the problem is that scale_fill_manual expect the order of its values and labels arguments to match. This isn't the case with your dataset.

Does

sl %>% ggplot() +
  geom_col(aes(x = x,
               y = 1,
               fill = hex)) +
  geom_text(aes(x = x,
                y = 0.5,
                label = class),
            angle = 90) +
  scale_fill_manual(values=sl$hex, labels=sl$class)

Give you what you want?

next time, please dput() your test data: it took me as long to create the test dataset as to answer your question. Also, using hex codes for colours make it difficult to check the colours are as expected. For a MWE, blue/green/black etx would have been more helpful.

enter image description here

Upvotes: 1

Related Questions