0

I was trying to use the solution offered here to find all the location from df which are within the 70 km distance from my point of interest userLocation=c(6.9,55,2), but it does not work properly.

    df = structure(list(lng = c(6.2694184, 6.25737207, 6.23839104, 6.25844252, 
6.22595901, 6.21351832, 6.2010845, 6.1886414, 6.1762058, 6.1637609, 
6.15132287, 6.13887619, 6.12643637, 6.14361895, 6.16332364, 6.18302157, 
6.2027276, 6.22242688, 6.24213488, 6.26842752, 6.26745135, 6.24518597, 
6.26645948, 6.24420242, 6.22357831, 6.26548171, 6.24321746, 6.2226023, 
6.20041884, 6.18070459, 6.16099845, 6.16716672, 6.17960629, 6.18686265, 
6.2078525, 6.19203657, 6.20447434, 6.21691835, 6.2293537, 6.24179593, 
6.26009321, 6.26448764, 6.2422317, 6.21927538, 6.20186455, 6.26350828, 
6.24124514, 6.22028969, 6.26251321, 6.2402584, 6.23404584, 6.26153227, 
6.22171658, 5.94065657, 6.10363006, 6.11606487, 6.12850589, 6.14093826, 
6.15337749, 6.16582359, 6.17826103, 6.19070472, 6.20313974, 6.20009703, 
5.96044213, 5.96988333, 5.98023582, 5.98966667, 5.99910246, 6.00003829, 
6.00947365, 6.01889843, 6.02832882, 6.01983402, 6.02925771, 6.038687, 
6.0481219, 6.05754688, 6.03963788, 6.04906608, 6.05848435, 6.06792377, 
6.07735326, 6.08677283, 6.05941948, 6.06885218, 6.07829049, 6.08771889, 
6.09713671, 6.10657633, 6.11600538, 6.07922538, 6.08864707, 6.10756108, 
6.12000483, 6.13243993, 6.12019786, 6.14488189, 6.15733073, 6.16977091, 
6.16621949, 6.13805015, 6.13652024, 5.941545, 6.20491484, 6.18423897, 
6.17806466, 6.16355552, 6.15738696, 6.14558294, 6.14286638, 6.13670293, 
6.12217027, 6.11601258, 6.10148275, 6.09533146, 6.08080511, 6.07464337, 
6.06011984, 6.03729438, 6.05394895, 6.02546329, 6.0136389, 6.03674112, 
6.05743408, 6.07812006, 6.09879971, 6.11948795, 6.11063647, 6.08914275, 
6.08440881, 6.0018212, 6.02491713, 5.98999461, 6.01308427, 5.97815849, 
6.00125809, 5.96632973, 5.98943792, 5.9995124, 6.02119838, 6.04364466, 
6.0223476, 6.04560587, 6.03821257, 6.06131821, 6.06046748, 5.97888909, 
5.95766873, 6.24771247, 6.04931495, 6.25538943, 6.23227728, 6.25434093, 
6.25329159, 6.25225759, 6.25120656, 6.25015469, 6.24911757, 6.06338238, 
6.08539205, 6.10756976, 6.12975108, 6.15193667, 6.17411029, 6.19630377, 
6.21848591, 6.22602495, 6.23123663, 6.20931486, 6.23019515, 6.20826628, 
6.22915282, 6.20721685, 6.22810966, 6.21962063, 6.20209266, 6.20618216, 
6.19702482, 6.1799057, 6.15772301, 6.13554395, 6.11336914, 6.09118237, 
6.09738412, 6.11958004, 6.12698723, 6.14767387, 6.16835417, 6.18613747, 
6.185096, 6.165456, 6.14476821, 6.15765091, 6.23561071, 6.08001353, 
6.22353732, 6.2376767, 6.21143885, 6.19936347, 6.18727866, 6.17520066, 
6.16311385, 6.15103386, 6.13894506, 6.12686243, 6.11478725, 6.10270261, 
6.09818625, 6.12128852, 6.2468456, 6.22571713, 6.24558662, 6.22445138, 
6.24434288, 6.22320086, 6.24308194, 6.22194875, 6.24182062, 6.22068065, 
6.24057332, 6.21942655, 6.2113264, 6.22341814, 6.19699748, 6.18490568, 
6.1988361, 6.17283631, 6.16074252, 6.14867115, 6.13657473, 6.13954049, 
6.16263694, 6.18482009, 6.20327221, 6.20009595, 6.19278885, 6.17005571
), lat = c(54.67598304, 54.83924292, 54.83162024, 54.82483795, 
54.82033259, 54.80904336, 54.79775292, 54.78646988, 54.77517665, 
54.76389082, 54.75260377, 54.74131515, 54.73002531, 54.72096456, 
54.71392047, 54.70687309, 54.69983176, 54.69278713, 54.68573957, 
54.68934722, 54.7027117, 54.69910571, 54.71606682, 54.71246092, 
54.70614626, 54.72943123, 54.72582507, 54.71951053, 54.71576339, 
54.72280423, 54.72985112, 54.74274399, 54.75402944, 54.73569581, 
54.72983408, 54.7653223, 54.77660496, 54.78789538, 54.79918423, 
54.81047187, 54.80230996, 54.74279524, 54.73918917, 54.74155047, 
54.75043676, 54.75615956, 54.75255324, 54.75849353, 54.76951451, 
54.76590829, 54.77879358, 54.78287875, 54.84106585, 54.79004116, 
54.73264696, 54.7439301, 54.755221, 54.76651031, 54.77779842, 
54.78908531, 54.80037062, 54.81166369, 54.82295519, 54.83631649, 
54.78306731, 54.79535153, 54.77609951, 54.7883729, 54.80065457, 
54.76912877, 54.78140068, 54.7936805, 54.80595963, 54.7621547, 
54.77443373, 54.78671208, 54.79898973, 54.81126633, 54.75518666, 
54.76746422, 54.77974071, 54.7920169, 54.80429202, 54.81656608, 
54.74821493, 54.76049101, 54.7727664, 54.78504073, 54.79732298, 
54.80959594, 54.82187682, 54.74124062, 54.75351485, 54.76118719, 
54.77247897, 54.78376916, 54.79513973, 54.79505815, 54.80634591, 
54.8176321, 54.8309898, 54.82587825, 54.81251828, 54.80340625, 
54.85043439, 54.85669012, 54.84379843, 54.8629602, 54.85006754, 
54.83850747, 54.86921769, 54.85633303, 54.87548056, 54.86259492, 
54.88174916, 54.86885358, 54.88800555, 54.8751176, 54.89427628, 
54.89688611, 54.88137801, 54.88534048, 54.87379377, 54.87235508, 
54.86608859, 54.85982748, 54.85356275, 54.84730376, 54.83491117, 
54.82992904, 54.84309445, 54.86224596, 54.86080945, 54.85069668, 
54.84926234, 54.8391549, 54.83771415, 54.82760306, 54.82617384, 
54.81401612, 54.81866848, 54.82193287, 54.83203, 54.85454492, 
54.8418856, 54.84463218, 54.83126946, 54.807705, 54.81314447, 
54.95082492, 54.90870481, 54.85261135, 54.8544958, 54.86597391, 
54.87933643, 54.89269028, 54.90605271, 54.91941509, 54.93277779, 
54.91930405, 54.92337651, 54.92712528, 54.93087901, 54.93462874, 
54.93838307, 54.94213376, 54.94588009, 54.93325056, 54.86785843, 
54.86365241, 54.88122101, 54.87701472, 54.89458354, 54.890377, 
54.90794604, 54.9204011, 54.92916856, 54.90373959, 54.91606989, 
54.92541899, 54.92166542, 54.91791682, 54.91416421, 54.91041621, 
54.89753741, 54.90128459, 54.88863077, 54.8823668, 54.87609923, 
54.88468492, 54.89804726, 54.89094652, 54.89720452, 54.90830415, 
55.08370977, 54.93641839, 55.07226944, 55.06170442, 55.06083624, 
55.04939327, 55.03795778, 55.02652115, 55.01508302, 55.00364374, 
54.99220296, 54.98077001, 54.96932695, 54.95789135, 54.94469353, 
54.94333719, 54.96418243, 54.9585686, 54.97754901, 54.9719349, 
54.99090692, 54.98529252, 55.00427341, 54.99865908, 55.01763087, 
55.01201625, 55.03099761, 55.02538271, 55.03790915, 55.04934232, 
55.02208092, 55.01064489, 54.99998971, 54.99920808, 54.98776941, 
54.97632995, 54.9648976, 54.95153594, 54.95007267, 54.95382515, 
54.96186591, 54.98662348, 54.97394968, 54.97118391)), class = "data.frame", row.names = c(NA, 
-238L))

What I have done is as follow : Add the point of interest to the beginning of df

df = rbind(userLocation,df)

Set the radius to 0.64 since according to here, every 0.1 is equivalent to 11.1 km !

radius <- 0.64
      #Identifying neighbors
      res <- nn2(df, k=nrow(df), searchtype="radius", radius = radius)

Since my point of interest is the first row in df I would expect all the non zero index in the first row are the points within my 70 km threshold Ind <- res$nn.idx[1,][res$nn.idx[1,]>0]

My Ind object has just one value! but if I plot the data, all of the points are within 70 km distance :

enter image description here

What is wrong here?

Vince
  • 20,017
  • 15
  • 45
  • 64
Haribo
  • 115
  • 5

1 Answers1

1

Well, the first thing that comes to mind is "do you have any locations meeting your query"? When testing this, the answer is no.

df <- rbind(c(6.9, 55), df)
radius <- 0.64
res.idx <- RANN::nn2(data=df, query=df, k=nrow(df), 
      searchtype="radius", radius = radius)$nn.idx
  res.idx[1,]

( d <- as.numeric(as.matrix(dist(df))[,1]) ) d[d<=0] <- NA which(d <= radius) min(d,na.rm=TRUE)

Your minimum distance is 0.6541357 so, you are not meeting the conditions of your query. If you change your distance threshold, you do return results.

radius = 0.80
res.idx <- RANN::nn2(data=df, query=df, k=nrow(df), 
      searchtype="radius", radius = radius)$nn.idx
  res.idx[1,]

Recheck our distance vector which(d <= radius) and we have matching results.

However, given the distortions (distance non-uniformity) in distance that you will see in a geographic projection, I would highly recommend transforming your data into a projected (distance based) coordinated system or using functions that account for the spherical geometry. Here we can illustrate how your analysis is going wrong without accounting for the spherical geometry (requires the s2 and sf libraries).

sdf <- s2::s2_geog_point(df[,1],df[,2])
  d <- s2::s2_distance_matrix(sdf,sdf)[1,] / 1000
which(d <= 70)
  length(which(d <= 70))
  nrow(df)

Low and behold, all of your observations are within 70KM. The direct call to s2 is the same as using the sf library

library(sf)
sf_use_s2()

sdf <- st_as_sf(df, coords = c("lng", "lat"), crs = 4326, agr = "constant") d <- st_distance(sdf)[1,] units(d) <- units::as_units("km") which(as.numeric(d) <= 70)

Jeffrey Evans
  • 31,750
  • 2
  • 47
  • 94
  • Thanks for your reply, this is exactly my confusion ! as you see on the map screenshot all of my df locations are within the 70 km distance from the userLocation object. What is confusing me is the unit for the radius parameter in nn2 command. Is that correct that every 0.1 unit in radius represent 11.1 km ?! on the other word what should I choose as radius which returns me all the neighbours with in the 70 km distance ? – Haribo Dec 17 '22 at 20:31