【问题标题】:Save a ggplot2 time series plot grob generated by ggplotGrob保存由 ggplotGrob 生成的 ggplot2 时间序列图 grob
【发布时间】:2018-09-28 11:56:31
【问题描述】:

This post describes a method 在时间序列图上创建一条两线 x 轴(年份低于月份)。不幸的是,我在这篇文章中使用的方法(选项 2)与 ggsave() 不兼容。

library(tidyverse)
library(lubridate)

df <- tibble(
  date = as.Date(41000:42000, origin = "1899-12-30"), 
  value = c(rnorm(500, 5), rnorm(501, 10))
)

p <- ggplot(df, aes(date, value)) + 
  geom_line() + 
  geom_vline(
    xintercept = as.numeric(df$date[yday(df$date) == 1]), color = "grey60"
  ) + 
  scale_x_date(date_labels = "%b", date_breaks = "month", expand = c(0, 0)) + 
  theme_bw() +
  theme(panel.grid.minor.x = element_blank()) + 
  labs(x = "")

# Get the grob
g <- ggplotGrob(p)

# Get the y axis
index <- which(g$layout$name == "axis-b")  # which grob
xaxis <- g$grobs[[index]]

# Get the ticks (labels and marks)
ticks <- xaxis$children[[2]]

# Get the labels
ticksB <- ticks$grobs[[2]]

# Edit x-axis label grob
# Find every index of Jun in the x-axis labels and a year label
junes <- grep("Jun", ticksB$children[[1]]$label)
ticksB$children[[1]]$label[junes] <- 
  paste0(
    ticksB$children[[1]]$label[junes], 
    "\n            ",  # adjust the amount of spaces to center the year
    unique(year(df$date))
  ) 

# Center the month labels between ticks
ticksB$children[[1]]$label <- 
  paste0(
    paste(rep(" ", 12), collapse = ""),  # adjust the integer to center month
    ticksB$children[[1]]$label
  )

# Put the edited labels back into the plot
ticks$grobs[[2]] <- ticksB
xaxis$children[[2]] <- ticks
g$grobs[[index]] <- xaxis

# Draw the plot
grid.newpage()
grid.draw(g)

# Save the plot
ggsave("plot.png", width = 11, height = 8.5, units = "in")

一个情节被保存,但没有岁月。我如何ggsave() 来自grid.draw(g) 的最终情节?这个grid.draw(g) 绘图如下所示,但实际的plot.png 文件略有不同,省略了三年201220132014

【问题讨论】:

  • ggsave("plot.png", plot = g, type = "cairo", width = 11, height = 8.5, units = "in", dpi = 150)?
  • 你为什么不用facet_grid()?会不会容易很多?
  • facet_grid() 将内容分解为面板。我不想要那种审美。我想要一条连续的线。谢谢楼上的回答!
  • 仅供参考,您可以自定义 facet_grid 中的面板,使其看起来像您想要的输出
  • @Tung 也许你可以回答,如果它比我自己的 (yours) 我会选择它。无论哪种方式,我都会赞成。谢谢

标签: r ggplot2 axis-labels facet-grid gtable


【解决方案1】:
library(tidyverse)
library(lubridate)
library(scales)

set.seed(123)
df <- tibble(
  date = as.Date(41000:42000, origin = "1899-12-30"), 
  value = c(rnorm(500, 5), rnorm(501, 10))
)

# create year column for facet
df <- df %>% 
  mutate(year = as.factor(year(date)))

p <- ggplot(df, aes(date, value)) + 
  geom_line() + 
  geom_vline(xintercept = as.numeric(df$date[yday(df$date) == 1]), color = "grey60") + 
  scale_x_date(date_labels = "%b", 
               breaks = pretty_breaks(),
               expand = c(0, 0)) +
  # switch the facet strip label to the bottom
  facet_grid(.~ year, space = 'free_x', scales = 'free_x', switch = 'x') +
  labs(x = "") +
  theme_bw(base_size = 14, base_family = 'mono') +
  theme(panel.grid.minor.x = element_blank()) + 
  # remove facet spacing on x-direction
  theme(panel.spacing.x = unit(0,"line")) +
  # switch the facet strip label to outside 
  # remove background color
  theme(strip.placement = 'outside',
        strip.background.x = element_blank())
