如何避免在 R 中的用户定义函数上使用 sapply()
How to avoid using sapply() on user defined functions in R
我是 R 编程的初学者。最近写了一个自定义函数如下:
foo <- function(x){
power <- 1:4
sum(x^power)
}
当 x 是单个数字时,此函数可以正常工作。例如,当 x = 1
时,结果为 4,当 x = 10
时,结果为 11110。但是,此函数不适用于向量。例如,当x <- c(1, 10)
时,结果是10102,这不是我想要的。我想要的结果是一个向量,例如 4 11110
。我知道这个问题可以通过在函数上使用 sapply()
或在函数内添加 for 循环来解决,但我认为可能还有另一种方法可以在不使用循环或“应用”函数的情况下重写函数。我尝试了不同的方法来重写函数但没有任何效果,有人可以帮我解决这个问题吗?谢谢!
我认为没有办法避免任何类型的隐式或显式循环,因为 power
是一个向量,而您将 x
传递给它,这是另一个向量。
这里有几个选项:
- 你最好的选择是
sapply
(你已经猜到了)。
sapply(c(1, 10), foo)
#[1] 4 11110
- 另一种方法是使用
Vectorize
,您无法“看到”循环但它仍然在下面循环,因为它是 mapply
. 的包装器
Vectorize(foo)(c(1, 10))
#[1] 4 11110
- 使用
outer
:
foo <- function(x){
power <- 1:4
rowSums(outer(x, power, `^`))
}
foo(c(1, 10))
#[1] 4 11110
显然您也可以编写一个简单的 for
循环并将 c(1, 10)
传递给它。
从数学上讲,一种简单直接的方法是重写 foo
函数,如下所示
foo <- function(x) {
power <- 1:4
ifelse(x==1,max(power),x*(x**(max(power))-1)/(x-1))
}
这给出了
> foo(c(1,10))
[1] 4 11110
这个有效:
foo <- function(x, power = 1:4){
ind <- 1 + seq_along(power)
power <- matrix(rep(power, length(x)), nrow = length(x), byrow = T)
x <- as.matrix(x)
m <- cbind(x, power)
m <- m[, 1]^m[, ind]
v <- rowSums(m)
return(v)
}
foo(x = c(1, 10))
## [1] 4 11110
运行速度比使用 sapply(x foo)
快约 8.5 倍(当 foo
是长度为 == 1,000,000 的向量时)。来晚了,不知道各位能不能再优化一下内部结构
我是 R 编程的初学者。最近写了一个自定义函数如下:
foo <- function(x){
power <- 1:4
sum(x^power)
}
当 x 是单个数字时,此函数可以正常工作。例如,当 x = 1
时,结果为 4,当 x = 10
时,结果为 11110。但是,此函数不适用于向量。例如,当x <- c(1, 10)
时,结果是10102,这不是我想要的。我想要的结果是一个向量,例如 4 11110
。我知道这个问题可以通过在函数上使用 sapply()
或在函数内添加 for 循环来解决,但我认为可能还有另一种方法可以在不使用循环或“应用”函数的情况下重写函数。我尝试了不同的方法来重写函数但没有任何效果,有人可以帮我解决这个问题吗?谢谢!
我认为没有办法避免任何类型的隐式或显式循环,因为 power
是一个向量,而您将 x
传递给它,这是另一个向量。
这里有几个选项:
- 你最好的选择是
sapply
(你已经猜到了)。
sapply(c(1, 10), foo)
#[1] 4 11110
- 另一种方法是使用
Vectorize
,您无法“看到”循环但它仍然在下面循环,因为它是mapply
. 的包装器
Vectorize(foo)(c(1, 10))
#[1] 4 11110
- 使用
outer
:
foo <- function(x){
power <- 1:4
rowSums(outer(x, power, `^`))
}
foo(c(1, 10))
#[1] 4 11110
显然您也可以编写一个简单的 for
循环并将 c(1, 10)
传递给它。
从数学上讲,一种简单直接的方法是重写 foo
函数,如下所示
foo <- function(x) {
power <- 1:4
ifelse(x==1,max(power),x*(x**(max(power))-1)/(x-1))
}
这给出了
> foo(c(1,10))
[1] 4 11110
这个有效:
foo <- function(x, power = 1:4){
ind <- 1 + seq_along(power)
power <- matrix(rep(power, length(x)), nrow = length(x), byrow = T)
x <- as.matrix(x)
m <- cbind(x, power)
m <- m[, 1]^m[, ind]
v <- rowSums(m)
return(v)
}
foo(x = c(1, 10))
## [1] 4 11110
运行速度比使用 sapply(x foo)
快约 8.5 倍(当 foo
是长度为 == 1,000,000 的向量时)。来晚了,不知道各位能不能再优化一下内部结构