计算宽数据帧中每对坐标之间的距离

Eri*_*een 4 gis r distance spatial

我想计算两个链接的空间坐标集(programadmin我的假数据集)之间的距离.数据采用宽格式,因此两对坐标都在同一行.

library(sp)
set.seed(1)
n <- 100
program.id <- seq(1, n)
c1 <- cbind(runif(n, -90, 90), runif(n, -180, 180))
c2 <- cbind(runif(n, -90, 90), runif(n, -180, 180))
dat <- data.frame(cbind(program.id, c1, c2))
names(dat) <- c("program.id", "program.lat", "program.long", "admin.lat", "admin.long")
head(dat)
#       program.id program.lat program.long  admin.lat  admin.long
# 1              1   -42.20844     55.70061 -41.848523   62.536404
# 2              2   -23.01770    -52.84898 -50.643849 -145.851172
# 3              3    13.11361    -82.70635   3.023431   -2.665397
# 4              4    73.47740    177.36626 -41.588893  -13.841337
# 5              5   -53.69725     48.05758 -57.389701  -44.922049
# 6              6    71.71014   -103.24507   3.343705  176.795719
Run Code Online (Sandbox Code Playgroud)

我知道如何在包中programadmin使用sp包创建一个距离矩阵:

ll <- c("program.lat", "program.long")
coords <- dat[ll]
dist <- apply(coords, 1, 
              function(eachPoint) spDistsN1(as.matrix(coords),
                                            eachPoint, longlat=TRUE))
Run Code Online (Sandbox Code Playgroud)

但我想要做的是dist.km在每对坐标之间创建一个距离()的nx1向量并将其添加到dat.

#       program.id program.lat program.long  admin.lat  admin.long  dist.km
# 1              1   -42.20844     55.70061 -41.848523   62.536404   567.35
# 2              2   -23.01770    -52.84898 -50.643849 -145.851172  8267.86
# ...
Run Code Online (Sandbox Code Playgroud)

有什么建议?我花了一段时间来处理旧的SO问题,但似乎没有什么是正确的.很高兴被证明是错误的.

更新

@Amit的解决方案适用于我的玩具数据集:

apply(dat,1,function(x) spDistsN1(matrix(x[2:3],nrow=1),x[3:4],longlat=TRUE))
Run Code Online (Sandbox Code Playgroud)

但是我认为我需要交换lat的顺序,长期的lat长列的顺序就在lat之前.来自?spDistsN1:

pts: A matrix of 2D points, first column x/longitude, second column y/latitude, or a SpatialPoints or SpatialPointsDataFrame object
Run Code Online (Sandbox Code Playgroud)

此外,除非我误解了逻辑,否则我认为Amit的解决方案应该抓住cols [2:3]和[4:5],而不是[2:3]和[3:4].

我现在的挑战是将其应用于我的实际数据.我在下面复制了一部分.

library(sp)
dat <- structure(list(ID = 1:4, 
                      subcounty = c("a", "b", "c", "d"), 
                      pro.long = c(33.47627919, 31.73605491, 31.54073482, 31.51748984), 
                      pro.lat = c(2.73996953, 3.26530095, 3.21327597, 3.17784981), 
                      sub.long = c(33.47552, 31.78307, 31.53083, 31.53083), 
                      sub.lat = c(2.740362, 3.391209, 3.208736, 3.208736)), 
                 .Names = c("ID", "subcounty", "pro.long", "pro.lat", "sub.long", "sub.lat"),     
                 row.names = c(NA, 4L), class = "data.frame")
head(dat) 
#     ID subcounty pro.long  pro.lat sub.long  sub.lat
#  1   1         a 33.47628 2.739970 33.47552 2.740362
#  2   2         b 31.73605 3.265301 31.78307 3.391209
#  3   3         c 31.54073 3.213276 31.53083 3.208736
#  4   4         d 31.51749 3.177850 31.53083 3.208736
apply(dat, 1, function(x) spDistsN1(matrix(x[3:4], nrow=1),
                                    x[5:6],
                                    longlat=TRUE)) 
Run Code Online (Sandbox Code Playgroud)

我收到错误: Error in spDistsN1(matrix(x[3:4], nrow = 1), x[5:6], longlat = TRUE) : pts must be numeric

我很困惑因为这些列是数字的:

> is.numeric(dat$pro.long)
[1] TRUE
> is.numeric(dat$pro.lat)
[1] TRUE
> is.numeric(dat$sub.long)
[1] TRUE
> is.numeric(dat$sub.lat)
[1] TRUE
Run Code Online (Sandbox Code Playgroud)

jlh*_*ard 5

你遇到的问题是apply(...)强制第一个参数到矩阵.根据定义,矩阵必须具有相同数据类型的所有元素.由于dat(dat$subcounty)中的一列是char,所以将apply(...)所有内容强制为char.在您的测试数据集中,所有内容都是数字的,因此您没有遇到此问题.

这应该工作:

dat$dist.km <- sapply(1:nrow(dat),function(i)
                spDistsN1(as.matrix(dat[i,3:4]),as.matrix(dat[i,5:6]),longlat=T))
Run Code Online (Sandbox Code Playgroud)

  • 因为我有类似的情况,我今天遇到了这个解决方案.我喜欢这个主意.我想知道我们是否能让它更好地发挥作用.我有一个像2GB的大数据集,并尝试使用data.table这个代码.处理实际上已经持续了一段时间.对于每一行,我们要求R创建两个矩阵并处理计算.我宁愿认为创建SPDF并处理相同的工作.至少对于每一行,我们不必将DF转换为矩阵.任何想法?我也想知道是否还有另一个功能可以更快地处理同一个工作. (2认同)