使用端点/ ggplot的中断计算设置ggplot网格线

时间:2018-05-25 03:05:34

标签: r ggplot2

我遇到了ggplot问题,我试图以非常小的外观制作线条图。我已经摆脱了传说,转而支持每行右侧的文字标签。如果标签不长,可能不会那么明显,但如果网格线停在最大x值(在这种情况下,在2015年),我会更好。

library(tidyverse)

df <- structure(list(industry = c("Accommodation & Food Services", "Construction", "Health Care & Social Asst.", "Retail Trade", 
        "Accommodation & Food Services", "Construction", "Health Care & Social Asst.", "Retail Trade"), 
    year = c(2002L, 2002L, 2002L, 2002L, 2015L, 2015L, 2015L, 2015L), 
    value = c(6.977, 5.264, 17.065, 14.528, 8.032, 4.648, 20.547, 12.568)), 
    class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -8L), 
    .Names = c("industry", "year", "value"))

ggplot(df, aes(x = year, y = value, color = industry)) +
  geom_line() +
  geom_text(aes(label = industry), data = . %>% filter(year == max(year)), size = 3, hjust = 0, nudge_x = 0.1) +
  scale_x_continuous(expand = expand_scale(mult = c(0.05, 0.85)), breaks = c(min(df$year), max(df$year)), name = NULL) +
  scale_y_continuous(limits = c(0, NA), name = "Value (thousands)") +
  theme_minimal() +
  theme(legend.position = "none", 
        panel.grid.major.x = element_blank(), 
        panel.grid.minor = element_blank())

我想避免完成整个事情in this answer,因为我有几个情节,想要快速将它们组合在一起。

我到目前为止提出的解决方案是创建一个伪网格线,方法是创建一个geom_segment虚拟数据,其中常规y值从最早的年份开始,到最后一年结束。这样做没问题,因为我知道我想要什么样的休息,并且可以设置scale_y_continuous以匹配geom_segment

break_df <- tibble(x1 = 2002, x2 = 2015, y = seq(0, 20, by = 5))

ggplot(df, aes(x = year, y = value, color = industry)) +
  geom_segment(aes(x = x1, xend = x2, y = y, yend = y), data = break_df, inherit.aes = F, size = 0.4, color = "gray85") +
  geom_line() +
  geom_text(aes(label = industry), data = . %>% filter(year == max(year)), size = 3, hjust = 0, nudge_x = 0.1) +
  scale_x_continuous(expand = expand_scale(mult = c(0.05, 0.85)), breaks = c(min(df$year), max(df$year)), name = NULL) +
  scale_y_continuous(limits = c(0, NA), name = "Value (thousands)", breaks = break_df$y) +
  theme_minimal() +
  theme(legend.position = "none", 
        panel.grid = element_blank())

reprex package(v0.2.0)创建于2018-05-24。

我想知道ggplot如何计算休息时间,以及它是否使用了我可以利用的功能?就像我可以提供给geom_segmentscale_y_continuous这些中断的内部计算一样,所以如果我没有设置单独的中断信息数据框,它们就会匹配。

或者,也许这是一种愚蠢的方法,并且有更好的方法来获得我想要的网格线。我认为也可能有一种方法可以使用trans function进行此操作,例如构建trans_new(),但我不知道该怎么做。

提前致谢!

1 个答案:

答案 0 :(得分:5)

我想提出一种使用annotation_custom()的替代方法,它实现了类似的外观,至少在这种情况下:

ggplot(df, aes(x = year, y = value, color = industry)) +
  geom_line() + 
  annotation_custom(
    grob = grid::rectGrob(gp = grid::gpar(col = NA, fill = "white")),
    xmin = max(df$year)
  ) +
  geom_text(aes(label = industry), data = . %>% filter(year == max(year)), 
            size = 3, hjust = 0, nudge_x = 0.1) +

  # note: my version of ggplot2 doesn't have the expand_scale function, but I suppose
  # it isn't critical to the question here
  scale_x_continuous(expand = c(0.2, 0), breaks = c(min(df$year), max(df$year)), 
                     name = NULL) +
  scale_y_continuous(limits = c(0, NA), name = "Value (thousands)") +
  theme_minimal() +
  theme(legend.position = "none", 
        panel.grid.major.x = element_blank(), 
        panel.grid.minor = element_blank())

plot

annotation_custom的默认位置参数为Inf / -Inf,将显示的grob拉伸到绘图面板的所有四个边缘,因此指定xmin = max(df$year)为足以让它覆盖max(df$year)右边所有内容的网格线。

此技巧最适用于没有可见panel.border组件的ggplot主题,例如theme_minimaltheme_greytheme_dark。如果您使用的是theme_bw / theme_linedraw / theme_light,那么幻觉会变得不那么有效。 (至于theme_classic / theme_void,它们没有网格线,因此无论哪种方式都无关紧要。)