2016-03-11 44 views
0

這裏的disagregation的一些代碼生成的data.frame秒的列表,然後將該原始列表轉換成其中每個列表元素的新列表中的每個數據幀的行的列表。向量化並行&列表

例如,
- l1具有長度10,每個元素是具有1000行的data.frame
- l2是長度爲1000(nrow(l1[[k]]))的列表,並且每個元素是從l1

l1 <- vector("list", length= 10) 
set.seed(65L) 
for (i in 1:10) { 
    l1[[i]] <- data.frame(matrix(rnorm(10000),ncol=10)) 
} 

l2 <- vector(mode="list", length= nrow(l1[[1]])) 
for (i in 1:nrow(l1[[1]])) { 
    l2[[i]] <- lapply(l1, function(l) return(unlist(l[i,]))) 
} 
元素包含行向量長度10( length(l1))的 list

編輯爲了闡明如何l1涉及l2,這裏是語言不可知的代碼。

for (j in 1:length(l1) { 
    for (i in 1:nrow(l1[[1]]) { # where nrow(l1[[1]]) == nrow(l1[[k]]) k= 2,...,10 
    l2[[i]][[j]] <- l1[[j]][i,] 
    } 
} 

如何加快通過矢量化或並行創建l2嗎?我遇到的問題是parallel::parLapplyLB拆分列表;然而,我不想拆分清單l1,我想要做的是拆分l1的每個元素內的行。一箇中間解決方案將通過使用一些*apply函數來替換for循環來矢量化我當前的方法。這顯然可以擴展到並行解決方案。

如果我可以接受的解決方案之前解決這個我自己,我會在這裏發佈我的回答。

+0

不分配給全球環境一流,添加到列表中,然後從全球環境中刪除。直接指定列表(在for循環中'l1 [[i]] < - ...')或者只是'l1 = replicate(10,data.frame(matrix(rnorm(10000),ncol = 10)),簡化= F)' – Gregor

+1

你真正的數據框是否有相同的列數? – Tensibai

+0

@Tensibai'l1'中的每個元素保證具有相同的行數但不是相同的列數 –

回答

1

我會徹底打破結構,並通過split重建第二個列表。這種方法需要更多的內存比原來的,但至少在給定的例子是>快10倍:

sgibb <- function(x) { 
    ## get the lengths of all data.frames (equal to `sapply(x, ncol)`) 
    n <- lengths(x) 
    ## destroy the list structure 
    y <- unlist(x, use.names = FALSE) 
    ## generate row indices (stores the information which row the element in y 
    ## belongs to) 
    rowIndices <- unlist(lapply(n, rep.int, x=1L:nrow(x[[1L]]))) 
    ## split y first by rows 
    ## and subsequently loop over these lists to split by columns 
    lapply(split(y, rowIndices), split, f=rep.int(seq_along(n), n)) 
} 

alex <- function(x) { 
    l2 <- vector(mode="list", length= nrow(x[[1]])) 
    for (i in 1:nrow(x[[1]])) { 
    l2[[i]] <- lapply(x, function(l) return(unlist(l[i,]))) 
    } 
    l2 
} 

## check.attributes is need because the names differ 
all.equal(alex(l1), sgibb(l1), check.attributes=FALSE) 

library(rbenchmark) 
benchmark(alex(l1), sgibb(l1), order = "relative", replications = 10) 
#  test replications elapsed relative user.self sys.self user.child sys.child 
#2 sgibb(l1)   10 0.808 1.000  0.808  0   0   0 
#1 alex(l1)   10 11.970 14.814 11.972  0   0   0 
+0

非常感謝!我在一個真正的測試數據集上獲得了8.57倍的改進 –