如何为R中专门定义的连续间隔定义自定义色带(ggplot)

jc3wubiy  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(68)

我试图创建一个图,在其中我可以自定义颜色渐变,使其在特定阈值下具有精确的颜色,并且我想定义阈值之间的颜色过渡/渐变。
例如,假设我想在Map上绘制一种疾病的流行率,

  • 上一页= 0 -->黑色
  • 0 <= prev < 1 -->从黑色到紫色的快速过渡,紫色介于两者之间,然后从紫色快速过渡到深蓝色。
  • 1 <= prev < 10 -->从深蓝色到蓝色的快速过渡,蓝色介于两者之间,然后从蓝色到绿色的快速过渡。
  • 10 <= prev < 50 -->从绿色快速过渡到黄色,黄色过渡到介于两者之间的橙子,然后从橙子快速过渡到红色。
  • prev >= 50 -->从红色到暗红色的过渡。

我的解决方案是定义一个长度为101的颜色rap,并定义每个间隔以近似所需的颜色值。
下面是我的方法。有人能提出更好的方法吗?

library(tidyverse)
library(terra) # map.pal
library(grid)
library(scales)
library(viridis) 
library(RColorBrewer)

ggplot(
  data = 
    tibble(
      x = seq(0,1, length.out = 500),
      y = 0
    ),
  mapping = aes(x = x, y = y, color = x)
) +
  geom_line(linewidth = 150) +
  scale_color_gradientn(
    colours = 
      c(
        "black", "#22002A",                                   # 0 to 1
        colorRampPalette(map.pal("viridis")[c(1, 8)])(5),     # 1 to 6
        colorRampPalette(c(map.pal("viridis")[c(9, 18)]))(2), # 6 to 8
        colorRampPalette(c(map.pal("viridis")[c(19, 48)]))(2),# 8 to 10
        colorRampPalette(
          c(map.pal("viridis")[49], 
            map.pal("haxby")[37], 
            "darkorange", 
            "red"))(55),                                      # 10 to 50
        colorRampPalette(c("red", "darkred"))(32),            # 50 to 99
        rep("white", 1)                                       # 100
      ),
    limits = c(0,1),
    breaks = c(0.1,  0.5),
    labels = c(0.1,  0.5),
    name = "Prevalence"
  ) +
  geom_vline(xintercept = 0.01) +
  geom_vline(xintercept = 0.1) +
  geom_vline(xintercept = 0.5) +
  theme(
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.title.y = element_blank()
  ) +
  ylim(c(-0.012, 0.012))

字符串
正如你在下面看到的,我很接近了,但是(1)不准确,(2)这个过程非常繁琐。
x1c 0d1x的数据
如果可以的话,请分享替代的、更准确的方法。

b09cbbtk

b09cbbtk1#

你让这个过程变得比实际需要的更复杂。你不需要使用scale_gradientn来创建色带-它已经创建了一个色带。你所需要做的就是根据你的规范指定颜色和你希望它们改变的值:

library(ggplot2)
library(scales)

cols <- c("black", "#22002A", "#443882", "#2F5B8E", 
  "#2D708E", "#3D8090", "#1F905B", "#E3E418", "darkorange2", "red", 
  "darkred", "white")

transitions <- c(0, 0.1, 0.9, 1.1, 2, 9, 10, 11, 49, 51, 99.9, 100)

字符串
唯一的复杂之处是你需要将transitions扩展到c(0, 1)范围:

scaled_transitions <- rescale(transitions, from = c(0, 100), to = c(0, 1))


现在您有了一个色标,通过使用colorsvalues参数,它可以根据需要Map到0-100范围内

ggplot(data.frame(x = seq(0, 100, length.out = 500)), aes(x, 0, fill = x)) +
  geom_raster(interpolate = TRUE) +
  scale_fill_gradientn(colors = cols, values = scaled_transitions) +
  geom_vline(xintercept = c(1, 10, 50), linewidth = 0.3)


x1c 0d1x的数据
如果您希望颜色之间有更多或更少的突然变化,可以调整上述代码中过渡的值。
我们可以看到这在类似于Map的设置中是什么样子的。我们希望平滑变化的场最终看起来像一个等高线图:

set.seed(1)
m <- MASS::kde2d(x = runif(5), runif(5), n = 500, lims = c(-.5, 1.5, -.5, 1.5))
df <- expand.grid(x = m$x, y = m$y)
df$z <- rescale(as.vector(m$z), from = range(m$z), to = c(0, 99))

ggplot(df, aes(x, y, fill = z)) +
  geom_raster() +
  scale_fill_gradientn(colors = cols, values = scaled_transitions,
                       limits = c(0, 100)) +
  coord_equal(expand = FALSE) +
  theme_bw(base_size = 20)


相关问题