首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算动物运动路径上各点之间的距离和时间

计算动物运动路径上各点之间的距离和时间
EN

Stack Overflow用户
提问于 2019-01-04 18:58:27
回答 2查看 729关注 0票数 1

我有一个大型的数据集(> 900万行),在站点上检测到单个动物的时间和位置。我想计算每一个站之间的距离,每一个动物的路径,因为它在不同的站之间旅行,以及它所花费的时间在不同的站之间。然后,我想总结一下路径各个部分的总距离和时间。

对于此数据集中的每个个体,每次在固定点检测到数据时,都会组织数据。如果个体长时间处于静止点,那么这个时期有多个记录(每隔30秒)。

我可以总结一下下面的数据,每次当一个人到达一个站点时,我可以得到1行数据(见下文)。然而,当一个人不止一次到达同一站时,输出就不识别了。

例如。

代码语言:javascript
复制
id <- c("A", "A", "A", "A", "A", "A", "A", "A", "B", "B")
site <- c("a", "a", "b", "a", "c", "c", "c", "d", "a", "b")
time <- seq(1:10)
lat <- c(1, 1, 2, 1, 3, 3, 3, 4, 1, 2)
lon <- c(1, 1, 2, 1, 3, 3, 3, 4, 1, 2)

df <- data.frame(id, site, time, lat, lon)

df %>% group_by(id, site, lat, lon) %>%
  summarize(timeStart = min(time), 
            timeEnd = max(time))

# A tibble: 6 x 6
# Groups:   id, site, lat [?]
  id    site    lat   lon timeStart timeEnd
  <fct> <fct> <dbl> <dbl>     <dbl>   <dbl>
1 A     a         1     1         1       4
2 A     b         2     2         3       3
3 A     c         3     3         5       7
4 A     d         4     4         8       8
5 B     a         1     1         9       9
6 B     b         2     2        10      10

一种将数据分组的方法,使对同一站的多次访问(其间有其他站点的访问)被确认为旅行的一个单独的“腿”。

然后,我需要计算每个站之间的大圆距离,以及timeEnd (第一站)和timeStart (第二站)之间的时间差。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-01-04 20:06:34

这可能不是您的完整解决方案,但这是一个好的开始。这将查找每一行数据之间的距离和时间差,并在id在行间更改时将值设置为NA。

代码语言:javascript
复制
df <- data.frame(id, site, time, lat, lon)

library(geosphere)
library(dplyr)

#sort data by id and time
df<-df[order(df$id, df$time), ]
#find distance between each point in column
# Note longitude is the first column
df$distance<-c(NA, distGeo(df[,c("lon", "lat")]))
#find delta time between each row for each id
df<-df %>% group_by(id) %>% mutate(dtime=case_when(site != lag(site) ~ time-lag(time),
                                               TRUE ~ NA_integer_))
#remove distances where there was no delta time (row pairs with different ids)
df$distance[is.na(df$dtime)]<-NA

#id summary
df%>% summarize(disttraveled=sum(distance, na.rm=TRUE), totaltime=sum(dtime, na.rm=TRUE))
票数 2
EN

Stack Overflow用户

发布于 2019-01-04 22:50:42

首先,data.table函数rleid用于创建一个分组变量:对于每个个人,站点的每一个更改都代表一个新的组。在每个组中,计算所需的统计数据:

代码语言:javascript
复制
library(data.table)
library(geosphere)
setDT(df)
df2 <- df[ , .(id = id[1],
               site = site[1],
               lat = lat[1],
               lon = lon[1],
               first_time = min(time),
               last_time = max(time)),
           by = .(id_site = rleid(id, site))]

然后,对于每个个体,用geosphere::distHaversine计算连续点之间的连续大圆距离.为了避免当个人只有一或两条记录*时出现问题,添加了一些检查:

代码语言:javascript
复制
df2[ , dist := if(.N == 1){
  0 } else if(.N == 2){
    c(0, distHaversine(c(lon[1], lat[1]), c(lon[2], lat[2])))
  } else c(0, distHaversine(as.matrix(.SD[ , .(lon, lat)]))), by = id]

#    id_site id site lat lon first_time last_time     dist
# 1:       1  A    a   1   1          1         2      0.0
# 2:       2  A    b   2   2          3         3 157401.6
# 3:       3  A    a   1   1          4         4 157401.6
# 4:       4  A    c   3   3          5         7 314755.2
# 5:       5  A    d   4   4          8         8 157281.8
# 6:       6  B    a   1   1          9         9      0.0
# 7:       7  B    b   2   2         10        10 157401.6
# 8:       8  C    a   1   1         11        11      0.0

因此,对于每一个人,距离只计算一次每一个新的网站。这与另一个答案形成对比,在每个时间步骤之间执行距离计算(看起来可能很多)。

*尝试例如distHaversine(cbind(1, 1)) (distGeo(cbind(1, 1)))或distHaversine(cbind(c(1, 1), c(1, 2))) (distGeo(cbind(c(1, 1), c(1, 2))))

数据

我添加了一个只有一条记录的个人作为测试用例。

代码语言:javascript
复制
id <- c("A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "C")
site <- c("a", "a", "b", "a", "c", "c", "c", "d", "a", "b", "a")
time <- seq(1:11)
lat <- c(1, 1, 2, 1, 3, 3, 3, 4, 1, 2, 1)
lon <- c(1, 1, 2, 1, 3, 3, 3, 4, 1, 2, 1)

df <- data.frame(id, site, time, lat, lon)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54044588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档