【问题标题】:plot points in front of lines for each group/ggplot2 equivalent of type="o"每个 group/ggplot2 等价于 type="o" 的线前的绘图点
【发布时间】:2017-03-23 17:52:36
【问题描述】:

假设我想绘制一个包含点和线的图形,其中点出现在在每组中对应的线的前面。特别是,我希望第 1 组用红色填充点绘制,这些点由一条线连接,但第 2 组用(仅)一条蓝线绘制,但我希望第 2 组绘制 组 1。例如,在基本图形中:

set.seed(101)
dd <- data.frame(x=rep(1:10,2),
         y=rep(1:10,2),
                 f=factor(rep(1:2,each=10)))
dd$y[11:20] <-     dd$y[11:20] + rnorm(10)
d1 <- subset(dd,f=="1")
d2 <- subset(dd,f=="2")

par(cex=1.5)
plot(y~x,data=d1,bg="red",pch=21,type="o")
lines(y~x,data=d2,col="blue",lwd=2)
legend("bottomright",c("group 1","group 2"),
       col=c("black","blue"),
       pch=c(21,NA),
       pt.bg=c("red",NA),
       lty=1,
       lwd=c(1,2))

(我的真实数据稍微复杂一些。)我有点疯狂地试图在ggplot2 中干净利落地做这件事。

如果我在线条之前画点,第 1 组的点会被同一组中的线条覆盖:

 library(ggplot2); theme_set(theme_bw())
 g0 <- ggplot(dd,aes(x,y,fill=f,colour=f,shape=f))+
     scale_fill_manual(values=c("red",NA))+
     scale_colour_manual(values=c("black","blue")) +
     scale_shape_manual(values=c(21,NA))
 g0 + geom_point()+  geom_line()
 ggsave("order2.png",width=3,height=3)

如果我在点之前画线,第 2 组的线会被第 1 组的点覆盖:

 g0 + geom_line()+  geom_point()
 ggsave("order3.png",width=3,height=3)

所需的顺序是(第 1 组线)、(第 1 组点)、(第 2 组线)。我可以通过手动再次覆盖geoms来做到这一点,一次一组,但这是方式丑陋的。

 g0 +  geom_line() + geom_point()+ 
     geom_point(data=d1)+
     geom_line(data=d2,show.legend=FALSE)
 ggsave("order4.png",width=3,height=3)

我认为“最好的”解决方案是编写一个低级的geom_linepoint,它可以按需要工作;我对此进行了一些研究,它是not entirely trivial ...有人可以提出更清洁、更简单的解决方案吗?

【问题讨论】:

  • 自定义 geom 似乎并不太难,因为您将回收现有组件并将它们简单地包装在一个新容器中。另一方面,与任何 ggplot2 hack 一样,您可能会冒着它在未来不经通知的情况下中断的风险。
  • 我认为它(1)会比你想象的更难一些,(2)会比你想象的更脆弱,因为现在有一个官方描述的创建新几何的机制(在我的问题中链接)。我开始研究geom_linepoint()(这是我一直想要的东西,但意识到geom_path(黑客/扩展的适当基础几何)比我可以快速解决的要复杂一些(例如,期望
  • 你可能是对的,我对大多数人有不同的看法。我在 2009 年写了一些自定义几何图形,其中之一是模仿 type = 'b',当时有一个 ggExtra 包用于附加组件,写了一个 wiki 页面来描述这个过程,等等。所以我觉得每个人似乎都突然变得令人费解认为扩展 ggplot2 并以某种方式对内部更改更加健壮是一回事。这些年来,我已经看到我贡献的 100 件事情被打破了,这让我对引入定制解决方案更加厌烦和谨慎。
  • 很公平......现在看来扩展更“有福”了(并且被 ggplot2 开发人员鼓吹),但这当然不是保证。
  • 您现在删除的解决方案出了什么问题...?

标签: r plot ggplot2


【解决方案1】:

这是一个“低技术”1 解决方案。下面是一个函数,它为给定分组变量的每个级别依次添加线层和点层。

linepoint = function(data, group.var, lsize=1.2, psize=4) {
  lapply(split(data, data[,group.var]), function(dg) {
    list(geom_line(data=dg, size=lsize),
         geom_point(data=dg, size=psize)) 
  })
}

ggplot(dd, aes(x,y, fill=f, colour=f,shape=f))+
  scale_fill_manual(values=c("red",NA))+
  scale_colour_manual(values=c("black","blue")) +
  scale_shape_manual(values=c(21,NA)) +
  linepoint(dd, "f")


1 与编写新的几何图形相比,“技术含量低”。 @baptiste(现已删除)的回答确实创建了一个新的 geom 并且似乎完成了工作,所以我不确定他为什么删除它。

【讨论】:

    猜你喜欢
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-06
    • 2011-09-25
    • 2017-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多