R 数据可视化 —— ggplot 标度(四)配色

10. 颜色

除了前面讲的位置标度之外,最常用的就是颜色属性的修改了。

配色也是一门艺术,像我这种没有艺术细胞的人就只能看着哪种配色方案漂亮就将就着用了🤣😂

10.1 ColorBrewer 配色

ColorBrewer 提供了 sequential, divergingqualitative 三种不同的配色类型,每种类型又有不同的配色方案。

有三个不同的标度函数来设置

# 针对离散型数据
scale_*_brewer()
# 针对连续型数据
scale_*_distiller()
# 针对分箱数据
scale_*_fermenter()

其中 * 代表 colour(轮廓颜色) 和 fill(填充色)。

palette 参数的值可以是下列字符串之一

  1. Diverging(双色渐变系)
BrBG, PiYG, PRGn, PuOr, RdBu, RdGy, RdYlBu, RdYlGn, Spectral
  1. Qualitative(多色系)
Accent, Dark2, Paired, Pastel1, Pastel2, Set1, Set2, Set3
  1. Sequential(单色系)
Blues, BuGn, BuPu, GnBu, Greens, Greys, Oranges, OrRd, PuBu, PuBuGn, PuRd, Purples, RdPu, Reds, YlGn, YlGnBu, YlOrBr, YlOrRd
示例

对于如下数据

dsamp <- diamonds[sample(nrow(diamonds), 1000), ]

我们可以为 colour 设置变量

(d <- ggplot(dsamp, aes(carat, price)) +
    geom_point(aes(colour = clarity)))

但是我觉得这种配色不太好看,想换一种。我们进行如下尝试

p1 <- d + scale_colour_brewer()

p2 <- d + scale_colour_brewer(palette = "Greens")

p3 <- d + scale_colour_brewer(palette = "Set1")

p4 <- d + scale_colour_brewer(palette = "Spectral")

plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

en...,这样来看,图 C 是比较好看的,图 D 看起来也行,单色系的就差了点喽。

连续型数据的设置方式也是类似的

d1 <- ggplot(dsamp, aes(carat, price)) +
  geom_point(aes(colour = depth))

d2 <- d + scale_colour_distiller(palette = "Greens")

d3 <- d + scale_colour_distiller(palette = "Set1")

d4 <- d + scale_colour_distiller(palette = "Spectral")

plot_grid(d1, d2, d3, d4, labels = LETTERS[1:4], nrow = 2)

为分箱数据配色

ggplot(dsamp, aes(carat, price)) +
  geom_point(aes(colour=depth)) +
  scale_colour_fermenter(palette = "Spectral")

为每个分箱设置颜色相同的配色

ggplot(dsamp, aes(carat, price, colour=price)) +
  geom_point() +
  scale_x_binned() +
  scale_colour_fermenter(palette = "Spectral")

获取更多的配色方案,可以访问 ColorBrewer 的网页:

http://colorbrewer2.org

配色好看,获取简单,推荐使用

还有一个网站
https://www.webdesignrankings.com/resources/lolcolors/

配色也还可以,只是都是 4 种颜色的。

10.2 渐变色

根据颜色梯度,可以将设置渐变色的函数分为三种:

  • scale_*_gradient:双色渐变,使用 lowhigh 两个参数控制两端的颜色

  • scale_*_gradient2:三色渐变,有 lowmidhigh 三个参数,lowhigh 作用同上,mid 默认值为 0 表示中点的颜色,可以使用 midpoint 参数设置中点位置

  • scale_*_gradientn:多色渐变,为 colours 参数设置一个颜色向量,不加其他参数会选择范围内的均匀分布值,离散型颜色可以指定 values 参数。

示例

对于如下数据

df <- data.frame(
  x = runif(100),
  y = runif(100),
  z1 = rnorm(100),
  z2 = abs(rnorm(100))
)

df_na <- data.frame(
  value = seq(1, 20),
  x = runif(20),
  y = runif(20),
  z1 = c(rep(NA, 10), rnorm(10))
)

