簡體   English   中英

我是否需要減少 R 中的 for 循環以及如何減少?

[英]Do I need to reduce for-loop in R and how?

I am a freshman in R coding, but I've heard that loop in R is much slower than other language like Python or C. 那么在R中編碼時是否需要減少循環?

具體來說,在這個模擬代碼中,我該如何提高我糟糕的編碼技能?

library(moments)
n <- c(5:20)
m <- c(1:10000)
skew <- c()
kurt <- c()
for(num in n){
  beta1 <- c()
  beta2 <- c()
  for(i in m){
    set.seed(num * 10000 + i)
    x <- rnorm(num, mean = 0, sd = 1)
    beta1 <- c(beta1, skewness(x))
    beta2 <- c(beta2, kurtosis(x) - 3)
  }
  skew <- c(skew, quantile(beta1, probs = c(0, 0.01, 0.1, 0.2, 0.5, 0.8, 0.9, 0.99, 1)))
  kurt <- c(kurt, quantile(beta2, probs = c(0, 0.01, 0.1, 0.2, 0.5, 0.8, 0.9, 0.99, 1)))
}

在 R 中不使用for循環的一個主要優點是利用其矢量化。 So while in languages like Python or C you code vector calculations for each element of a vector, in R you can conveniently code the calculation for the entire vector at once (see Edit below) and also reduce computation time by actually using fast underlying C, Fortran等功能。

我會將您想要對單個樣本大小進行的所有計算放入 function statFUN並將其放入lapply以循環遍歷樣本大小的向量n

對於分位數,我們可以使用我推薦的applymatrixStats::rowQuantiles ,因為它更快。

在運行lapply之前應該只需要一次res set.seed() ,所有結果都可以用那個種子重現。

n <- 5:20  ## different sample sizes
m <- 1e4   ## number of replications in each iteration
probs <- c(0, 0.01, 0.1, 0.2, 0.5, 0.8, 0.9, 0.99, 1)

library(moments)
library(matrixStats)

statFUN <- function(i, num) {
  r <- replicate(i, {
    x <- rnorm(num, mean=0, sd=1)
    c(kurt=kurtosis(x) - 3, skew=skewness(x))
  })
  # t(apply(r, 1, quantile, probs=probs))  ## using base R
  rowQuantiles(r, probs=probs)  ## using matrixStats
}

set.seed(42)
res <- lapply(n, statFUN, m)

結果

結果是每個樣本大小的峰度分res和偏度分位數的列表。

res
# [[1]]
#               0%          1%         10%         20%
# kurt -0.04710729 -0.04658709 -0.04190536 -0.03670343
# skew -0.03045563 -0.02969417 -0.02284104 -0.01522645
#              50%          80%           90%         99%
# kurt -0.03388803 -0.006250622  1.068998e-03 0.007656657
# skew -0.01028591 -0.006132523 -5.883157e-05 0.005407491
#             100%
# kurt 0.008388619
# skew 0.006014860
# 
# [[2]]
#               0%          1%         10%         20%
# kurt -0.09089922 -0.08859363 -0.06784329 -0.04478737
# skew -0.03252828 -0.03165837 -0.02382918 -0.01513009
#               50%          80%        90%        99%
# kurt -0.023634727 -0.005277533 0.01038904 0.02448896
# skew  0.003433589  0.017711708 0.01947178 0.02105585
#            100%
# kurt 0.02605562
# skew 0.02123186
#
# [...]

在哪里

length(res)
# [1] 16

編輯

這里有一個小例子來更好地說明 R 中矢量化的實際含義。 雖然在大多數編程語言中,兩個向量的相加是按元素編碼的,但在 R 中,向量的相加可以直接編碼(即以向量化的方式)。

a <- 1:9
b <- rev(a)

## element wise addition of vectors a and b
s1 <- c()
for (i in seq(a)) {
  s1[i] <- a[i] + b[i]
}
s1
# [1] 10 10 10 10 10 10 10 10 10

## direct addition of vectors a and b (i.e. vectorized)
s2 <- a + b
s2
# [1] 10 10 10 10 10 10 10 10 10

我們可以查看*apply系列,而不是for循環。 但是,大多數情況下仍然隱藏着 for 循環。 (要查看 function 代碼類型,例如lapply不帶括號或任何東西。)

您可能想閱讀例如那些很棒的問答:

注意:向量化實際上只是 R 的語言特性。 所謂的“向量化函數”通常在內部使用 C、Fortran 等代碼,在這些代碼中你仍然可以在最后找到 for 循環,但使用的是更快的語言。 例如,參見sum()時調用 summary.c的源代碼

暫無
暫無

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

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