【问题标题】:How to vectorize an R function with arguments that can be supplied with NULL values?如何使用可以提供 NULL 值的参数对 R 函数进行矢量化?
【发布时间】:2017-07-24 14:58:18
【问题描述】:

用接受向量、静态值和NULLs 的参数对 R 函数进行向量化的最佳方法是什么?当我 Map() 一个带有参数的函数时遇到问题,这些参数有时由 NULLs 提供。我收到以下错误消息(使用下面的代码复制):

Error in mapply(FUN = f, ..., SIMPLIFY = FALSE) : zero-length inputs cannot be mixed with those of non-zero length

为了重现这个问题,我编写了一个函数,它使用来自data 的参数返回n 模拟值,并可选择实现minmax 值。

#' foo (example function with some args defaulting to NULL)
#'
#' Returns simulated normal values using population parameters from data
#' 
#' @param data Numeric vector used to calculate population parameters
#' @param n Number of simulated data points to return
#' @param min Optional. Creates a truncation effect. Simulated values
#'   below min will be replaced with min.
#' @param max Optional. Creates a truncation effect. Simulated values
#'   above max will be replaced with max.
#' @return Numeric vector of simulated values.
foo <- function(data, n, min = NULL, max = NULL) {
  x <- rnorm(n, mean(data), sd(data))
  if (!is.null(min)) {
    x[x < min] <- min
  }
  if (!is.null(max)) {
    x[x > max] <- max
  }
  x
}

我正在使用列表并希望该函数返回列表。所以,这里的数据向量是一个数值向量的列表。

## data vector
data <- replicate(5, rnorm(3), simplify = FALSE)

其他参数可以接受静态 (length(x) == 1) 或动态值 (length(x) == length(data))。当提供非 NULL 值时,无论 args 被赋予一个还是多个值,它都有效。

## static args (this works)
n <- 10
min <- -1.96
max <- 1.96
Map(foo, data, n, min, max)

## vector args (this works)
n <- sample(2:100, 5)
min <- runif(5, -4, -1)
max <- runif(5, 1, 4)
Map(foo, data, n, min, max)

但是当向 args 传递 NULL 值时,它会中断。

## null args (this doesn't work)
n <- sample(2:100, 5)
min <- NULL
max <- NULL
Map(foo, data, n, min, max)

## it doesn't matter if n is a vector
n <- 10
min <- NULL
max <- NULL
Map(foo, data, n, min, max)


Error in mapply(FUN = f, ..., SIMPLIFY = FALSE) : 
  zero-length inputs cannot be mixed with those of non-zero length

【问题讨论】:

  • 您想在输入列表中使用 each 向量的mean 吗?还是输入列表中所有个向量(聚合)的mean
  • 这不是我要修复的实际功能,但相当于假设我想独立使用每个向量。
  • 因为在你的函数中,你声明了min=NULLmax=NULL,你可以避免在你的调用中不传递minmax。使用 Map(foo,data,10) 对我有用。
  • 这是作为一个函数使用的,所以有时它会被赋予 NULL 有时不会。我意识到我可以为每个不包含潜在的NULL 值的排列创建不同的Map() 调用,但是有问题的实际函数有几个默认为NULL 的参数,所以我宁愿一次性完成.
  • 改为传递Map(foo,data,10,NA,NA)min &lt;- NAmax &lt;- NA...

标签: r


【解决方案1】:

我认为您要查找的代码是

n <- sample(2:100, 5)
min <- list(NULL)
max <- list(NULL)
Map(foo, data, n, min, max)

Map 函数期望函数后面的每个参数是一个向量或参数列表,它们将被回收到最长的长度。所以在这种情况下,我们有 length(data)length(n) 等于 5 和 length(min)length(max) 等于 1,所以 min 和 max 列表中的单个 NULL 被回收 5 次并每次传递给函数.

或者,如果您想要执行类似“应用”的操作,其中一些参数是向量,而其他参数是标量(即要传递给函数的每次调用的单个值),请使用 mapply,传递向量参数直接和 MoreArgs 中的标量参数:

n <- sample(2:100, 5)
min <- NULL
max <- NULL
mapply(foo, data, n, MoreArgs=list(min, max))

(另外,为了与您的代码保持一致,我在这里没有这样做,但您几乎应该总是将参数传递给具有名称的应用类型函数(例如MoreArgs=list(min=min, max=max)。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 2018-12-24
    • 2018-01-01
    相关资源
    最近更新 更多