Как назначить цвета для категориальных переменных в ggplot2, имеющих устойчивое отображение?

Я забирал скорость с R в прошлом месяце.

Вот мой вопрос:

Каким образом можно назначить цвета для категориальных переменных в ggplot2, имеющих устойчивое сопоставление? Мне нужны согласованные цвета по набору графиков, которые имеют разные подмножества и различное количество категориальных переменных.

Например,

plot1 <- ggplot(data, aes(xData, yData,color=categoricaldData)) + geom_line()

где categoricalData имеет 5 уровней.

И затем

plot2 <- ggplot(data.subset, aes(xData.subset, yData.subset, 
                                 color=categoricaldData.subset)) + geom_line()

где categoricalData.subset имеет 3 уровня.

Однако определенный уровень, который находится в обоих наборах, будет иметь другой цвет, что затрудняет чтение графиков вместе.

Нужно ли создавать вектор цветов в кадре данных? Или есть другой способ назначить определенные цвета для категорий?

Ответ 1

Для простых ситуаций, таких как пример в OP, я согласен с тем, что ответ Тьерри является лучшим. Тем не менее, я считаю полезным отметить другой подход, который становится проще, когда вы пытаетесь поддерживать согласованные цветовые схемы в нескольких кадрах данных, которые не все получены путем подмножества одного большого кадра данных. Управление уровнями факторов в нескольких кадрах данных может стать утомительным, если их извлекают из отдельных файлов, и не все уровни факторов отображаются в каждом файле.

Один из способов решения этой проблемы - создать пользовательскую ручную цветовую шкалу следующим образом:

#Some test data
dat <- data.frame(x=runif(10),y=runif(10),
        grp = rep(LETTERS[1:5],each = 2),stringsAsFactors = TRUE)

#Create a custom color scale
library(RColorBrewer)
myColors <- brewer.pal(5,"Set1")
names(myColors) <- levels(dat$grp)
colScale <- scale_colour_manual(name = "grp",values = myColors)

а затем добавьте цветовую гамму на график по мере необходимости:

#One plot with all the data
p <- ggplot(dat,aes(x,y,colour = grp)) + geom_point()
p1 <- p + colScale

#A second plot with only four of the levels
p2 <- p %+% droplevels(subset(dat[4:10,])) + colScale

Первый сюжет выглядит следующим образом:

enter image description here

а второй график выглядит следующим образом:

enter image description here

Таким образом, вам не нужно запоминать или проверять каждый фрейм данных, чтобы увидеть, что у них есть соответствующие уровни.

Ответ 2

В той же ситуации, указанной в malcook в его комментарии: к сожалению, < ответ href= "https://stackoverflow.com/a/6924503/15485" > Thierry не работает с ggplot2 версии 0.9.3.1.

png("figure_%d.png")
set.seed(2014)
library(ggplot2)
dataset <- data.frame(category = rep(LETTERS[1:5], 100),
    x = rnorm(500, mean = rep(1:5, 100)),
    y = rnorm(500, mean = rep(1:5, 100)))
dataset$fCategory <- factor(dataset$category)
subdata <- subset(dataset, category %in% c("A", "D", "E"))

ggplot(dataset, aes(x = x, y = y, colour = fCategory)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = fCategory)) + geom_point()

Здесь это первая цифра:

ggplot A-E, mixed colors

а вторая цифра:

ggplot ADE, mixed colors

Как мы видим, цвета не остаются фиксированными, например, E переключается с пурпурного на blu.

Как было предложено malcook в его комментарии и hadley в его комментарии код, который использует limits, работает правильно:

ggplot(subdata, aes(x = x, y = y, colour = fCategory)) +       
    geom_point() + 
    scale_colour_discrete(drop=TRUE,
        limits = levels(dataset$fCategory))

дает следующий рисунок, который является правильным:

correct ggplot

Это вывод из sessionInfo():

R version 3.0.2 (2013-09-25)
Platform: x86_64-pc-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] methods   stats     graphics  grDevices utils     datasets  base     

other attached packages:
[1] ggplot2_0.9.3.1

loaded via a namespace (and not attached):
 [1] colorspace_1.2-4   dichromat_2.0-0    digest_0.6.4       grid_3.0.2        
 [5] gtable_0.1.2       labeling_0.2       MASS_7.3-29        munsell_0.4.2     
 [9] plyr_1.8           proto_0.3-10       RColorBrewer_1.0-5 reshape2_1.2.2    
[13] scales_0.2.3       stringr_0.6.2 

Ответ 3

Самое простое решение - преобразовать вашу категориальную переменную в коэффициент до подмножества. Суть в том, что вам нужна переменная фактора с точно такими же уровнями во всех ваших подмножествах.

library(ggplot2)
dataset <- data.frame(category = rep(LETTERS[1:5], 100), 
    x = rnorm(500, mean = rep(1:5, 100)), y = rnorm(500, mean = rep(1:5, 100)))
dataset$fCategory <- factor(dataset$category)
subdata <- subset(dataset, category %in% c("A", "D", "E"))

С символьной переменной

ggplot(dataset, aes(x = x, y = y, colour = category)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = category)) + geom_point()

С фактор-переменной

ggplot(dataset, aes(x = x, y = y, colour = fCategory)) + geom_point()
ggplot(subdata, aes(x = x, y = y, colour = fCategory)) + geom_point()

Ответ 4

Основываясь на очень полезном ответе на joran, я смог придумать это решение для стабильной цветовой шкалы для булева коэффициента (TRUE, FALSE).

boolColors <- as.character(c("TRUE"="#5aae61", "FALSE"="#7b3294"))
boolScale <- scale_colour_manual(name="myboolean", values=boolColors)

ggplot(myDataFrame, aes(date, duration)) + 
  geom_point(aes(colour = myboolean)) +
  boolScale

Так как ColorBrewer не очень полезен с бинарными цветовыми шкалами, два необходимых цвета определяются вручную.

Здесь myboolean - это имя столбца в myDataFrame, содержащего коэффициент TRUE/FALSE. date и duration - это имена столбцов, которые должны отображаться на оси x и y графика в этом примере.

Ответ 5

Это старый пост, но я искал ответа на этот же вопрос,

Почему бы не попробовать что-то вроде:

scale_color_manual(values = c("foo" = "#999999", "bar" = "#E69F00"))

Если у вас есть категориальные ценности, я не вижу причины, почему это не должно работать.