以下代码使用二维合并将钻石的price
绘制为carat
和depth
的函数。
library(ggplot2)
data(diamonds)
gp <- ggplot(diamonds,aes(x=carat,y=depth,z=price))
gp <- gp +stat_summary_2d()
gp
我现在不仅要代表价格,还要代表另一个x
连续变量作为不同的颜色通道。因此,蓝色的强度会给我price
,红色的强度会给我x
(还有可能在绿色通道中编码的第三个变量)。
实现此目标的最佳方法是什么?我是否必须手动对数据进行分类,计算汇总并绘制结果栅格,还是有一种更快的方法?
或者是否可以使用z
值在三个不同的图上执行此操作,然后通过将每个图分配给不同的颜色通道来合并它们?
更新 对于更明确的示例,以下代码生成三个图(请参见下文)。我想将它们合并为一个图,每个图与一个颜色通道相关联,这样我在一个图中可以有一个红色斑点,一个绿色斑点和一个蓝色博客。
library(ggplot2)
n <- 10000
cx <- c(-1, 0, 1)
cy <- c(0,1,-1)
x <- rnorm(n,0,1)
y <- rnorm(n,0,1)
v <- list()
v <- lapply(seq(3),function(i)dnorm(x,cx[i],0.5)*dnorm(y,cy[i],0.5))
data <- data.frame(x,y,v1=v[[1]]/max(v[[1]]),v2=v[[2]/max(v[[2]]), v3=v[[3]]/max(v[[3]]))
gp1 <- ggplot(data, aes(x=x,y=y,z=v1)) + stat_summary_2d() + scale_colour_identity()
gp2 <- ggplot(data, aes(x=x,y=y,z=v2)) + stat_summary_2d() + scale_colour_identity()
gp3 <- ggplot(data, aes(x=x,y=y,z=v3)) + stat_summary_2d()+ scale_colour_identity()
答案 0 :(得分:4)
使用layer_data()
函数,我们可以获取在图层上计算的任何值,然后按需使用它。假设您的示例中已经包含了三个图; gp1
,gp2
和gp3
。
我们将十六进制转换之前的颜色值保存在新的data.frame中:
cols <- data.frame(r = layer_data(gp1)$value,
g = layer_data(gp2)$value,
b = layer_data(gp3)$value)
由于这些是计算的密度,因此最好先将其缩放为[0,1]以内,然后再将其转换为彩色六色表示法:
cols <- apply(cols, 2, scales::rescale)
cols <- rgb(cols[,1], cols[,2], cols[,3])
现在,由于每个图之间的x和y数据都相同,因此我们只需从其中一个图上获取x-y坐标,然后将其与我们的新颜色组合即可:
newdata <- cbind(layer_data(gp1)[,c("x","y")], cols)
由于我们的颜色已经是ggplot可以理解为颜色的格式,因此我们将使用scale_fill_identity()
进行绘制:
ggplot(newdata, aes(x, y, fill = cols)) +
geom_raster() +
scale_fill_identity()
为我提供了以下内容:
或者,我们也可以将每个颜色通道绘制为一层,并使用alpha
进行混合:
cols <- data.frame(r = layer_data(gp1)$value,
g = layer_data(gp2)$value,
b = layer_data(gp3)$value)
newdata <- cbind(layer_data(gp1)[,c("x","y")], cols)
ggplot(newdata, aes(x, y)) +
geom_raster(aes(alpha = r), fill = "red") +
geom_raster(aes(alpha = g), fill = "green") +
geom_raster(aes(alpha = b), fill = "blue")
哪个给了我以下内容:
但是,请记住,添加图层的顺序将影响绘图的外观。以我为例,蓝色排在最后,因此所有其他值上都有蓝色光泽。
编辑:通过添加scale_alpha_continuous(range = c(0,1))
可以大大消除光泽。生成的图看起来很像下一个方法,但是没有将红色和绿色混合为明亮的黄色,我认为这是更现实的。但是,无法再估计数据的范围! (结束编辑)
另一种避免主要颜色光泽的alpha策略的方法是将rgb值映射到hsv空间,保持'v'恒定并将alpha设置为行总和:
cols <- data.frame(r = layer_data(gp1)$value,
g = layer_data(gp2)$value,
b = layer_data(gp3)$value)
cols <- apply(cols, 2, scales::rescale)
hsv <- t(rgb2hsv(cols[,1], cols[,2], cols[,3]))
hsv <- hsv(h = hsv[,1], s = hsv[,2], v = 1, alpha = scales::rescale(rowMeans(cols)))
newdata <- cbind(layer_data(gp1)[,c("x","y")], hsv)
ggplot(newdata, aes(x, y, fill = hsv)) +
geom_raster() +
scale_fill_identity()
但是您可以使用该方法问自己一个问题,您认为红色和绿色位之间的黄色位表示数据的准确性如何?另外,由于我们不再具有背景形状,因此无法再看到数据的范围。
请注意,并非每种导出方法都支持使用颜色的alpha值。
编辑:很遗憾,我不知道优美的图例解决方案,如果有人这样做,请告诉我!