12

I'm still learning R. Is there some automated way to identify if an R operation or a function is vectorized? To identify if an R object is a vector, I can use is.vector(x), which returns TRUE if x is a vector or False otherwise. Is there something similar for vectorized?

For example:

x <- c(1,2,3)
y <- c(3,4,5)
x+y
#[1] 4 6 8

Since, + is vectorized, it automatically adds individual elements of a vector x with individual elements of y. Otherwise, I'd have to use a for loop to achieve a similar output.

for(i in seq_along(x)){
  cat(sprintf("%i ", x[i]+y[i]))
}
#4 6 8 

My so far limited understanding of the term Vectorized entails automatic operation on elements which I'd otherwise have to do on individual elements of a vector one by one.

Is there a method you recommend to use to identify if an operation or a function in R is vectorized?

Thank you.

Anon Mousy
  • 155
  • 6

1 Answers1

7

Vectorization in R basically means that any looping is moved to a faster, compiled language such as C or FORTRAN. For that to occur the vector(s) in question should be "atomic" - i.e. it should be "flat" and homogeneous - and the vector type, which you can check with typeof(), should make sense for the operation(s) being performed. If it is atomic then it is vectorized.

You can check if a vector is atomic using is.atomic(). Another type of vector that is not vectorized is called "recursive", which you can check using is.recursive(). Recursive objects can contain other objects of any type, i.e. they can be heterogeneous. Lists and data frames are recursive.

Try something like the following to gain some insight into atomic vs. recursive:

# Atomic:
1
1:3
c("a", "b", "c")
c(T, F, T)

# Recursive:
list(nums = 1:3, letts = c("a", "b", "c"), logics = c(T, F, T))
data.frame(nums = 1:3, letts = c("a", "b", "c"), logics = c(T, F, T))

# Vectors can be atomic or recursive:
is.vector(1:9) # TRUE
is.atomic(1:9) # TRUE
is.recursive(1:9) # FALSE

is.vector(list(nums = 1:9, chars = "x")) # TRUE
is.atomic(list(1:9)) # FALSE
is.recursive(list(1:9)) # TRUE

# Matrices are atomic, data frames are recursive:
is.vector(matrix(1:9, 3)) # FALSE
is.atomic(matrix(1:9, 3)) # TRUE
is.recursive(matrix(1:9, 3)) # FALSE

is.vector(as.data.frame(matrix(1:9, 3))) # FALSE
is.atomic(as.data.frame(matrix(1:9, 3))) # FALSE
is.recursive(as.data.frame(matrix(1:9, 3))) # TRUE

I think you can assume that many, if not most, of the R functions that you use most frequently are vectorized. I don't think there is any way to check this other than by looking at the documentation or the function internals. Whenever you think about writing a for loop to do simple element-wise operations, think about how to do it using vectorization. With enough practice it will become second nature to you. For more details I can recommend this blog post from Noam Ross.

  • @AnonMousy happy to help. If the answer helped you would you consider selecting it as the accepted answer by clicking the √? That way others with a similar question know what worked too. –  Oct 26 '19 at 13:51