The simulation is about the cars entering a public car park area over
a period of 12 hours.
We use the Poisson distribution to simulate the number
of cars entering during each 30 minutes period.
Next, for each car that enters, we simulate the period it stays in the
parking by using the Geometric distribution.
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.0 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
# create the DataFrame structure
# we track the cars entering over each 30 min period, from 8:00 am to 8:00 pm
# date_obs <- as.Date("2023-12-10")
set.seed(25)
n_entering <- rpois(n = 24, lambda = 10)
cars_movements <- data.frame(ent_period = 0, id_car = 0, stay_period = 0)
# populate the DataFrame
for (ii in 1:24) {
cc <- n_entering[ii]
ent_cars <- expand_grid(ent_period = ii, id_car = 1:cc)
ent_cars$id_car <- ent_cars$id_car + 100 * ii
ent_cars$stay_period = rgeom(n = cc, prob = 0.25)
cars_movements <- bind_rows(cars_movements, ent_cars)
}
# define the exit period as ent_period + stay_period
cars_movements <- cars_movements %>%
mutate(ext_period = ent_period + stay_period)
print(head(cars_movements, 12))
## ent_period id_car stay_period ext_period
## 1 0 0 0 0
## 2 1 101 5 6
## 3 1 102 2 3
## 4 1 103 1 2
## 5 1 104 2 3
## 6 1 105 1 2
## 7 1 106 1 2
## 8 1 107 6 7
## 9 1 108 3 4
## 10 1 109 8 9
## 11 2 201 5 7
## 12 2 202 0 2
# define the starting time (the time when the car park opens)
start_time <- as.POSIXct("08:00", format = "%H:%M")
# convert the period number to time (N.B.: there are 1800 seconds in a period of 30 minutes)
cars_movements <- cars_movements %>%
mutate(ent_period_t = start_time + ent_period * 1800, ext_period_t = start_time + ext_period * 1800) %>%
filter(id_car != 0)
print(head(cars_movements, 12))
## ent_period id_car stay_period ext_period ent_period_t
## 1 1 101 5 6 2025-10-03 08:30:00
## 2 1 102 2 3 2025-10-03 08:30:00
## 3 1 103 1 2 2025-10-03 08:30:00
## 4 1 104 2 3 2025-10-03 08:30:00
## 5 1 105 1 2 2025-10-03 08:30:00
## 6 1 106 1 2 2025-10-03 08:30:00
## 7 1 107 6 7 2025-10-03 08:30:00
## 8 1 108 3 4 2025-10-03 08:30:00
## 9 1 109 8 9 2025-10-03 08:30:00
## 10 2 201 5 7 2025-10-03 09:00:00
## 11 2 202 0 2 2025-10-03 09:00:00
## 12 2 203 1 3 2025-10-03 09:00:00
## ext_period_t
## 1 2025-10-03 11:00:00
## 2 2025-10-03 09:30:00
## 3 2025-10-03 09:00:00
## 4 2025-10-03 09:30:00
## 5 2025-10-03 09:00:00
## 6 2025-10-03 09:00:00
## 7 2025-10-03 11:30:00
## 8 2025-10-03 10:00:00
## 9 2025-10-03 12:30:00
## 10 2025-10-03 11:30:00
## 11 2025-10-03 09:00:00
## 12 2025-10-03 09:30:00
# range of entering and exiting periods
range(cars_movements$ent_period_t)
## [1] "2025-10-03 08:30:00 CEST" "2025-10-03 20:00:00 CEST"
range(cars_movements$ext_period_t)
## [1] "2025-10-03 09:00:00 CEST" "2025-10-04 04:30:00 CEST"
# set plotting area width in inches
options(repr.plot.width = 14)
# define the graphic object ent_plot
ent_plot <- cars_movements %>% group_by(ent_period_t) %>%
summarize(num_cars = n()) %>%
ggplot(aes(x = ent_period_t, y = num_cars)) + geom_line(linewidth = 2, color = "forestgreen")
# define the ext_data
ext_data <- cars_movements %>% group_by(ext_period_t) %>%
summarize(num_cars = n())
# plot the cars entering and exiting
ent_plot +
geom_line(data = ext_data, aes(x = ext_period_t, y = num_cars), linewidth = 2, color = "red") +
scale_x_datetime(limits = c(min(cars_movements$ent_period_t),
max(cars_movements$ent_period_t)),
date_labels = "%H:%M", date_breaks = "1 hour") +
labs(title = "Cars entering (green) and exiting (red)", x = "time", y = "number of cars")
## Warning: Removed 10 rows containing missing values or values outside the scale range
## (`geom_line()`).
# plot the cars entering and exiting (the latter with negative sign)
ent_plot +
geom_line(data = ext_data, aes(x = ext_period_t, y = -num_cars), linewidth = 2, color = "red") +
scale_x_datetime(limits = c(min(cars_movements$ent_period_t),
max(cars_movements$ent_period_t)),
date_labels = "%H:%M", date_breaks = "1 hour") +
geom_hline(aes(yintercept = 0)) +
labs(title = "Cars entering (green) and exiting (red)", x = "time", y = "number of cars")
## Warning: Removed 10 rows containing missing values or values outside the scale range
## (`geom_line()`).