如何在ggplot函数内部传递可选参数

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

我想将ybreak函数中的plot1参数设置为可选。如果未指定此参数(NULL条件),那么我只想返回g ggplot,否则请使用自定义ybreak。我通过引用类似的答案尝试了以下代码,但它行不通。

plot1 <- function(df, x, y, ybreak = NULL) {
  g <- ggplot(df, aes_string(x = x, y = y)) 

  if (is.na(ybreak) == F) {
    g + scale_y_continuous(breaks = ybreak)
  }
  else {
    g
  }
}

plot1(mtcars, x = "mpg", y = "disp")
plot1(mtcars, x = "mpg", y = "disp", ybreak = seq(70, 500, by = 50))


> plot1(mtcars, x = "mpg", y = "disp")
Error in if (is.na(ybreak) == F) { : argument is of length zero
> plot1(mtcars, x = "mpg", y = "disp", ybreak = seq(70, 500, by = 50))
Warning message:
In if (is.na(ybreak) == F) { :
  the condition has length > 1 and only the first element will be used
r ggplot2 optional-parameters
2个回答
1
投票

第一种情况:ybreak = NULL

is.na(NULL)

返回:

logical(0)

因此,(因为逻辑(0)为零):

is.na(NULL) == FALSE

返回:

logical(0)

但是如果我们使用is.nullNULL是什么)而不是is.naNAsomething(只是一个数字)):

is.null(NULL)

返回:

[1] TRUE

然后:

is.null(NULL) == FALSE
[1] FALSE

第二种情况:ybreak = seq(70, 500, by = 50)

is.na(seq(70, 500, by = 50))
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
if (is.na(seq(70, 500, by = 50)) == FALSE) print("something")
[1] "something"
Warning message:
  In if (is.na(seq(70, 500, by = 50)) == FALSE) print("something") :
  the condition has length > 1 and only the first element will be used

但是我们可以使用all一次检查多个布尔值:

if (all(is.na(seq(70, 500, by = 50)) == FALSE)) print("something")
l[1] "something"

0
投票

R的椭圆或三点功能旨在处理可选参数。如果您的函数将具有更多可选参数,则这可能很有用。在您提供的示例中,以以下方式构造输入参数。

plot1 <- function(df, x, y, ...) {

}

处理...以查找特定的变量名可能有些棘手,但是使用功能evalsubstitutealist可以帮助解决这个问题。添加以下几行会将可选参数放入列表中。

plot1 <- function(df, x, y, ...) {
    args <- eval(substitute(alist(...)))
    inputs <- purrr::map(args, as.list)
}

注意:需要purrr软件包。

要评估所有可选参数以查找特定名称,您可以使用上述类似的代码。这是完整的示例。

library(ggplot2)

plot1 <- function(df, x, y, ...) {

    # eval inputs
    args <- eval(substitute(alist(...)))
    inputs <- purrr::map(args, as.list)
    print(args)
    print(inputs)

    # define base plot
    g <- ggplot(df, aes_string(x = x, y = y)) + geom_point()

    # return chart with breaks only if optional arguments are present
    # and if ybreaks exists
    if (length(inputs) > 0 && !is.na(inputs$ybreak)) {

        # rebuild seq
        breaks <- inputs$ybreak
        new_seq <- seq(breaks[[2]], breaks[[3]], by = breaks$by)

        # add to chart
        g <- g + scale_y_continuous(breaks = new_seq)
    }

    # return chart 
    return(g)
}

如果您有多个可选参数,则将is.na(inputs$ybreak)条件嵌套在length(inputs) > 0中。因为仅当提交一个或多个可选参数时才需要对可选参数进行求值。

取决于您的功能以及打算如何使用它,您可以使用更简单的方法,例如:

plot1 <- function(df, x, y, ...) {
   args <- list(ybreaks = ..1)
}

但是,对于包装或生产代码,以前的方法可能是更好的选择。

有关更多信息,请参见Advanced R: Chapter 6 Functions

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