我正在尝试计算并保存一个输出文件,该文件给出了与R中多个样本相关的长/纬坐标的所有距离。
数据示例:
Sample Latitude Longitude
A 70 141
B 72 142
C 71 143
D 69 141
我目前正在使用r中的geosphere包,特别是distVincentyEllipsoid函数。您可以像这样使用它:
distVincentyEllipsoid(p1 = c(141,70), p2 = c(142,72))
但是这只能在两个样本之间给你一个距离,我需要在15个样本中获得所有样本之间的距离,并将它们写入列出样本和相关距离的输出文件。
示例输出:
Samples Distance(m)
A-B 8
A-C 26
B-C 13
A-D 20
感谢。
答案 0 :(得分:4)
您可以这样做:
sample_names <- data$Sample
nrow_data <- nrow(data)
test <- function(x){
return (list(Sample = paste(sample_names[x[1]],sample_names[x[2]],sep='-'),
Distance.m = distVincentyEllipsoid(p1 = data[x[1],3:2], p2 = data[x[2],3:2])))
}
ans <- combn(1:nrow_data,2,test)
ans_df <- data.frame(Sample = unlist(ans[1,]),Distance.m = unlist(ans[2,]))
## Sample Distance.m
##1 A-B 226082.2
##2 A-C 134163.1
##3 A-D 111555.6
##4 B-C 117066.1
##5 B-D 336761.1
##6 C-D 235802.0
答案 1 :(得分:4)
以下是outer
函数的另一种解决方案。
library(geosphere)
myList <- setNames(split(df[,c(3,2)], seq_len(nrow(df))), df$Sample)
distMat <- outer(myList, myList, Vectorize(distVincentyEllipsoid))
这给出了距离矩阵,其距离由distVincentyEllipsoid
定义。结果如下:
> distMat
A B C D
A 0.0 226082.2 134163.1 111555.6
B 226082.2 0.0 117066.1 336761.1
C 134163.1 117066.1 0.0 235802.0
D 111555.6 336761.1 235802.0 0.0
将其转换为您想要的格式。
library(tidyr); library(dplyr)
distMat[lower.tri(distMat)] <- 0
distDf <- data.frame(distMat)
distDf$P1 <- row.names(distDf)
gather(distDf, P2, Distance, -P1) %>% filter(Distance != 0) %>%
mutate(Sample = paste(P1, P2, sep = "-")) %>% select(Sample, Distance)
Sample Distance
1 A-B 226082.2
2 A-C 134163.1
3 B-C 117066.1
4 A-D 111555.6
5 B-D 336761.1
6 C-D 235802.0
注意:没有时间比较效率,但由于此解决方案避免了原始数据帧中的高级采样数据。它应该相对较快。
答案 2 :(得分:3)
所以你想要的是两个位置的每个组合,然后是相关的位置,
您可以使用联接和data.table
包
library(data.table)
library(geosphere)
testdata <- data.table(Sample = LETTERS[1:4],
Latitude = c(70,72,71,69),
Longitude = c(141,142,143,141))
# Create each pair of combinations with combn
combTable <- rbindlist(combn(testdata$Sample,2,simplify = FALSE,FUN = as.list))
# Join on the first column
setkey(testdata,Sample)
setkey(combTable,V1)
combTable <- testdata[combTable]
#Join on the second column
setkey(combTable,V2)
combTable <- testdata[combTable]
# Mapply to fit the function's requirements of two vectors for each call
combTable[,.(dist = mapply(function(Lat1, Lon1, Lat2, Lon2)
distVincentyEllipsoid(c(Lon1, Lat1), c(Lon2, Lat2)),
Latitude,
Longitude,
i.Latitude,
i.Longitude,
SIMPLIFY =FALSE ),
Sample,
i.Sample)]
编辑:一步完成此操作而不存储中间变量,并按@ Arun的注释(并使用magrittr语法):
library(magrittr)
combTable <-
testdata[combTable, on = c('Sample' = 'V1')] %>%
testdata[., on = c(`Sample` = 'V2')] %>%
.[,.(dist = mapply(function(Lat1, Lon1, Lat2, Lon2)
distVincentyEllipsoid(c(Lon1, Lat1),c(Lon2, Lat2)),
Latitude,
Longitude,
i.Latitude,
i.Longitude,
SIMPLIFY = FALSE),
Sample,
i.Sample)]