2014-11-03 13 views
6

Supponiamo di avere i seguenti datiricampionamento da id soggetti di R in

set.seed(123) 
dat <- data.frame(var1=c(10,35,13,19,15,20,19), id=c(1,1,2,2,2,3,4)) 
(sampledIDs <- sample(min(dat$id):max(dat$id), size=3, replace=TRUE)) 
> [1] 2 4 2 

Il sampledIDs è un vettore di id che viene campionato (con sostituzione) da dat$id. Ho bisogno del codice che si traduce in (e funziona anche per un grande insieme di dati con più variabili):

var1 id 
    13 2 
    19 2 
    15 2 
    19 4 
    13 2 
    19 2 
    15 2 

Il codice dat[which(dat$id%in%sampledIDs),] non mi dà quello che voglio, dal momento che il risultato di questo codice è

var1 id 
    13 2 
    19 2 
    15 2 
    19 4 

dove il soggetto con dat$id==2 appare una sola volta in questi dati (ho capito perché questo è il risultato, ma non so come ottenere ciò che voglio). Qualcuno può aiutarmi per favore?


EDIT: Grazie per le risposte, qui il tempo di esecuzione di tutte le risposte (per coloro che sono interessati):

                test replications elapsed relative user.self 
3 dat[unlist(lapply(sampledIDs, function(x) which(x == dat$id))), ]   1000 0.67 1.000  0.64 
1 dat[which(sapply(sampledIDs, "==", dat$id), arr.ind = TRUE)[, 1], ]   1000 0.67 1.000  0.67 
2  do.call(rbind, split(dat, dat$id)[as.character(sampledIDs)])   1000 1.83 2.731  1.83 
4        setkey(setDT(dat), id)[J(sampledIDs)]   1000 1.33 1.985  1.33 
+1

+1 per fornire l'analisi delle risposte, nonché un problema chiaramente dichiarato. –

+0

Qual era la dimensione dei dati? Stavi citando che hai un grosso numero di dati –

+0

Non proprio grandi dati, ma più osservazioni/variabili che nell'esempio: ''data.frame': \t 4454 obs. di 15 variabili'. – Giuseppe

risposta

5

Questo sarebbe probabilmente l'approccio più veloce per un grande dati impostati utilizzando data.tablebinary search

library(data.table) 
setkey(setDT(dat), id)[J(sampledIDs)] 
# var1 id 
# 1: 13 2 
# 2: 19 2 
# 3: 15 2 
# 4: 19 4 
# 5: 13 2 
# 6: 19 2 
# 7: 15 2 

Edit: Ecco un punto di riferimento per un non set di dati così grande (1e + 05 righe) che illustra quale è il chiaro vincitore

library(data.table) 
library(microbenchmark) 

set.seed(123) 
n <- 1e5 
dat <- data.frame(var1 = sample(seq_len(100), n, replace = TRUE), id = sample(seq_len(10), n, replace = TRUE)) 
(sampledIDs <- sample(min(dat$id) : max(dat$id), size = 3, replace = TRUE)) 
dat2 <- copy(dat) 

Sven1 <- function(dat) dat[unlist(lapply(sampledIDs, function(x) which(x == dat$id))), ] 
Sven2 <- function(dat) dat[which(sapply(sampledIDs, "==", dat$id), arr.ind = TRUE)[ , 1], ] 
flodel <- function(dat) do.call(rbind, split(dat, dat$id)[as.character(sampledIDs)]) 
David <- function(dat2) setkey(setDT(dat2), id)[J(sampledIDs)] 

Res <- microbenchmark(Sven1(dat), 
         Sven2(dat), 
         flodel(dat), 
         David(dat2)) 
Res 
# Unit: milliseconds 
#  expr  min  lq median  uq  max neval 
# Sven1(dat) 4.356151 4.817557 6.715533 7.313877 45.407768 100 
# Sven2(dat) 9.750984 12.385677 14.324671 16.655005 54.797096 100 
# flodel(dat) 36.097602 39.680006 42.236017 44.314981 82.261879 100 
# David(dat2) 1.813387 2.068749 2.154774 2.335442 8.665379 100 

boxplot(Res) 

enter image description here


Se, ad esempio, vorremmo assaggiare più quindi solo 3 Ids, ma consente di dire, 10, il punto di riferimento diventa ridicolo

(sampledIDs <- sample(min(dat$id) : max(dat$id), size = 10, replace = TRUE)) 
[1] 7 6 10 9 5 9 5 3 7 3 
# Unit: milliseconds 
#  expr  min   lq  median   uq  max neval 
# Sven1(dat) 80.124502 89.141162 97.908365 104.111738 175.40919 100 
# Sven2(dat) 99.010410 127.797966 159.404395 170.751069 209.96887 100 
# flodel(dat) 129.722435 144.847505 157.737362 178.242103 232.41293 100 
# David(dat2) 2.431682 2.721038 2.855103 3.057796 19.60826 100 

enter image description here

3

si può fare:

do.call(rbind, split(dat, dat$id)[as.character(sampledIDs)]) 
3

One approccio:

dat[unlist(lapply(sampledIDs, function(x) which(x == dat$id))), ] 
#  var1 id 
# 3  13 2 
# 4  19 2 
# 5  15 2 
# 7  19 4 
# 3.1 13 2 
# 4.1 19 2 
# 5.1 15 2 

Un approccio alternativo:

dat[which(sapply(sampledIDs, "==", dat$id), arr.ind = TRUE)[ , 1], ] 
Problemi correlati