R-bloggers

Close To Me: finding close parkruns

[This article was first published on Rstats – quantixed, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

I saw a fun video on YouTube recently in which some runners attempted to do two parkruns in one day. I don’t mean run the same parkrun course twice, I mean they ran one parkrun at one course and then drove to a different course and ran that one too. The challenge was to do both parkruns and beat the last person (the tail walker) on the second course to the finish line.

Spoiler alert: if you want the suspense, watch the video and then return here.

In the video, they take on Warwick Racecourse parkrun first. A driver is waiting and they zoom to Leamington Spa parkrun and run that next. The drive is around 12 min. They are helped by being extremely good runners – in fact, one of them (Harry) finishes first at Warwick – and Leamington happens to start a few minutes late. Even so, they breeze past the tail walker to complete the challenge.

I saw Ryan who co-hosts Raley Adventures YouTube channel at a recent running event and he mentioned the cool thing would be to not rely on Haley (his co-host) to drive between the parkruns, but to actually run between them. This got me thinking: where are the closest pairs of parkruns, and which of those are in the Midlands where Raley Adventures are based?

It was pretty straightforward, given a list of coordinates of all UK parkruns, to figure this out in R. Click here for the answer, or read on for the code.

The code

Using the list, we can find the distance between all pairs of parkrun coordinates and then set a limit of 3 km to define a runnable pair. The 12 min drive from Warwick to Leamington equates to 3 km in running for fast chaps like Ryan and Harry.

uk-parkrunsDownload
library(leaflet)
library(htmlwidgets)

## Functions ----

# function to get the distance between two rows of the dataframe
haversine_distance <- function(lat1, lon1, lat2, lon2) {
  R <- 6371  # Earth radius in km
  dlat <- (lat2 - lat1) * pi / 180
  dlon <- (lon2 - lon1) * pi / 180
  a <- sin(dlat / 2) * sin(dlat / 2) +
    cos(lat1 * pi / 180) * cos(lat2 * pi / 180
    ) * sin(dlon / 2) * sin(dlon / 2)
  c <- 2 * atan2(sqrt(a), sqrt(1 - a))
  d <- R * c
  return(d)
}

## Script ----

# load in the csv in Data it has no headers
df <- read.csv("Data/uk-parkruns.csv", header = FALSE)
# label columns
colnames(df) <- c("Event", "Place", "Lat", "Lon")
# drop all rows that have the word "juniors" in Event
df <- df[!grepl("juniors", df$Event, ignore.case = TRUE), ]

# now find the nearest neighbors for each parkrun using haversine formula
df$Nearest_Neighbor <- NA
df$Distance_to_Nearest_Neighbor_km <- NA
for (i in 1:nrow(df)) {
  row <- df[i, ]
  min_distance <- Inf
  nearest_event <- NA
  for (j in 1:nrow(df)) {
    if (i != j) {
      neighbor_row <- df[j, ]
      dist <- haversine_distance(row$Lat, row$Lon,
                                 neighbor_row$Lat, neighbor_row$Lon)
      if (dist < min_distance) {
        min_distance <- dist
        nearest_event <- neighbor_row$Event
      }
    }
  }
  df$Nearest_Neighbor[i] <- nearest_event
  df$Distance_to_Nearest_Neighbor_km[i] <- round(min_distance, 2)
}

# sort by distance to nearest neighbor
df <- df[order(df$Distance_to_Nearest_Neighbor_km), ]

write.csv(df, "Output/Data/uk-parkruns-with-nearest-neighbors.csv",
 row.names = FALSE)

# make a leaflet map to visualize the parkruns and their nearest neighbors
map <- leaflet(df) |>
  addTiles() |>
  addCircleMarkers(~Lon, ~Lat,
                   label = ~paste0(Event,
                                  "-- Nearest Neighbour: ",
                                  Nearest_Neighbor,
                                  "-- Distance (km): ",
                                  Distance_to_Nearest_Neighbor_km),
                   radius = 4,
                   color=~ifelse(df$Distance_to_Nearest_Neighbor_km < 3 , "red", "blue"),
                   stroke = FALSE,
                   fillOpacity = 0.7)
# save the map as an html file
saveWidget(map, "Output/Plots/uk-parkruns-nearest-neighbors-map.html", selfcontained = TRUE)

The closest parkruns

Amazingly there were 115 runnable pairs of parkruns (there are caveats to this, see below).

Here’s the top 20 or so in the table to see the closest 10 or so pairs.

EventPlaceLatLonNearest_NeighborDistance_to_Nearest_Neighbor_km
LeazesLeazes Park54.977078-1.625633Town Moor1.38
Town MoorExhibition Park, Newcastle54.988451-1.617143Leazes1.38
Cuningar LoopCuningar Loop55.84069-4.201428Tollcross1.57
TollcrossTollcross55.847494-4.179461Cuningar Loop1.57
Jesmond DeneJesmond Dene54.99188-1.592839Town Moor1.6
AlexandraAlexandra Park53.450142-2.248827South Manchester1.66
South ManchesterPlatt Fields Park53.446072-2.224689Alexandra1.66
Brighton & HoveHove Park, Brighton50.84214-0.172498Preston Park1.68
Preston ParkPreston Park50.841557-0.148616Brighton & Hove1.68
Old Deer ParkOld Deer Park, Richmond51.464417-0.306973Richmond Park1.69
Richmond ParkRichmond Park, Richmond upon Thames51.451962-0.292886Old Deer Park1.69
Elder ParkElder Park55.863235-4.32197Victoria1.71
VictoriaVictoria Park55.877504-4.332347Elder Park1.71
CatfordMountsfield Park51.44824-0.00863Hilly Fields1.74
Hilly FieldsHilly Fields51.460143-0.025019Catford1.74
BurnageVarley Park, Stockport SK4 3EA53.407152-2.209185Fletcher Moss1.77
Colchester CastleCastle Park51.891670.902724Highwoods1.77
Fletcher MossFletcher Moss Park53.40999-2.23551Burnage1.77
HighwoodsHighwoods Country Park51.9046820.917561Colchester Castle1.77
DulwichDulwich Park, Dulwich51.443869-0.079206Peckham Rye1.82
Peckham RyePeckham Rye Park51.455486-0.060688Dulwich1.82

Newcastle-upon-Tyne has three parkruns that are runnable. Leazes to Town Moor (and vice versa) is 1.38 km, while Jesmond Deane is only 1.6 km away from Town Moor.

Let’s take a look at the map to see what is close by.

The map opens in a zoomed out view revealing a parkrun in the Falkland Islands which is 12333 km away from… Land’s End in England!

I struggled to embed the map here, so here’s a screen grab of me looking at a few candidate pairs. Red dots are parkruns with a neighbour that is less than 3 km away, all others are blue dots.

< video height="1080" style="aspect-ratio: 1920 / 1080;" width="450" controls src="https://quantixed.org/wp-content/uploads/2026/01/leaflet.mp4">

And here’s a screenshot of the pairs in the Midlands for a potential running challenge.

Potential pairs

Caveats

I excluded the junior events here, but obviously both parkruns need to be current i.e. held on the same day. Maybe some of the sites have been discontinued, or they could be cancelled on the day.

The biggest issue here is that the coordinates are often to the middle of the park. Whether a pair is truly runnable would depend on where the finish of the first parkrun is relative to the start of the second one. I couldn’t find a trove of gpx files or something that would help me to do this.

I set a distance of 3 km to define a runnable pair. This might be too generous. In the video they run Leamington second because it has a reputation for starting a few minutes late. It’s also a more challenging course which means the tail walker is more likely to be slower. These things tip the balance. They also rested during the drive, which would need to be factored in if the challenge was to run between a pair. On the other hand, the tail walker might take an hour to do a park run, in which case, pairs that are greater than 3 km would be doable.

Conclusion

I definitely think it is doable to run between a pair of parkruns. There are plenty of options and I would love to see them try to do it!

The post title is taken from “Close To Me” by The Cure.

To leave a comment for the author, please follow the link and comment on their blog: Rstats – quantixed.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Exit mobile version