Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 702
Kian Avatar asked Dec 05 '25 14:12

Kian


2 Answers

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
like image 112
dickoa Avatar answered Dec 07 '25 02:12

dickoa


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
like image 24
tonytonov Avatar answered Dec 07 '25 02:12

tonytonov



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!