ggplot остановить geom_segment, показывающий поверх geom_boxplot в легенде - PullRequest
1 голос
/ 23 апреля 2019

Я пытаюсь получить что-то похожее на ответ Glen_b на на этот вопрос . По сути, я хочу, чтобы стрелка вверху моего коробочного графика указывала на то, что с помощью ggplot есть больше выбросов вне масштаба.

Я могу сделать так, чтобы основная часть сюжета выглядела так, как мне хотелось бы, но у меня возникают проблемы с получением разумной легенды.

Я собрал пример:

library(plyr)
library(dplyr)
library(ggplot2)

#create test data frame with extreme outlier
mpg_test <- mpg

mpg_test[1,"hwy"] = 250
pmax = 50
pmin = min(mpg_test$hwy)

outliersabovepmax <- filter(mpg_test, hwy > pmax) %>% mutate(hwy= pmax) 

#basic plot without cropping/adding arrows
p <- ggplot(mpg_test, aes(x = class, y=hwy, colour = class)) + geom_boxplot()
p

Я могу сделать так, чтобы основная часть сюжета выглядела так, как мне хотелось бы:

#plot that I want
p2 <- p + 
  geom_segment(data = outliersabovepmax, 
               aes(xend = class, y = hwy-1, yend = hwy+1, 
                   linetype = "Outlier above"), 
               arrow = arrow(), show.legend = T) +
  coord_cartesian(ylim = c(pmin, pmax))

Но я бы хотел, чтобы легенда не показывала стрелку на цветной легенде.

Обычно я ожидал бы, что смогу сделать что-то вроде:

p2 + 
  guides(colour = guide_legend(override.aes = list(linetype = "blank")))

но поскольку на боксплоте также используется тип линии, я просто получаю черные квадраты, если я делаю это. Я также не хочу устанавливать show.legend = F для geom_segment, поскольку хочу, чтобы стрелка в легенде.

В качестве бонуса мне бы хотелось, чтобы стрелка в легенде была повернута вверх. Но это не так важно.

Участок, который я получаю:

plot that I get

Участок, который я хотел бы (сделан в краске) plot with legend that I'd like

1 Ответ

0 голосов
/ 23 апреля 2019

Может быть, что-то вроде этого?

p + 
  # hide legend in actual segment layer
  geom_segment(data = outliersabovepmax, 
               aes(xend = class, y = hwy-1, yend = hwy+1), 
               arrow = arrow(), show.legend = F)+

  # have invisible segment layer that shows legend
  geom_segment(data = outliersabovepmax, 
               aes(xend = class, y = hwy-1, yend = hwy+1, linetype = "Outlier above"), 
               arrow = arrow(), alpha = 0, show.legend = T) +

  # override alpha for linetype legend
  guides(linetype = guide_legend(override.aes = list(alpha = 1))) +

  coord_cartesian(ylim = c(pmin, pmax))

plot

И если вы хотите изменить раскладку ключа легенды geom_segment, выможет копаться в базовом коде для GeomSegment:

library(grid)
GeomSegment2 <- ggproto("GeomSegment2", GeomSegment,
                        draw_key = function (data, params, size)                         {
                          data$linetype[is.na(data$linetype)] <- 0
                          segmentsGrob(
                            # vertical instead of horizontal line
                            0.5, 0.1, 0.5, 0.9, #0.1, 0.5, 0.9, 0.5, 
                            gp = gpar(col = alpha(data$colour, data$alpha), 
                                      lwd = data$size * .pt, 
                                      lty = data$linetype, 
                                      lineend = "butt"), 
                            arrow = params$arrow)
                        })
geom_segment2 <- function (mapping = NULL, data = NULL, stat = "identity", 
                           position = "identity", ..., arrow = NULL, arrow.fill = NULL, 
                           lineend = "butt", linejoin = "round", na.rm = FALSE, 
                           show.legend = NA, inherit.aes = TRUE) {
  layer(data = data, mapping = mapping, stat = stat, geom = GeomSegment2, 
        position = position, show.legend = show.legend, inherit.aes = inherit.aes, 
        params = list(arrow = arrow, arrow.fill = arrow.fill, 
                      lineend = lineend, linejoin = linejoin, na.rm = na.rm, 
                      ...))
}

Использование:

p + 
  # hide legend in actual segment layer
  geom_segment(data = outliersabovepmax, 
               aes(xend = class, y = hwy-1, yend = hwy+1), 
               arrow = arrow(), show.legend = F)+

  # have invisible segment layer that shows legend
  geom_segment2(data = outliersabovepmax, 
               aes(xend = class, y = hwy-1, yend = hwy+1, linetype = "Outlier above"), 
               arrow = arrow(), alpha = 0, show.legend = T) +

  # override alpha for linetype legend
  guides(linetype = guide_legend(override.aes = list(alpha = 1))) +

  coord_cartesian(ylim = c(pmin, pmax))

2nd plot

...