如何使用ggplot2

时间:2019-04-30 09:44:12

标签: r ggplot2

以下代码使用二维合并将钻石的price绘制为caratdepth的函数。

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()

plot 2

plot3

plot

1 个答案:

答案 0 :(得分:4)

使用layer_data()函数,我们可以获取在图层上计算的任何值,然后按需使用它。假设您的示例中已经包含了三个图; gp1gp2gp3

我们将十六进制转换之前的颜色值保存在新的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()

为我提供了以下内容:

enter image description here

或者,我们也可以将每个颜色通道绘制为一层,并使用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")

哪个给了我以下内容:

enter image description here

但是,请记住,添加图层的顺序将影响绘图的外观。以我为例,蓝色排在最后,因此所有其他值上都有蓝色光泽。

编辑:通过添加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()

enter image description here

但是您可以使用该方法问自己一个问题,您认为红色和绿色位之间的黄色位表示数据的准确性如何?另外,由于我们不再具有背景形状,因此无法再看到数据的范围。

请注意,并非每种导出方法都支持使用颜色的alpha值。

编辑:很遗憾,我不知道优美的图例解决方案,如果有人这样做,请告诉我!