簡體   English   中英

如何使用 *apply 系列的 function 計算余弦循環?

[英]How to compute cosine for loop with function from *apply family?

我需要將此 for 循環轉換為小型循環,因為 50k 帳戶需要更多時間,並且我需要使用 *apply 系列中的 function 來提高性能。

a <- data.frame(a=c(1, 2, 2, 3), b=c(2, 3, 4, 5))
b <- data.frame(a=c(1), b=c(2))

##### **by using apply function I need convert this code**
library('lsa')
res <- c()
for (i in 1:nrow(a)) {
  cosinevalue <- cosine(as.numeric(a[i, ]), as.numeric(b))[1]
  res <- rbind(res, as.numeric(cosinevalue))
}

a$cosinevalue <- res

使用vapply

vapply(seq_len(nrow(a)), \(i) lsa::cosine(unlist(a[i, ]), unlist(b)), numeric(1))
# [1] 1.0000000 0.9922779 1.0000000 0.9970545

或者Vectorize它,它快三倍。

Vectorize(lsa::cosine, vectorize.args='x')(as.data.frame(t(a)), unlist(b)) |> unname()
# [1] 1.0000000 0.9922779 1.0000000 0.9970545

我們也可以使用“apply()”:

a <- data.frame(a=c(1,2,2,3),b=c(2,3,4,5))
b <- data.frame(a=c(1),b=c(2))

library(lsa)

a$cosinevalue <- apply(a, MARGIN = 1, FUN =  function(x) cosine(as.numeric(x), as.numeric(b))[1])

a 
#>   a b cosinevalue
#> 1 1 2   1.0000000
#> 2 2 3   0.9922779
#> 3 2 4   1.0000000
#> 4 3 5   0.9970545

您也可以重寫循環並預定義 output 向量:

library(lsa)

out <- numeric(nrow(a))

for (i in 1:nrow(a)){
  out[i] <- cosine(as.numeric(a[i,]), as.numeric(b))[1]
}
a$cosinevalue <- out

a
#>   a b cosinevalue
#> 1 1 2   1.0000000
#> 2 2 3   0.9922779
#> 3 2 4   1.0000000
#> 4 3 5   0.9970545

下面是我的兩種方法和@jay.sf 的兩種方法以及原始舊循環之間的基准。 我們可以看到apply最快,而循環最慢。

bench::mark(
  iterations = 100,
  check = FALSE,
  
  "apply" = apply(a, MARGIN = 1, FUN =  function(x) cosine(as.numeric(x), as.numeric(b))[1]),
  
  "vapply" =  vapply(seq_len(nrow(a)), \(i) cosine(unlist(a[i, ]), unlist(b)), numeric(1)),
  
  "vectorize" = Vectorize(cosine, vectorize.args = 'x')(as.data.frame(t(a)), unlist(b)) |> unname(),
  
  "for_loop_new"= {
    out <- numeric(nrow(a))
    for (i in seq_along(a)){
      out[i] <- cosine(as.numeric(a[i,]), as.numeric(b))[1]
    }
  },
  "for_loop_old" = {
    res <- c()
    for (i in 1:nrow(a)) {
      cosinevalue <- cosine(as.numeric(a[i, ]), as.numeric(b))[1]
      res <- rbind(res, as.numeric(cosinevalue))
    }
  }
)
#> # A tibble: 5 x 6
#>   expression        min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>   <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 apply         116.7us  120.7us     8157.   125.7KB      0  
#> 2 vapply        194.6us 199.85us     4923.    39.2KB      0  
#> 3 vectorize     293.7us  302.5us     3258.    48.8KB     32.9
#> 4 for_loop_new   3.48ms   3.56ms      263.    45.4KB     11.0
#> 5 for_loop_old   4.57ms   4.67ms      204.    29.6KB     13.0

代表 package (v2.0.1) 於 2022 年 9 月 20 日創建

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM