2016-05-24 48 views
6

Ho un database con> 300.000 registrazioni di osservazioni sugli animali. Ogni riga rappresenta una posizione animale. Ogni animale ha un identificativo univoco (id1) e diverse colonne con attributi correlati a quella posizione dell'animale, tra cui la data di osservazione e le coordinate x e y.Misurare la distanza tra il primo e l'ultimo record di posizione al giorno e l'animale in R

Qualcuno potrebbe aiutarmi a creare un codice che mi permetterà ai seguenti:

1) i dati sottoinsieme sia da date e id1

2) Misurare la distanza (coordinate sono in UTM così distanza sarà in metri) tra la prima e registrare posizione LAST per ogni date per ogni differente id1

Un esempio dei dati è il seguente:

mydata<-read.table(text = 
"id1 date x y 
1 11/02/2014 478776.4332 7922167.59 
1 11/02/2014 478776.4333 7922170.59 
1 11/02/2014 478776.4334 7922180.59 
1 12/02/2014 478776.4335 7922190.59 
1 12/02/2014 478776.4350 7922192.59 
1 12/02/2014 478776.4360 7922195.59 
2 11/02/2014 478776.4338 7922167.59 
2 11/02/2014 478776.4339 7922183.59 
2 11/02/2014 478776.4340 7922185.59 
2 12/02/2014 478776.4350 7922188.30 
2 12/02/2014 478776.4360 7922190.59 
2 12/02/2014 478776.4390 7922198.59 
3 11/02/2014 478776.4338 7922167.59 
3 11/02/2014 478776.4345 7922175.59 
3 11/02/2014 478776.4355 7922178.85 
3 12/02/2014 478776.4368 7922180.59 
3 12/02/2014 478776.4398 7922183.59 
3 12/02/2014 478776.4399 7922185.59 
4 11/02/2014 478776.4338 7922167.59 
4 11/02/2014 478776.4340 7922172.59 
4 11/02/2014 478776.4345 7922178.59 
3 11/02/2014 478776.4350 7922179.59 
3 12/02/2014 478776.4355 7922184.59 
3 12/02/2014 478776.4360 7922187.59 
3 12/02/2014 478776.4365 7922198.59", 
header = TRUE) 

Un'alternativa molto meno efficiente sarebbe quella di selezionare il primo e l'ultimo record per ogni date e id1 e quindi misurare la distanza tra tutte le coppie di punti. Ho trovato un codice per selezionare il record LAST per ogni singolo animale, ma io ancora incorporare il sottoinsieme per data così:

myid.uni <- unique(mydata$id1) 
a<-length(myid.uni) 

last <- c() 

for (i in 1:a) { 
    temp<-subset(mydata, id1==myid.uni[i]) 
    if (dim(temp)[1] > 1) { 
    last.temp<-temp[dim(temp)[1],] 
    } 
    else { 
    last.temp<-temp 
    } 
    last<-rbind(last, last.temp) 
} 

qualcuno potrebbe aiutarmi con entrambe le strategie, preferenzialmente con il modo più semplice per fare Questo?

Grazie!

risposta

5

utilizzando dplyr:

library(dplyr) 
mydata %>% 
    group_by(id1, date) %>% 
    summarize(x1 = first(x), y1 = first(y), x2 = last(x), y2 = last(y)) %>% 
    mutate(distance = sqrt((x2-x1)^2+(y2-y1)^2)) 

Risultati:

Source: local data frame [7 x 7] 
Groups: id1 [4] 

    id1  date  x1  y1  x2  y2 distance 
    (int)  (fctr) (dbl) (dbl) (dbl) (dbl)  (dbl) 
1  1 11/02/2014 478776.4 7922168 478776.4 7922181 13.000000 
2  1 12/02/2014 478776.4 7922191 478776.4 7922196 5.000001 
3  2 11/02/2014 478776.4 7922168 478776.4 7922186 18.000000 
4  2 12/02/2014 478776.4 7922188 478776.4 7922199 10.290001 
5  3 11/02/2014 478776.4 7922168 478776.4 7922180 12.000000 
6  3 12/02/2014 478776.4 7922181 478776.4 7922199 18.000000 
7  4 11/02/2014 478776.4 7922168 478776.4 7922179 11.000000 
+2

Può essere utile includere "organizzare (id1, data)" in modo che il primo e l'ultimo riflettano realmente la prima e l'ultima osservazione nel caso in cui siano ordinati in modo diverso. Inoltre, 'summarise_each (funs (first, last))' può essere giustificato per risparmiare un po 'di digitazione. – coffeinjunky

+0

@coffeinjunky Grazie! L'organizzazione di id1 e data non garantisce che i dati siano in ordine. Dopo che le righe sono state raggruppate per id1 e data, non è presente alcuna colonna (ad esempio un timestamp) per ordinare le osservazioni. Il problema sopra esposto presuppone che le osservazioni siano nell'ordine corretto (dopo il raggruppamento su id1 e data). 'summarize_each()' è un bel suggerimento. –

+0

Oui, hai ragione! Scusate! Ho in qualche modo immaginato di vedere un timbro orario ... deduco che questo significhi che è tempo per me di prendere più caffè ... – coffeinjunky

5

è possibile costruire i dati utilizzando data.table

# load data.table and make mytable a data.table 
library(data.table) 
setDT(mydata) 

# contstruct new dataset 
newData <- mydata[, .(startx=head(x, 1), endx=tail(x, 1), 
         starty=head(y, 1), endy=tail(y, 1)), 
        by=.(id1, date)] 
# calculate distance 
newData[, distance := sqrt((endx-startx)^2+(endy-starty)^2)] 

utilizzare la stessa (euclideo) formula della distanza come @ Edward- r-Mazurek.

+1

Grazie per il tuo suggerimento e lmo. – AnnK