[英]Subset list of vectors by position in a vectorized way
我有一個向量列表,我試圖選擇(例如)每個向量中的第2和第4個元素。 我可以使用lapply
來做到這lapply
:
list_of_vec <- list(c(1:10), c(10:1), c(1:10), c(10:1), c(1:10))
lapply(1:length(list_of_vec), function(i) list_of_vec[[i]][c(2,4)])
[[1]]
[1] 2 4
[[2]]
[1] 9 7
[[3]]
[1] 2 4
[[4]]
[1] 9 7
[[5]]
[1] 2 4
但有沒有辦法以矢量化的方式做到這一點 - 避免應用函數之一? 我的問題是我的實際list_of_vec
相當長,所以lapply
需要一段時間。
選項1 @ Athe使用do.call
的聰明解決方案?:
do.call(rbind, list_of_vec)[ ,c(2,4)]
選項2更有效地使用lapply
:
lapply(list_of_vec, `[`, c(2, 4))
選項3矢量化解決方案:
starts <- c(0, cumsum(lengths(list_of_vec)[-1]))
matrix(unlist(list_of_vec)[c(starts + 2, starts + 4)], ncol = 2)
選項4您想要改進的lapply
解決方案:
lapply(1:length(list_of_vec), function(i) list_of_vec[[i]][c(2,4)])
我將測試一些數據集:
# The original data
list_of_vec <- list(c(1:10), c(10:1), c(1:10), c(10:1), c(1:10))
# A long list with short elements
list_of_vec2 <- rep(list_of_vec, 1e5)
# A long list with long elements
list_of_vec3 <- lapply(list_of_vec, rep, 1e3)
list_of_vec3 <- rep(list_of_vec3, 1e4)
原始清單 :
Unit: microseconds
expr min lq mean median uq max neval cld
o1 2.276 2.8450 3.00417 2.845 3.129 10.809 100 a
o2 2.845 3.1300 3.59018 3.414 3.414 23.325 100 a
o3 3.698 4.1250 4.60558 4.267 4.552 20.480 100 a
o4 5.689 5.9735 17.52222 5.974 6.258 1144.606 100 a
更長的清單,短元素 :
Unit: milliseconds
expr min lq mean median uq max neval cld
o1 146.30778 146.88037 155.04077 149.89164 159.52194 184.92028 10 b
o2 185.40526 187.85717 192.83834 188.42749 190.32103 213.79226 10 c
o3 26.55091 27.27596 28.46781 27.48915 28.84041 32.19998 10 a
o4 407.66430 411.58054 426.87020 415.82161 437.19193 473.64265 10 d
更長的清單,長元素 :
Unit: milliseconds
expr min lq mean median uq max neval cld
o1 4855.59146 4978.31167 5012.0429 5025.97619 5072.9350 5095.7566 10 c
o2 17.88133 18.60524 103.2154 21.28613 195.0087 311.4122 10 a
o3 855.63128 872.15011 953.8423 892.96193 1069.7526 1106.1980 10 b
o4 37.92927 38.87704 135.6707 124.05127 214.6217 276.5814 10 a
看起來像向量化解決方案如果列表很長並且元素很短lapply
勝出,但lapply
是具有更長元素的長列表的明顯贏家。 一些選項輸出列表,其他選項輸出矩陣。 所以請記住你想要的輸出。 祝好運!!!
如果列表由長度相同的向量組成,則可以先將其轉換為矩陣,然后獲取所需的列。
matrix_of_vec <- do.call(rbind,list_of_vec)
matrix_of_vec[ ,c(2,4)]
否則我擔心你必須堅持申請家庭。 最有效的方法是使用並行包進行並行計算(令人驚訝)。
corenum <- parallel::detectCores()-1
cl<-parallel::makeCluster(corenum)
parallel::clusterExport(cl,"list_of_vec"))
parallel::parSapply(cl,list_of_vec, '[', c(2,4) )
在這段代碼中, '['
是子集函數的名稱, c(2,4)
是傳遞給它的參數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.