Vectorized conditional statement in R and Racket
2019 Apr 15
@travishinkelman.com
Racket's if
is not vectorized like ifelse
in R. Instead, this Racket code
(if (test-expr)
true-expr
false-expr)
is the same as this R code.
if (test_expr){
true_expr
} else {
false_expr
}
In contrast, R's ifelse
function is vectorized meaning that the same operation is applied to multiple elements of a vector. Below, we use ifelse
to return a vector of the same length as the original vector with all negative values replaced by zero.
> a = c(-999, 2, -999, 4, 5, 6, 7, -999, 9, 10)
> ifelse(a < 0, 0, a)
[1] 0 2 0 4 5 6 7 0 9 10
In Racket, we use map
and an anonymous function, specified with lambda
, to apply if
to the elements of a list.
> (define a '(-999 2 -999 4 5 6 7 -999 9 10))
> (map (lambda (x) (if (< x 0) 0 x)) a)
'(0 2 0 4 5 6 7 0 9 10)
To apply if
to a vector, we use vector-map
.
> (define b #(-999 2 -999 4 5 6 7 -999 9 10))
> (vector-map (lambda (x) (if (< x 0) 0 x)) b)
'#(0 2 0 4 5 6 7 0 9 10)
It is also possible to write similar code in R using sapply
. The curly braces can be omitted when if else
is written inline.
> sapply(a, function(x) if (x < 0) 0 else x)
[1] 0 2 0 4 5 6 7 0 9 10
R and Racket have a shared heritage in Scheme and Lisp that can yield some strikingly similar code.