在 geom_tile() / geom_raster() 中标记特定的瓷砖

12
假设我有一个像这样的数据框:
molten <- data.frame(
  Var1 = factor(
    rep(c("A", "B", "C", "D"), 5),
    levels = c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J")
  ),
  Var2 = rep(6:10, each = 4L),
  value = c(
    -0.468920099229389, 0.996105987531978, -0.527496444770932, -0.767851702991822,
    -0.36077954422072, -0.145335912847538, 0.114951323188032, 0.644232124274217,
    0.971443502096584, 0.774515290180507, -0.436252398260595, -0.111174676975868,
    1.16095688943808, 0.44677656465583, -0.708779168274131, 0.460296447139761,
    -0.475304748445917, -0.481548436194392, -1.66560630161765, -2.06055347675196
  ),
  na = rep(c(FALSE, TRUE, FALSE, TRUE, FALSE), c(8L, 1L, 7L, 1L, 3L)),
  row.names = c(
    51L, 52L, 53L, 54L, 61L, 62L, 63L, 64L, 71L, 72L, 73L, 74L,
    81L, 82L, 83L, 84L, 91L, 92L, 93L, 94L
  )
)

head(molten)

  Var1 Var2      value    na
1    A    1 -0.2413015 FALSE
2    B    1  1.5077282 FALSE
3    C    1 -1.0798806 TRUE
4    D    1  2.0723791 FALSE

现在,我想使用ggplot绘制一个瓷砖(或光栅)图,并标记那些具有na=TRUE的瓷砖。目前,我将这些标记绘制为点:

g <- ggplot( molten ) +
  geom_raster( aes( x = Var1, y = Var2, fill = value )  ) + 
  scale_fill_gradient2( low = "blue", high = "red", na.value="black", name = "" ) +
  geom_point( aes( x = Var1, y = Var2, size= as.numeric(na) ) )

tiles with points

然而,我不太喜欢这个图的两个原因:

  1. 即使 molten$na = FALSE,仍然会绘制一个点。当然,我可以指定 data=molten[ molten$na, ],但实际上应该可以在不指定另一个数据集的情况下实现。
  2. 我不喜欢这些点,而是更愿意在瓷砖周围或中间有边框或条纹。但是我不知道如何实现这一点。如果我要使用 geom_segment() 来创建条纹,我应该如何指定 yendxend

但实际上,这应该是可以在不指定另一个数据集的情况下实现的。为什么?为不同层指定单独的数据集是 ggplot 的一个重要特性,也正是您想要做的事情(至少对于(1)而言)的正确方式。 - joran
那么使用 size = ifelse(na, 1, NA) 而不是 size = as.numeric(na) 怎么样? - bdemarest
@bdemarest 因为它根本不起作用:geom_point(aes(x=Var1, y=Var2, size=ifelse(na, 1, NA))) 在每个瓷砖中都会给我一个点。 - Beasterfield
@joran 如果你说这就是它应该的工作方式,那很好,我只是希望能在不进行子集操作的情况下使其工作,并且认为我可能错过了什么。 - Beasterfield
@Beasterfield:抱歉!我没有测试过它。如果您能让您的示例可重现,我很乐意尝试其他几个方法。也许您可以给我们dput(subset(molten, Var2 > 5 & Var1 %in% c("A", "B", "C", "D")))的输出? - bdemarest
@bdemarest 我以为我的示例是可以复制的而不需要使用 dput。无论如何,请看我的编辑。 - Beasterfield
2个回答

18

以下是两种可能的方法:

在示例1中,我使用了 ifelsescale_size_manual 来控制是否在每个单元格中绘制点。

在示例2中,我创建了一个小辅助数据框,并使用 geom_rect 绘制矩形代替点。为方便起见,我将Var2转换为因子(factor)。在ggplot2中,每个离散/因子轴上的步长为1.0,这使得可以轻松计算geom_rect的值。

# Using ggplot2 version 0.9.2.1
library(ggplot2)

# Test dataset from original post has been assigned to 'molten'.

molten$Var2 = factor(molten$Var2)

# Example 1.
p1 = ggplot(data=molten, aes(x=Var1, y=Var2, fill=value)) +
     geom_raster() +
     scale_fill_gradient2(low="blue", high="red", na.value="black", name="") +
     geom_point(aes(size=ifelse(na, "dot", "no_dot"))) +
     scale_size_manual(values=c(dot=6, no_dot=NA), guide="none") +
     labs(title="Example 1")

ggsave(plot=p1, filename="plot_1.png", height=3, width=3.5) 

输入图片说明

# Example 2.
# Create auxiliary data.frame.
frames = molten[molten$na, c("Var1", "Var2")]
frames$Var1 = as.integer(frames$Var1)
frames$Var2 = as.integer(frames$Var2)

p2 = ggplot(data=molten) +
     geom_raster(aes(x=Var1, y=Var2, fill=value)) +
     scale_fill_gradient2(low="blue", high="red", na.value="black", name="") +
     geom_rect(data=frames, size=1, fill=NA, colour="black",
       aes(xmin=Var1 - 0.5, xmax=Var1 + 0.5, ymin=Var2 - 0.5, ymax=Var2 + 0.5)) +
     labs(title="Example 2")

ggsave(plot=p2, filename="plot_2.png", height=3, width=3.5) 

输入图像描述


第二个答案是我实际上正在寻找的,它应该可以与 geom_segement() 一起用于条纹。谢谢你。不幸的是,这个解决方案对我不起作用,因为列组被 facet_wrap( ..., scale= "free_x" ) 分面了。无论如何,问题没有详细说明,所以我接受你的答案。 - Beasterfield
@Beasterfield 你如何将点的颜色改为除黑色以外的其他颜色? - user2300940

6

正如评论中@joran所建议的那样,您可以将数据子集传递给特定层。

使用您的示例数据

g <- ggplot( molten ) +
  geom_raster( aes( x = Var1, y = Var2, fill = value )  ) + 
  scale_fill_gradient2( low = "blue", high = "red", na.value="black", name = "" ) +
  geom_point(data = molten[molten$na,], aes( x = Var1, y = Var2, size= as.numeric(na) ) )


g

enter image description here

如果您希望图例说明点的含义

在这种情况下,您可以使用“legend.title”选项来为图例添加标题。例如:

 g <- ggplot( molten ) +
  geom_raster( aes( x = Var1, y = Var2, fill = value )  ) + 
  scale_fill_gradient2( low = "blue", high = "red", na.value="black", name = "" ) +
  geom_point(data = molten[molten$na,], aes( x = Var1, y = Var2, colour = 'black' )) +
  scale_colour_manual(name = 'Ooh look', values = 'black', labels = 'Something cool')

enter image description here


3
对于“Ooh look”这个例子点赞。 - Shadow
@mnel,您如何将点的颜色更改为除黑色以外的其他颜色? - user2300940

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接