ggplot2 中的动态中点 scale_fill_gradient2

Dynamic midpoint in ggplot2's scale_fill_gradient2

我正在使用 ggplot2 在 R 中制作热图,我想为 scale_fill_gradient2 动态更改 midpoint 的值。我希望每一行的中点是 v1v2.

的最大值

这是原始图和数据:

library(ggplot2)
set.seed(1L)

s = sprintf("d%s", 1:9)
vars = sprintf("v%s", 1:6)
data = data.frame(s = rep(s, 6), stringsAsFactors = FALSE)
data$variable = rep(vars, rep.int(9, 6))
data$variable = as.factor(data$variable)
data$value = round(runif(54, min=-100, max=100), 1)

pdf(save)
heatmap = ggplot(data = data, aes(x = variable, y = s, fill = value)) +
  geom_tile(color = "black", aes(width = 1)) +
  scale_fill_gradient2(low = cbbPalette$pink, high = cbbPalette$green, mid = cbbPalette$grey,
                       midpoint = 0, space = "Lab",
                       name = title) +
  scale_color_discrete("exps", data$variable) +
  theme_minimal() +
  theme(axis.text.x = element_text(vjust = 1,
                                   size = title.size), legend.title = element_blank(),
        axis.text.y = element_text(size = title.size),
        strip.text.x = element_text(size = title.size)) +
  coord_fixed()

#add numbers to cells
heatmap = heatmap + geom_text(aes(x = variable, y = s, label = value), color = cbbPalette$black, size = 3) +
  theme(
    axis.title.x = element_blank(),
    axis.title.y = element_blank(),
    panel.grid.major = element_blank(),
    panel.border = element_blank(),
    panel.background = element_blank(),
    axis.ticks = element_blank(),
    legend.justification = c(0.5, 0),
    legend.direction = "horizontal",
    legend.position = "top") + 
  guides(fill = guide_colorbar(barwidth = 7, barheight = 1,
                               title.position = "top", title.hjust = 0.5))
# Print the heatmap
print(heatmap)
dev.off()

我试图通过取 v1v2 的最大值来更改中点,但这会影响所有行而不是单独影响每一行。

scale_fill_gradient2(low = cbbPalette$pink, high = cbbPalette$green, mid = cbbPalette$grey,
                       midpoint = data[data$variable == "v1", "value"], space = "Lab",
                       name = title)

比例尺并不是这样工作的,因为它们将一系列值映射到一组颜色。因此,特定颜色意味着整个图的特定值。我最好的建议是通过减去 v1/v2 的最大值来预先规范化数据。请参阅下面代码中的示例(您的示例中有一些变量,但我替换的共享代码中没有)。

library(ggplot2)
library(tidyverse)

set.seed(1L)

s = sprintf("d%s", 1:9)
vars = sprintf("v%s", 1:6)
data = data.frame(s = rep(s, 6), stringsAsFactors = FALSE)
data$variable = rep(vars, rep.int(9, 6))
data$variable = as.factor(data$variable)
data$value = round(runif(54, min=-100, max=100), 1)

new_data <- data %>% group_by(s) %>%
  mutate(value = value - max(value[variable %in% c("v1", "v2")]))

ggplot(data = new_data, aes(x = variable, y = s, fill = value)) +
  geom_tile(color = "black", aes(width = 1)) +
  scale_fill_gradient2(low = "pink", high = "green", mid = "grey",
                       midpoint = 0, space = "Lab",
                       name = "title") +
  scale_color_discrete("exps", data$variable) +
  theme_minimal() +
  coord_fixed()