Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Setup of Problem
While working with nifti
objects from the oro.nifti
, I tried to table the values of the image. The table took a long time to compute. I thought this was due to the added information about a medical image, but I found that the same sluggishness happened when coercing the nifti
object to an array
as well.
Quick, illustrative simulation
But, if I coerced the data to a vector
using the c
function, things were much faster. Here's a simple example of the problem.
library(microbenchmark) dim1 = 30 n = dim1 ^ 3 vec = rbinom(n = n, size = 15, prob = 0.5) arr = array(vec, dim = c(dim1, dim1, dim1)) microbenchmark(table(vec), table(arr), table(c(arr)), times = 100) Unit: milliseconds expr min lq mean median uq max table(vec) 5.767608 5.977569 8.052919 6.404160 7.574409 51.13589 table(arr) 21.780273 23.515651 25.050044 24.367534 25.753732 68.91016 table(c(arr)) 5.803281 6.070403 6.829207 6.786833 7.374568 9.69886 neval cld 100 a 100 b 100 a
As you can see, it's much faster to run table
on the vector than the array, and the coercion of an array to a vector doesn't take much time compared to the tabling and is comparable in speed.
Explanation of simulation
If the code above is clear, you can skip this section. I created an array that was 30 × 30 × 30 from random binomial variables with half probabily and 15 Bernoulli trials. To keep things on the same playing field, the array (arr
) and the vector (vec
) have the same values in them. The microbenchmark
function (and package of the same name) will run the command 100 times and displays the statistics of the time component.
Why, oh why?
I've looked into the table
function, but cannot seem to find where the bottleneck occurs. Now, for and array
of 30 × 30 × 30, it takes less than a tenth of a second to compute. The problem is when the data is 512 × 512 × 30 (such as CT data), the tabulation using the array form can be very time consuming.
I reduced the replicates, but let's show see this in a reasonable image dimension example:
library(microbenchmark) dims = c(512, 512, 30) n = prod(dims) vec = rbinom(n = n, size = 15, prob = 0.5) arr = array(vec, dim = dims) microbenchmark(table(vec), table(arr), table(c(arr)), times = 10) Unit: seconds expr min lq mean median uq max table(vec) 1.871762 1.898383 1.990402 1.950302 1.990898 2.299721 table(arr) 8.935822 9.355209 9.990732 10.078947 10.449311 11.594772 table(c(arr)) 1.925444 1.981403 2.127866 2.018741 2.222639 2.612065 neval cld 10 a 10 b 10 a
Conclusion
I can't figure out why right now, but it seems that coercing an array (or nifti image) to a vector before running table
can significantly speed up the procedure. If anyone has any intuition why this is, I'd love to hear it. Hope that helps your array tabulations!
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.