以下代码绘制了price作为2d binning carat和depth使用2d binning 的函数的菱形。
library(ggplot2)
data(diamonds)
gp <- ggplot(diamonds,aes(x=carat,y=depth,z=price))
gp <- gp +stat_summary_2d()
gp
Run Code Online (Sandbox Code Playgroud)
我现在想不仅代表价格,还代表另一个连续变量,例如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()
Run Code Online (Sandbox Code Playgroud)
利用该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)
Run Code Online (Sandbox Code Playgroud)
由于这些是计算的密度,因此最好先将它们重新缩放为[0,1]以内,然后再将它们转换为彩色六色表示法:
cols <- apply(cols, 2, scales::rescale)
cols <- rgb(cols[,1], cols[,2], cols[,3])
Run Code Online (Sandbox Code Playgroud)
现在,由于每个图之间的x和y数据相同,因此我们只需从其中一个图上获取xy坐标,然后将其与我们的新颜色组合即可:
newdata <- cbind(layer_data(gp1)[,c("x","y")], cols)
Run Code Online (Sandbox Code Playgroud)
因为我们的颜色已经是ggplot可以理解为颜色的格式,所以我们将使用scale_fill_identity()来绘制该颜色:
ggplot(newdata, aes(x, y, fill = cols)) +
geom_raster() +
scale_fill_identity()
Run Code Online (Sandbox Code Playgroud)
为我带来了以下内容:
另外,我们还可以将每个颜色通道绘制为一层并将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")
Run Code Online (Sandbox Code Playgroud)
这给了我以下几点:
但是,请记住,添加图层的顺序将影响绘图的外观。以我为例,蓝色排在最后,因此所有其他值上都有蓝色光泽。
编辑:可以通过添加大致删除光泽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()
Run Code Online (Sandbox Code Playgroud)
但是,您可以使用该方法问自己一个问题,您认为红色和绿色位之间的黄色位表示数据的准确性如何?另外,由于我们不再具有背景形状,因此我们无法再看到数据的范围。
请注意,并非每种导出方法都支持使用颜色的alpha值。
编辑:很遗憾,我不知道优美的图例解决方案,如果有人这样做,请告诉我!