首页 文章

你能手动控制ggplot2 geom_point躲避/重叠顺序吗? [重复]

提问于
浏览
3

这个问题在这里已有答案:

最近对ggplot2(2.2.0)的更新打破了我们的一些情节,因为绘制点的顺序已经改变 . 例如,以下代码:

library(dplyr)
library(ggplot2)
library(tibble)


df <- tribble(~a, ~x, ~y,
              "I", "A",  2,
              "I", "B",  3,
              "II","A",  2,
              "II","B",  3)

ggplot(df, aes(x = x, y = y, color = a)) +
  geom_point(size = 5, position = position_dodge(width = 0.1))+
  coord_cartesian(ylim = c(0,15))

在两个最新版本的ggplot2之间生成不同的版本,

see here

注意点重叠顺序的差异(即新版本与顶部最左边的点重叠) . 我可以通过反转因子顺序来反转类别重叠的顺序:

library(dplyr)
library(ggplot2)
library(tibble)
library(forcats)


df <- tribble(~a, ~x, ~y,
              "I", "A",  2,
              "I", "B",  3,
              "II","A",  2,
              "II","B",  3)

ggplot(df, aes(x = x, y = y, color = fct_rev(a))) +
  geom_point(size = 5, position = position_dodge(width = 0.1))+
  coord_cartesian(ylim = c(0,15))

但这没有帮助,因为它现在也扭转了躲闪顺序 .

this plot

有没有人知道有什么方法可以重现以前的行为?是否可以手动反转绘制点的顺序而不改变它们被躲闪的顺序?

1 回答

  • 5

    Build 自己的位置躲避也不是很困难:

    library(ggplot2)
    
    # My private Idaho^H^H^H^H^Hdodge ---------------------------------------------------
    
    collide2 <- function(data, width = NULL, name, strategy, check.width = TRUE) {
      if (!is.null(width)) {
        if (!(all(c("xmin", "xmax") %in% names(data)))) {
          data$xmin <- data$x - width / 2
          data$xmax <- data$x + width / 2
        }
      } else {
        if (!(all(c("xmin", "xmax") %in% names(data)))) {
          data$xmin <- data$x
          data$xmax <- data$x
        }
        widths <- unique(data$xmax - data$xmin)
        widths <- widths[!is.na(widths)]
        width <- widths[1]
      }
    
      ####### THIS is the line that was added that is causing you angst
      # data <- data[order(data$xmin, -data$group), ]
    
      intervals <- as.numeric(t(unique(data[c("xmin", "xmax")])))
      intervals <- intervals[!is.na(intervals)]
    
      if (length(unique(intervals)) > 1 & any(diff(scale(intervals)) < -1e-6)) {
        warning(name, " requires non-overlapping x intervals", call. = FALSE)
      }
    
      if (!is.null(data$ymax)) {
        plyr::ddply(data, "xmin", strategy, width = width)
      } else if (!is.null(data$y)) {
        data$ymax <- data$y
        data <- plyr::ddply(data, "xmin", strategy, width = width)
        data$y <- data$ymax
        data
      } else {
        stop("Neither y nor ymax defined")
      }
    }
    
    position_dodge2 <- function(width = NULL) {
      ggproto(NULL, PositionDodge2, width = width)
    }
    
    PositionDodge2 <- ggproto(
      "PositionDodge", 
      Position,
      required_aes = "x",
      width = NULL,
      setup_params = function(self, data) {
        if (is.null(data$xmin) && is.null(data$xmax) && is.null(self$width)) {
          warning("Width not defined. Set with `position_dodge(width = ?)`",
                  call. = FALSE)
        }
        list(width = self$width)
      },
    
      compute_panel = function(data, params, scales) {
        collide2(data, params$width, "position_dodge2", ggplot2:::pos_dodge, check.width = FALSE)
      }
    )
    
    # End new Dodge ---------------------------------------------------------------------
    

    测试…

    library(dplyr)
    library(tibble)
    library(gridExtra)
    
    df <- tribble(~a, ~x, ~y,
                  "I", "A",  2,
                  "I", "B",  3,
                  "II","A",  2,
                  "II","B",  3)
    
    grid.arrange(
      ggplot(df, aes(x = x, y = y, color = a)) +
        geom_point(size = 5, position = position_dodge2(width = 0.1)) +
        coord_cartesian(ylim = c(0,15)) +
        labs(title="Old behaviour")
      ,
      ggplot(df, aes(x = x, y = y, color = a)) +
        geom_point(size = 5, position = position_dodge(width = 0.1)) +
        coord_cartesian(ylim = c(0,15)) +
        labs(title="New behaviour")
      ,
      ncol=2
    )
    

    enter image description here

相关问题