position_dodgev按geom_line中的连接点顺序导致错误

时间:2019-05-14 19:57:17

标签: r ggplot2

我想绘制一个时间过程x,其中y值经常重复(整数得分1-4),并且我想一次可视化许多对象。

因为有太多的重叠,所以理想的是垂直位置躲闪,例如包中的position_dodgev。但是,当我尝试将点与geom_line连接时,连接顺序混乱了,并基于y值而不是x值进行连接。

我尝试了一次坐标翻转解决方法,但未成功。将geom_line替换为geom_path(确保按x比例排序)也无效。

以下是可重现的示例:

#data
df<-tibble(x=c(1,2,3,4,5,1,2,3,4,5,1,2,3,4,5),
           y=c(1,2,3,7,7,1,2,3,7,7,2,1,6,7,7),
           group=c('a','a','a','a','a','b','b','b','b','b','c','c','c','c','c'))


#horizontal dodge masks groups
ggplot(df, aes(x=x, y=y,col=group,group=group)) +
  geom_point(position=position_dodge(width=0.3))+
  geom_line(position=position_dodge(width=0.3))


#line connection error with vertical dodge
library(ggstance)
ggplot(df, aes(x=x, y=y,col=group,group=group)) +
  geom_point(position=position_dodgev(height=0.3))+
  geom_line(position=position_dodgev(height=0.3))

水平闪避按预期工作,但不允许在重复的y值范围内可视化所有重叠的组。来自ggstance的垂直闪避以错误的顺序连接了c组中的点。

enter image description here

2 个答案:

答案 0 :(得分:2)

我不确定是什么导致了此问题。知道position_dodge不打算与geomsit's been called a bug一起使用时,我对此感到很惊讶,而不是同时使用。

但是无论如何,我找到了一种解决方法,方法是使用ggplot_build分解图,重新排列对象中geom_line的点,然后重新组装图。看下面:

g <- ggplot(df, aes(x=x, y=y,col=group,group=group)) +
  geom_point(position=position_dodgev(height=0.3)) +
  geom_line(position=position_dodgev(height=0.3))

gg <- ggplot_build(g)

# -- look at gg$data to understand following lines --
#gg$data[[2]]: data associated with geom_line as it is the 2nd geom
#c(1,2) & c(2,1): I have $group==3 ...
# ... so just need to flip 1st and 2nd datapoints within that group 

gg$data[[2]][gg$data[[2]]$group==3,][c(1,2),] <- 
gg$data[[2]][gg$data[[2]]$group==3,][c(2,1),]

gt <- ggplot_gtable(gg)

plot(gt)

enter image description here

答案 1 :(得分:0)

我怀疑问题是由于PositionDodgev的{​​{1}}函数引起的,该函数接收按x值排序的数据集,并在创建后返回按y值排序的数据集(在每个组中)进行垂直位置躲避的必要转换。

以下变通办法定义了一个新的ggproto对象,该对象继承自compute_panel,但是在返回数据集之前对PositionDodgev中的数据集进行了重新排序:

compute_panel

用法:

# new ggproto based on PositionDodgev
PositionDodgeNew <- ggproto(
  "PositionDodgeNew", 
  PositionDodgev,
  compute_panel = function (data, params, scales){

    result <- ggstance:::collidev(data, params$height, 
                                  name = "position_dodgev", 
                                  strategy = ggstance:::pos_dodgev, 
                                  n = params$n, 
                                  check.height = FALSE)

    result <- result[order(result$group, result$x), ] # reordering by group & x

    result
  })

# position function that uses PositionDodgeNew instead of PositionDodgev
position_dodgenew <- function (height = NULL, preserve = c("total", "single")) {
  ggproto(NULL, PositionDodgeNew, height = height, preserve = match.arg(preserve))
}

plot