3
\$\begingroup\$

I have a functional script that converts polar coordinates to Cartesian coordinates and then matches a value in a separate array to the coordinates. It works well, but I find that it takes a long time to run due to the length of the matrices being processed. Each file has four columns and 2,880,000 rows which means that I have 11,520,000 total values being processed. The data looks like this-

   [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3

The array rf.190301 is a three dimensional array that looks like this-

, , 1

     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3

, , 2

     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3

, , 3

     [,1] [,2] [,3]
[1,]    1    1    1
[2,]    2    2    2
[3,]    3    3    3

I'm fairly new to R and am just looking for a way to optimize what I'm trying to do in order to make it run a bit faster.

Polar2Cart <- function(x) {

Cart.x <- matrix(NA, nrow = 2880000, ncol = 4)

   for (i in 1:nrow(x)) {

      z[i]<- x[i,1]
      t[i]<- x[i,2]
      r[i]<- x[i,3]

        theta.polar[i] <- (x[i,2] * (pi/180))
        r.polar[i] <- (x[i,3] * 0.075)

            x.cart[i] <- r.polar[i]*cos(theta.polar[i])
            y.cart[i] <- r.polar[i]*sin(theta.polar[i])
            value[i] <- rf.190301[z[i], t[i], r[i]]

        Cart.x[i,] <- cbind(z[i], y.cart[i], x.cart[i], value[i])
     }
}
\$\endgroup\$
1
\$\begingroup\$

You are missing a key feature of the R language: "vectorization". A fancy word for saying that most functions are implemented in such a way that you can provide them vectors and they will apply the computations to each element. As an example, the multiplication function * is vectorized so you can do r.polar <- x[, 3] * 0.075 and it will return the full vector of x[i, 3] * 0.075 where i goes from 1 to nrow(x). This is less typing than doing for (i in 1:nrow(x)) { r.polar[i] <- (x[i,3] * 0.075) } and also a lot faster as you can test.

Applying that idea throughout your code, you can rewrite your Polar2Cart as follows:

Polar2Cart <- function(x) {
   z <- x[, 1]
   t <- x[, 2]
   r <- x[, 3]
   theta.polar <- t * pi / 180
   r.polar <-  r * 0.075
   x.cart <- r.polar * cos(theta.polar)
   y.cart <- r.polar * sin(theta.polar)
   value  <- rf.190301[cbind(z, t, r)]
   Cart.x <- cbind(z, y.cart, x.cart, value)
}

One thing that needs explanation is the use of rf.190301[cbind(z, t, r)]. It is a little known use of the [ function documented as follows (you can access the doc by typing ?"[")

A third form of indexing is via a numeric matrix with one column for each dimension: each row of the index matrix then selects a single element of the array, and the result is a vector.

Finally, a recommendation. Be careful using single characters as variable names, since R already uses a few of them for built-in variables or functions. You could for example confuse your variable t for the t() function for transposing data. Other single character variable names used by R that come to mind are c (concatenation), q (quit), T (TRUE), F (FALSE), I (inhibit). Anyway, it is always better to use descriptive variable names and that usually implies more than one character.

\$\endgroup\$
  • \$\begingroup\$ Thank you so much for this! I took an R class a couple years ago, but I haven't used it much since. I really appreciate your knowledge and the great way that you convey it! Thanks again! \$\endgroup\$ – user86777 Oct 14 '15 at 13:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.