在每个人多次旅行的数据框中插入缺失的纬度、经度
interpolate missing lat, lon in dataframe with multiple trips per individual
我有以下数据框 (df) 并想以等距间隔(例如每 250 米)或时间间隔(例如每 2 分钟)插入经纬度坐标。
> head(df)
ID Latitude Longitude trip date.time
1 1 10.30447 -109.2323 1 2005-01-07 11:25:26
2 1 10.30425 -109.2321 1 2005-01-07 11:25:36
3 1 10.30314 -109.2326 1 2005-01-07 11:25:46
4 1 10.30199 -109.2328 1 2005-01-07 11:25:56
5 1 10.30079 -109.2334 1 2005-01-07 11:26:06
6 1 10.30006 -109.2331 1 2005-01-07 11:26:16
我尝试使用 R 包 zoo 和我在发布的类似问题中找到的以下代码来做到这一点:
full.time <- with(df,seq(date.time[1],tail(date.time,1),by=1))
library(zoo)
df.zoo <- zoo(df[,3:4],df$date.time) # convert to zoo object
result <- na.approx(df.zoo,xout=full.time) # interpolate; result is also a zoo object
head(result)
但是,由于我的数据框包含多个人 (df$ID) 的多次旅行 (df$trip),我收到以下错误消息:
> df.zoo <- zoo(df[,3:4],df$date.time) # convert to zoo object
Warning message:
In zoo(df[, 3:4], df$datetime) :
some methods for “zoo” objects do not work if the index entries in ‘order.by’ are not unique
如何 运行 以上代码(在循环中?)计算个人行程?
您的样本不具有代表性:您要求以 2 分钟为增量进行插值,但数据集跨度 < 2 分钟。所以在这个例子中我使用了 30 秒。增量。此外,您只提供了 1 个 ID/type 组合,因此无法验证它是否如您所愿。尽管如此它应该。
有几种方法可以做到这一点;我发现 data.table 是最方便的 - 而且肯定是最快的。
df$date.time <- as.POSIXct(df$date.time) # make sure date.time is POSIXct
library(data.table)
interp.time <- function(var,dt) approx(dt,var,xout=seq(min(dt),max(dt),by="30 sec"))$y
result <- setDT(df)[,lapply(.SD,interp.time,dt=date.time),
by=list(ID,trip),
.SDcols=c("Latitude","Longitude","date.time")]
result[,date.time:=as.POSIXct(date.time, origin="1970-01-01")]
result
# ID trip Latitude Longitude date.time
# 1: 1 1 10.30447 -109.2323 2005-01-07 11:25:26
# 2: 1 1 10.30199 -109.2328 2005-01-07 11:25:56
对距离执行此操作有点复杂,因为我们当然不能在 lon/lat 数据上使用欧氏距离。下面的解决方案使用 geotools
包中的 distHaversine(...)
来计算累积 Haversine 距离,然后对其进行插值。这里我们使用50m而不是250m。
library(geosphere) # for distHaversine
get.dist <- function(lon, lat) distHaversine(tail(cbind(lon,lat),-1),head(cbind(lon,lat),-1))
df[,dist:=c(0,cumsum(get.dist(Longitude,Latitude))),by=list(ID,trip)]
interp.dist <- function(var,dist) approx(dist,var,xout=seq(min(dist),max(dist),by=50))$y
result <- setDT(df)[,lapply(.SD,interp.dist,dist=dist),
by=list(ID,trip),
.SDcols=c("Latitude","Longitude","dist")]
# plot the result
plot(Latitude~Longitude,df, pch=20, asp=1)
lines(Latitude~Longitude,df, col="blue")
points(Latitude~Longitude,result, col="red")
lines(Latitude~Longitude,result, col="red")
请注意,您必须将绘图的纵横比设置为 1:1,否则距离会失真。
我有以下数据框 (df) 并想以等距间隔(例如每 250 米)或时间间隔(例如每 2 分钟)插入经纬度坐标。
> head(df)
ID Latitude Longitude trip date.time
1 1 10.30447 -109.2323 1 2005-01-07 11:25:26
2 1 10.30425 -109.2321 1 2005-01-07 11:25:36
3 1 10.30314 -109.2326 1 2005-01-07 11:25:46
4 1 10.30199 -109.2328 1 2005-01-07 11:25:56
5 1 10.30079 -109.2334 1 2005-01-07 11:26:06
6 1 10.30006 -109.2331 1 2005-01-07 11:26:16
我尝试使用 R 包 zoo 和我在发布的类似问题中找到的以下代码来做到这一点:
full.time <- with(df,seq(date.time[1],tail(date.time,1),by=1))
library(zoo)
df.zoo <- zoo(df[,3:4],df$date.time) # convert to zoo object
result <- na.approx(df.zoo,xout=full.time) # interpolate; result is also a zoo object
head(result)
但是,由于我的数据框包含多个人 (df$ID) 的多次旅行 (df$trip),我收到以下错误消息:
> df.zoo <- zoo(df[,3:4],df$date.time) # convert to zoo object
Warning message:
In zoo(df[, 3:4], df$datetime) :
some methods for “zoo” objects do not work if the index entries in ‘order.by’ are not unique
如何 运行 以上代码(在循环中?)计算个人行程?
您的样本不具有代表性:您要求以 2 分钟为增量进行插值,但数据集跨度 < 2 分钟。所以在这个例子中我使用了 30 秒。增量。此外,您只提供了 1 个 ID/type 组合,因此无法验证它是否如您所愿。尽管如此它应该。
有几种方法可以做到这一点;我发现 data.table 是最方便的 - 而且肯定是最快的。
df$date.time <- as.POSIXct(df$date.time) # make sure date.time is POSIXct
library(data.table)
interp.time <- function(var,dt) approx(dt,var,xout=seq(min(dt),max(dt),by="30 sec"))$y
result <- setDT(df)[,lapply(.SD,interp.time,dt=date.time),
by=list(ID,trip),
.SDcols=c("Latitude","Longitude","date.time")]
result[,date.time:=as.POSIXct(date.time, origin="1970-01-01")]
result
# ID trip Latitude Longitude date.time
# 1: 1 1 10.30447 -109.2323 2005-01-07 11:25:26
# 2: 1 1 10.30199 -109.2328 2005-01-07 11:25:56
对距离执行此操作有点复杂,因为我们当然不能在 lon/lat 数据上使用欧氏距离。下面的解决方案使用 geotools
包中的 distHaversine(...)
来计算累积 Haversine 距离,然后对其进行插值。这里我们使用50m而不是250m。
library(geosphere) # for distHaversine
get.dist <- function(lon, lat) distHaversine(tail(cbind(lon,lat),-1),head(cbind(lon,lat),-1))
df[,dist:=c(0,cumsum(get.dist(Longitude,Latitude))),by=list(ID,trip)]
interp.dist <- function(var,dist) approx(dist,var,xout=seq(min(dist),max(dist),by=50))$y
result <- setDT(df)[,lapply(.SD,interp.dist,dist=dist),
by=list(ID,trip),
.SDcols=c("Latitude","Longitude","dist")]
# plot the result
plot(Latitude~Longitude,df, pch=20, asp=1)
lines(Latitude~Longitude,df, col="blue")
points(Latitude~Longitude,result, col="red")
lines(Latitude~Longitude,result, col="red")
请注意,您必须将绘图的纵横比设置为 1:1,否则距离会失真。