R:从数值中获取十六进制颜色 - 如何在渐变比例中定义中点

R: getting hex colors from numeric values - how to define midpoint in gradient scale

我有一个数字向量,我想将它转换为十六进制颜色代码。颜色应遵循从可能的最小值(红色;0)到我定义的中间值(均值,黑色)到可能的最大值(绿色;1)的梯度分布。

对于 ggplot,我会使用 scale_*_gradientn 函数。但现在我需要实际的十六进制值,而且我正在努力计算它们。

library(tidyverse)
#> Warning: package 'dplyr' was built under R version 3.6.2

data <- data.frame("a"=runif(100),
                   "b"=runif(100))


# ggplot example ----------------------------------------------------------

data <- data.frame("a"=runif(100),
                   "b"=runif(100))

mean_a <- mean(data$a)

ggplot(data)+
  geom_point(aes(x=a,
                 y=b,
                 color=a),
             stat="identity")+
  scale_color_gradientn(colors=c("red","black","green"),
                        values=c(0, mean_a, 1))+
  theme(legend.position = NULL)

映射 scale_color_gradientn 函数显然不是前进的方向:

data %>% 
  mutate(color_values=map(a, scale_color_gradientn, 
                          colors=c("red","black","green"),
                          values=c(0, mean_a, 1))) %>% 
  head()
#>           a         b                      color_values
#> 1 0.2863037 0.9902960 <environment: 0x000000001d002f30>
#> 2 0.6169960 0.9527580 <environment: 0x000000001d038798>
#> 3 0.3126825 0.8807853 <environment: 0x000000001d06e098>
#> 4 0.5464037 0.2307841 <environment: 0x000000001d0a39a8>
#> 5 0.5162976 0.8147066 <environment: 0x000000001d0d92a8>
#> 6 0.7519632 0.6821084 <environment: 0x000000001d10cc98>

reprex package (v0.3.0)

于 2020 年 2 月 17 日创建

我在 colorRamp 函数上遇到了这个 SO entry,但是,它似乎没有提供任何定义手动 'mid' 点的选项。

我也在 colorspace 包上看到了这个 ,它允许定义中点。但是,我再次未能在 ggplot 之外应用它。

感谢任何提示!

您可以在 ggplot 中获取遵循 colorbar 梯度的十六进制值,如下所示:

gg_build()解法

    set.seed(1)
    data <- data.frame("a"=runif(100),"b"=runif(100))

    mean_a <- mean(data$a)

    p1 <- ggplot(data)+
      geom_point(aes(x=a,
        y=b,
        color=a),
        stat="identity")+
      scale_color_gradientn(
        colors=c("red","black","green"),
        values=c(0, mean_a, 1))+
      theme(legend.position = NULL)

    # get plot build
    build <- ggplot_build(p1)

    # select hex value and x-value data
    hex_df <- build$data[[1]][, c("colour", "x")]

    # order hex value data to follow x-axis
    hex_df_ordered <- hex_df[order(hex_df$x),]

比例尺::gradient_n_pal() 解决方案

这可能是您想要使用 scales 包函数 gradient_n_pal 的方法,它由 scale_color_gradientn:

调用
    library(ggplot2)
    library(scales)
    library(ggpubr)

    # create data
    set.seed(1)
    data <- data.frame("a"=runif(100), "b"=runif(100))
    #get mean_a
    mean_a <- mean(data$a)
    # order the data by a
    data <- data[order(data$a),]
    # encode the values in a character variable for reference
    data$a_char <- as.character(data$a)

    # use the scales::gradient_n_pal to create a palette function
    pal <- scales::gradient_n_pal(colours = c("red","black","green"),
      values= c(0, mean_a, 1))
    # use data in a to generate palette-generated values in the data
    data$hex_from_scales <- pal(data$a)

    # plot with scale_color_gradientn
    p1 <- ggplot(data)+
      geom_point(aes(x=a,
        y=b,
        color=a),
        stat="identity", show.legend = F)+
      scale_color_gradientn(colors=c("red","black","green"),values=c(0, mean_a, 1))+
      ggtitle("Using scale_color_gradientn ")+
      theme(legend.position = NULL)

    # plot with scale_color_manual and gradient_n_pal generated hex values
    p2 <- ggplot(data)+
      geom_point(aes(x=a,
        y=b,
        color=a_char),
        stat="identity", show.legend = F)+
      scale_color_manual(values = data$hex_from_scales)+
      ggtitle("Using gradient_n_pal")+
      theme(legend.position = NULL)

    plots <- ggpubr::ggarrange(p1, p2, ncol = 2)

此代码生成这些图:

结论

从两个图的相似性来看,您似乎可以使用以下代码片段获取数值向量的十六进制值:

        # create a palette function
        pal <- scales::gradient_n_pal(colours = c("red","black","green"),values= c(0, mean_a, 1))
        # get palette-generated values from your vector
        data$hex_from_scales <- pal(data$a)

同样值得注意的是,此解决方案生成 与上面提出的 ggplot_build() 解决方案略有 不同的十六进制代码。我的眼睛告诉我差异很小。眼见为实!