Come faccio a campione n valori al più vicino casuale valore y quando i dati non sono continui?

StackOverflow https://stackoverflow.com/questions/3950877

Domanda

Ho un insieme di dati che include un elenco di specie, la loro conta, e il conteggio dei giorni dal momento in cui l'indagine è iniziata. Dal momento che molti giorni non sono stati campionati, giorno non è continua. Così, per esempio, ci potrebbero essere gli uccelli contati il ??giorno 5,6,9,10,15,34,39 e così via. Ho impostato la prima data per essere giorno 0.

Dati esempio:

species     counts      day
Blue tit    234         0
Blue tit    24          5
Blue tit    45          6
Blue tit    32          9
Blue tit    6           10
Blue tit    98          15
Blue tit    40          34
Blue tit    57          39
Blue tit    81          43
..................

Ho bisogno di bootstrap questi dati e ottenere un set di dati risultante dove mi specificare quando avviare, quale intervallo di procedere in e del numero di punti di campionamento.

Esempio: Diciamo che prendo a caso il giorno 5 come il giorno di inizio, l'intervallo di 30, e il numero di righe da campione 2. Vuol dire che inizierò a 5, aggiungere 30 ad essa, e il look per 2 file di circa 35 giorni (ma non al giorno 35 stesso). In questo caso mi prendo le due righe in cui giorno è 34 e 39.

Avanti aggiungo 30 a 35 e il look per due punti in tutto 65. Sciacquare, ripetere finché non arrivare alla fine del set di dati.

ho scritto questa funzione per fare il campionamento, ma ha difetti (vedi sotto):

resample <- function(x, ...) x[sample.int(length(x), ...)]
 locate_points<- function(dataz,l,n) #l is the interval, n is # points to sample. This is called by another function that specifies start time among other info.
{
   tlength=0
   i=1
    while(tlength<n)   
    {
        low=l-i
        high=l+i
        if(low<=min(dataz$day)) { low=min(dataz$day) }
        if(high>=max(dataz$day)) { high=max(dataz$day) }
        test=resample(dataz$day[dataz$day>low & dataz$day<high & dataz$day!=l])
          tlength=length(test)
         i=i+1
      } 
  test=sort(test)
  k=test[1:n]
 return (k)
 } 

Due questioni ho bisogno di aiuto:

  1. Mentre la mia funzione non restituisce il numero desiderato di punti, non è centrata intorno al mio valore di ricerca. Ha senso perché, come ho più ampia, ottengo più punti e quando ho sorta quelle e prendo il primo n, tendono a non essere i valori bassi.

  2. In secondo luogo, come faccio ad ottenere le righe effettive fuori? Per ora ho un'altra funzione per individuare queste righe utilizzando which, quindi rbind 'ing quelle righe insieme. Sembra che ci dovrebbe essere un modo migliore.

grazie!

È stato utile?

Soluzione

Che ne dite di qualcosa di simile al seguente:

day = 1:1000

search = seq(from=5, to=max(day), by=30)
x = sort(setdiff(day, search))
pos = match(x[unlist(lapply(findInterval(search, x), seq, len=2))], day)

day[pos]

Per ottenere le righe dal vostro data.frame solo sottoinsieme che:

rows = data[pos, ]

Questo è forse un po 'più pulita la non elencati / lapply / ss combinata:

pos = match(x[outer(c(0, 1), findInterval(search, x), `+`)], day)

Si noti inoltre che se si desidera una finestra più grande (per esempio, dicono 4), il suo solo una questione di andare un po 'indietro:

pos = match(x[outer(-1:2, findInterval(search, x), `+`)], day)

Altri suggerimenti

Ho amato la soluzione di Carlo, che funziona perfettamente per il caso n = 2. Ahimè, non è estendibile a finestre più grandi. Ha ancora il problema descritto da OP: con le finestre più grandi, la selezione non è centrata intorno al valore di ricerca. Dato n è anche, mi si avvicinò con seguente soluzione, fortemente basata su Charles idea.

La funzione controlla i confini. se ci sono 100 giorni, e il successivo punto centrale è dire che il penultimo giorno, una finestra di 4 vorrebbe dire che si seleziona indice di 101, che dà NA. Questa funzione sposta la finestra in modo tutti gli indici selezionati trovano all'interno dei dati originali. Questo ha anche l'effetto collaterale che a seconda dei valori di avviamento (st), lunghezza (l) e la finestra (n) valori di inizio e fine hanno una maggiore probabilità di selezionato due volte. Le lunghezze devono essere sempre almeno due volte la dimensione della finestra.

L'output della funzione sono gli indici del campione bootstrap. Può essere usato come variabile pos di Carlo su vettori e dataframes.

bboot <- function(day,st,l,n){
  mid <- seq(st,max(day),by=l)
  x <-sort(setdiff(day,mid))
  lx <- length(x)

  id <- sapply(mid,
          function(y){
            m <- match(T,x>y)
            seq(
              from=min( lx-n, max(1,m+(-n/2)) ),
              to=min( lx, max(n,m+(n/2-1)) )
            )
          }
        )

  pos <- match(x[id],day)
  return(pos)
}

Poi

>   day <- sample(1:100,50)
> sample.rownr <- bboot(day,10,20,6)
> sort(day)
 [1]  3  4  5  7  9 10 13 15 16 18 19 21 22 24 25 26 27 28 29 
[20] 30 31 32 35 36 38 40 45 49 51 52 54 55 58 59 62 65 69 72 73
[40] 74 80 84 87 88 91 92 94 97 98 99
> day[sample.rownr]
 [1]  5  7  9 13 15 16 27 28 29 31 32 35 40 45 49 51 52 54 62 
[20] 65 69 72 73 74 84 87 88 91 92 94
> 

modifica: per quanto riguarda bootstrapping per le serie temporali, si dovrebbe passare attraverso il CRAN taskview su serie temporali , in particolare la sezione relativa ricampionamento. Per la serie irregolari tempo, il pacchetto zoo offre anche abbastanza alcune altre funzionalità che possono tornare utili.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top