UrbanAnalyst / gtfsrouter

Routing and analysis engine for GTFS (General Transit Feed Specification) data
https://urbananalyst.github.io/gtfsrouter/
81 stars 17 forks source link

Add option to generate isochrones with fewest transfers #50

Closed mpadge closed 3 years ago

mpadge commented 3 years ago

So that times to each point in the isochrone calculation reflect the minimal-transfer trip, and resultant isochrones may not reach as far as default fastest-trip isochrones. Ping @AlexandraKapp

mpadge commented 3 years ago

The follow reprex shows an example of this in action:

devtools::load_all (".", export_all = TRUE)
#> Loading gtfsrouter
gtfs <- extract_gtfs ("vbb.zip")
#> ▶ Unzipping GTFS archive
#> ✔ Unzipped GTFS archive
#> ▶ Extracting GTFS feed✔ Extracted GTFS feed 
#> ▶ Converting stop times to seconds✔ Converted stop times to seconds 
#> ▶ Converting transfer times to seconds✔ Converted transfer times to seconds
gtfs <- gtfs_timetable (gtfs, day = "tuesday")

from <- "Berlin Hauptbahnhof"
start_time <- 8 * 3600
start_stns <- station_name_to_ids (from, gtfs, FALSE)
end_time <- start_time + 3600

add_ids <- function (isotrips, gtfs) {
    isotrips$isotrips <- lapply (isotrips$isotrips, function (i) {
                                     i$stop_num <- match (i$stop_id, gtfs$stop_ids$stop_ids)
                                     i$time <- hms::hms (i$earliest_arrival)
                                     return (i) })
    return (isotrips)   }
iso_fastest <- get_isotrips (gtfs, start_stns, start_time, end_time, minimise_transfers = FALSE)
iso_fastest <- add_ids (iso_fastest, gtfs)
iso_min_tr <- get_isotrips (gtfs, start_stns, start_time, end_time, minimise_transfers = TRUE)
iso_min_tr <- add_ids (iso_min_tr, gtfs)

i <- which (!vapply (seq_along (iso_fastest$isotrips), function (i)
                     identical (iso_fastest$isotrips [[i]], iso_min_tr$isotrips [[i]]),
                     logical (1)))
index <- which (!names (iso_fastest$isotrips [[i]]) %in%
                c ("parent_station", "stop_lon", "stop_lat", "earliest_arrival", "stop_num"))
iso_fastest$isotrips [[i]] [, index]
#>         stop_id                                   stop_name  route_id   trip_id
#> 1  060003201213                     S+U Berlin Hauptbahnhof 10157_109 141444939
#> 2  060100001755              S+U Friedrichstr. Bhf (Berlin) 10157_109 141444939
#> 3  060100002733                 S Hackescher Markt (Berlin)      <NA>      <NA>
#> 4  070301008805                 S Hackescher Markt (Berlin) 17452_900 144790566
#> 5  070301008806         Berlin, Spandauer Str./Marienkirche 17452_900 144790566
#> 6  070301008807 S+U Alexanderplatz Bhf/Gontardstr. (Berlin) 17452_900 144790566
#> 7  070301008808            U Alexanderplatz (Berlin) [Tram] 17452_900 144790566
#> 8  070301008809            Berlin, Mollstr./Otto-Braun-Str. 17452_900 144790566
#> 9  070301009407                   Berlin, Am Friedrichshain 17452_900 144790566
#> 10 070301009408                        Berlin, Hufelandstr. 17452_900 144790566
#> 11 070301009409     Berlin, Greifswalder Str./Danziger Str. 17452_900 144790566
#> 12 070301009410                S Greifswalder Str. (Berlin) 17452_900 144790566
#> 13 070301009411                    Berlin, Thomas-Mann-Str. 17452_900 144790566
#>            trip_headsign     time
#> 1      S Strausberg Nord 08:01:12
#> 2      S Strausberg Nord 08:03:54
#> 3                   <NA> 08:05:24
#> 4  Berlin, Zingster Str. 08:12:00
#> 5  Berlin, Zingster Str. 08:13:00
#> 6  Berlin, Zingster Str. 08:16:00
#> 7  Berlin, Zingster Str. 08:18:00
#> 8  Berlin, Zingster Str. 08:21:00
#> 9  Berlin, Zingster Str. 08:22:00
#> 10 Berlin, Zingster Str. 08:24:00
#> 11 Berlin, Zingster Str. 08:25:00
#> 12 Berlin, Zingster Str. 08:27:00
#> 13 Berlin, Zingster Str. 08:28:00
iso_min_tr$isotrips [[i]] [, index]
#>         stop_id                                   stop_name  route_id   trip_id
#> 1  070301008860                     S+U Berlin Hauptbahnhof 17459_900 144797099
#> 2  070301008861                       Berlin, Invalidenpark 17459_900 144797099
#> 3  070301008882  U Naturkundemuseum (Berlin) [Chausseestr.] 17459_900 144797099
#> 4  070301009372         Berlin, Torstr./U Oranienburger Tor 17459_900 144797099
#> 5  070301009403               S Oranienburger Str. (Berlin) 17459_900 144797099
#> 6  070301008812                       Berlin, Monbijouplatz 17459_900 144797099
#> 7  070301008805                 S Hackescher Markt (Berlin) 17452_900 144790566
#> 8  070301008806         Berlin, Spandauer Str./Marienkirche 17452_900 144790566
#> 9  070301008807 S+U Alexanderplatz Bhf/Gontardstr. (Berlin) 17452_900 144790566
#> 10 070301008808            U Alexanderplatz (Berlin) [Tram] 17452_900 144790566
#> 11 070301008809            Berlin, Mollstr./Otto-Braun-Str. 17452_900 144790566
#> 12 070301009407                   Berlin, Am Friedrichshain 17452_900 144790566
#> 13 070301009408                        Berlin, Hufelandstr. 17452_900 144790566
#> 14 070301009409     Berlin, Greifswalder Str./Danziger Str. 17452_900 144790566
#> 15 070301009410                S Greifswalder Str. (Berlin) 17452_900 144790566
#> 16 070301009411                    Berlin, Thomas-Mann-Str. 17452_900 144790566
#>            trip_headsign     time
#> 1  Berlin, Zingster Str. 08:00:00
#> 2  Berlin, Zingster Str. 08:02:00
#> 3  Berlin, Zingster Str. 08:04:00
#> 4  Berlin, Zingster Str. 08:05:00
#> 5  Berlin, Zingster Str. 08:07:00
#> 6  Berlin, Zingster Str. 08:08:00
#> 7  Berlin, Zingster Str. 08:12:00
#> 8  Berlin, Zingster Str. 08:13:00
#> 9  Berlin, Zingster Str. 08:16:00
#> 10 Berlin, Zingster Str. 08:18:00
#> 11 Berlin, Zingster Str. 08:21:00
#> 12 Berlin, Zingster Str. 08:22:00
#> 13 Berlin, Zingster Str. 08:24:00
#> 14 Berlin, Zingster Str. 08:25:00
#> 15 Berlin, Zingster Str. 08:27:00
#> 16 Berlin, Zingster Str. 08:28:00

