基于几种颜色创建属于我自己的调色板

R语言中的颜色库 r语言色卡_f5


主要有以下几个方面:

  • 将颜色与其对应的十六进制矢量联系起来
  • 创建访问十六进制矢量的函数
  • 调色板命名
  • 访问调用调色板
  • 创建兼容ggplot2的尺度函数

首先我们创建一个颜色变量

library(ggplot2)
theme_set(theme_minimal())
my_colors <- c(
  `purple` = "#7b0099",
  `yellow` = "#ff9900",
  `black`  = "#221f1f",
  `white`  = "#f5f5f1",
  `red`    = "#e50914"
)


后续如果需要对颜色进行修改或添加都可以在这个颜色变量中进行。


下面创建一个可以从该变量中提取颜色对应的十六进制的函数

my_cols <- function(...){
  cols <- c(...)
  
  if (is.null(cols))
    return(my_colors)
  my_colors[cols]
}

此时我们可以十分方便获取颜色的十六进制,下面演示一下:

my_cols()
my_cols("purple")
my_cols("purple","yellow")
my_cols("yellow","purple")



此时我们可以在ggplot2中调用这些颜色

library(gapminder)
head(gapminder)
ggplot(gapminder, aes(gdpPercap, lifeExp))+
  geom_point(color=my_cols("purple"), size=2, alpha=0.8)+
  scale_x_log10()



R语言中的颜色库 r语言色卡_R语言中的颜色库_02

R语言中的颜色库 r语言色卡_十六进制_03

创建调色板

调色板就是一个颜色列表方便我们后面使用,将各种颜色组合搭配

my_palettes <- list(
  `main`  = my_cols("purple","yellow","red"),
  `cool`  = my_cols("purple","yellow"),
  `hot`   = my_cols("yellow","black","red"),
  `mixed` = my_cols("purple","yellow","white","red"),
  `bw`    = my_cols("black","white")
)



在这个颜色列表中实际上我们创建了好几种颜色组合,下面创建一个函数来访问并调用它们

my_pal <- function(palette="main", reverse=FALSE, ...){
  pal <- my_palettes[[palette]]
  if (reverse) pal <- rev(pal)
  colorRampPalette(pal, ...)
}

该函数通过不同颜色组合名称从列表中获取一个颜色组合(默认条件下是main),同时可以设置是否颠倒颜色顺序,之后传递给函数colorRampPaette()创建调色板。因此其返回的是一个函数。

通过这个函数可以基于调色板返回不同数目的颜色,进而可以在原始颜色之间创建多级颜色梯度

my_pal("cool")

my_pal("cool")(10)

R语言中的颜色库 r语言色卡_f5_04

pie(rep(1,10), col = my_pal("cool")(10))




R语言中的颜色库 r语言色卡_十六进制_05

上图展示的10种颜色就是my_pal("cool")(10)返回的十六进制对应的颜色,这就为ggplot2中的尺度颜色函数创造了可能

Scales for ggplot2

ggplot2中颜色映射有colorfill即颜色和填充。

#' Color scale constructor for my_colors
#' 
#' @param palette Character name of palette in my_palettes
#' @param discrete Boolean indicating whether color aesthetic is discrete or not
#' @param reverse Boolean indicating whether the palette should be reversed
#' @param ... Additional arguments passed to discrete_scale() or scale_color_gradientn(), used #' #' respectively when discrete is TRUE or FALSE
#' 
scale_color_my <- function(palette="main", discrete=TRUE, reverse=FALSE, ...){
  pal <- my_pal(palette = palette, reverse = reverse)
  
  if (discrete){
    discrete_scale("colour", paste0("my_", palette), palette = pal, ...)
  }else{
    scale_color_gradientn(colours = pal(256), ...)
  }
}
#' Fill scale constructor for my_colors
#'
#' @param palette Character name of palette in my_palettes
#' @param discrete Boolean indicating whether color aesthetic is discrete or not
#' @param reverse Boolean indicating whether the palette should be reversed
#' @param ... Additional arguments passed to discrete_scale() or scale_color_gradientn(), used #' #' respectively when discrete is TRUE or FALSE
#' 
scale_fill_my <- function(palette="main", discrete=TRUE, reverse=FALSE, ...){
  pal <- my_pal(palette = palette, reverse = reverse)
  if (discrete){
    discrete_scale("fill",paste0("my_", palette), palette = pal, ...)
  }else{
    scale_fill_gradientn(colours = pal(256), ...)
  }
}



