Reputation: 3229
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
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
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
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