Tal Galili
2013-Oct-21 09:19 UTC
[R] Reproducing density(..., kernel='rectangular', width=1) using convolve? (for educational purposes)
Hello dear R-help members, I am currently teaching students on kernel density estimators, and I was hoping to show them an animation of the convolution which is taking place in the "density" function. I wrote a (somewhat clunky) piece of code to reproduce the density function, but I seem to get rather different results (which means I am missing something). If any of you are in the mood to help and see what is wrong (or if you have your own piece of code which already does this), it would be lovely for future students who are studying this method. Here is the code I got thus far: #### The function to reproduce set.seed(13413) some_data <- c(round(rnorm(100))) plot(density(some_data, kernel='rectangular', width=1, n = 10**5), lwd = 3) #### The attempt convolve_new <- function(data_range, kernel_range, data_fun, kernel_fun, normalize = TRUE) { # data_range, kernel_range - MUST have the same length # if we have the range of a kernel function and of the data function # we would like to have one move over the other without any problems. y_data_fun <- data_fun(data_range) y_kernel_fun <- kernel_fun(kernel_range) n_kernel <- length(y_kernel_fun) n_data <- length(y_kernel_fun) conv_vec <- convolve(y_data_fun, rev(y_kernel_fun), type = "o") items_to_remove <- floor(n_kernel/2) conv_vec <- head(conv_vec,-items_to_remove) conv_vec <- tail(conv_vec,-items_to_remove) dx <- ifelse(normalize, mean(diff(data_range)), 1)# this is dx conv_vec * dx } w_R_01 <- function(u) { ifelse(abs(u)<=.5 & u >=0,1,0) } # fun1 <- dnorm # kernel fun1 <- w_R # kernel # fun2 <- w_R_01 # data fun2 <- # data function(x) { sapply(x, function(y) sum(some_data %in% y)) } # fun2(1) # the_data_range <- seq(-2,2, by = .01) the_data_range <- sort(c(seq(min(some_data),max(some_data), by = .01), some_data)) the_kernel_range <- the_data_range convo_the_range <- convolve_new(the_data_range, the_kernel_range, fun2, fun1) the_animation_range <- seq(-2,2, by = .2) # plot(convo_the_range/sum(convo_the_range)~the_range, type = "l") for(i in the_animation_range) { # curve(fun2, # from = min(the_data_range), to = max(the_data_range), ylim c(0,3), # n=10**3) plot(fun2(the_data_range) ~ the_data_range, type= "h") abline(v = i, lty = 2, col = "purple", lwd = 2) temp_fun1 <- function(x) {fun1(x-i)} curve(temp_fun1, from = min(the_animation_range), to = max(the_animation_range), add = TRUE, n=10**3, lwd = 3, col = 2) # temp_convolution_range <- function(x) {convolution_range(x, fun1 temp_fun1, fun2 = fun2)} # # curve(convolution_range, from = -3, to =3, add = TRUE) ss<- the_data_range<=i lines(convo_the_range[ss]~the_data_range[ss], type = "l", col = 3, lwd 3) rug(some_data) } Thanks, Tal ----------------Contact Details:------------------------------------------------------- Contact me: Tal.Galili@gmail.com | Read me: www.talgalili.com (Hebrew) | www.biostatistics.co.il (Hebrew) | www.r-statistics.com (English) ---------------------------------------------------------------------------------------------- [[alternative HTML version deleted]]