Filtering, selecting, and editing feeds

GTFSwizard separates three related operations:

Assign each result to a new object when you need to compare scenarios.

Filter a feed

Filter functions keep related identifiers consistent across the feed.

route_ids <- gtfs$routes$route_id[1:2]
route_feed <- filter_route(gtfs, route_ids)

service_id <- gtfs$trips$service_id[1]
service_feed <- filter_service(gtfs, service_id)

time_feed <- filter_time(gtfs, from = "06:00:00", to = "09:00:00")

filter_stop() and filter_time() deliberately retain partial trips. This is useful for corridor, express-service, and time-window experiments. The retained trip can therefore begin or end at a different stop than it did in the source feed.

stop_ids <- gtfs$stops$stop_id[1:5]
partial_feed <- filter_stop(gtfs, stop_ids)

Service patterns describe exact sets of services active on calendar dates. Filtering a pattern retains precisely its represented dates and services. With no explicit pattern, filter_servicepattern() uses the most frequent active pattern.

typical_feed <- filter_servicepattern(gtfs)
#> Warning: GTFSwizard: no `servicepattern` supplied; using `servicepattern-1`,
#> the most frequent pattern.

Use filter_date() only with dates inside the feed calendar. Calendar and calendar-date tables are rebuilt to represent the retained dates.

active_date <- gtfs$dates_services$date[
  lengths(gtfs$dates_services$service_id) > 0
][1]
date_feed <- filter_date(gtfs, active_date)

Select or group without filtering

selection() resembles dplyr::group_by() but stores GTFS-specific selection metadata while leaving all feed tables unchanged. Bare names create groups; logical expressions restrict the records represented by those groups.

grouped <- selection(gtfs, route_id, direction_id)
attr(grouped, "selection")$groups
#> # A tibble: 6 × 6
#>   route_id direction_id n_stop_calls routes    trips      stops     
#>   <chr>           <int>        <int> <list>    <list>     <list>    
#> 1 6                   0         1260 <chr [1]> <chr [63]> <chr [20]>
#> 2 6                   1         1280 <chr [1]> <chr [64]> <chr [20]>
#> 3 7                   0          150 <chr [1]> <chr [15]> <chr [10]>
#> 4 7                   1          150 <chr [1]> <chr [15]> <chr [10]>
#> 5 8                   0          290 <chr [1]> <chr [29]> <chr [10]>
#> 6 8                   1          290 <chr [1]> <chr [29]> <chr [10]>

selected <- selection(
  gtfs,
  route_id,
  route_id %in% route_ids
)

selected <- unselection(selected)

Edit scheduled times

The editing functions return modified copies. They do not write back to the zip archive or object from which the feed was loaded.

trip_ids <- gtfs$trips$trip_id[1:2]
stop_ids <- gtfs$stops$stop_id[1:3]

delayed <- delay_trip(gtfs, trip = trip_ids, duration = 300)
faster <- edit_speed(gtfs, trips = trip_ids, stops = stop_ids, factor = 1.2)
fixed_dwell <- set_dwelltime(
  gtfs, duration = 30, trips = trip_ids, stops = stop_ids
)
scaled_dwell <- edit_dwelltime(
  gtfs, trips = trip_ids, stops = stop_ids, factor = 1.5
)

duration is expressed in seconds. A speed or dwell-time factor is a multiplier: values above one increase the stated quantity and values between zero and one decrease it.

Split trips

split_trip() can create split + 1 approximately equal consecutive parts, or split at selected internal stop IDs. It keeps the original stop order and updates references handled by the package.

trip_id <- gtfs$trips$trip_id[1]
split_equal <- split_trip(gtfs, trip = trip_id, split = 1)
#> GTFSwizard: building straight-line shapes from ordered stop coordinates.

trip_stops <- gtfs$stop_times$stop_id[gtfs$stop_times$trip_id == trip_id]
if (length(trip_stops) > 2) {
  split_at_stop <- split_trip(gtfs, trip = trip_id, stops = trip_stops[2])
}
#> GTFSwizard: building straight-line shapes from ordered stop coordinates.

The first and final stops are not valid split boundaries. When several trips are edited together, stop IDs are interpreted within each selected trip.

Merge and export scenarios

By default, merge_gtfs() suffixes identifiers and their foreign-key references to avoid collisions between feeds.

merged <- merge_gtfs(
  filter_route(gtfs, gtfs$routes$route_id[1]),
  filter_route(gtfs, gtfs$routes$route_id[2])
)

Export only when the scenario is ready. write_gtfs() writes a new archive at the requested path and does not overwrite the original unless the same path is explicitly supplied.

output <- tempfile(fileext = ".zip")
write_gtfs(delayed, output)
unlink(output)