【问题标题】:Color variation with geom_polygongeom_polygon 的颜色变化
【发布时间】:2016-04-06 08:33:20
【问题描述】:

我想创建一个绘图,其中线条之间的区域根据变量的因子填充。我希望多边形在行ya > yb 时为红色,在yb > ya 时为绿色。

xa <- c(1,2,3,4,5,6)
ya <- c(1,10,15,7,12,3)
xb <- c(1,2,3,4,5,6)
yb <- c(5,10,14,12,2,11)
toyset <- as.data.frame(cbind(xa, ya, xb, yb))
toyset$color<-ifelse(toyset$yb>ya,"green","red")

poly_df <- rbind(setNames(toyset[,c(1,2,5)],c('x','y','color')),
             setNames(toyset[6:1,3:5],c('x','y','color')))

这根本不起作用:

ggplot(toyset) + 
 geom_line(aes(xa, ya), colour="red") + 
 geom_line(aes(xb, yb), colour="green") +
 geom_polygon(data = poly_df,aes(x = x,y = y,fill=poly_df$color))

这里的多边形没问题,但没有不同的颜色(见图):

ggplot(toyset) + 
 geom_line(aes(xa, ya), colour="red") + 
 geom_line(aes(xb, yb), colour="green") +
 geom_polygon(data = poly_df,aes(x = x,y = y),fill=poly_df$color)

【问题讨论】:

  • 我猜你需要先定义五个多边形中每一个的坐标,并为每个多边形分配一个id和颜色,然后你可以使用geom_polygon(data = poly_df, aes(x = x,y = y, fill = id, colour = id))
  • 我不是已经通过创建 poly_df 做到了这一点吗?
  • 我不这么认为。您还需要包括两条线相交的点。
  • 那么只有它们相交的点并删除其他点?因为它们相交的点已经在那里了。
  • 不,它们不是,您需要这些来完成 poly_df。如果我没记错的话,您正在寻找五个多边形,每个多边形需要 3 个(第一个和最后一个)或 4 个(多边形 2,3 和 4)组 x 和 y 坐标。例如。第二个已经有坐标 (x=2, y=10), (x=3, y=15) 和 (x=3, y=14) 但缺少两条线相交的坐标,有些在 (x =3.2, y=13.8)。

标签: r ggplot2


【解决方案1】:

按照blog 中的示例,您可以进行如下操作。

我们使用初始玩具数据集(稍作调整)

x1 <- c(1, 2, 3, 4, 5, 6)
y1 <- c(1, 10, 15, 7, 12, 3)
y2 <- c(5, 10, 14, 12, 2, 11)
toyset <- as.data.frame(cbind(x1, y1, y2))

为了改变两条线交叉点的填充颜色,我们计算交点。

toyset$slope1 <- c(NA, with(toyset, diff(y1)/diff(x1)))
toyset$slope2 <- c(NA, with(toyset, diff(y2)/diff(x1)))
toyset$intcpt1 <- with(toyset, y1 - slope1 * x1)
toyset$intcpt2 <- with(toyset, y2 - slope2 * x1)
toyset$x2 <- with(toyset, (intcpt1 - intcpt2)/(slope2 - slope1))
toyset$y3 <- with(toyset, slope1 * x2 + intcpt1)
toyset <- toyset[, c(-4:-7)]

为确保计算正确,我们可以目视检查交叉点的位置:

ggplot(toyset) + geom_line(aes(x1, y1), colour = "red") +
  geom_line(aes(x1, y2), colour = "darkgreen") +
  geom_point(aes(x2, y3), colour = "darkblue", size = 3)

由于我们将使用geom_ribbon,因此交叉点也需要以geom_ribbon(x, ymin, ymax) 预期的形式呈现——y3 的简单副本即可完成此操作。

toyset$y4 <- toyset$y3

我们执行额外的错误检查并将每个数据点分配给适当的间隔。

toyset[which(toyset$x2 > toyset$x1), c("x2", "y3", "y4")] <- NA
toyset$segment <- findInterval(toyset$x1, 
                               c(min(toyset$x2, na.rm = TRUE), 
                                     toyset$x2[which(!is.na(toyset$x2))]))

为了让ggplot2 能够在每个线条交叉处改变填充颜色,它需要知道每个颜色区域的起点和终点。这意味着需要复制中间的交叉点,因为它们是两个相邻区域的一部分,填充了不同的颜色。

toyset$x3 <- c(tail(toyset$x2, -1), NA)
toyset$y5 <- c(tail(toyset$y3, -1), NA)
toyset$y6 <- toyset$y5

现在需要将两条线的坐标和彩色区域的起点/终点合并成一个长格式的data.frame。

toyset1 <- toyset[, c(1:3, 7)]
toyset2 <- toyset[!is.na(toyset$x2), c(4:6, 7)]
toyset3 <- toyset[!is.na(toyset$x3), c(8:10, 7)]

names(toyset2) <- names(toyset1)
names(toyset3) <- names(toyset1)

combo <- rbind(toyset1, toyset2)
combo <- rbind(combo, toyset3)
combo <- combo[is.finite(combo$y1), ]
combo <- combo[order(combo$x1), ]

我们现在可以相应地填充细分。

ggplot(combo, aes(x1, ymin = y1, ymax = y2))+ 
  geom_ribbon(aes(fill = factor(segment%%2)), alpha = 0.5) +
  geom_path(aes(y = y1), colour = "red", size = 1) + 
  geom_path(aes(y = y2), colour = "darkgreen", size = 1) +
  scale_fill_manual(values = c("red", "green"))

Segments filled

【讨论】:

  • 啊,是的,这似乎有效!谢谢!如果您也在这里发布完整答案,我可以将其标记为已回答。仅仅链接博客可能会导致信息随着时间的推移而丢失。
  • 对不起,我对 stackoverflow 还很陌生。不确定是否有更简单的方法来解决这个问题,但我希望我的完整答案能有所帮助!
猜你喜欢
  • 2017-09-01
  • 2018-04-03
  • 2013-08-15
  • 2017-07-17
  • 2016-08-14
  • 1970-01-01
  • 2013-11-26
  • 2011-04-12
  • 2013-03-30
相关资源
最近更新 更多