## Code by Walker Harrison @walkwearscrocs ## From https://www.walker-harrison.com/posts/2021-02-13-visualizing-how-a-kernel-draws-a-smooth-line/ library(tidyverse) theme_set(theme_bw()) set.seed(0) n <- 100 x <- runif(n, 0, 4*pi) y <- sin(x)*x^2*exp(-x/2) + rnorm(n, sd = 0.3) df <- data.frame(x, y) x_new <- seq(min(x), max(x), length.out = 100) y_smoothed <- map_dbl(x_new, ~sum(dnorm(x, mean = .x, sd = 0.5) * y)/ sum(dnorm(x, mean = .x, sd = 0.5))) df_smoothed <- data.frame(x_new, y_smoothed) ## ## Recreation of the animation by June Choe @yjunechoe ## library(gganimate) # CRAN v1.0.7 library(ragg) # CRAN v1.1.0 kernel_anim <- df_smoothed %>% # Rename the `x_new` column to avoid ambiguity with the global variable `x_new` # because `transition_reveal()` evaluates the `along` argument in global env first rename( reveal_along = x_new, y = y_smoothed ) %>% ggplot(aes(x = reveal_along, y = y)) + # Static global points geom_point( aes(x = x), data = df ) + # Dynamic local points geom_point( aes(x = x, size = size, col = col, group = group), data = map_dfr(df_smoothed$x_new, ~ { df %>% mutate( reveal_along = .x, size = dnorm(x, mean = .x, sd = 0.5), col = dnorm(x, mean = .x, sd = 0.5), group = row_number() ) }), show.legend = FALSE ) + # Moving line and point geom_line() + geom_point(size = 3, fill = "white", color = "black", shape = 21) + # Engine transition_reveal(reveal_along) animate( kernel_anim, nframes = length(x_new), fps = 10, device = agg_png(), width = 6, height = 4, units = "in" , res = 300 )