The dataset contains a list of scrapped rollercoaster Wikipedia pages that include, but not limited to, the roller coaster’s name, length in meters, speed in mph, general location, opening date, composition, maufacturer, cost to build, and height. There are several missing entries for multiple variables that will be filtered out. The variables in the focus in the analysis of this dataset will include: rollercoaster’s length, speed, name, and age. These variables will be visually analyzed to understand any associations between rollercoaster variables.
The creator for the dataset is Rob Mulla, who used code to scrap rollercoaster wikipedia articles to create this dataset. The code can be found here: https://github.com/RobMulla/twitch-stream-projects/tree/main/001-rollercoaster-dataset
Load Libraries
library("tidyverse")
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr 1.2.1 ✔ readr 2.2.0
✔ forcats 1.0.1 ✔ stringr 1.6.0
✔ ggplot2 4.0.3 ✔ tibble 3.3.1
✔ lubridate 1.9.5 ✔ tidyr 1.3.2
✔ purrr 1.2.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
Rows: 1087 Columns: 56
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (46): coaster_name, Length, Speed, Location, Status, Opening date, Type,...
dbl (10): Inversions, year_introduced, latitude, longitude, speed1_value, sp...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Uses filter & mutate to do so with smaller functions gsub and as.numeric to clean and convert the character array into numerical values. The age is an approximation as it only looks at the years the rides were opened and subtracts that from the current year.
Exploratory Plots
Plot 1 : Ride Age and Length.
ggplot(clean_rollercoaster, aes(x= age, y= Length_m, color = age)) +geom_point() +geom_smooth(method ="lm",formula = y ~ x,se =TRUE,color ="black" )+theme_minimal() +labs(x="Roller Coaster Age", y ="Roller Coaster Length (Meters)", title ="Roller Coaster Length Plotted against Roller Coaster Age", color ="Age")
PLot 2: Roller Coaster’s Speed and Age
ggplot( clean_rollercoaster,aes(x = age, y = speed_mph, color = age)) +geom_point() +geom_smooth(method ="lm",formula = y ~ x,se =TRUE,color ="black" ) +theme_minimal() +labs(x ="Roller Coaster Age (years)",y ="Roller Coaster Speed (mph)",title ="Roller Coaster Speed Plotted Against Age",color ="Age" )
Final Visulization Plot
# Select four locations with many roller coastersfinal_plot_data <- clean_rollercoaster |>filter( Location %in%c("Kings Island","Cedar Point","Six Flags Magic Mountain","Carowinds" ) )# Select the fastest coasters to label by namefast_coasters <- final_plot_data |>filter(speed_mph >=90)# Final visualizationggplot( final_plot_data,aes(x = age,y = speed_mph,color = Location )) +geom_point(size =3,alpha =0.6 ) +geom_smooth(method ="lm",formula = y ~ x,se =FALSE,linetype ="dotdash",linewidth =0.7 ) +geom_text(data = fast_coasters,aes(label = coaster_name),nudge_y =3,size =3,show.legend =FALSE ) +scale_color_brewer(name ="Roller Coaster Location",palette ="Set1" ) +theme_minimal(base_size =12) +labs(title ="Roller Coaster Speed and Age Across Four Amusement Parks",subtitle ="Dashed lines are the Linear Relationships for each location",x ="Roller Coaster Age (years)",y ="Maximum Roller Coaster Speed (mph)",caption =paste("Source: Rob Mulla, Roller Coaster Dataset;","compiled from Wikipedia roller-coaster pages" ) )
To prepare the roller-coaster dataset for analysis, I first filtered out observations with missing values for length, speed, coaster name, or opening date. Because the opening-date information was stored as character text and included multiple date formats, I used a regular expression with gsub() to extract the four-digit opening year. I converted the extracted year to numeric form and estimated each roller coaster’s age by subtracting the opening year from 2026. The Length column also contained text, units, and multiple formats, so I used str_extract() to extract the number immediately before the meter symbol and parse_number() to convert it into a numeric variable named Length_m. After creating the new variables, I filtered out rows in which age or length remained missing or non-finite. These steps produced numeric variables that could be used correctly in scatterplots and linear-regression models.
The final visualization examines the relationship between roller-coaster age and maximum speed. Age is displayed on the x-axis in years, and speed is displayed on the y-axis in miles per hour. The points are colored according to four selected locations: Kings Island, Cedar Point, Six Flags Magic Mountain, and Carowinds. A different dashed linear-regression line is calculated for each location because location is mapped to color for the entire graph. The graph does not display confidence-interval bands because se = FALSE was used. Roller coasters reaching at least 90 miles per hour are labeled by name to identify especially fast rides. Overall, the graph appears to suggest that newer roller coasters tend to reach higher speeds, although there is considerable variation within and across locations. Some older coasters remain relatively fast, while some newer coasters have only moderate speeds. The overlap among the four locations suggests that location alone does not fully explain differences in roller-coaster speed.
I originally wanted to include every available location and label every roller coaster by name. However, including all locations created too many categories, colors, and legend entries, while labeling every point caused the coaster names to overlap. To keep the final visualization readable, I limited it to four amusement-park locations and labeled only coasters with speeds of at least 90 miles per hour. I also considered including roller-coaster length in the same visualization, but displaying age, speed, location, and selected coaster names already communicated several variables without making the graph overly crowded or difficult to interpret.