Mercelo
Mercelo

Reputation: 231

ggplot2 with colour blind ggthemes except black

I want to create a general line of code I can apply to any ggplot grouped barchart I make. I want it to make my graphs colour blind friendly. In the library ggthemes, the scale_fill_colorblind function does just the job. My problem is that black is often picked as one of the colours; I sometimes need to overlay confidence intervals and other stuff, so black is not really an option.

library(ggplot2)
library(ggthemes)
ggplot(diamonds, aes(clarity, fill=cut)) + geom_bar(position="dodge")+
scale_fill_colorblind()

Is there any way to to have within the scale_fill_colourblind some code that tells it not to pick black? I don't want to list the colours manually because I want it to be compatible with lots of different data (some may have two "fills", some 10 etc...).

Any help would be greatly appreciated.

Upvotes: 2

Views: 4128

Answers (3)

randy
randy

Reputation: 1091

This answer builds on the answer from Alec but creates a function that returns scale_fill_discrete with a type argument equal to a vector of the last 7 colors used by scale_fill_colorblind. You do not have to specify the number of groups in your data; if there are N groups, scale_fill_discrete will use the first N colors in its type argument. The function I wrote will also let you select which colors you want, so you can drop black or use the 2nd, 4th, and 5th colors.

Load packages

library(ggplot2)
# Included because this is what I used to make the images:
theme_set(theme_minimal()) 
library(ggthemes)

Define color/fill functions

# Fill
scale_fill_colorblind7 = function(.ColorList = 2L:8L, ...){
    scale_fill_discrete(..., type = colorblind_pal()(8)[.ColorList])
}

# Color
scale_color_colorblind7 = function(.ColorList = 2L:8L, ...){
    scale_color_discrete(..., type = colorblind_pal()(8)[.ColorList])
}

The default value of .ColorList is 2:8 because there are 8 colors in the colorblind palette, and the first is black (the one we want to drop).

Usage

Use the functions like any other scale function:

ggplot(diamonds, aes(clarity, fill = cut)) + 
  geom_bar(position = "dodge") +
  scale_fill_colorblind7()

Histogram of diamond clarity by cut

You can also specify breaks as part of the ... argument.They get passed through to ... in scale_fill_discrete.

ggplot(diamonds, aes(clarity, fill = cut)) + 
  geom_bar(position = "dodge") +
  scale_fill_colorblind7(breaks = diamonds$cut)

Histogram of diamond clarity by cut

Don't like those colors? Tell the function which colors to use (their positions):

ggplot(diamonds, aes(clarity, fill = cut)) + 
  geom_bar(position = "dodge") +
  scale_fill_colorblind7(.ColorList = c(3,4,7,6,1))

Histogram of diamond clarity by cut

Upvotes: 4

Alec
Alec

Reputation: 75

Another option is use scale_fill_manual with ggthemes::colorblind_pal.

library(ggplot2)
library(ggthemes)
ggplot(diamonds, aes(clarity, fill = cut)) + 
  geom_bar(position = "dodge") +
  scale_fill_colorblind()


n <- length(unique(diamonds$cut))

# or 
n <- data.table::uniqueN(diamonds$cut)

# Manually fill the geom with breaks provided by the data
#  and getting one extra color from ggthemes::colorblind_pal
#  then dropping black (the first color)
ggplot(diamonds, aes(clarity, fill = cut)) + 
  geom_bar(position = "dodge") +
  scale_fill_manual(breaks = diamonds$cut, 
                    values = colorblind_pal()(n + 1)[-1])

Upvotes: 2

baptiste
baptiste

Reputation: 77116

at best a hack,

ggthemes_data$colorblind  <- ggthemes_data$colorblind[-1]
assignInNamespace("ggthemes_data", ggthemes_data, ns="ggthemes")

last_plot() + scale_fill_colorblind()

Upvotes: 4

Related Questions