2016-05-24 4 views
6

Ich habe eine Datenbank mit> 300.000 Aufzeichnungen von Tierbeobachtungen. Jede Zeile repräsentiert einen Tierstandort. Jedes Tier hat eine eindeutige ID (id1) und mehrere Spalten mit Attributen, die sich auf diesen Tierort beziehen, einschließlich Datum der Beobachtung und x- und y-Koordinaten.Messen Sie die Entfernung zwischen dem ersten und letzten Ort Datensatz pro Tag und Tier in R

Könnte mir jemand helfen, einen Code zu erstellen, der mich auf die folgenden erlaubt:

1) Subset Daten durch beide date und id1

2) Messen Sie den Abstand (Koordinaten in UTM so Abstand sein in Metern) zwischen dem ersten und den letzten Standort-Verzeichnis für jeden date für jedes unterschiedliches id1

Ein Beispiel für die Daten ist der folgende:

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) 

Eine viel weniger effiziente Alternative wäre, die ersten und letzten Datensätze für jede date und id1 auszuwählen und dann die Entfernung zwischen allen Paaren von Punkten zu messen. Ich fand einen Code die letzte Datensatz für jedes einzelnes Tier zu wählen, aber ich werde immer noch als auch die Teilmenge von Datum übernehmen muß:

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) 
} 

mir jemand mit entweder Strategie helfen könnte, vorzugsweise mit dem direkteste Weg zu tun Dies?

Vielen Dank!

Antwort

5

mit 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)) 

Ergebnisse:

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

Es kann nützlich sein, 'arrange (id1, date)' einzuschließen, so dass die erste und die letzte wirklich die erste und die letzte Beobachtung wiedergeben, falls sie anders angeordnet sind. Außerdem kann 'summarise_each (Spaß (erster, letzter))' gerechtfertigt sein, um etwas Tipparbeit zu sparen. – coffeinjunky

+0

@coffeinjunky Danke! Die Anordnung nach ID1 und Datum stellt nicht sicher, dass die Daten in Ordnung sind. Nachdem die Zeilen nach ID1 und Datum gruppiert wurden, gibt es keine Spalte (z. B. einen Zeitstempel), um die Beobachtungen zu ordnen. Das oben gestellte Problem setzt voraus, dass die Beobachtungen in der richtigen Reihenfolge sind (nach der Gruppierung von ID1 und Datum). 'summarize_each()' ist ein cooler Vorschlag. –

+0

Oui, du hast Recht! Es tut uns leid! Ich habe mir irgendwie vorgestellt, einen Zeitstempel zu sehen ... Ich folge daraus, dass es Zeit ist, dass ich mehr Kaffee bekomme ... – coffeinjunky

5

können Sie die Daten konstruieren mit 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)] 

Ich benutze die gleiche (euklidische) Abstand Formel @ Edward- R-Mazurek.

+1

Vielen Dank für Ihren Vorschlag auch lmo. – AnnK

Verwandte Themen