在R中,使用向量化在列表中查找向量的元素
我有一个向量v1在R中,使用向量化在列表中查找向量的元素,r,vectorization,R,Vectorization,我有一个向量v1 v1 = c(1, 200, 4000) 我想在L1向量列表中找到v1元素的索引,即没有循环,其中 > L1 [[1]] [1] 1 2 3 4 [[2]] [1] 100 200 300 400 [[3]] [1] 1000 2000 3000 4000 输出应该是c(1,2,4) 有没有不使用循环或应用(在计算上与使用循环相同)的方法可以做到这一点?我必须对很长的向量执行此操作。我们可以做到 sapply(L1, function(x) which(x %in
v1 = c(1, 200, 4000)
我想在L1向量列表中找到v1元素的索引,即没有循环,其中
> L1
[[1]]
[1] 1 2 3 4
[[2]]
[1] 100 200 300 400
[[3]]
[1] 1000 2000 3000 4000
输出应该是c(1,2,4)
有没有不使用循环或应用(在计算上与使用循环相同)的方法可以做到这一点?我必须对很长的向量执行此操作。我们可以做到
sapply(L1, function(x) which(x %in% v1))
#[1] 1 2 4
或使用矢量化
Vectorize(function(x) which(x %in% v1))(L1)
#[1] 1 2 4
如果将每个元素与另一个元素的对应元素进行检查
mapply(function(x, y) which(x %in% y), L1, v1)
#[1] 1 2 4
正如@nicola提到的,match
也可以用于获取第一个索引。如果有重复的元素,那么哪个有用
mapply(match, v1, L1)
#[1] 1 2 4
或者使用purrr::map2
purrr::map2_int(L1, v1, ~ .x %in% .y %>%
which)
#[1] 1 2 4
你可以试试这样的
v1 = c(1, 200, 4000)
L1 <- list(1:4, 1:4*100, 1:4*1000)
setNames(rep(1:length(L1), times=lengths(L1)), unlist(L1))[as.character(v1)]
# 1 200 4000
# 1 2 3
v1=c(12004000)
L1我们也可以使用
unlist(lapply(L1, function(x) which(x %in% v1)))
#[1] 1 2 4
或使用
unlist(Map(function(x, y) which(x %in% y), L1, v1 ))
#[1] 1 2 4
我们能做到这一点,似乎是目前为止最快的
v1 <- c(1, 200, 4000)
L1 <- list(1:4, 1:4*100, 1:4*1000)
sequence(lengths(L1))[match(v1, unlist(L1))]
# [1] 1 2 4
sequence(lengths(L1))[which(unlist(L1) %in% v1)]
# [1] 1 2 4
应用与使用循环是一样的,在计算效率方面sapply
比Vectorize
要快得多,同时在OP.Lol中对示例进行基准测试。使用match
(效率更高):mapply(match,v1,L1)
@akrun这不是一个选项,而是一个选项:)(使用其中有很多无用的比较)。@akrun没错,但我想这是有意的,否则输出应该(或可能)如果允许多个匹配,请创建一个列表。L1
的元素之间是否有重叠?需要明确的是,值是否可能同时属于L1[[1]]
和L1[[2]]
?另一个问题:您想检查v1
的第一个元素在L1
的第一个元素内的位置,第二个元素与第二个元素的位置,依此类推?是的,这是可能的。L1相对于v1是随机的。好的,谢谢。我上面评论的第二个问题呢?对不起,我没看到。。。是的,v1的每个元素都应该对照LIf的每个元素进行检查,因此,在一般情况下,建议的答案不会给出所需的输出。
library(microbenchmark)
library(tidyverse)
microbenchmark(
akrun_sapply = {sapply(L1, function(x) which(x %in% v1))},
akrun_Vectorize = {Vectorize(function(x) which(x %in% v1))(L1)},
akrun_mapply = {mapply(function(x, y) which(x %in% y), L1, v1)},
akrun_mapply_match = {mapply(match, v1, L1)},
akrun_map2 = {purrr::map2_int(L1, v1, ~ .x %in% .y %>% which)},
CPak = {setNames(rep(1:length(L1), times=lengths(L1)), unlist(L1))[as.character(v1)]},
zacdav = {sequence(lengths(L1))[match(v1, unlist(L1))]},
zacdav_which = {sequence(lengths(L1))[which(unlist(L1) %in% v1)]},
times = 10000
)
Unit: microseconds
expr min lq mean median uq max neval
akrun_sapply 18.187 22.7555 27.17026 24.6140 27.8845 2428.194 10000
akrun_Vectorize 60.119 76.1510 88.82623 83.4445 89.9680 2717.420 10000
akrun_mapply 19.006 24.2100 29.78381 26.2120 29.9255 2911.252 10000
akrun_mapply_match 14.136 18.4380 35.45528 20.0275 23.6560 127960.324 10000
akrun_map2 217.209 264.7350 303.64609 277.5545 298.0455 9204.243 10000
CPak 15.741 19.7525 27.31918 24.7150 29.0340 235.245 10000
zacdav 6.649 9.3210 11.30229 10.4240 11.5540 2399.686 10000
zacdav_which 7.364 10.2395 12.22632 11.2985 12.4515 2492.789 10000