Come faccio a campione n valori al più vicino casuale valore y quando i dati non sono continui?
-
08-10-2019 - |
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:
-
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.
-
In secondo luogo, come faccio ad ottenere le righe effettive fuori? Per ora ho un'altra funzione per individuare queste righe utilizzando
which
, quindirbind
'ing quelle righe insieme. Sembra che ci dovrebbe essere un modo migliore.
grazie!
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.