I'm trying to substantially decrease computing time for my code.
I have 2 data.frames:
1.NewCus_withGeo
head(newCus)
U_ID U_LAT U_LONG
31902101 47.57080 -52.69588
26428781 45.50141 -73.55854
26428801 45.40768 -73.95121
28130841 45.44952 -73.82955
26428961 45.54130 -73.47751
26428981 45.35496 -75.67068
2.localD
head(localD)
ID D_ID D_LAT D_LONG
1533582_23821 1533582 45.40462 -75.62618
1533582_97592 1533582 45.21759 -75.71293
1533582_23811 1533582 46.83400 -71.28574
4126692_23811 4126692 46.79560 -71.27572
4134402_23811 4134402 46.74568 -71.44606
4135162_23811 4135162 46.82987 -71.23739
4138752_23841 4138752 46.34229 -72.54294
I want to get for every U_ID the 5 D_ID with smallest euclidean distance but only if that distance is under 0.3.
I want as a result another data.frame containing for each U_ID with close enough D_ID the 5 closest D_ID and the distance between U_ID and D_ID which would look like this:
head(result_df)
U_ID D_ID dist
26428781 4244252 0.0008656102
26428781 4088692 0.0055139426
26428781 4177752 0.0060150366
26428781 4182572 0.0067220964
26428781 4191862 0.0076759495
26428801 4135212 0.0455715423
26428801 4216202 0.0726350403
I came up with this code to do it:
EDIT Thanks to Rui Barradas who improved function's performance
EDIT 2 to further improve function's performance we can use data.table to improve time on subseting
library(data.table)
newCus = data.table(newCus)
distance <- function(x,y){
# Subsetting newCus to get only one U_ID
tb <- newCus[U_ID == x]
# distance calculations
dist = (tb$U_LAT - y$D_LAT)^2 + (tb$U_LONG - y$D_LONG)^2
if(min(dist) <= 0.3^2){
# Putting the data.frame together
NewCus_dist <- data.frame(U_ID = tb$U_ID, D_ID = y$D_ID, dist = dist)
# Keeping top 5 D_ID
NewCus_dist <- NewCus_dist[order(dist)[1:5], ]
NewCus_dist$dist <- sqrt(NewCus_dist$dist)
} else {
NewCus_dist <- NULL
}
NewCus_dist
}
Then using this function in a do.call and lapply function to iterate over the U_ID and get the result in a data.frame
result_df = do.call("rbind", lapply(newCus$U_ID, distance, localD))
Is there a better and faster way to code this?