## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5 ) ## ----setup, echo=FALSE, message=FALSE----------------------------------------- library(RandomWalker) library(dplyr) library(ggplot2) ## ----basic_syntax------------------------------------------------------------- # 1D walk (default) walk_1d <- random_normal_walk(.num_walks = 5, .n = 100, .dimensions = 1) # 2D walk walk_2d <- random_normal_walk(.num_walks = 5, .n = 100, .dimensions = 2) # 3D walk walk_3d <- random_normal_walk(.num_walks = 5, .n = 100, .dimensions = 3) ## ----distribution_examples, eval=FALSE---------------------------------------- # # 2D Brownian motion # brownian_motion(.num_walks = 10, .n = 500, .dimensions = 2) # # # 3D geometric Brownian motion # geometric_brownian_motion( # .num_walks = 10, # .n = 500, # .initial_value = 100, # .dimensions = 3 # ) # # # 2D Cauchy walk (heavy tails) # random_cauchy_walk(.num_walks = 10, .n = 200, .dimensions = 2) # # # 3D exponential walk # random_exponential_walk(.num_walks = 5, .n = 300, .dimensions = 3) ## ----inspect_data------------------------------------------------------------- # 2D walk walk_2d <- random_normal_walk(.num_walks = 3, .n = 100, .dimensions = 2) # View structure head(walk_2d, 10) names(walk_2d) # 3D walk walk_3d <- random_normal_walk(.num_walks = 3, .n = 100, .dimensions = 3) # View structure head(walk_3d, 10) names(walk_3d) ## ----basic_2d_plot, fig.alt="2D random walk trajectories showing multiple walks with start points marked as white circles and end points as red triangles"---- # Generate 2D walk walk_2d <- random_normal_walk(.num_walks = 10, .n = 200, .dimensions = 2) # Plot trajectories ggplot(walk_2d, aes(x = cum_sum_x, y = cum_sum_y, color = walk_number)) + geom_path(alpha = 0.6, linewidth = 0.5) + geom_point(data = walk_2d %>% filter(step_number == 1), size = 3, shape = 21, fill = "white") + # Start points geom_point(data = walk_2d %>% group_by(walk_number) %>% slice_max(step_number), size = 3, shape = 24, fill = "red") + # End points coord_equal() + theme_minimal() + labs( title = "2D Random Walk Trajectories", x = "X Position", y = "Y Position", color = "Walk" ) ## ----step_numbers_2d, fig.alt="Single 2D random walk with step numbers labeled at intervals of 10 steps, colored by step progression"---- # Generate single walk walk_2d <- random_normal_walk(.num_walks = 1, .n = 100, .dimensions = 2) # Plot with step labels at intervals walk_2d_labeled <- walk_2d %>% filter(step_number %% 10 == 0 | step_number == 1) ggplot(walk_2d, aes(x = cum_sum_x, y = cum_sum_y)) + geom_path(color = "steelblue", linewidth = 1) + geom_point(data = walk_2d_labeled, aes(color = step_number), size = 3) + geom_text(data = walk_2d_labeled, aes(label = step_number), hjust = -0.3, vjust = -0.3, size = 3) + scale_color_viridis_c() + coord_equal() + theme_minimal() + labs( title = "2D Random Walk with Step Numbers", x = "X Position", y = "Y Position", color = "Step" ) ## ----heatmap_2d, fig.alt="Heat map showing the density of 100 random walks with 500 steps each, using a plasma color scale to indicate visit frequency"---- library(ggplot2) # Generate many walks walk_2d <- random_normal_walk(.num_walks = 100, .n = 500, .dimensions = 2) # Create density heat map ggplot(walk_2d, aes(x = cum_sum_x, y = cum_sum_y)) + geom_bin2d(bins = 50) + scale_fill_viridis_c(option = "plasma") + coord_equal() + theme_minimal() + labs( title = "2D Random Walk Density Heat Map", subtitle = "100 walks, 500 steps each", x = "X Position", y = "Y Position", fill = "Count" ) ## ----animated_2d, eval=FALSE-------------------------------------------------- # library(ggplot2) # library(gganimate) # # # Generate walk # walk_2d <- random_normal_walk(.num_walks = 5, .n = 100, .dimensions = 2) # # # Create animation # p <- ggplot(walk_2d, aes(x = cum_sum_x, y = cum_sum_y, color = walk_number)) + # geom_path(aes(group = walk_number), alpha = 0.5) + # geom_point(size = 3) + # coord_equal() + # theme_minimal() + # labs(title = "Step: {frame_along}", x = "X", y = "Y") + # transition_reveal(step_number) # # # Render # animate(p, nframes = 100, fps = 10) ## ----3d_scatter, eval=FALSE--------------------------------------------------- # library(plotly) # # # Generate 3D walk # walk_3d <- random_normal_walk(.num_walks = 5, .n = 200, .dimensions = 3) # # # Create 3D plot # plot_ly( # data = walk_3d, # x = ~cum_sum_x, # y = ~cum_sum_y, # z = ~cum_sum_z, # color = ~walk_number, # type = "scatter3d", # mode = "lines", # line = list(width = 2) # ) %>% # layout( # title = "3D Random Walk Trajectories", # scene = list( # xaxis = list(title = "X Position"), # yaxis = list(title = "Y Position"), # zaxis = list(title = "Z Position") # ) # ) ## ----3d_markers, eval=FALSE--------------------------------------------------- # library(plotly) # library(dplyr) # # # Generate 3D walk # walk_3d <- random_normal_walk(.num_walks = 3, .n = 100, .dimensions = 3) # # # Mark start and end points # walk_with_markers <- walk_3d %>% # mutate( # point_type = case_when( # step_number == 1 ~ "Start", # step_number == max(step_number) ~ "End", # TRUE ~ "Path" # ) # ) # # # Create plot # plot_ly(data = walk_with_markers) %>% # # Add paths # add_trace( # data = walk_with_markers %>% filter(point_type == "Path"), # x = ~cum_sum_x, y = ~cum_sum_y, z = ~cum_sum_z, # color = ~walk_number, # type = "scatter3d", # mode = "lines", # line = list(width = 2), # showlegend = FALSE # ) %>% # # Add start points # add_trace( # data = walk_with_markers %>% filter(point_type == "Start"), # x = ~cum_sum_x, y = ~cum_sum_y, z = ~cum_sum_z, # type = "scatter3d", # mode = "markers", # marker = list(size = 8, color = "green", symbol = "circle"), # name = "Start" # ) %>% # # Add end points # add_trace( # data = walk_with_markers %>% filter(point_type == "End"), # x = ~cum_sum_x, y = ~cum_sum_y, z = ~cum_sum_z, # type = "scatter3d", # mode = "markers", # marker = list(size = 8, color = "red", symbol = "diamond"), # name = "End" # ) %>% # layout( # title = "3D Random Walk with Start/End Markers", # scene = list( # xaxis = list(title = "X"), # yaxis = list(title = "Y"), # zaxis = list(title = "Z") # ) # ) ## ----3d_projections, fig.width=10, fig.height=8, fig.alt="Three projection plots showing X-Y, X-Z, and Y-Z views of 3D random walks, arranged with X-Y on top and X-Z and Y-Z side by side below"---- library(ggplot2) library(patchwork) # Generate 3D walk walk_3d <- random_normal_walk(.num_walks = 5, .n = 200, .dimensions = 3) # X-Y projection p_xy <- ggplot(walk_3d, aes(x = cum_sum_x, y = cum_sum_y, color = walk_number)) + geom_path(alpha = 0.6) + coord_equal() + theme_minimal() + labs(title = "X-Y Projection") # X-Z projection p_xz <- ggplot(walk_3d, aes(x = cum_sum_x, y = cum_sum_z, color = walk_number)) + geom_path(alpha = 0.6) + coord_equal() + theme_minimal() + labs(title = "X-Z Projection") # Y-Z projection p_yz <- ggplot(walk_3d, aes(x = cum_sum_y, y = cum_sum_z, color = walk_number)) + geom_path(alpha = 0.6) + coord_equal() + theme_minimal() + labs(title = "Y-Z Projection") # Combine p_xy / (p_xz | p_yz) + plot_layout(guides = "collect") + plot_annotation(title = "3D Random Walk - All Projections") ## ----distance_2d, eval=FALSE, fig.alt="Line plot showing distance from origin over time for 10 random walks in 2D, with a dashed black line showing the theoretical expectation"---- # library(dplyr) # # # 2D walk # walk_2d <- random_normal_walk(.num_walks = 10, .n = 500, .dimensions = 2) # # # Calculate distance # walk_with_distance <- walk_2d %>% # euclidean_distance(.x = x, .y = y) # # # Visualize distance over time # library(ggplot2) # # ggplot(walk_with_distance, aes(x = step_number, y = distance, color = walk_number)) + # geom_line(alpha = 0.7) + # # Add theoretical expectation # geom_line(aes(y = sqrt(2 * step_number)), color = "black", linetype = "dashed", linewidth = 1) + # theme_minimal() + # labs( # title = "Distance from Origin in 2D Random Walk", # subtitle = "Dashed line shows theoretical E[distance] = sqrt(2n)", # x = "Step", # y = "Euclidean Distance" # ) ## ----distance_3d, eval=FALSE-------------------------------------------------- # # 3D walk # walk_3d <- random_normal_walk(.num_walks = 100, .n = 1000, .dimensions = 3) # # # Calculate distance # walk_with_distance <- walk_3d %>% # euclidean_distance(.x = x, .y = z) # # # Analyze distance distribution at specific steps # library(dplyr) # # distance_at_steps <- walk_with_distance %>% # filter(step_number %in% c(100, 250, 500, 1000)) %>% # group_by(step_number) %>% # reframe( # mean_dist = mean(distance), # sd_dist = sd(distance), # theoretical_mean = sqrt(3 * step_number) # ) # # print(distance_at_steps) ## ----radial_dist, eval=FALSE, fig.alt="Histogram with density overlay showing the radial distribution of final positions for 500 random walks"---- # library(dplyr) # library(ggplot2) # # # Generate many 2D walks # walk_2d <- random_normal_walk(.num_walks = 500, .n = 200, .dimensions = 2) # # # Get final positions # final_positions <- walk_2d %>% # group_by(walk_number) %>% # slice_max(step_number) %>% # euclidean_distance(.x = x, .y = y) # # # Plot radial distribution # ggplot(final_positions, aes(x = distance)) + # geom_histogram(aes(y = after_stat(density)), bins = 50, fill = "steelblue", alpha = 0.7) + # geom_density(color = "darkblue", linewidth = 1) + # theme_minimal() + # labs( # title = "Radial Distribution of Final Positions (2D)", # subtitle = "500 walks, 200 steps each", # x = "Distance from Origin", # y = "Density" # ) ## ----convex_hull, eval=FALSE, fig.alt="2D random walk paths with a black polygon showing the convex hull of all final positions"---- # library(dplyr) # library(ggplot2) # # # Generate 2D walks # walk_2d <- random_normal_walk(.num_walks = 20, .n = 200, .dimensions = 2) # # # Get final positions # final_positions <- walk_2d %>% # group_by(walk_number) %>% # slice_max(step_number) # # # Calculate convex hull # hull <- chull(final_positions$cum_sum_x, final_positions$cum_sum_y) # hull_points <- final_positions[c(hull, hull[1]), ] # Close the polygon # # # Plot # ggplot(walk_2d, aes(x = cum_sum_x, y = cum_sum_y, color = walk_number)) + # geom_path(alpha = 0.3) + # geom_point(data = final_positions, size = 3) + # geom_polygon(data = hull_points, aes(x = cum_sum_x, y = cum_sum_y), # fill = NA, color = "black", linewidth = 1) + # coord_equal() + # theme_minimal() + # labs( # title = "2D Random Walks with Convex Hull", # subtitle = "Black polygon shows convex hull of final positions", # x = "X Position", # y = "Y Position" # ) ## ----particle_diffusion, eval=FALSE, fig.alt="Line plot showing particle diffusion distance from origin over time, with individual particle paths in light colors and mean distance in bold red"---- # # Simulate particle diffusion in a petri dish # particles <- brownian_motion( # .num_walks = 50, # .n = 1000, # .delta_time = 0.1, # .dimensions = 2 # ) # # # Visualize # particles %>% # euclidean_distance(.x = x, .y = y) %>% # ggplot(aes(x = step_number, y = distance, color = walk_number)) + # geom_line(alpha = 0.3) + # stat_summary(aes(group = 1), fun = mean, geom = "line", # color = "red", linewidth = 1.5) + # theme_minimal() + # labs( # title = "Particle Diffusion in 2D", # subtitle = "Red line shows mean distance", # x = "Time Step", # y = "Distance from Origin" # ) ## ----drone_path, eval=FALSE--------------------------------------------------- # # Simulate drone wandering in 3D space # drone_path <- brownian_motion( # .num_walks = 1, # .n = 500, # .delta_time = 0.5, # .initial_value = 100, # Start at 100m altitude # .dimensions = 3 # ) # # # 3D visualization # library(plotly) # # plot_ly( # data = drone_path, # x = ~cum_sum_x, # y = ~cum_sum_y, # z = ~cum_sum_z, # type = "scatter3d", # mode = "lines+markers", # marker = list( # size = 2, # color = ~step_number, # colorscale = "Viridis", # showscale = TRUE # ), # line = list(width = 2, color = "steelblue") # ) %>% # layout( # title = "Drone Flight Path (3D Random Walk)", # scene = list( # xaxis = list(title = "X (meters)"), # yaxis = list(title = "Y (meters)"), # zaxis = list(title = "Altitude (meters)") # ) # ) ## ----animal_movement, eval=FALSE, fig.alt="2D random walk showing animal foraging behavior with path colored by distance from home, and a red triangle marking the home location"---- # # Simulate animal foraging behavior # # Using Cauchy walk for heavy tails (occasional long jumps) # animal_movement <- random_cauchy_walk( # .num_walks = 1, # .n = 200, # .scale = 1, # .dimensions = 2 # ) # # # Add "home" location # animal_movement <- animal_movement %>% # mutate( # distance_from_home = sqrt(cum_sum_x^2 + cum_sum_y^2) # ) # # # Plot # ggplot(animal_movement, aes(x = cum_sum_x, y = cum_sum_y)) + # geom_path(color = "darkgreen", linewidth = 0.8, alpha = 0.6) + # geom_point(aes(color = distance_from_home), size = 2) + # geom_point(x = 0, y = 0, size = 5, color = "red", shape = 17) + # Home # scale_color_viridis_c(option = "magma") + # coord_equal() + # theme_minimal() + # labs( # title = "Animal Foraging Path (2D Cauchy Walk)", # subtitle = "Red triangle marks home location", # x = "X Position", # y = "Y Position", # color = "Distance\nfrom Home" # ) ## ----performance, eval=FALSE-------------------------------------------------- # # Reduce number of dimensions if not needed # walk_2d <- random_normal_walk(.num_walks = 100, .n = 1000, .dimensions = 2) # # # Instead of # # walk_3d <- random_normal_walk(.num_walks = 100, .n = 1000, .dimensions = 3) ## ----viz_perf, eval=FALSE----------------------------------------------------- # # Sample walks or steps for large datasets # walk_large <- random_normal_walk(.num_walks = 1000, .n = 1000, .dimensions = 2) # # # Sample walks # walk_sample <- walk_large %>% # filter(walk_number %in% sample(levels(walk_number), 50)) # # # Or downsample steps # walk_downsample <- walk_large %>% # filter(step_number %% 10 == 0) ## ----coord_systems, eval=FALSE------------------------------------------------ # # Good - maintains true spatial relationships # ggplot(walk_2d, aes(x = cum_sum_x, y = cum_sum_y)) + # geom_path() + # coord_equal() # Important! # # # Bad - distorts spatial relationships # ggplot(walk_2d, aes(x = cum_sum_x, y = cum_sum_y)) + # geom_path() # No coord_equal() ## ----boundaries, eval=FALSE, fig.alt="2D random walk with reflecting boundaries shown by a black rectangle, demonstrating how walks bounce back when reaching the boundary"---- # # Reflecting boundary (bounce back) # walk_2d <- random_normal_walk(.num_walks = 10, .n = 500, .dimensions = 2) # # walk_bounded <- walk_2d %>% # mutate( # cum_sum_x = pmin(pmax(cum_sum_x, -50), 50), # Bound between -50 and 50 # cum_sum_y = pmin(pmax(cum_sum_y, -50), 50) # ) # # # Visualize # ggplot(walk_bounded, aes(x = cum_sum_x, y = cum_sum_y, color = walk_number)) + # geom_path(alpha = 0.6) + # geom_rect(xmin = -50, xmax = 50, ymin = -50, ymax = 50, # fill = NA, color = "black", linewidth = 1) + # coord_equal() + # theme_minimal() + # labs(title = "2D Walk with Reflecting Boundaries")