comparing and matching lattitude and longitude

hello to all ! here i set the code of matching nearest 10 location ie latitude and longitude, but how i can set the matching upto the distance of 5 kms based on the latitude and longitude please help.

library(data.table)
df<-structure(list(ID=c(1:10), lat=runif(10,33.45,33.75),lon=runif(10,72.83,73.17))
              , col.Names = c("ID","lat", "lon"), row.names = c(NA, -10L), class = c("data.table","data.frame"))
df
#>     ID      lat      lon
#>  1:  1 33.68233 72.92916
#>  2:  2 33.55997 72.97740
#>  3:  3 33.47232 73.04953
#>  4:  4 33.46897 72.98756
#>  5:  5 33.67684 72.98104
#>  6:  6 33.48391 72.96725
#>  7:  7 33.63800 72.90785
#>  8:  8 33.48453 72.96621
#>  9:  9 33.60884 72.90020
#> 10: 10 33.54021 73.08702
ref<-structure(list(ID=letters[1:10], lat=runif(10,33.45,33.75),lon=runif(10,72.83,73.17))
               , col.Names = c("ID","lat", "lon"),row.names = c(NA, -10L), class = c("data.table","data.frame"))
ref
#>     ID      lat      lon
#>  1:  a 33.66542 73.10833
#>  2:  b 33.71145 72.90245
#>  3:  c 33.57325 72.97382
#>  4:  d 33.55873 72.92102
#>  5:  e 33.61398 72.85792
#>  6:  f 33.69885 73.08856
#>  7:  g 33.53006 73.15598
#>  8:  h 33.52525 72.87853
#>  9:  i 33.52487 73.12073
#> 10:  j 33.61578 72.84094
#Setting to data.table format
setDT(df)
setDT(ref)
#creating a table with cartesian join 
df1<-setkey(df[,c(k=1,.SD)],k)[ref[,c(k=1,.SD)],allow.cartesian=TRUE][,k:=NULL]
df1
#calculating the Euclidean distance and giving a rank in ascending order of distance
df1[,EuDist:=sqrt((lat-i.lat)^2+(lon-i.lon)^2)][,distRank:=rank(EuDist,ties="random"),by=.(ID)]
df1
#>      ID      lat      lon i.ID    i.lat    i.lon     EuDist distRank
#>   1:  1 33.68233 72.92916    a 33.66542 73.10833 0.17996157        8
#>   2:  2 33.55997 72.97740    a 33.66542 73.10833 0.16810868        7
#>   3:  3 33.47232 73.04953    a 33.66542 73.10833 0.20185022        6
#>   4:  4 33.46897 72.98756    a 33.66542 73.10833 0.23060174        8
#>   5:  5 33.67684 72.98104    a 33.66542 73.10833 0.12780210        4
#>   6:  6 33.48391 72.96725    a 33.66542 73.10833 0.22989046        8
#>   7:  7 33.63800 72.90785    a 33.66542 73.10833 0.20234162        8
#>   8:  8 33.48453 72.96621    a 33.66542 73.10833 0.23004091        8
#>   9:  9 33.60884 72.90020    a 33.66542 73.10833 0.21568261        8
#>  10: 10 33.54021 73.08702    a 33.66542 73.10833 0.12701024        4
#>  11:  1 33.68233 72.92916    b 33.71145 72.90245 0.03951384        1
#>  12:  2 33.55997 72.97740    b 33.71145 72.90245 0.16900951        8
#>  13:  3 33.47232 73.04953    b 33.71145 72.90245 0.28074411       10
#>  14:  4 33.46897 72.98756    b 33.71145 72.90245 0.25698340       10
#>  15:  5 33.67684 72.98104    b 33.71145 72.90245 0.08586844        1
#>  16:  6 33.48391 72.96725    b 33.71145 72.90245 0.23659522        9
#>  17:  7 33.63800 72.90785    b 33.71145 72.90245 0.07365001        3
#>  18:  8 33.48453 72.96621    b 33.71145 72.90245 0.23571019        9
#>  19:  9 33.60884 72.90020    b 33.71145 72.90245 0.10263562        6
#>  20: 10 33.54021 73.08702    b 33.71145 72.90245 0.25177267        9
#>  21:  1 33.68233 72.92916    c 33.57325 72.97382 0.11787153        4
#>  22:  2 33.55997 72.97740    c 33.57325 72.97382 0.01375320        1
#>  23:  3 33.47232 73.04953    c 33.57325 72.97382 0.12617001        3
#>  24:  4 33.46897 72.98756    c 33.57325 72.97382 0.10518032        1
#>  25:  5 33.67684 72.98104    c 33.57325 72.97382 0.10383966        2
#>  26:  6 33.48391 72.96725    c 33.57325 72.97382 0.08958759        2
#>  27:  7 33.63800 72.90785    c 33.57325 72.97382 0.09243951        5
#>  28:  8 33.48453 72.96621    c 33.57325 72.97382 0.08904791        2
#>  29:  9 33.60884 72.90020    c 33.57325 72.97382 0.08177875        4
#>  30: 10 33.54021 73.08702    c 33.57325 72.97382 0.11791923        3
#>  31:  1 33.68233 72.92916    d 33.55873 72.92102 0.12387668        5
#>  32:  2 33.55997 72.97740    d 33.55873 72.92102 0.05639660        2
#>  33:  3 33.47232 73.04953    d 33.55873 72.92102 0.15486017        4
#>  34:  4 33.46897 72.98756    d 33.55873 72.92102 0.11172734        2
#>  35:  5 33.67684 72.98104    d 33.55873 72.92102 0.13248861        5
#>  36:  6 33.48391 72.96725    d 33.55873 72.92102 0.08795142        1
#>  37:  7 33.63800 72.90785    d 33.55873 72.92102 0.08036315        4
#>  38:  8 33.48453 72.96621    d 33.55873 72.92102 0.08687333        1
#>  39:  9 33.60884 72.90020    d 33.55873 72.92102 0.05427151        2
#>  40: 10 33.54021 73.08702    d 33.55873 72.92102 0.16702963        6
#>  41:  1 33.68233 72.92916    e 33.61398 72.85792 0.09872874        2
#>  42:  2 33.55997 72.97740    e 33.61398 72.85792 0.13112112        4
#>  43:  3 33.47232 73.04953    e 33.61398 72.85792 0.23829204        8
#>  44:  4 33.46897 72.98756    e 33.61398 72.85792 0.19450795        6
#>  45:  5 33.67684 72.98104    e 33.61398 72.85792 0.13823387        6
#>  46:  6 33.48391 72.96725    e 33.61398 72.85792 0.16992046        5
#>  47:  7 33.63800 72.90785    e 33.61398 72.85792 0.05540803        1
#>  48:  8 33.48453 72.96621    e 33.61398 72.85792 0.16877134        5
#>  49:  9 33.60884 72.90020    e 33.61398 72.85792 0.04258693        1
#>  50: 10 33.54021 73.08702    e 33.61398 72.85792 0.24068319        8
#>  51:  1 33.68233 72.92916    f 33.69885 73.08856 0.16024618        6
#>  52:  2 33.55997 72.97740    f 33.69885 73.08856 0.17788011        9
#>  53:  3 33.47232 73.04953    f 33.69885 73.08856 0.22986206        7
#>  54:  4 33.46897 72.98756    f 33.69885 73.08856 0.25108440        9
#>  55:  5 33.67684 72.98104    f 33.69885 73.08856 0.10974798        3
#>  56:  6 33.48391 72.96725    f 33.69885 73.08856 0.24680860       10
#>  57:  7 33.63800 72.90785    f 33.69885 73.08856 0.19067227        7
#>  58:  8 33.48453 72.96621    f 33.69885 73.08856 0.24678059       10
#>  59:  9 33.60884 72.90020    f 33.69885 73.08856 0.20875706        7
#>  60: 10 33.54021 73.08702    f 33.69885 73.08856 0.15864522        5
#>  61:  1 33.68233 72.92916    g 33.53006 73.15598 0.27319280       10
#>  62:  2 33.55997 72.97740    g 33.53006 73.15598 0.18106787       10
#>  63:  3 33.47232 73.04953    g 33.53006 73.15598 0.12110022        2
#>  64:  4 33.46897 72.98756    g 33.53006 73.15598 0.17916242        5
#>  65:  5 33.67684 72.98104    g 33.53006 73.15598 0.22836406       10
#>  66:  6 33.48391 72.96725    g 33.53006 73.15598 0.19429297        7
#>  67:  7 33.63800 72.90785    g 33.53006 73.15598 0.27059219       10
#>  68:  8 33.48453 72.96621    g 33.53006 73.15598 0.19516020        7
#>  69:  9 33.60884 72.90020    g 33.53006 73.15598 0.26764305       10
#>  70: 10 33.54021 73.08702    g 33.53006 73.15598 0.06970563        2
#>  71:  1 33.68233 72.92916    h 33.52525 72.87853 0.16504459        7
#>  72:  2 33.55997 72.97740    h 33.52525 72.87853 0.10479478        3
#>  73:  3 33.47232 73.04953    h 33.52525 72.87853 0.17901009        5
#>  74:  4 33.46897 72.98756    h 33.52525 72.87853 0.12269721        3
#>  75:  5 33.67684 72.98104    h 33.52525 72.87853 0.18299775        8
#>  76:  6 33.48391 72.96725    h 33.52525 72.87853 0.09788408        3
#>  77:  7 33.63800 72.90785    h 33.52525 72.87853 0.11650451        6
#>  78:  8 33.48453 72.96621    h 33.52525 72.87853 0.09667442        3
#>  79:  9 33.60884 72.90020    h 33.52525 72.87853 0.08635775        5
#>  80: 10 33.54021 73.08702    h 33.52525 72.87853 0.20902829        7
#>  81:  1 33.68233 72.92916    i 33.52487 73.12073 0.24797555        9
#>  82:  2 33.55997 72.97740    i 33.52487 73.12073 0.14756146        6
#>  83:  3 33.47232 73.04953    i 33.52487 73.12073 0.08848840        1
#>  84:  4 33.46897 72.98756    i 33.52487 73.12073 0.14442795        4
#>  85:  5 33.67684 72.98104    i 33.52487 73.12073 0.20641768        9
#>  86:  6 33.48391 72.96725    i 33.52487 73.12073 0.15885001        4
#>  87:  7 33.63800 72.90785    i 33.52487 73.12073 0.24107046        9
#>  88:  8 33.48453 72.96621    i 33.52487 73.12073 0.15969962        4
#>  89:  9 33.60884 72.90020    i 33.52487 73.12073 0.23597725        9
#>  90: 10 33.54021 73.08702    i 33.52487 73.12073 0.03703397        1
#>  91:  1 33.68233 72.92916    j 33.61578 72.84094 0.11050706        3
#>  92:  2 33.55997 72.97740    j 33.61578 72.84094 0.14743105        5
#>  93:  3 33.47232 73.04953    j 33.61578 72.84094 0.25316251        9
#>  94:  4 33.46897 72.98756    j 33.61578 72.84094 0.20748264        7
#>  95:  5 33.67684 72.98104    j 33.61578 72.84094 0.15282112        7
#>  96:  6 33.48391 72.96725    j 33.61578 72.84094 0.18260720        6
#>  97:  7 33.63800 72.90785    j 33.61578 72.84094 0.07050185        2
#>  98:  8 33.48453 72.96621    j 33.61578 72.84094 0.18143458        6
#>  99:  9 33.60884 72.90020    j 33.61578 72.84094 0.05965897        3
#> 100: 10 33.54021 73.08702    j 33.61578 72.84094 0.25741980       10
#>      ID      lat      lon i.ID    i.lat    i.lon     EuDist distRank
#selecting the shortest distance
df1<-df1[distRank==1]

