【问题标题】:How to assign several names to lat-lon observations如何为经纬度观测分配多个名称
【发布时间】:2014-02-23 17:35:10
【问题描述】:

我有两个数据框:df1 包含带有经纬度坐标的观测值; df2 的名称带有经纬度坐标。我想创建一个新变量 df1$names,它对于每个观察值都包含在指定距离内的 df2 的名称。

df1 的一些示例数据:

df1 <- structure(list(lat = c(52.768, 53.155, 53.238, 53.253, 53.312, 53.21, 53.21, 53.109, 53.376, 53.317, 52.972, 53.337, 53.208, 53.278, 53.316, 53.288, 53.341, 52.945, 53.317, 53.249), lon = c(6.873, 6.82, 6.81, 6.82, 6.84, 6.748, 6.743, 6.855, 6.742, 6.808, 6.588, 6.743, 6.752, 6.845, 6.638, 6.872, 6.713, 6.57, 6.735, 6.917), cat = c(2L, 1L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 3L, 2L, 2L, 2L, 2L, 2L), diff = c(6.97305555555555, 3.39815972222222, 14.2874305555556, -0.759791666666667, 34.448275462963, 4.38783564814815, 0.142430555555556, 0.698599537037037, 1.22914351851852, 7.0008912037037, 1.3349537037037, 8.67978009259259, 1.6090162037037,    25.9466782407407, 9.45068287037037, 4.76284722222222, 1.79163194444444, 16.8280787037037, 1.01336805555556, 3.51240740740741)), .Names = c("lat", "lon", "cat", "diff"), row.names = c(125L, 705L, 435L, 682L, 186L, 783L, 250L, 517L, 547L, 369L, 618L, 280L, 839L, 614L, 371L, 786L, 542L, 100L, 667L, 785L), class = "data.frame")

df2 的一些示例数据:

df2 <- structure(list(latlonloc = structure(c(6L, 3L, 4L, 2L, 5L, 1L), .Label = c("Boelenslaan", "Borgercompagnie", "Froombosch", "Garrelsweer", "Stitswerd", "Tinallinge"), class = "factor"), lat = c(53.356789, 53.193886, 53.311237, 53.111339, 53.360848, 53.162031), lon = c(6.53493, 6.780792, 6.768608, 6.82354, 6.599604, 6.143804)), .Names = c("latlonloc", "lat", "lon"), class = "data.frame", row.names = c(NA, -6L))

使用geosphere 包创建距离矩阵:

library(geosphere)
mat <- distm(df1[,c('lon','lat')], df2[,c('lon','lat')], fun=distHaversine)

得到的距离以米为单位(至少我认为是,否则距离矩阵有问题)。

使用(df1$cat)^2)*1000 计算指定的距离。我试过df1$names &lt;- df2$latlonloc[apply(distmat, 1, which(distmat &lt; ((df1$cat)^2)*1000 ))],但收到错误消息:

Error in match.fun(FUN) : 
  'which(distmat < ((df1$cat)^2) * 1000)' is not a function, character or symbol

这可能不是正确的方法,但我需要的是:

df1$names &lt;- #code or function which gives me a string of names which are within a specified distance of the observation

如何创建一个字符串,其名称在指定的观测距离内?

【问题讨论】:

  • 当您调用apply 时,第三个参数必须是一个函数,可以是简单的函数名称,也可以是一个完整的函数,其参数将对应于apply 的第一个参数的每个元素.你需要像apply(distmat, 1, function(x) ...) 这样的东西,其中... 是一些使用x 参数的函数体。不过,我无法从您的代码中看出您想要/需要的是什么。
  • @Thomas 我编辑了这个问题。现在清楚了吗?
  • 你期望which(distmat &lt; ((df1$cat)^2) * 1000)给你什么?
  • @Thomas 我希望它会给我一组与观察结果有一定距离 ((df1$cat)^2)*1000) 的名称。
  • which 被记录为给出整数。你为什么认为它会给出名字?

标签: r distance geographic-distance


【解决方案1】:

您需要对df1(或mat)的每一行进行操作,以计算出每一行df2 中每个对象的距离。从中,您可以选择符合您的距离标准的那些。

我认为您对apply 的使用和which 的使用有些困惑。要真正让which 为您工作,您需要将其应用于mat 的每一行,而您当前的代码将其应用于整个mat 矩阵。另请注意,这里很难使用apply,因为您将mat 的每一行与((df1$cat)^2)*1000) 定义的向量的相应元素进行比较。因此,我将向您展示使用sapplylapply 的示例。您也可以在这里使用mapply,但我认为sapply/mapply 的语法更清晰。

为了解决您想要的输出,我展示了两个示例。对于df1 中的每一行,返回一个列表,其中包含df2 中距离阈值内的项目名称。这不会轻易地回到您原来的 df1 作为变量,因为列表中的每个元素都可以包含多个名称。第二个示例将这些名称作为一个逗号分隔的字符串粘贴在一起,以创建您要查找的新变量。

示例 1:

out1 <- lapply(1:nrow(df1), function(x) {
    df2[which(mat[x,] < (((df1$cat)^2)*1000)[x]),'latlonloc']
})

结果:

> str(out1)
List of 20
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 2
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 4
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 6 4 5
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 
 $ : Factor w/ 6 levels "Boelenslaan",..: 4
 $ : Factor w/ 6 levels "Boelenslaan",..: 

示例 2:

out2 <- sapply(1:nrow(df1), function(x) {
    paste(df2[which(mat[x,] < (((df1$cat)^2)*1000)[x]),'latlonloc'], collapse=',')
})

结果:

> out2
 [1] ""                                 ""                                
 [3] ""                                 ""                                
 [5] ""                                 ""                                
 [7] ""                                 "Borgercompagnie"                 
 [9] ""                                 "Garrelsweer"                     
[11] ""                                 ""                                
[13] ""                                 ""                                
[15] "Tinallinge,Garrelsweer,Stitswerd" ""                                
[17] ""                                 ""                                
[19] "Garrelsweer"                      ""

我认为其中的第二个可能最接近您的目标。

【讨论】:

  • 示例 2 给了我想要的答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 1970-01-01
  • 2018-11-26
  • 2017-06-15
相关资源
最近更新 更多