上面每个函数都制定一个调色板(默认是main),调色板是基于离散变量或连续变量,以及是否颠倒颜色顺序,同时还传递给了相关的ggplot2函数。下面可以试试它们在绘图过程中的表现

ggplot(gapminder,aes(gdpPercap, lifeExp, color=continent))+
  geom_point(size=2, alpha=0.8)+
  scale_x_log10()+
  scale_color_my()



R语言中的颜色库 r语言色卡_R语言中的颜色库_06

我们可以更换调色板试试

ggplot(gapminder,aes(gdpPercap, lifeExp, color=continent))+
  geom_point(size=2, alpha=0.8)+
  scale_x_log10()+
  scale_color_my(palette = "hot")



R语言中的颜色库 r语言色卡_十六进制_07

如果是连续变量的话

ggplot(iris, aes(Sepal.Width, Sepal.Length, color = Sepal.Length)) +
    geom_point(size = 4, alpha = .8) +
    scale_color_my(discrete = FALSE, palette = "bw", reverse = TRUE)



R语言中的颜色库 r语言色卡_sed_08

上面是颜色,下面试试填充

ggplot(mpg, aes(manufacturer, fill = manufacturer)) +
    geom_bar() +
    theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
    scale_fill_my(palette = "mixed", guide = "none")




R语言中的颜色库 r语言色卡_R语言中的颜色库_09

所有测试代码

library(ggplot2)
theme_set(theme_minimal())
my_colors <- c(
  `purple` = "#7b0099",
  `yellow` = "#ff9900",
  `black`  = "#221f1f",
  `white`  = "#f5f5f1",
  `red`    = "#e50914"
)
my_cols <- function(...){
  cols <- c(...)
  
  if (is.null(cols))
    return(my_colors)
  my_colors[cols]
}
my_cols()
my_cols("purple")
my_cols("purple","yellow")
my_cols("yellow","purple")
library(gapminder)
head(gapminder)
ggplot(gapminder, aes(gdpPercap, lifeExp))+
  geom_point(color=my_cols("purple"), size=2, alpha=0.8)+
  scale_x_log10()
my_palettes <- list(
  `main`  = my_cols("purple","yellow","red"),
  `cool`  = my_cols("purple","yellow"),
  `hot`   = my_cols("yellow","black","red"),
  `mixed` = my_cols("purple","yellow","white","red"),
  `bw`    = my_cols("black","white")
)
my_pal("cool")
my_pal("cool")(10)
pie(rep(1,10), col = my_pal("cool")(10))
scale_color_my <- function(palette="main", discrete=TRUE, reverse=FALSE, ...){
  pal <- my_pal(palette = palette, reverse = reverse)
  
  if (discrete){
    discrete_scale("colour", paste0("my_", palette), palette = pal, ...)
  }else{
    scale_color_gradientn(colours = pal(256), ...)
  }
}
scale_fill_my <- function(palette="main", discrete=TRUE, reverse=FALSE, ...){
  pal <- my_pal(palette = palette, reverse = reverse)
  if (discrete){
    discrete_scale("fill",paste0("my_", palette), palette = pal, ...)
  }else{
    scale_fill_gradientn(colours = pal(256), ...)
  }
}
ggplot(gapminder,aes(gdpPercap, lifeExp, color=continent))+
  geom_point(size=2, alpha=0.8)+
  scale_x_log10()+
  scale_color_my()
ggplot(gapminder,aes(gdpPercap, lifeExp, color=continent))+
  geom_point(size=2, alpha=0.8)+
  scale_x_log10()+
  scale_color_my(palette = "hot")
ggplot(iris, aes(Sepal.Width, Sepal.Length, color = Sepal.Length)) +
  geom_point(size = 4, alpha = .8) +
  scale_color_my(discrete = FALSE, palette = "bw", reverse = TRUE)
ggplot(mpg, aes(manufacturer, fill = manufacturer)) +
  geom_bar() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  scale_fill_my(palette = "mixed", guide = "none")