df1$lat
#>  [1] 33.68233 33.67684 33.55997 33.46897 33.48391 33.48453 33.63800 33.60884
#>  [9] 33.47232 33.54021
df1$lon
#>  [1] 72.92916 72.98104 72.97740 72.98756 72.96725 72.96621 72.90785 72.90020
#>  [9] 73.04953 73.08702
df1$i.lat
#>  [1] 33.71145 33.71145 33.57325 33.57325 33.55873 33.55873 33.61398 33.61398
#>  [9] 33.52487 33.52487
df1$i.lon
#>  [1] 72.90245 72.90245 72.97382 72.97382 72.92102 72.92102 72.85792 72.85792
#>  [9] 73.12073 73.12073

Created on 2020-10-03 by the reprex package (v0.3.0)

Hi,

Here is an example how you can start filtering locations based on coordinate distance

library(geodist)
library(dplyr)


#Set seed for reproducibility of random data generation
set.seed(72)

#Data
df<-structure(
  list(ID=paste0("ID", 1:5), 
       lat=runif(5,33.45,33.75),
       lon=runif(5,72.83,73.17)), 
  col.Names = c("ID","lat", "lon"), 
  row.names = c(NA, -5L), 
  class = c("data.table","data.frame"))

df
#>    ID      lat      lon
#> 1 ID1 33.72442 73.10041
#> 2 ID2 33.69615 73.11888
#> 3 ID3 33.71310 73.06058
#> 4 ID4 33.71217 73.08081
#> 5 ID5 33.60412 73.04575

