假设我在 R
ggplot2
中创建了一个简单的热图。我需要对正空间和负空间使用某些预定义的颜色,其中 0 应该是白色,例如白色。是否可以绘制图块,使值根据正/负区域中相同的值范围采用颜色,但打印最终的颜色条仅显示值的实际范围?
This和this问题似乎相关,但他们关心的是在中点周围获得不对称的颜色条。
在左侧面板中,我有当前的颜色栏,在中间面板中,有预期的颜色栏,在右侧面板中,有链接问题的方法。在左侧面板中,值原则上是正确的,但打印了从 1.9 到 -1.9 的完整颜色条。右侧面板中的问题在于,它挤压了中点上方/下方范围内的完整颜色条,这意味着,例如,0.4 和 -0.4(左上角)具有不同的颜色。原则上colorbar的大小当然应该是一样的。
有没有一种方法可以理想地直接或间接(例如事后)实现这一目标?
这是对应的代码:
library(ggplot2)
df <- expand.grid(
x = c(1, 2, 3),
y = c(1, 2, 3),
g = c("one", "two")
)
one <- c(1.90, 1.40, 1.10, 0.90, 0.80, 0.50, 0.40, 0.30, 0.20)
two <- c(1.90, 1.40, 1.10, 0.90, 0.80, -0.50, -0.40, -0.30, -0.20)
df$v <- c(one, two)
min_value <- min(df$v)
max_value <- max(df$v)
min_label <- round(min_value, 2)
max_label <- round(max_value, 2)
midpoint = 0
ggplot(df, aes(x = x, y = y, fill = v)) +
facet_wrap(. ~ g, ncol = 2) +
geom_tile(color = "black") +
geom_text(aes(label = round(df$v, 2)), color = "red") +
scale_y_discrete(expand = c(0,0)) +
scale_x_discrete(expand = c(0,0)) +
scale_fill_gradientn(
colors = c(hcl.colors(5, "Inferno")[1:5], "white", hcl.colors(5, "Inferno")[5:1]),
#values=c(1, (midpoint-min_value)/(max_value-min_value), 0), # uncomment for right heatmap and comment limits
limits = c(-max_value, max_value),
breaks = c(min_value, max_value),
labels = c(min_label, max_label)
) +
guides(
fill = guide_colorbar(
barheight = unit(5, "cm"),
ticks.colour = "black",
ticks.linewidth = 0.5,
frame.colour = "black",
frame.linewidth = 0.5
))
实现所需结果的一个选项是将
abs(v)
映射到 fill
上,并使用适当的 values=
向量,我使用 scales::rescale
:
library(ggplot2)
ggplot(df, aes(x = x, y = y, fill = abs(v))) +
facet_wrap(. ~ g, ncol = 2) +
geom_tile(color = "black") +
geom_text(aes(label = round(v, 2)), color = "red") +
scale_y_discrete(expand = c(0, 0)) +
scale_x_discrete(expand = c(0, 0)) +
scale_fill_gradientn(
colors = c(hcl.colors(5, "Inferno")[1:5], "white", hcl.colors(5, "Inferno")[5:1]),
values = scales::rescale(
max_value * seq(-1, 1, length.out = 11),
from = c(min_value, max_value)
),
limits = c(min_value, max_value),
breaks = c(min_value, max_value),
labels = c(min_label, max_label)
) +
guides(
fill = guide_colorbar(
barheight = unit(5, "cm"),
ticks.colour = "black",
ticks.linewidth = 0.5,
frame.colour = "black",
frame.linewidth = 0.5
)
)