Created on 2020-11-24 by the reprex package (v0.3.0)

Setting minimise_transfers = TRUE replaces former trip with one transfer with alternative that takes 01:12 longer, but has no transfers.

mpadge commented 3 years ago

Re-opening because the minimal transfer versions have one potential issue. Removing the condition that trips must be the shortest opens the possibility of circular trips. The following code, extending directly from the reprex above, demonstrates:

from <- "Berlin Hauptbahnhof"
start_time <- 8 * 3600
start_stns <- station_name_to_ids (from, gtfs, FALSE)
end_time <- start_time + 3600 + 1800

iso_min_tr <- get_isotrips (gtfs, start_stns, start_time, end_time, minimise_transfers = TRUE)
iso_min_tr <- add_ids (iso_min_tr, gtfs)

ends <- vapply (iso_min_tr$isotrips, function (i) tail (i$stop_name, 1), character (1))
index <- grep ("S Westkreuz", ends)
cindex <- which (!names (iso_min_tr$isotrips [[1]]) %in%
                c ("parent_station", "stop_lon", "stop_lat", "earliest_arrival", "stop_num"))
iso_min_tr$isotrips [[index]] [, cindex]
#>         stop_id                            stop_name  route_id   trip_id
#> 1  060003201214              S+U Berlin Hauptbahnhof 10170_109 141456259
#> 2  060003102224                  S Bellevue (Berlin) 10170_109 141456259
#> 3  060003103234                S Tiergarten (Berlin) 10170_109 141456259
#> 4  060023201256 S+U Zoologischer Garten Bhf (Berlin) 10170_109 141456259
#> 5  060024203304              S Savignyplatz (Berlin) 10170_109 141456259
#> 6  060024101338        S Charlottenburg Bhf (Berlin) 10170_109 141456259
#> 7  060024102371                 S Westkreuz (Berlin)      <NA>      <NA>
#> 8  060024100801                 S Westkreuz (Berlin) 10155_109 141441866
#> 9  060024106801            S Messe Nord/ICC (Berlin)      <NA>      <NA>
#> 10 060024106802            S Messe Nord/ICC (Berlin) 10155_109 141441562
#> 11 060024100802                 S Westkreuz (Berlin) 10155_109 141441562
#>                trip_headsign     time
#> 1              S Spandau Bhf 08:00:12
#> 2              S Spandau Bhf 08:02:48
#> 3              S Spandau Bhf 08:04:54
#> 4              S Spandau Bhf 08:06:54
#> 5              S Spandau Bhf 08:08:48
#> 6              S Spandau Bhf 08:10:48
#> 7                       <NA> 08:12:36
#> 8                  S Westend 08:16:48
#> 9                       <NA> 08:18:00
#> 10 S Königs Wusterhausen Bhf 08:18:30
#> 11 S Königs Wusterhausen Bhf 08:20:12

Created on 2020-11-24 by the reprex package (v0.3.0)