p

ggsave("plot.png", plot = p, 
       type = "cairo", 
       width = 11, height = 8.5, units = "in", 
       dpi = 150)


使用theme_classic()

p <- ggplot(df, aes(date, value)) + 
  geom_line() + 
  geom_vline(xintercept = as.numeric(df$date[yday(df$date) == 1]), color = "grey60") + 
  scale_x_date(date_labels = "%b", 
               breaks = pretty_breaks(),
               expand = c(0, 0)) +
  # switch the facet strip label to the bottom
  facet_grid(.~ year, space = 'free_x', scales = 'free_x', switch = 'x') +
  labs(x = "") +
  theme_classic(base_size = 14, base_family = 'mono') +
  theme(panel.grid.minor.x = element_blank()) + 
  # remove facet spacing on x-direction
  theme(panel.spacing.x = unit(0,"line")) +
  # switch the facet strip label to outside 
  # remove background color
  theme(strip.placement = 'outside',
        strip.background.x = element_blank())
p

添加最顶部和最右侧的边框

ymax <- ceiling(1.1 * max(df$value, na.rm = TRUE))
xmax <- max(df$date, na.rm = TRUE)

p <- ggplot(df, aes(date, value)) + 
  geom_line() + 
  geom_vline(xintercept = as.numeric(df$date[yday(df$date) == 1]), color = "grey60") + 
  scale_x_date(date_labels = "%b", 
               breaks = pretty_breaks(),
               expand = c(0, 0)) +
  # switch the facet strip label to the bottom
  facet_grid(.~ year, space = 'free_x', scales = 'free_x', switch = 'x') +
  labs(x = "") +
  theme_classic(base_size = 14, base_family = 'mono') +
  theme(panel.grid.minor.x = element_blank()) + 
  # remove facet spacing on x-direction
  theme(panel.spacing.x = unit(0,"line")) +
  # switch the facet strip label to outside 
  # remove background color
  theme(strip.placement = 'outside',
        strip.background.x = element_blank()) +
  ### add top and right most borders
  scale_y_continuous(expand = c(0, 0), limits = c(0, ymax)) +
  geom_hline(yintercept = ymax) +
  geom_vline(xintercept = as.numeric(df$date[df$date == xmax])) +
  theme(panel.grid.major = element_line())
p

reprex package (v0.2.1.9000) 于 2018 年 10 月 1 日创建

【讨论】:

  • 太棒了!唯一我不喜欢的是它在灰色 60 垂直线的顶部绘制黑色刻面线。如果将颜色切换为红色并使线条变粗(最终看起来像赛车条纹),这一点很明显。如何消除黑色刻面线? geom_vline(xintercept = as.numeric(df$date[yday(df$date) == 1]), color = "red", size = 2)
  • @stackinator:你可以用theme_classic()代替theme_bw()
  • 不需要使用theme_bw,包括panel.grid.majorpanel.grid.minor.y等添加网格线ggplot2.tidyverse.org/reference/theme.html
  • 我忘记了如果我们使用theme_classic,则不需要theme(panel.border = element_blank()),所以留下一个
  • 顺便评论:默认情况下ggsave() 将保存last_plot(),因此您可以省去将绘图分配给变量p 并完全省略参数plot = p,如果您正在努力为了简洁...
【解决方案2】:

取自上面的Tung cmets。在操作问题的代码块末尾添加以下内容。

ggsave(
  "plot.png", 
  plot = g, 
  type = "cairo", 
  width = 11, 
  height = 8.5, 
  units = "in", 
  dpi = 150
  )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-11
    • 2019-04-22
    • 1970-01-01
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多