#Generate the distance table using haversine distance
distTable = geodist(df, measure = "haversine")
rownames(distTable) = df$ID
colnames(distTable) = df$ID

distTable
#>           ID1       ID2       ID3       ID4      ID5
#> ID1     0.000  3582.402  3897.376  2270.045 14317.57
#> ID2  3582.402     0.000  5719.616  3950.689 12283.55
#> ID3  3897.376  5719.616     0.000  1876.689 12208.72
#> ID4  2270.045  3950.689  1876.689     0.000 12458.58
#> ID5 14317.575 12283.553 12208.718 12458.584     0.00


#Get all locations within a 5000m radius from one location
result = distTable[distTable[, "ID1"] <= 5000, "ID1"]
#>      ID1      ID2      ID3      ID4 
#>    0.000 3582.402 3897.376 2270.045

#Convert the result to a data frame and add the lat/lon
result = data.frame(ID = names(result), distance = result) %>% 
  left_join(df, by = "ID") %>% arrange(distance)

result
#>  ID distance      lat      lon
#> ID1    0.000 33.72442 73.10041
#> ID4 2270.045 33.71217 73.08081
#> ID2 3582.402 33.69615 73.11888
#> ID3 3897.376 33.71310 73.06058

Created on 2020-10-03 by the reprex package (v0.3.0)

