【问题标题】:Overlay two ggplot2 stat_density2d plots with alpha channels用 alpha 通道覆盖两个 ggplot2 stat_density2d 图
【发布时间】:2014-07-27 13:02:35
【问题描述】:

我想用 alpha 通道覆盖两个 ggplot2 图,以使生成的图像显示两个数据集。这是我的测试数据:

data = read.table(text="P1 -1 0 4\nP2 0 0 2\nP3 2 1 8\nP4 -2 -2 6\nP5 0.5 2 12")
data2 = read.table(text="Q1 1 1 3\nQ2 1 -1 2\nQ3 -1 1 8")
colnames(data) = c("name","x","y","score")
colnames(data2) = c("name","x","y","score")

这是我绘制这些数据的方式:

ggplot(data, aes(x=x,y=y)) + 
  stat_density2d(data=data,geom="tile", aes(fill = ..density..,alpha=..density..), contour=FALSE) + 
  theme(legend.position="none") + scale_fill_gradient (low = "#FFFFFF", high = "#FF0000") + 
  xlim(-3,3) + ylim(-3,3) + 
  geom_point()

ggplot(data2, aes(x=x,y=y)) + 
  stat_density2d(data=data2,geom="tile", aes(fill = ..density..,alpha=..density..), contour=FALSE) + 
  theme(legend.position="none") + 
  scale_fill_gradient (low = "#FFFFFF", high = "#00FF00") + 
  xlim(-3,3) + ylim(-3,3) + 
  geom_point()

第一个图显示data,第二个图data2

我现在想要两个情节的组合。下图是我想要得到的。我使用桌面上的图像编辑程序通过将两个图像作为图层相乘来生成它。

我尝试将一个数据集绘制在另一个数据集之上,但这不会将两个图层相乘,并且第二种颜色会覆盖第一个。

ggplot(data, aes(x=x,y=y)) + 
  stat_density2d(data=data,geom="tile", aes(fill = ..density..,alpha=..density..), contour=FALSE) + 
  theme(legend.position="none") + scale_fill_gradient (low = "#FFFFFF", high = "#FF0000") + 
  xlim(-3,3) + ylim(-3,3) + 
  stat_density2d(data=data2,geom="tile", aes(fill = ..density..,alpha=..density..), contour=FALSE) + 
  scale_fill_gradient (low = "#FFFFFF", high = "#00FF00")

此外,我收到此警告:“填充”的比例已存在。为“填充”添加另一个比例,它将替换现有比例。

有没有办法在 R 中做到这一点?还是有另一种方法(使用其他功能,例如smoothScatter)来获得这个或类似的结果?作为一种解决方法,我想我会在服务器上使用 ImageMagick 获得类似的结果,但我更愿意在 R 中完成所有操作。

更新 1

ImageMagick 中两层的乘法是这样完成的;

composite -compose multiply data-red.png data-green.png im-multiply.png

这给出了与上面相同的结果。

更新 2

@Roland 在他的回答中教我如何在同一个图中绘制两个数据集。虽然这很好,但仍然存在一个问题:图像取决于您将数据提供给绘图的顺序。

ggplot(rbind(data.frame(data, group="a"), data.frame(data2, group="b")), aes(x=x,y=y)) + 
  stat_density2d(geom="tile", aes(fill = group, alpha=..density..), contour=FALSE) + 
  scale_fill_manual(values=c("a"="#FF0000", "b"="#00FF00")) + 
  geom_point() + 
  theme_minimal() + 
  xlim(-3.3, 3.3) + ylim(-3.3, 3.3) +
  coord_cartesian(xlim = c(-3.2, 3.2), ylim = c(-3.2, 3.2))

给出这个结果:

当交换两个数据集的顺序时(现在数据集“b”又名 data2 首先出现,然后是数据集 data 又名“a”),你会得到类似的结果,但现在红色占主导地位,因为它是稍后绘制的,因此会覆盖绿色数据。

ggplot(rbind(data.frame(data2, group="a"), data.frame(data, group="b")), aes(x=x,y=y)) + 
  stat_density2d(geom="tile", aes(fill = group, alpha=..density..), contour=FALSE) + 
  scale_fill_manual(values=c("b"="#FF0000", "a"="#00FF00")) +
  geom_point() + theme_minimal() + 
  xlim(-3.3, 3.3) + ylim(-3.3, 3.3) + 
  coord_cartesian(xlim = c(-3.2, 3.2), ylim = c(-3.2, 3.2))

我需要一个不依赖于数据集顺序的解决方案。

【问题讨论】:

标签: r plot ggplot2


【解决方案1】:

您应该以相同的比例绘制两种密度:

ggplot(rbind(data.frame(data, group="a"), data.frame(data2, group="b")), 
       aes(x=x,y=y)) + 
  stat_density2d(geom="tile", aes(fill = group, alpha=..density..), 
                 contour=FALSE) + 
  scale_fill_manual(values=c("a"="#FF0000", "b"="#00FF00")) +
  geom_point() +
  theme_minimal() +
  xlim(-3.3, 3.3) + ylim(-3.3, 3.3) +
  coord_cartesian(xlim = c(-3.2, 3.2), ylim = c(-3.2, 3.2))

否则,您会显示扭曲的数据图片。

【讨论】:

  • 这是对我尝试的巨大改进。谢谢你。这两层是否有机会相乘?使用您的代码,后一个数据集在视觉上占主导地位,因此绿色比红色更亮。如果我交换 datadata2,红色会变亮。
  • a 组的局部密度最大值高于 b 组。情节确实反映了这一点。我不知道你所说的“倍增”是什么意思。
  • 但是当a组的最大值(用红色绘制)更高时,为什么绿色(b组)更亮?如果您在代码中更改 datadata2rbind(data.frame(data2, group="a"), data.frame(data, group="b")values=c("b"="#FF0000", "a"="#00FF00") - 那么红色比绿色更亮。通过“相乘”,我指的是图像编辑中两层的混合模式。这种模式是对称的,所以执行顺序无关紧要。
  • 对不起,我在写作时把它弄混了。 b组的最大值更高。
  • 为什么b组的最大值应该更高?事实上,您的解决方案取决于您将数据提供给ggplot 的顺序。稍后打印的数据会覆盖前者。
【解决方案2】:

这里的解决方案与@Roland 完全相同,只是我建议使用 conttour line。这使您可以欣赏重叠。 我看不出 geom_tile 和您对“乘法”的想法如何让您欣赏这一点。也许如果您将蓝色和红色用于非重叠区域,并将“加权”紫色用于重叠区域。但我猜你必须在绘制之前在上一步中计算它。

ggplot(rbind(data.frame(data, group="a"), data.frame(data2, group="b")), 
       aes(x=x,y=y)) + 
  stat_density2d(geom="density2d", aes(color = group,alpha=..level..),
                 size=2,
                 contour=TRUE) + 
  #scale_color_manual(values=c("a"="#FF0000", "b"="#00FF00")) +
  geom_point() +
  theme_minimal() +
  xlim(-3.3, 3.3) + ylim(-3.3, 3.3) +
  coord_cartesian(xlim = c(-3.2, 3.2), ylim = c(-3.2, 3.2))

【讨论】:

  • 我猜你的意思是scale_color_manual而不是scale_fill_manual
  • @WilliamZhang 。是的,谢谢。 Actullay 我复制/粘贴了 Roland 的解决方案并做了最小的更改。我现在更正我的帖子。
  • 谢谢,这是一种有趣的视觉方法。虽然它适用于我展示的测试数据,但我不确定这是否适用于我的真实数据。尽管如此 +1。
猜你喜欢
  • 2015-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多