有没有办法用非标准参数编写自定义 ggplot 主题函数?

问题描述 投票:0回答:1

我正在尝试编写一个自定义 ggplot 主题,如下所示https://joeystanley.com/blog/custom-themes-in-ggplot2/

这很简单,但我想增加一些复杂性,我的一些图只需要 X 轴上的网格线,而其他图只需要 Y 轴上的网格线(两者都不需要)。我想向主题函数添加一个参数来指定哪个是绘制轴,这样在图形脚本中,我可以调用

my_theme(gridline_axis = "x")
并让网格线仅在 x 轴上绘制。

但是,我一直无法弄清楚如何在 theme() 函数中添加条件参数。我相信挑战在于让条件语句作为主题的参数进行评估——尽管我尝试过 toString()、eval() 和 allocate()。

my_theme <- function(gridline_axis = "x") {
  
  draw_axis = ifelse(gridline_axis == "x", yes = "x", no = "y")
  blank_axis = ifelse(draw_axis == "x", yes = "y", no = "x")
  
  
  my_theme = theme_bw(base_size = 12) %+replace%
    
    theme(      
      #gridline settings -- user input of "x" produces major gridlines on the x axis and removes on Y axis
      paste("panel.grid.major.",toString(blank_axis),sep = "") = element_blank(),    
      paste("panel.grid.minor.",toString(blank_axis),sep = "") = element_blank(),
      paste("panel.grid.major.",toString(draw_axis),sep = "") = element_line(
        color = "gray",
        linewidth = 0.5,
        linetype = 1
      ),
      paste("panel.grid.minor.",toString(draw_axis),sep = "") = element_line(linetype = 1)
    )
  
}

返回:

Error: unexpected '=' in:
"      #gridline settings -- user input of "x" produces major gridlines on the x axis and removes on Y axis
      toString(paste("panel.grid.major.",toString(blank_axis),sep = "")) ="

我还尝试在对 theme() 的主要调用中构建 if 语句——这是不成功的,因为它覆盖了 if 语句之外对 theme() 调用的任何内容。

我还尝试在我不想更改的主题部分之后使用 theme_set() ,然后根据我确实希望更改的部分的 if 语句使用 theme_update() 。虽然我不知道为什么,但失败了。

我试图通过基于 if else 语句完全复制 %+replace% 来避免重复我不想在任何绘图上更改的参数。

提前致谢

r if-statement ggplot2 themes
1个回答
0
投票

问题是您不能在

=
的左侧使用表达式。另外,虽然我总是试图避免重复代码,但对于当前的用例,我会使用像这样的
if-else

my_theme <- function(gridline_axis = "x") {
  t <- theme_bw(base_size = 12)

  grid_major <- element_line(
    color = "gray",
    linewidth = 0.5,
    linetype = 1
  )
  grid_minor <- element_line(linetype = 1)

  t <- t %+replace%
    if (gridline_axis == "x") {
      theme(
        panel.grid.major.y = element_blank(),
        panel.grid.minor.y = element_blank(),
        panel.grid.major.x = grid_major,
        panel.grid.minor.x = grid_minor
      )
    } else {
      theme(
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank(),
        panel.grid.major.y = grid_major,
        panel.grid.minor.y = grid_minor
      )
    }

  t
}

library(ggplot2)

p <- ggplot(mtcars, aes(mpg, wt)) +
  geom_point()

p +
  my_theme()


p +
  my_theme("y")

这里的第二种方法是使用

do.call
的选项,这可能更符合您想要实现的目标:

my_theme <- function(gridline_axis = "x") {
  t <- theme_bw(base_size = 12)

  draw_axis <- if (gridline_axis == "x") "x" else "y"
  blank_axis <- if (gridline_axis == "x") "y" else "x"
  
  panel_grid <- list(
    element_blank(), 
    element_blank(),
    element_line(
      color = "gray",
      linewidth = 0.5,
      linetype = 1
    ),
    element_line(linetype = 1)
  )
  
  names(panel_grid) <- c(
    paste0("panel.grid.", c("minor", "major"), ".", blank_axis),
    paste0("panel.grid.major.", draw_axis),
    paste0("panel.grid.minor.", draw_axis)
  )
  
  t %+replace%
    do.call(theme, args = panel_grid)
}

p +
  my_theme()


p +
  my_theme("y")

© www.soinside.com 2019 - 2024. All rights reserved.