Изменить цвета на определенную палитру для объектов ggplot

Я хотел бы изменить цвета по умолчанию на определенную палитру для всех объектов типа geom_* с помощью функции.

Ниже приведен пример для geom_line() и использования функции change_colours()

# load ggplot2 and tidyr library
require(ggplot2)
require(tidyr)

# create a mock data frame
df <- data.frame(cbind(var1=500*cumprod(1+rnorm(300, 0, 0.04)),
                       var2=400*cumprod(1+rnorm(300, 0, 0.04)),
                       var3=300*cumprod(1+rnorm(300, 0, 0.04))))
df$TS <- as.POSIXct(Sys.time()+seq(300))
df <- gather(df, stock, price, -TS)

# create basic base graph
p <- ggplot(df, aes(x=TS, y=price, group=stock))+geom_line(aes(colour=stock))

# custom pallet
custom_pal <- c("#002776", "#81BC00", "#00A1DE", "#72C7E7", "#3C8A2E", "#BDD203", 
                "#313131", "#335291", "#9AC933", "#33B4E5", "#8ED2EC", "#63A158", 
                "#CADB35", "#575757", "#4C689F", "#A7D04C", "#4CBDE8", "#9DD8EE", 
                "#76AD6D", "#D1DF4F", "#8C8C8C", "#7F93BA", "#C0DE80", "#80D0EE", 
                "#B8E3F3", "#9DC496", "#DEE881", "#B4B4B4", "#99A9C8", "#CDE499", 
                "#99D9F2", "#C7E9F5", "#B1D0AB", "#E5ED9A", "#DCDCDC")

# the function the change colours
change_colours <- function(ggplot_obj, pal){
  p <- ggplot_obj
  group_data <- p$data[, as.character(p$mapping$group)]
  n_groups <- length(unique(group_data))
  group_data_cols <- pal[group_data]

  p + theme_light()+ geom_line(colour=group_data_cols)
}

p
p1 <- change_colours(ggplot_obj=p, pal=custom_pal)
p1

Я надеюсь изменить функцию change_colours(), чтобы она была более общей для всех слоев типа geom_*

Любая помощь приветствуется.


person h.l.m    schedule 04.01.2016    source источник
comment
Я не понимаю вопроса. Похоже, ваш код уже делает то, о чем вы просили. Какая у вас просьба?   -  person Mike Wise    schedule 05.01.2016
comment
Ах, я понял. Для всех примитивов ...   -  person Mike Wise    schedule 05.01.2016


Ответы (1)


Следующее должно сделать то, что вам нужно. Обратите внимание, что он изменяет только цвета, сопоставленные с переменными. Цвет, переданный непосредственно geom_*, не изменится (пример ниже). О подходе, который изменяет colour или fill (в зависимости от того, что отображается первым), см. В нижней половине этого сообщения.

change_colours <- function(p, palette) {
  n <- nlevels(p$data[[deparse(p$mapping$group)]])
  tryCatch(as.character(palette), 
           error=function(e) stop('palette should be a vector of colours', call.=FALSE))
  if(n > length(palette)) stop('Not enough colours in palette.')
  pal <- function(n) palette[seq_len(n)]
  p + theme_light() + discrete_scale('colour', 'foo', pal)
}

# Here, df is from the OP's post
p <- ggplot(df, aes(x=TS, y=price, group=stock)) 

Примеры:

# NB: custom_pal is defined in the OP's post
change_colours(p + geom_line(aes(colour=stock)), custom_pal)

введите здесь описание изображения

change_colours(p + geom_point(aes(colour=stock)), custom_pal)

введите здесь описание изображения

И с другой палитрой:

change_colours(p + geom_smooth(aes(colour=stock)), 
               c('firebrick', 'midnightblue', 'violet', 'seagreen'))

введите здесь описание изображения

Как упоминалось выше, это изменит только colour и fill, которые отображаются в переменные. Например, это не повлияет на следующие цвета:

change_colours(p + geom_point(colour=rep(c('tomato', 'hotpink', 'cadetblue'), each=300)), 
               custom_pal)

введите здесь описание изображения


В ответ на комментарий OP вы может легко определить, какие типы сопоставлений используются (например, alpha, colour, fill). Вы только посмотрите на p$layers[[1]]$mapping.

Если мы предположим, что первое fill или colour отображение первого слоя является отображением, для которого вы хотите изменить цвета, вы можете сделать:

change_colours <- function(p, palette, type) {
  n <- nlevels(p$data[[deparse(p$mapping$group)]])
  tryCatch(as.character(palette), 
           error=function(e) stop('palette should be a vector of colours', call.=FALSE))
  if(n > length(palette)) stop('Not enough colours in palette.')
  if(missing(type)) 
    type <- grep('colour|fill', names(p$layers[[1]]$mapping), value=TRUE)[1]
  pal <- function(n) palette[seq_len(n)]
  p + theme_light() + discrete_scale(type, 'foo', pal)
}

# Here, df is from the OP's post
p <- ggplot(df, aes(x=TS, y=price, group=stock))

Примеры:

Замена заливки вместо цвета:

change_colours(p + geom_point(aes(fill=stock), pch=21), 
               c('white', 'grey50', 'grey80'))

введите здесь описание изображения

Отображение приоритета первого сопоставленного эстетического цвета / заливки:

change_colours(p + geom_point(aes(fill=stock, color=stock), pch=21) +
                 geom_smooth(aes(color=stock)), 
               c('black', 'grey50', 'grey80'))

введите здесь описание изображения

change_colours(p + geom_point(aes(color=stock, fill=stock), pch=21) +
                 geom_smooth(aes(color=stock)), 
               c('black', 'grey50', 'grey80'))

введите здесь описание изображения

Отмените приоритет первого сопоставленного эстетического элемента с помощью аргумента type, например:

change_colours(p + geom_point(aes(color=stock, fill=stock), pch=21) +
                 geom_smooth(aes(color=stock)), 
               c('black', 'grey50', 'grey80'), type='fill')
person jbaums    schedule 04.01.2016
comment
Есть ли способ проверить, используется ли заливка или используется ли цвет в качестве «основной» кисти для окраски »? например при попытке: df2 <- df %>% group_by(stock) %>% summarise(mean_px=mean(price)); p2 <- ggplot(df2,aes(x=stock,y=mean_px))+geom_bar(aes(fill=stock),stat='identity') тогда новая функция change_colours не совсем работает ... - person h.l.m; 05.01.2016