简体   繁体   中英

How to efficiently apply a two variable function to data.frame( or matrix) elements - to fill an output matrix?

I am trying to find more efficient way(s) to fill an output matrix by applying a function to elements in a data.frame . I experimented with the apply() family functions and the outer() function but couldn't make them work.

Maybe someone here might be able to help? Here's a simplified version of my script. Thanks!

set.seed(192)
n = 1000
distMatrix <- matrix(nrow=n,ncol=n) 

# Co-ordinates
coord <- data.frame(x = runif(n,min=0,max=n),
                    y = runif(n,min=0,max=n))

# Distance Function
distance <- function(A,B) { sqrt( (A['x']-B['x'])^2 + (A['y']-B['y'])^2  ) }

# Fill distMatrix -- this part could use better programming. Note that I am only
# filling the upper triangular part of distMatrix.
for (r in 1:(n-1)) {
    for (c in (r+1):n) {
        distMatrix[[r,c]] <- distance(coord[r,],coord[c,])
    }
}

You can use:

distFun <- function(A,B) 
  sqrt(
    (coord[A, "x"] - coord[B, "x"]) ^ 2 + 
    (coord[A, "y"] - coord[B, "y"]) ^ 2  
  )
distMatrix <- outer(1:nrow(coord), 1:nrow(coord), distFun)

Notice that we need to pass outer two vectors. Here we use the indeces of the rows of the data frame. outer then produces two new vectors that together represent every possible combination of our original vectors, and passes those to our function. Our function then pulls the relevant coordinates for our calculations (here coord is assumed to be defined ahead of the function).

One key thing to understand when using outer is that our function is called only once. outer just computes the vector inputs assuming our function is vectorized, and then applies the corresponding dimensions to the result.

Also, look at ?dist :

dist(coord)

Try it with a smaller matrix (maybe 10 by 10) to see the result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM