File size: 2,245 Bytes
1ca14ec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# ============================================================================
# Prep: GTFS timetable, stop headways, and feed zip → data/output
# ============================================================================
# Inputs:  data/source/muni_gtfs-current/*.txt
# Outputs: data/output/gtfs_timetable_monday.rds
#          data/output/gtfs_stop_headways.csv
#          data/output/sf_muni_gtfs.zip
#
# Run after updating the GTFS extract. Then upload data/output/* to HuggingFace.

# library(tidyverse)
library(dplyr)
library(tidyr)
library(readr)
library(purrr)
library(tibble)
library(stringr)
library(forcats)
library(lubridate)
library(ggplot2)
library(gtfsrouter)
library(tidytransit)
library(glue)

out_dir <- "data/output"
dir.create(out_dir, recursive = TRUE, showWarnings = FALSE)
out_dir_abs <- normalizePath(out_dir, mustWork = TRUE)

gtfs_dir <- "data/source/muni_gtfs-current"
if (!dir.exists(gtfs_dir)) {
  stop(glue("GTFS folder not found: {gtfs_dir}"))
}
gtfs_txt <- list.files(gtfs_dir, pattern = "\\.txt$", full.names = FALSE)
if (length(gtfs_txt) == 0L) {
  stop(glue("No .txt files under {gtfs_dir}"))
}

# --- Zip feed (same bytes consumers will download from HuggingFace) ----------
# Absolute zip path before setwd(); normalizePath(zip) is NA if the file does not exist yet
zip_abs <- file.path(out_dir_abs, "sf_muni_gtfs.zip")
old_wd <- getwd()
setwd(gtfs_dir)
utils::zip(zip_abs, files = gtfs_txt)
setwd(old_wd)

# --- gtfsrouter Monday timetable ------------------------------------------------
gr <- gtfsrouter::extract_gtfs(zip_abs, quiet = TRUE)
tt <- gtfsrouter::gtfs_timetable(gr, day = "Monday")
saveRDS(tt, file.path(out_dir_abs, "gtfs_timetable_monday.rds"), compress = "gzip")

# --- AM peak headways (inspectable CSV) ---------------------------------------
gt <- tidytransit::read_gtfs(zip_abs)
hw <- tidytransit::get_stop_frequency(gt, start_time = 7 * 3600, end_time = 9 * 3600) |>
  group_by(stop_id) |>
  summarise(
    mean_headway_min    = mean(mean_headway, na.rm = TRUE) / 60,
    n_departures_peak   = sum(n_departures, na.rm = TRUE),
    .groups             = "drop"
  ) |>
  mutate(stop_id = as.character(stop_id))

readr::write_csv(hw, file.path(out_dir_abs, "gtfs_stop_headways.csv"))