简体   繁体   English

如何避免在 R 中的用户定义函数上使用 sapply()

[英]How to avoid using sapply() on user defined functions in R

I am a beginner with R programming.我是 R 编程的初学者。 Recently I wrote a user-defined function as follows:最近写了一个用户自定义的function如下:

foo <- function(x){
power <- 1:4
sum(x^power)
}

This function works fine when x is a single number.当 x 是单个数字时,此 function 工作正常。 For example, when x = 1 , the result is 4 and when x = 10 the result is 11110. However, this function doesn't work with vectors.例如,当x = 1时,结果为 4,当x = 10时,结果为 11110。但是,此 function 不适用于向量。 For example, when x <- c(1, 10) , the result is 10102 which is not what I want.例如,当x <- c(1, 10)时,结果是 10102 这不是我想要的。 My desire result is a vector such as 4 11110 .我想要的结果是一个向量,例如4 11110 I know this problem can be solved by using sapply() on function or add a for-loop inside the function, but I think there might be another way to rewrite the function without using loops or "apply" functions.我知道这个问题可以通过在 function 上使用sapply()或在 function 中添加一个 for 循环来解决,但我认为可能有另一种方法来重写 ZC1C425268E68385D1AB4Z5074 没有循环的函数。 I have tried different ways to rewrite the function but nothing works, can somebody help me to solve the problem?我尝试了不同的方法来重写 function 但没有任何效果,有人可以帮我解决问题吗? Thanks!谢谢!

Mathematically, a simple and more straightforward approach is to rewrite foo function like below在数学上,一个简单直接的方法是重写foo function 如下

foo <- function(x) {
  power <- 1:4
  ifelse(x==1,max(power),x*(x**(max(power))-1)/(x-1))
}

which gives这使

> foo(c(1,10))
[1]     4 11110

I don't think there is a way to avoid any kind of implicit or explicit loop since power is a vector and you are passing x to it which is another vector.我认为没有办法避免任何类型的隐式或显式循环,因为power是一个向量,而您将x传递给它,它是另一个向量。

Here are few options:这里有几个选项:

  1. Your best bet is sapply (which you have already figured out).你最好的选择是sapply (你已经想通了)。
sapply(c(1, 10), foo)
#[1]     4 11110
  1. Another way is to use Vectorize where you cannot "see" the loop but it still loop beneath as it is a wrapper to mapply .另一种方法是使用Vectorize ,您无法“看到”循环,但它仍然在下方循环,因为它是mapply的包装器。
Vectorize(foo)(c(1, 10))
#[1]     4 11110
  1. Using outer :使用outer
foo <- function(x){
  power <- 1:4
  rowSums(outer(x, power, `^`))
}
foo(c(1, 10))
#[1]     4 11110

and obviously you can write a simple for loop as well and pass c(1, 10) to it.显然你也可以编写一个简单for循环并将c(1, 10)传递给它。

This works:这有效:

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

Runs about 8.5x faster than using sapply(x foo) (when foo is a vector of length == 1,000,000).运行速度比使用sapply(x foo)快大约 8.5 倍(当foo是长度 == 1,000,000 的向量时)。 It's a bit late here, so I don't know whether you could optimise the internals a little better.这里有点晚了,所以我不知道你是否可以更好地优化内部结构。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM