Please look at the following small working example:
#### Pseudo data
nobs1 <- 4000
nobs2 <- 5000
mylon1 <- runif(nobs1, min=0, max=1)-76
mylat1 <
Here are two solutions, one is partly vectorised that uses sapply, and I think the other is fully vectorised, but I've written a couple of functions for part of the vector calculations so there may be a better way.
I also only ran these for nobs1 = 4, 40 & 400 and nobs2 = 5, 50 & 500 as my laptop struggles for memory with large matrices.
Solution - sapply
R <- 6371 # Earth mean radius [km]
delta.lon <- sapply(mylon2, "-", mylon1)
delta.lon <- sin(delta.lon/2)^2
coslat2 <- cos(mylat2)
coslat1 <- cos(mylat1)
delta.lan <- sapply(mylat2, "-", mylat1)
delta.lan <- sin(delta.lan/2)^2
a <- delta.lan + t(sapply(coslat1, "*", coslat2) * t(delta.lon))
b <- ifelse(sqrt(a)<1,sqrt(a),1)
c <- asin(b)
d <- 2 * c
e <- R * d
f <- c(t(e))
And to check the output
sum(f)
sum(mydistance)
all.equal(f, mydistance)
> sum(f)
[1] 647328856
> sum(mydistance)
[1] 647328856
> all.equal(f, mydistance)
[1] TRUE
Solution - with functions
R <- 6371 # Earth mean radius [km]
#function to calculate the difference between each
#element of different sized vectors and return a matrix
vecEleDif <- function(vec1, vec2)
{
#the order of arguments is vec2 - vec1
len1 <- length(vec1);len2 <- length(vec2)
dummy1 <- matrix(rep.int(vec1, len2), nrow=len1)
dummy2 <- matrix(rep.int(vec2, len1), nrow=len2)
res <- t(dummy2 - t(dummy1))
}
#Function to calculate the product of each
#element of two different size vectors
vecEleProd <- function(vec1, vec2)
{
#the order of the arguments is vec2 * vec1
len1 <- length(vec1); len2 <- length(vec2)
dummy1 <- matrix(rep.int(vec1, len2), nrow=len1)
dummy2 <- matrix(rep.int(vec2, len1), nrow=len2)
res <- t(dummy2 * t(dummy1))
}
ptm <- proc.time()
delta.lon <- sin(vecEleDif(mylon2, mylon1)/2)^2
delta.lan <- sin(vecEleDif(mylat2, mylat1)/2)^2
cosprod <- vecEleProd(cos(mylat1), cos(mylat2))
a <- delta.lan + (t(cosprod) * delta.lon)
b <- ifelse(sqrt(a)<1,sqrt(a),1)
c <- asin(b)
d <- 2 * c
e <- R * d
f <- c((e))
proc.time() - ptm
and check the output:
sum(f)
sum(mydistance)
all.equal(f, mydistance)
> sum(f)
[1] 647745044
> sum(mydistance)
[1] 647745044
>
> all.equal(f, mydistance)
[1] TRUE