/ / R maneira rápida de extrair elementos das listas de List - r, list

R maneira rápida de extrair elementos das listas de List-r, list

Olá a todos, Eu estou trabalhando com grande lista, que contém listas. Cada uma das sub-listas contém n elementos. Eu sempre quero pegar o terceiro, por exemplo

l = list()
l[[1]] = list(A=runif(1), B=runif(1), C=runif(1))
l[[2]] = list(A=runif(1), B=runif(1), C=runif(1))
l[[3]] = list(A=runif(1), B=runif(1), C=runif(1))

res = sapply(l, function(x) x$C)
res = sapply(l, function(x) x[[3]]) #alternative

Mas minha lista contém vários milhares de elementos e estou realizando essa operação várias vezes. Então, há uma maneira mais rápida de fazer a operação acima?

O melhor é

Mario

Respostas:

6 para resposta № 1

Se você fizer isso várias vezes, então seria melhor converter sua lista para uma estrutura mais fácil como data.table.

library(data.table)
DT=rbindlist(l);
res = DT$C
# or if you prefer the 3rd element, not necessarily called "C" then:
res = DT[[3]] # or DT[,C] which might be faster. Please check @richard-scriven comment

Alternativamente, se você quiser manter a base R, você pode usar rbind

res = do.call(rbind.data.frame, l)$C # or [[3]]

Isso tornaria as coisas mais fáceis?

ATUALIZAR

Aqui estão alguns benchmarks mostrando diferentes soluções para o problema:

preparações:

library(data.table)
library(microbenchmark)

# creating a list and filling it with items
nbr   = 1e5;
l     = vector("list",nbr)
for (i in 1:nbr) {
l[[i]] = list(A=runif(1), B=runif(1), C=runif(1))
}

# creating data.frame and data.table versions
DT <- rbindlist(l)
DF <- data.frame(rbindlist(l))

avaliação comparativa:

# doing the benchmarking
op <-
microbenchmark(
LAPPLY.1 = lapply(l, function(x) x$C),
LAPPLY.2 = lapply(l, `[`, "C"),
LAPPLY.3 = lapply(l, `[[`, "C"),

SAPPLY.1 = sapply(l, function(x) x$C),
SAPPLY.2 = sapply(l, function(x) x[[3]]),
SAPPLY.3 = sapply(l, `[[`, 3),
DT.1     = rbindlist(l)$C,

DT.2     = DT$C,
DF.2     = DF$C,
times    = 100
)

resultados:

op

## Unit: microseconds
## expr        min     lq   mean median     uq   max neval
## LAPPLY.1 124088 142390 161672 154415 163240 396761  100
## LAPPLY.2 111397 134745 156012 150062 165229 364539  100
## LAPPLY.3  66965  71608  82975  77329  84949 323041  100
## SAPPLY.1 133220 149093 166653 159222 172495 311857  100
## SAPPLY.2 105917 119533 137990 133364 139216 346759  100
## SAPPLY.3  70391  74726  81910  80520  85792 110062  100
## DT.1      46895  48943  49113  49178  49391  51377  100
## DT.2          8     18     37     47     49     58  100
## DF.2          7     13     33     40     42     82  100

(1) Em geral, seria melhor usar uma tabela como estrutura, como data.frame ou data.table, em primeiro lugar, selecionando as colunas desses custos com o mínimo de tempo.

(2) Se isso não for possível, é melhor primeiro transformar a lista em um data.frame ou data.table para extrair os valores em uma única operação.

(3) Interessantemente usando solavanco ou lapidado com a base R (otimizada) [[-função resulta em tempos de processo que são apenas duas vezes mais ruins do que usando rbind e que extraem os valores como coluna.