问题
I have a relatively simple heatmap using geom_tile
in ggplot2. It's just a small matrix of continuous data as colored boxes (df1
) and I'd like to overlay a second, logical geom_tile that outlines the TRUE
values (df2
). Can such a thing be done? I know that adding two heatmaps together seems like it would be ugly but these are small and pretty simple affairs.
library(ggplot2)
n <- 4
df1 <- data.frame(x = rep(letters[1:n], times = n),
y = rep(1:n, each = n),
z = rnorm(n ^ 2))
df2 <- data.frame(x = rep(letters[1:n], times = n),
y = rep(1:n, each = n),
z = FALSE)
df2$z[c(2,14)] <- TRUE
p1 <- ggplot(df1, aes(x = x, y = y))
p1 <- p1 + geom_tile(aes(fill = z), colour = "grey20")
p1 <- p1 + scale_fill_gradient2(low = "darkgreen",
mid = "white",
high = "darkred",
breaks = c(min(df1$z), max(df1$z)),
labels = c("Low", "High"))
p1
# overlay df2 to outline the TRUE boxes or dim the FALSE boxes with alpha?
# p1 <- p1 + geom_tile(data = df2, aes(fill = z), colour = "grey20")
回答1:
Just merge the two datasets into one so you can map the first z-value to fill, and the other to alpha:
ggplot(merge(df1, df2, by = c('x', 'y')), aes(x = x, y = y)) +
geom_tile(aes(fill = z.x, alpha = z.y), colour = "grey20") +
scale_fill_gradient2(low = "darkgreen",
mid = "white",
high = "darkred",
breaks = c(min(df1$z), max(df1$z)),
labels = c("Low", "High"))
You could use stroke color instead of alpha, but strokes get partially covered by geom_tile
:
ggplot(merge(df1, df2, by = c('x', 'y')), aes(x = x, y = y)) +
geom_tile(aes(fill = z.x, colour = z.y), size = 2) +
scale_fill_gradient2(low = "darkgreen",
mid = "white",
high = "darkred",
breaks = c(min(df1$z), max(df1$z)),
labels = c("Low", "High")) +
scale_color_manual(values = c('#00000000', 'blue'))
so to get it to plot properly, you'll have to hack it through with one layer for fills, then one layer for outlines with clear fill:
ggplot(merge(df1, df2, by = c('x', 'y')), aes(x = x, y = y)) +
geom_raster(aes(fill = z.x)) +
geom_tile(aes(colour = z.y), fill = '#00000000', size = 2) +
scale_fill_gradient2(low = "darkgreen",
mid = "white",
high = "darkred",
breaks = c(min(df1$z), max(df1$z)),
labels = c("Low", "High")) +
scale_color_manual(values = c('#00000000', 'blue'))
回答2:
I had a similar approach to @JasonWang but I went with setting both colour and size of the border.
p1 + geom_tile(data=df2, aes(colour=factor(z, c(TRUE, FALSE)), size=factor(z, c(TRUE, FALSE))), alpha=0) +
scale_colour_manual("z", values=c("blue4", "white")) +
scale_size_manual("z", values=c(3, 0))
来源:https://stackoverflow.com/questions/42641106/add-a-second-geom-tile-layer-in-ggplot