我需要有效地找到两个向量之间的索引(而不是逻辑向量)。我可以这样做:
which(c("a", "q", "f", "c", "z") %in% letters[1:10])
以同样的方式,最好使用which.max
找到最大数字的位置:
which(c(1:8, 10, 9) %in% max(c(1:8, 10, 9)))
which.max(c(1:8, 10, 9))
我想知道我是否有最有效的方法来找到2个向量中匹配项的位置。
编辑: 根据下面的问题/评论。我在矢量列表上运行。这个问题涉及对句子进行操作,如下所示,这些句子被分解成一个单词。该列表可以包含10000-20000或更多字符向量。然后根据该索引,我将获得之前的4个单词和索引之后的4个单词并计算得分。
x <- list(c('I', 'like', 'chocolate', 'cake'), c('chocolate', 'cake', 'is', 'good'))
y <- rep(x, 5000)
lapply(y, function(x) {
which(x %in% c("chocolate", "good"))
})
答案 0 :(得分:4)
使用data.table
这是一种相对较快的方法:
require(data.table)
vv <- vapply(y, length, 0L)
DT <- data.table(y = unlist(y), id = rep(seq_along(y), vv), pos = sequence(vv))
setkey(DT, y)
# OLD CODE which will not take care of no-match entries (commented)
# DT[J(c("chocolate", "good")), list(list(pos)), by=id]$V1
setkey(DT[J(c("chocolate", "good"))], id)[J(seq_along(vv)), list(list(pos))]$V1
首先,我们将您的列表重新列入名为DT
的{{1}}列中。此外,我们还创建了另外两个名为y
和id
的列。 pos
告诉列表中的索引,id
告诉pos
中的位置。然后,通过在id
上创建关键列,我们可以执行快速子集化。通过此子集,我们将为每个id
获得相应的pos
值。在我们为列表中的每个id
收集所有pos
然后只输出列表列(V1)之前,我们通过将键设置为{{{}来处理那些与我们的查询不匹配的条目。 1}}首先对id
的所有可能值进行子集化和子集化(因为对于不存在的条目,这将导致id
。
id
代码进行基准测试:NA
答案 1 :(得分:2)
C ++答案比单个字符更快,但我认为使用字符串向量引入了足够的开销,现在它变慢了:
char1 <- c("a", "q", "f", "c", "z")
char2 <- letters[1:10]
library(inline)
cpp_whichin_src <- '
Rcpp::CharacterVector xa(a);
Rcpp::CharacterVector xb(b);
int n_xa = xa.size();
int n_xb = xb.size();
NumericVector res(n_xa);
std::vector<std::string> sa = Rcpp::as< std::vector<std::string> >(xa);
std::vector<std::string> sb = Rcpp::as< std::vector<std::string> >(xb);
for(int i=0; i < n_xa; i++) {
for(int j=0; j<n_xb; j++) {
if( sa[i] == sb[j] ) res[i] = i+1;
}
}
return res;
'
cpp_whichin <- cxxfunction(signature(a="character",b="character"), cpp_whichin_src, plugin="Rcpp")
which.in_cpp <- function(char1, char2) {
idx <- cpp_whichin(char1,char2)
idx[idx!=0]
}
which.in_naive <- function(char1, char2) {
which(char1 %in% char2)
}
which.in_CW <- function(char1, char2) {
unlist(sapply(char2,function(x) which(x==char1)))
}
which.in_cpp(char1,char2)
which.in_naive(char1,char2)
which.in_CW(char1,char2)
**基准**
library(microbenchmark)
microbenchmark(
which.in_cpp(char1,char2),
which.in_naive(char1,char2),
which.in_CW(char1,char2)
)
set.seed(1)
cmb <- apply(combn(letters,2), 2, paste,collapse="")
char1 <- sample( cmb, 100 )
char2 <- sample( cmb, 100 )
Unit: microseconds
expr min lq median uq max
1 which.in_cpp(char1, char2) 114.890 120.023 126.6930 135.5630 537.011
2 which.in_CW(char1, char2) 697.505 725.826 766.4385 813.8615 8032.168
3 which.in_naive(char1, char2) 17.391 20.289 22.4545 25.4230 76.826
# Same as above, but with 3 letter combos and 1000 sampled
Unit: microseconds
expr min lq median uq max
1 which.in_cpp(char1, char2) 8505.830 8715.598 8863.3130 8997.478 9796.288
2 which.in_CW(char1, char2) 23430.493 27987.393 28871.2340 30032.450 31926.546
3 which.in_naive(char1, char2) 129.904 135.736 158.1905 180.260 3821.785