'outer()' 函数中 'match.arg()' 的问题
Problem with 'match.arg()' inside 'outer()' function
Background/Problem
我正在尝试使用 outer()
函数将函数应用于两个向量的所有成对组合作为参数。在我的例子中,输入之一是一个字符向量,它应该作为一个内部函数 (cor()
) 的参数,它需要 运行 match.arg()
就可以了。
示例 1(有效)
当内部函数不需要它时,这很好用,例如 paste()
。
# define function to test
f1 <- function(method, vec_len){
paste(method, vec_len)
}
# define inputs to test
methods <- c("pearson", "spearman", "kendall")
vec_lens <- 33:35
# outer runs fine
outer(methods, vec_lens, f1)
#> [,1] [,2] [,3]
#> [1,] "pearson 33" "pearson 34" "pearson 35"
#> [2,] "spearman 33" "spearman 34" "spearman 35"
#> [3,] "kendall 33" "kendall 34" "kendall 35"
示例 2(不起作用)
然而,当内部函数需要 运行 match.arg()
输入时,这会失败:
# function that parses string with match.arg fails
f2 <- function(method, vec_len){
x <- runif(vec_len, 0, 10)
y <- x + rnorm(vec_len)
cor(x, y, method = method)
}
# outer fails on match.arg within cor()
outer(methods, vec_lens, f2)
#> Error in match.arg(method): 'arg' must be of length 1
我的研究
从我所做的研究 (1, 2, 3) 看来,这可能与无法访问全局环境的内部函数的作用域有关,但我不确定也不相信知道如何修复它。
顺便说一句
我知道代码没问题,因为我可以通过循环得到结果:
# desired result by loop
out <- list()
for (method in methods) {
for (j in seq_along(vec_lens)) {
out[[method]][[j]] <- f2(method, vec_lens[j])
names(out[[method]])[j] <- vec_lens[j]
}
}
do.call(rbind, out)
#> 33 34 35
#> pearson 0.9351946 0.9491004 0.9516057
#> spearman 0.9067513 0.9315508 0.9456583
#> kendall 0.8371212 0.8146168 0.7983193
我们可以用Vectorize
换行
set.seed(24)
outer(methods, vec_lens, FUN = Vectorize(f2))
[,1] [,2] [,3]
[1,] 0.9060101 0.9661931 0.9572807
[2,] 0.9542112 0.9495798 0.9490196
[3,] 0.8863636 0.8680927 0.7983193
给出与 for
循环相同的输出(dimnames
除外)
> set.seed(24)
> out <- list()
> for (method in methods) {
+ for (j in seq_along(vec_lens)) {
+ out[[method]][[j]] <- f2(method, vec_lens[j])
+ names(out[[method]])[j] <- vec_lens[j]
+ }
+ }
> do.call(rbind, out)
33 34 35
pearson 0.9060101 0.9309473 0.9637686
spearman 0.9532086 0.9254393 0.9526611
kendall 0.8257576 0.8074866 0.7983193
Background/Problem
我正在尝试使用 outer()
函数将函数应用于两个向量的所有成对组合作为参数。在我的例子中,输入之一是一个字符向量,它应该作为一个内部函数 (cor()
) 的参数,它需要 运行 match.arg()
就可以了。
示例 1(有效)
当内部函数不需要它时,这很好用,例如 paste()
。
# define function to test
f1 <- function(method, vec_len){
paste(method, vec_len)
}
# define inputs to test
methods <- c("pearson", "spearman", "kendall")
vec_lens <- 33:35
# outer runs fine
outer(methods, vec_lens, f1)
#> [,1] [,2] [,3]
#> [1,] "pearson 33" "pearson 34" "pearson 35"
#> [2,] "spearman 33" "spearman 34" "spearman 35"
#> [3,] "kendall 33" "kendall 34" "kendall 35"
示例 2(不起作用)
然而,当内部函数需要 运行 match.arg()
输入时,这会失败:
# function that parses string with match.arg fails
f2 <- function(method, vec_len){
x <- runif(vec_len, 0, 10)
y <- x + rnorm(vec_len)
cor(x, y, method = method)
}
# outer fails on match.arg within cor()
outer(methods, vec_lens, f2)
#> Error in match.arg(method): 'arg' must be of length 1
我的研究
从我所做的研究 (1, 2, 3) 看来,这可能与无法访问全局环境的内部函数的作用域有关,但我不确定也不相信知道如何修复它。
顺便说一句
我知道代码没问题,因为我可以通过循环得到结果:
# desired result by loop
out <- list()
for (method in methods) {
for (j in seq_along(vec_lens)) {
out[[method]][[j]] <- f2(method, vec_lens[j])
names(out[[method]])[j] <- vec_lens[j]
}
}
do.call(rbind, out)
#> 33 34 35
#> pearson 0.9351946 0.9491004 0.9516057
#> spearman 0.9067513 0.9315508 0.9456583
#> kendall 0.8371212 0.8146168 0.7983193
我们可以用Vectorize
set.seed(24)
outer(methods, vec_lens, FUN = Vectorize(f2))
[,1] [,2] [,3]
[1,] 0.9060101 0.9661931 0.9572807
[2,] 0.9542112 0.9495798 0.9490196
[3,] 0.8863636 0.8680927 0.7983193
给出与 for
循环相同的输出(dimnames
除外)
> set.seed(24)
> out <- list()
> for (method in methods) {
+ for (j in seq_along(vec_lens)) {
+ out[[method]][[j]] <- f2(method, vec_lens[j])
+ names(out[[method]])[j] <- vec_lens[j]
+ }
+ }
> do.call(rbind, out)
33 34 35
pearson 0.9060101 0.9309473 0.9637686
spearman 0.9532086 0.9254393 0.9526611
kendall 0.8257576 0.8074866 0.7983193