我想找到一種有效的操作來在串列中進行以下查找:
L = list(10:15,11:20)
a = c(3,7)
b = numeric()
for(i in 1:length(a)) b[i] = L[[i]][a[i]]
我認為for回圈效率低下,我想這可以使用例如sapply. L我的主要目標是在很長的時候有效地做到這一點。
uj5u.com熱心網友回復:
另一種apply方法是sapply().
sapply(1:length(a), function(x) L[[x]][a[x]])
[1] 12 17
uj5u.com熱心網友回復:
我們可以使用
library(dplyr)
stack(setNames(L, a)) %>%
group_by(ind) %>%
summarise(out = values[[as.numeric(as.character(first(ind)))]]) %>%
pull(out)
[1] 12 17
或者base R使用vapply哪個會更快
vapply(seq_along(L), \(i) L[[i]][a[i]], numeric(1))
[1] 12 17
或imap用作緊湊選項
library(purrr)
imap_dbl(setNames(L, a), ~ .x[as.numeric(.y)])
3 7
12 17
uj5u.com熱心網友回復:
您可以使用Map或mapply。由于mapply可以自動簡化為向量,因此我們可以在這里b一次性使用它:
b <- mapply(function(list_members, indices) list_members[indices],
list_members = L, indices = a, SIMPLIFY = TRUE)
b
#> [1] 12 17
uj5u.com熱心網友回復:
使用unlist、cumsum和的基本 R 矢量化解lengths:
b <- unlist(L)[a c(0, cumsum(lengths(L)[1:(length(L) - 1L)]))]
基準測驗(折騰Rcpp解決方案)*
library(purrr)
L <- lapply(sample(4:10, 1e5, TRUE), seq)
a <- sapply(lengths(L), function(x) sample(x, 1))
Rcpp::cppFunction("IntegerVector ListIndex(const List& L, const IntegerVector& a) {
const int n = a.size();
IntegerVector b = n;
for (int i = 0; i < n; i ) b(i) = as<IntegerVector>(L[i])(a(i) - 1);
return b;
}")
microbenchmark::microbenchmark(sapply = sapply(1:length(a), function(x) L[[x]][a[x]]),
vapply = vapply(seq_along(L), function(i) L[[i]][a[i]], numeric(1)),
purr = imap_dbl(setNames(L, a), ~ .x[as.numeric(.y)]),
unlist = unlist(L)[a c(0, cumsum(lengths(L)[1:(length(L) - 1L)]))],
rcpp = ListIndex(L, a))
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> sapply 100.0269 113.1525 124.18244 119.43035 127.0836 317.3143 100
#> vapply 99.5311 108.3551 115.51503 112.98505 116.9035 283.3678 100
#> purr 224.4690 236.1904 249.42162 241.49435 256.4136 438.9548 100
#> unlist 28.8191 29.5713 30.56450 30.19490 31.1107 43.1079 100
#> rcpp 22.1024 22.3875 24.23332 22.68845 23.2310 44.0746 100
*我無法獲得 akrun 的dplyr解決方案來處理更大的向量。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/454351.html
