Kian
Kian

Reputation: 3229

Vectorised kernel function in R

It is easy to build a Gaussian kernel function so that it can handle a vector input:

K_gaussian <- function(x){return(1/sqrt(2*pi)*(exp(-0.5*x*x)))}
K_gaussian(seq(-1,1,0.5))
# [1] 0.2419707 0.3520653 0.3989423 0.3520653 0.2419707

But I run into trouble when I try to code up, for example, an Epanechnikov kernel:

K_ep <- function(x){if(abs(x)>1){return(0)} else{return(3/4*(1-x*x))}}

because the if statement messed things up. For example, the following doesn't give vectored output:

K_ep(seq(-2,2,0.25))
# [1] 0

Warning message:
In if (abs(x) > 1) { :
the condition has length > 1 and only the first element will be used

How can I fix this problem?

Upvotes: 3

Views: 130

Answers (3)

dickoa
dickoa

Reputation: 18437

You have two options to vectorize your function. Since you only have one parameter, the easiest option here is to use sapply

K_ep(seq(-2,2,0.25))
sapply(seq(-2, 2, 0.25), K_ep)
##  [1] 0.00000 0.00000 0.00000 0.00000 0.00000 0.32812 0.56250
##  [8] 0.70312 0.75000 0.70312 0.56250 0.32812 0.00000 0.00000
## [15] 0.00000 0.00000 0.00000

However, sometimes you want to vectorize over many parameters and sapply cannot apply anymore. You will need mapply or Vectorize (a wrapper)

K_epvect <- Vectorize(K_ep, vectorize.args = "x")
K_epvect(seq(-2,2,0.25))
##  [1] 0.00000 0.00000 0.00000 0.00000 0.00000 0.32812 0.56250
##  [8] 0.70312 0.75000 0.70312 0.56250 0.32812 0.00000 0.00000
## [15] 0.00000 0.00000 0.00000

Upvotes: 2

Vincent
Vincent

Reputation: 955

In the particular case where you want to return 0 when a condition is true/false, you can also simplify your function using something like :

K_ep <- function(x){return((abs(x)>1)*3/4*(1-x*x))}}

(this one function didn't have to be simplified but it can help in some cases)

Upvotes: 1

tonytonov
tonytonov

Reputation: 25638

Use ifelse:

K_ep2 <- function(x){ifelse(abs(x)>1, 0, 3/4*(1-x*x))}
K_ep2(seq(-2,2,0.25))
 [1] 0.000000 0.000000 0.000000 0.000000 0.000000 0.328125 0.562500 0.703125 0.750000 0.703125 0.562500 0.328125 0.000000 0.000000 0.000000
[16] 0.000000 0.000000

Upvotes: 1

Related Questions