You can implement something based on the distance matrix to get different filters for your data now.

Hope this helps,
PJ

1 Like

okay how i can get the latitude and longitude of these distances back again, because i need latitude and longitude to use further
#> ID1 ID2 ID3 ID4
#> 0.000 3582.402 3897.376 2270.045

Hi,

I updated the code above and used the dplyr package to merge the info in the end.

Hope this helps,
PJ

1 Like

i am trying to get distance of 5 locations from center location its giving error please help

library(geodist)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union


#Set seed for reproducibility of random data generation
set.seed(72)

#Data
df<-structure(
  list(ID=paste0("ID", 1:5), 
       lat=runif(5,33.45,33.75),
       lon=runif(5,72.83,73.17)), 
  col.Names = c("ID","lat", "lon"), 
  row.names = c(NA, -5L), 
  class = c("data.table","data.frame"))

df
#>    ID      lat      lon
#> 1 ID1 33.72442 73.10041
#> 2 ID2 33.69615 73.11888
#> 3 ID3 33.71310 73.06058
#> 4 ID4 33.71217 73.08081
#> 5 ID5 33.60412 73.04575

#Generate the distance table using haversine distance
distTable = geodist(df,df[1,], measure = "haversine")
rownames(distTable) = df$ID
colnames(distTable) = df$ID
#> Error in dimnames(x) <- dn: length of 'dimnames' [2] not equal to array extent

distTable
#>          [,1]
#> ID1     0.000
#> ID2  3582.402
#> ID3  3897.376
#> ID4  2270.045
#> ID5 14317.575

#Get all locations within a 5000m radius from one location
result = distTable[distTable[,] <= 5000]

result
#> [1]    0.000 3582.402 3897.376 2270.045
#Convert the result to a data frame and add the lat/lon
result = data.frame(ID = names(result), distance = result) %>% 
  left_join(df, by = "ID") %>% arrange(distance)
#> Error in data.frame(ID = names(result), distance = result): arguments imply differing number of rows: 0, 4

result
#> [1]    0.000 3582.402 3897.376 2270.045

Created on 2020-10-24 by the reprex package (v0.3.0)

HI again,

Here is a way to implement more filters

library(geodist)
library(dplyr)


#Set seed for reproducibility of random data generation
set.seed(72)

#Pick the center location
centerId = "ID1"

#Use a distance filter
filterDist = T
maxDist = 5000

#Filter the n closest
filterClosest= T
nClosest = 2

#Data
df<-structure(
  list(ID=paste0("ID", 1:5), 
       lat=runif(5,33.45,33.75),
       lon=runif(5,72.83,73.17)), 
  col.Names = c("ID","lat", "lon"), 
  row.names = c(NA, -5L), 
  class = c("data.table","data.frame"))

#Generate the distance table using haversine distance
distTable = geodist(df, measure = "haversine")
rownames(distTable) = df$ID
colnames(distTable) = df$ID

#Get the column of interest
result = distTable[,centerId]

#Apply filters if set
if(filterDist){
  result = result[result <= maxDist]
}

if(filterClosest){
  result = result[1:(nClosest + 1)]
}

#Convert the result to a data frame and add the lat/lon
result = data.frame(ID = names(result), distance = result) %>% 
  left_join(df, by = "ID") %>% arrange(distance)

result
   ID distance      lat      lon
1 ID1    0.000 33.72442 73.10041
2 ID2 3582.402 33.69615 73.11888
3 ID3 3897.376 33.71310 73.06058

Hope this helps,
PJ

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.