簡體   English   中英

替換R中的嵌套for循環的最佳方法

[英]Best way to replace a nested for loop in R

R中的for循環通常被認為是緩慢的:很難避免意外的內存讀/寫。 但是,如何替換嵌套的for循環? 哪種方法最好?

請注意,這是一個通用問題:下面的f函數只是一個示例,它可能更加復雜或返回不同的對象。 我只想看看人們可以采用R來避免嵌套for循環的所有不同方法。

考慮以下示例:

al <- c(2,3,4)
bl <- c("foo", "bar")
f <- function(n, c) { #Just one simple example function, could be much more complicated
    data.frame(n=n, c=c, val=n*nchar(c))
}
d <- data.frame()
for (a in al) { 
    for (b in bl) {
        d <- rbind(d, f(a, b))
        #one could undoubtedly do this a lot better
        #even keeping to nested for loops
    }
}

一個人可以用這種絕對可怕的方式替換它(僅作為一個粗略的例子):

eg <- expand.grid(al, bl)
d <- do.call(rbind,
    lapply(1:dim(eg)[1],
           function(i) {f(as.numeric(eg[i,1]), as.character(eg[i, 2]))}
           )
)

或使用library(purrr) ,它的library(purrr)

d <- map_dfr(bl, function(b) map2_dfr(al, b, f))

...有無數種不同的方法。 哪一個最簡單,哪一個最快?

這是筆記本電腦上以前三種方法的性能的快速評估: 在此處輸入圖片說明

只需使用expand.gridnchar向量化。 不需要forapply循環:

eg <- expand.grid(c=bl, n=al, stringsAsFactors = FALSE)
eg$val <- eg$n * nchar(eg$c)

# RE-ORDER COLUMNS
eg <- eg[c("n", "c", "val")]

或單行transform

eg <- transform(expand.grid(c=bl, n=al, stringsAsFactors = FALSE),
                val=n * nchar(c))[c("n", "c", "val")]

並且如果在f函數中設置stringsAsFactors = FALSE

f <- function(n, c) {
  data.frame(n=n, c=c, val=n*nchar(c), stringsAsFactors = FALSE)
}

輸出等效於for循環數據幀:

all.equal(d, eg)
# [1] TRUE
n=rep(al,length(bl));e=rep(bl,length(al))
> cbind.data.frame(n,c=e,val=mapply(function(x,y)x*nchar(y),n,e))
  n   c val
1 2 foo   6
2 3 bar   9
3 4 foo  12
4 2 bar   6
5 3 foo   9
6 4 bar  12

要么:

n=rep(al,length(bl));e=rep(bl,length(al))
cbind.data.frame(n,c=e,val=c(outer(al,bl,function(x,y)x*nchar(y))))
  n   c val
1 2 foo   6
2 3 bar   9
3 4 foo  12
4 2 bar   6
5 3 foo   9
6 4 bar  12

暫無
暫無

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

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