其默认配色为浅蓝色到深蓝色的双色渐变

# 默认双色渐变
p1 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z2))

# 调整双色渐变区间
p2 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z2)) +
  scale_colour_gradient(low = "white", high = "black")

# 三色渐变
p3 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1)) +
  scale_colour_gradient2()

# 调整三色渐变区间
p4 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1)) +
  scale_colour_gradient2(low = "green", high = "blue", midpoint = 1)

plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

自定义颜色范围,以及 NA 值的处理

# 自定义颜色范围,使用函数来生成 10 个连续的颜色
p5 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1)) +
  scale_colour_gradientn(colours = topo.colors(10))

p6 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1)) +
  scale_colour_gradientn(colours = rainbow(10))

# 去除 NA 值
p7 <- ggplot(df_na, aes(x = value, y)) +
  geom_bar(aes(fill = z1), stat = "identity") +
  scale_fill_gradient(low = "yellow", high = "red", na.value = NA)

p8 <- ggplot(df_na, aes(x, y)) +
  geom_point(aes(colour = z1)) +
  scale_colour_gradient(low = "yellow", high = "red", na.value = NA)

plot_grid(p5, p6, p7, p8, labels = LETTERS[1:4], nrow = 2)

10.3 灰色渐变

使用 startend 控制灰度范围

示例

默认颜色

p <- ggplot(mtcars, aes(mpg, wt)) + geom_point(aes(colour = factor(cyl)))

p + scale_colour_grey()

更改设置

# 设置终端灰度
p1 <- p + scale_colour_grey(end = 0.5)
# 更改主题
p2 <- p + scale_colour_grey() + theme_bw()

# 缺失值
miss <- factor(sample(c(NA, 1:5), nrow(mtcars), replace = TRUE))

p3 <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point(aes(colour = miss)) +
  scale_colour_grey()
# 更改缺失值的颜色
p4 <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point(aes(colour = miss)) +
  scale_colour_grey(na.value = "green")


plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

10.4 分箱渐变色

分箱渐变色与渐变色类似,只是应用的数据不同。也有三个函数,对应于双色、三色以及多色渐变

scale_*_steps()
scale_*_steps2()
scale_*_stepsn()

用起来和渐变色很相似

df <- data.frame(
  x = runif(100),
  y = runif(100),
  z1 = rnorm(100)
)

p1 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1))

p2 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1)) +
  scale_colour_steps(low = "skyblue", high = "blue")

p3 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1)) +
  scale_colour_steps2()

p4 <- ggplot(df, aes(x, y)) +
  geom_point(aes(colour = z1)) +
  scale_colour_stepsn(colours = terrain.colors(10))

plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

10.5 色轮颜色

这种设置方式主要用于将离散型数据均匀地映射到色轮上的颜色。

这种配色方案被称为 HLC,包含三部分:

  • 色相(hue):0-360 之间的值(代表角度),代表颜色。如红、黄、蓝等

  • 亮度(luminance):表示颜色的明亮程度,0 表示黑色,100 表示白色

  • 色度(chroma):颜色的纯度,色度为 0 表示灰色,最大值根据色相和亮度的组合而变化

而标度函数

scale_*_hue(
  ...
  h = c(0, 360) + 15,
  c = 100,
  l = 65,
)

有对应的参数 hcl 用于设置这些值。

示例
dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
d <- ggplot(dsamp, aes(carat, price)) + 
  geom_point(aes(colour = clarity))

p1<- d + scale_colour_hue()

p2 <- d + scale_colour_hue("Clarity")

p3 <- d + scale_colour_hue(expression(clarity[beta]))


d + scale_colour_hue(l = 40, c = 30)

plot_grid(d, p1, p2, p3, labels = LETTERS[1:4], nrow = 2)

调整亮度和色相

p1 <- d + scale_colour_hue(l = 40, c = 30)

p2 <- d + scale_colour_hue(l = 70, c = 30)

