我有一个向量列表,我试图选择(例如)每个向量中的第二个和第四个元素。我可以使用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
但是有一种方法可以向量化的方式进行操作-避免使用apply函数之一?我的问题是我的实际list_of_vec
相当长,因此lapply
需要一段时间。
答案 0 :(得分:2)
选项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
显然是赢家。一些选项输出列表,其他选项则输出矩阵。因此,请记住您想要的输出是什么。祝你好运!
答案 1 :(得分:1)
如果列表由相同长度的向量组成,则可以先将其转换为矩阵,然后获取所需的列。
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)
是您传递给它的参数。