在一个函数中使用2个参数....

时间:2015-08-04 08:30:01

标签: r function ggplot2

我知道问题的标题听起来很愚蠢,但我想创建一个函数test_f,它可以使用test_f中使用的几个函数参数(我使用了最新版本的ggplot2新函数aes_)。 E.g。

devtools::install_github('hadley/scales')
devtools::install_github('hadley/ggplot2')

test <- function(data,x,y,...){
  ggplot(data, aes_(substitute(x), substitute(y)))+
    geom_point(...)+
    scale_y_continuous(...)
}

test(mtcars, qsec, mpg,limit = c(1,100))

一切正常,但

test(mtcars, qsec, mpg,size = 5)

它显示错误:Error in scale_y_continuous: Unused parameter (size = 5)

我知道为什么会这样,但我想知道是否有可能将...用于多个内部函数而不是将所有参数放入test_f,如下所示?

test <- function(data,x,y,..., size = 5, limit = c(1,100){
   ...
   ...
}

2 个答案:

答案 0 :(得分:3)

你可以,但它只取决于接收函数如何处理事情:

f2 <- function(three, ...) {

  g <- as.list(match.call())

  print(sprintf("three (from named args) = %d", three))

  if ("five" %in% names(g)) print(sprintf("five (from ...) = %d", g$five))

}

f1 <- function(x, y, ...) {

  if (missing(x)) stop("x is missing", call.=FALSE)
  if (missing(y)) stop("y is missing", call.=FALSE)

  g <- as.list(match.call())

  print(sprintf("x = %d", x))
  print(sprintf("y = %d", y))

  f2(...)  

}

f1(1, 2, three=4, five=6)
## [1] "x = 1"
## [1] "y = 2"
## [1] "three (from named args) = 4"
## [1] "five (from ...) = 6"

由于您遇到的问题是scale_y_continuous(因此,continuous_scale)抱怨未使用的参数,您只能传入...接受的内容。名单。这意味着你的功能有一些内部的工作,但它绝对可行:

mygg <- function(data, x, y, ...) {

  gg <- ggplot(data=data, aes_(substitute(x), substitute(y)))

  # get what geom_point accepts
  geom_point_aes <- c("x", "y", "alpha", "colour", "color", "fill", "shape", "size", "stroke")
  point_params <- unique(c(geom_point_aes, 
                           names(formals(geom_point)), 
                           names(formals(layer))))

  # get what scale_y_continuous accepts
  scale_y_params <- unique(c(names(formals(scale_y_continuous)), 
                             names(formals(continuous_scale))))

  # get all ... params passed in (if any)
  args <- list(...)

  if (length(args) > 0) {

    # get all the arg names
    arg_names <- names(args)

    # which ones are left for point
    gg <- gg + do.call(geom_point, 
                       sapply(intersect(arg_names, point_params), 
                              function(x) { list(args[[x]]) }))

    # which ones are left for scale_y
    gg <- gg + do.call(scale_y_continuous, 
                       sapply(intersect(arg_names, scale_y_params), 
                              function(x) { list(args[[x]]) }))

  } else {

    gg <- gg + geom_point() + scale_y_continuous()

  }

  return(gg)

}

我不会用png混乱答案,但如果你运行以下内容,你应该看看修改过的函数做了什么。

mygg(mtcars, mpg, wt)

mygg(mtcars, mpg, wt, color="blue")

mygg(mtcars, mpg, wt, limits=c(3,4))

mygg(mtcars, mpg, wt, fill="green", color="blue", shape=21, limits=c(3,4), left="over")

答案 1 :(得分:1)

它可能值得一提的是使用一个或两个列表来包装可选参数的替代策略。借用其他答案,

mygg <- function(data, x, y, 
                 geom_pars = list(), 
                 scale_pars = list()) {

  p <- ggplot(data=data, aes_(substitute(x), substitute(y)))
  g <- do.call(geom_point, geom_pars)
  s <- do.call(scale_y_continuous, scale_pars)

  p + list(g, s)

}

调用函数有点冗长,但通常不那么容易混淆,因为我们明确了参数的位置。

mygg(mtcars, mpg, wt)

mygg(mtcars, mpg, wt, geom_pars=list(color="blue"))

mygg(mtcars, mpg, wt, scale_pars=list(limits=c(3,4)))

mygg(mtcars, mpg, wt, 
    geom_pars=list(fill="green", color="blue", shape=21), 
    scale_pars=list(limits=c(3,4)))