p3 <- d + scale_colour_hue(l = 70, c = 150)

p4 <- d + scale_colour_hue(l = 80, c = 150)

plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

设置色相的范围

p1 <- d + scale_colour_hue(h = c(0, 90))

p2 <- d + scale_colour_hue(h = c(90, 180))

p3 <- d + scale_colour_hue(h = c(180, 270))

p4 <- d + scale_colour_hue(h = c(270, 360))

plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

设置透明度

d <- ggplot(dsamp, aes(carat, price, colour = clarity))

p2 <- d + geom_point(alpha = 0.9)

p3 <- d + geom_point(alpha = 0.5)

p4 <- d + geom_point(alpha = 0.2)

plot_grid(p2, p3, p4, labels = LETTERS[1:4], nrow = 3)

这个图设置透明度之后好看多了

NA 值设置特殊的颜色

miss <- factor(sample(c(NA, 1:5), nrow(mtcars), replace = TRUE))

p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point(aes(colour = miss))

p2 <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point(aes(colour = miss)) +
  scale_colour_hue(na.value = "black")

plot_grid(p1, p2, labels = LETTERS[1:4], nrow = 2)

10.6 Viridis 配色

viridis 提供的颜色映射,让无论是在彩色还是黑白图片均能够很容易看出区别。

它还被设计能够让色盲观众也能看清

示例

对于如下数据

> dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
> dsamp
# A tibble: 1,000 x 10
   carat cut       color clarity depth table price     x     y     z
   <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
 1  1.01 Very Good E     SI1      62.1    56  5461  6.43  6.48  4.01
 2  0.91 Premium   F     SI2      61.7    58  3609  6.22  6.29  3.86
 3  1.26 Very Good H     SI1      60.6    60  6546  6.97  7     4.23
 4  1.31 Premium   H     VS2      61.4    59  7550  7.01  6.96  4.29
 5  1.53 Very Good D     SI1      59.2    57 11873  7.52  7.55  4.46
 6  1.5  Ideal     H     SI2      62.4    58  8471  7.29  7.26  4.54
 7  1.24 Premium   F     VS1      61.5    57  9333  6.97  6.86  4.25
 8  1.14 Premium   H     SI1      59.3    59  5458  6.8   6.76  4.02
 9  0.62 Very Good E     SI2      63.4    56  1426  5.4   5.45  3.44
10  0.72 Premium   G     VS2      62.9    57  2795  5.73  5.65  3.58
# … with 990 more rows

默认的颜色设置方式会根据因子的顺序上色

ggplot(dsamp, aes(carat, price)) +
  geom_point(aes(colour = clarity))

viridis_d 函数用于离散数据配色,可以使用 option 参数设置不同的调色板

# viridis_d 用于离散数据
txsamp <- subset(txhousing, city %in%
                   c("Houston", "Fort Worth", "San Antonio", "Dallas", "Austin"))
d <- ggplot(data = txsamp, aes(x = sales, y = median)) +
    geom_point(aes(colour = city))

# 设置配色和标签
p1 <- d + scale_colour_viridis_d("City\nCenter")

# 选择调色板,使用 ?scales::viridis_pal 获取更多细节
p2 <- d + scale_colour_viridis_d(option = "plasma")

p3 <- d + scale_colour_viridis_d(option = "inferno")

plot_grid(d, p1, p2, p3, labels = LETTERS[1:4], nrow = 2)

设置填充色

# 设置填充色
p <- ggplot(txsamp, aes(x = median, fill = city)) +
  geom_histogram(position = "dodge", binwidth = 15000)
p1 <- p + scale_fill_viridis_d()

# 反转颜色
p2 <- p + scale_fill_viridis_d(direction = -1)

plot_grid(p1, p2, labels = LETTERS[1:4], nrow = 2)

连续型数据及分箱数据颜色设置

# 连续型数据
v <- ggplot(faithfuld) +
    geom_tile(aes(waiting, eruptions, fill = density))

p2 <- v + scale_fill_viridis_c()

