Executive Summary
This interactive analysis provides a data-driven exploration of library programming, focusing on strategic insights derived from event registration patterns, consistency, and alignment with library mission.
Core Methodology
Our analysis considers multiple dimensions beyond raw attendance: - Program Consistency - Strategic Alignment - Community Engagement Potential - Operational Efficiency
Data Preparation
Show code
# Load required libraries
library (tidyverse)
library (janitor)
library (lubridate)
library (kableExtra)
library (plotly)
library (DT)
# Load and prepare the data
event_data <- read_csv ("event_data_with_analysis.csv" ,
col_types = cols (),
na = c ("" , "NA" , "N/A" )) %>%
clean_names () %>%
mutate (
# Parse event dates and times in UTC
event_start_time = ymd_hms (event_start_time, tz = "UTC" ),
# Convert to local time (Central Time)
local_start_time = with_tz (event_start_time, tzone = "America/Chicago" ),
# Extract local time components
event_date = as.Date (local_start_time),
event_year = year (event_date),
event_month = month (event_date),
# Create primary subject categorization
primary_subject = map_chr (as.character (event_subjects), function (subjects) {
if (is.na (subjects)) return ("Uncategorized" )
priority_subjects <- c (
"Books & Authors" , "ESL" , "Technology Classes" ,
"Business & Nonprofit" , "Makerplace" , "Senior Center" ,
"Genealogy" , "Health & Wellness" , "Arts & Culture"
)
tags <- str_split (subjects, ";" )[[1 ]] %>%
str_trim () %>%
.[! str_detect (., "^ \\ d+$" )]
for (subject in priority_subjects) {
if (any (str_detect (tags, fixed (subject)))) {
return (subject)
}
}
return (tags[1 ] %||% "Uncategorized" )
}),
# Filter for valid events
is_valid_event =
! str_detect (tolower (event_title %||% "" ), "child|kid|family|youth" ) &
! str_detect (tolower (primary_subject), "child|kid|family|youth" ) &
! str_detect (tolower (event_title %||% "" ), "cancel" ) &
! is.na (event_date) &
! is.na (actual_registrations) &
actual_registrations > 0
) %>%
filter (is_valid_event)
# Strategic categories
strategic_categories <- list (
skill_development = c ("Technology Classes" , "Business & Nonprofit" , "Jobs & Careers" ),
community_connection = c ("Books & Authors" , "Arts & Culture" , "Lectures" ),
inclusive_access = c ("ESL" , "Senior Center" , "Genealogy" ),
local_empowerment = c ("Civics & Voting" , "Health & Wellness" )
)
# Print data overview
cat ("Total events:" , nrow (event_data), " \n " )
Show code
cat ("Years covered:" , min (event_data$ event_year), "to" , max (event_data$ event_year), " \n " )
Years covered: 2021 to 2025
Program Consistency Analysis
Show code
# Analyze program consistency
program_consistency <- event_data %>%
group_by (primary_subject, event_year) %>%
summarise (
yearly_events = n (),
avg_registrations = mean (actual_registrations),
median_registrations = median (actual_registrations),
registration_variability = sd (actual_registrations) / mean (actual_registrations),
.groups = 'drop'
) %>%
group_by (primary_subject) %>%
summarise (
total_years_active = n_distinct (event_year),
avg_yearly_events = mean (yearly_events),
avg_registrations = mean (avg_registrations),
consistency_score = 1 / (1 + mad (yearly_events)), # Mean Absolute Deviation
.groups = 'drop'
) %>%
mutate (
program_stability = case_when (
consistency_score > 0.8 ~ "Highly Stable" ,
consistency_score > 0.5 ~ "Moderately Stable" ,
TRUE ~ "Needs Review"
)
) %>%
arrange (program_stability, desc (avg_registrations))
# Interactive table with sorting
datatable (program_consistency,
options = list (pageLength = 10 ),
caption = "Program Consistency and Stability Analysis" ) %>%
formatRound (columns = c ('avg_yearly_events' , 'avg_registrations' , 'consistency_score' ), digits = 2 )
Interactive Visualizations
Strategic Category Registration Trends
Show code
# Aggregate data by strategic category
trend_data <- event_data %>%
mutate (
strategic_category = case_when (
primary_subject %in% strategic_categories$ skill_development ~ "Skill Development" ,
primary_subject %in% strategic_categories$ community_connection ~ "Community Connection" ,
primary_subject %in% strategic_categories$ inclusive_access ~ "Inclusive Access" ,
primary_subject %in% strategic_categories$ local_empowerment ~ "Local Empowerment" ,
TRUE ~ "Other"
)
) %>%
group_by (strategic_category, event_year) %>%
summarise (
total_registrations = sum (actual_registrations),
.groups = 'drop'
)
# Create interactive trend plot
trend_plot <- ggplot (trend_data,
aes (x = event_year,
y = total_registrations,
color = strategic_category,
group = strategic_category,
text = paste (
"Year:" , event_year,
"<br>Total Registrations:" , total_registrations,
"<br>Category:" , strategic_category
))) +
geom_line (size = 1.2 ) +
geom_point (size = 3 ) +
labs (
title = "Strategic Category Registration Trends" ,
x = "Year" ,
y = "Total Registrations" ,
color = "Strategic Category"
) +
theme_minimal ()
# Convert to interactive plotly
ggplotly (trend_plot, tooltip = "text" )
Key Insights and Strategic Recommendations
Program Stability Observations
Identified programs with consistent performance
Highlighted areas needing strategic review
Strategic Alignment
Mapped programs to library’s mission dimensions
Assessed alignment with community development goals
Temporal Trends
Analyzed registration trends over time
Provided forward-looking recommendations
Recommended Actions
Preserve Stable Programs
Focus on high-alignment, growing programs
Maintain core community services
Optimize Moderate Performers
Conduct detailed reviews
Explore format and timing adjustments
Redesign Struggling Programs
Gather community input
Consider alternative delivery methods
Note: This analysis provides a data-driven framework for strategic programming decisions, emphasizing mission alignment and community impact.