我有一个数据库,里面有超过300000条动物观察记录。每一行代表一个动物的位置。每只动物都有一个唯一的id(id1
)和几个列,其中包含与该动物位置相关的属性,包括观察日期以及x和y坐标。
有人能帮我创建一个代码,允许我进行以下操作吗:
1)date
和id1
的子集数据
2) 测量每个不同id1
的每个date
的第一个和最后一个位置记录之间的距离(坐标以UTM为单位,因此距离以米为单位)
数据示例如下:
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)
效率低得多的替代方案是为每个date
和id1
选择第一个和最后一个记录,然后测量所有点对之间的距离。我找到了一个代码来为每只动物选择最后一条记录,但我仍然需要按日期合并子集:
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)
}
有人能帮我制定其中一种策略吗,最好是用最直接的方法来做到这一点?
谢谢!
使用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))
结果:
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
您可以使用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)]
我使用与@edward-r-mazurek相同的(欧几里得)距离公式。