p3 <- v + scale_fill_viridis_c(option = "plasma")
# 分箱数据
p4 <- v + scale_fill_viridis_b()

plot_grid(v, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

10.6 连续型和离散型

其实使用上面的函数已经够了,下面的操作也只是对上面的函数进行整合,功能都是一样的。

连续型

对于连续型数据的配色方案,其实我们上面也都涉及到。在这里我们要使用的是下面两个函数

scale_colour_continuous(
  ...,
  type = getOption("ggplot2.continuous.colour", default = "gradient")
)

scale_fill_continuous(
  ...,
  type = getOption("ggplot2.continuous.fill", default = "gradient")
)

这两个函数主要是通过获取 ggplot2.continuous.colourggplot2.continuous.fill 两个选项的值来设置颜色的,默认是渐变色

type 参数还可以设置为:

  • "viridis"
  • 返回连续颜色向量的函数
示例

对于如下数据

> faithfuld
# A tibble: 5,625 x 3
   eruptions waiting density
       <dbl>   <dbl>   <dbl>
 1      1.6       43 0.00322
 2      1.65      43 0.00384
 3      1.69      43 0.00444
 4      1.74      43 0.00498
 5      1.79      43 0.00542
 6      1.84      43 0.00574
 7      1.88      43 0.00592
 8      1.93      43 0.00594
 9      1.98      43 0.00581
10      2.03      43 0.00554
# … with 5,615 more rows

我们可以绘制一张热图

v <- ggplot(faithfuld, aes(waiting, eruptions, fill = density)) +
  geom_tile()

更改颜色方案

p1 <- v + scale_fill_continuous(type = "gradient")

p2 <- v + scale_fill_continuous(type = "viridis")

p3 <- v + scale_fill_gradient()

p4 <- v + scale_fill_viridis_c()

plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

可以看到,ACBD 是一样的。

离散型

类似于连续型设置颜色的函数,离散型函数也是通过获取两个选项的值来设置颜色的

scale_colour_discrete(
  ...,
  type = getOption("ggplot2.discrete.colour", getOption("ggplot2.discrete.fill"))
)

scale_fill_discrete(
  ...,
  type = getOption("ggplot2.discrete.fill", getOption("ggplot2.discrete.colour"))
)

例如,我们要绘制如下图形

ggplot(mpg, aes(cty, colour = factor(class), fill = factor(class))) +
  geom_density(alpha = 0.2) 

默认是以 scale_fill_hue() 配色方案

使用 scale_*_discrete 来更改配色

okabe <- c("#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")

ggplot(mpg, aes(cty, colour = factor(class), fill = factor(class))) +
  geom_density(alpha = 0.2) +
  scale_color_discrete(type = okabe) +
  scale_fill_discrete(type = okabe)

也可以通过设置 ggplot2.discrete.colourggplot2.discrete.fill 的值来更改配色

withr::with_options(
  list(ggplot2.discrete.fill = okabe),
  print(plot_cty(class))
)

还可以根据颜色变量的取值数目,设置默认的配色

discrete_palettes <- list(
  c("skyblue", "orange"),
  RColorBrewer::brewer.pal(3, "Set2"),
  RColorBrewer::brewer.pal(6, "Accent")
)

p1 <- plot_cty(year) + scale_fill_discrete(type = discrete_palettes)
p2 <- plot_cty(drv) + scale_fill_discrete(type = discrete_palettes)
p3 <- plot_cty(fl) + scale_fill_discrete(type = discrete_palettes)
# 也可以传递返回离散颜色的函数
p4 <- plot_cty(class) + scale_fill_discrete(type = scale_fill_brewer)

plot_grid(p1, p2, p3, p4, labels = LETTERS[1:4], nrow = 2)

在上面的例子中(图 A-C),我们在列表中根据离散数据的取值数目(因子的 level)设置不同的配色。

在只有 1-2level 时使用的是 skyblueorange,有 3level 使用 Set2 配色,4-6level 使用 Accent 配色。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容