Giter VIP home page Giter VIP logo

gtfsrouter's Introduction

gtfsrouter

R build status codecov Project Status: Active CRAN_Status_Badge CRAN Downloads

R package for public transport routing with GTFS (General Transit Feed Specification) data.

Installation

You can install latest stable version of gtfsrouter from CRAN with:

install.packages ("gtfsrouter")

Alternatively, the current development version can be installed using any of the following options:

# install.packages("remotes")
remotes::install_git ("https://git.sr.ht/~mpadge/gtfsrouter")
remotes::install_git ("https://codeberg.org/UrbanAnalyst/gtfsrouter")
remotes::install_bitbucket ("urbananalyst/gtfsrouter")
remotes::install_gitlab ("UrbanAnalyst/gtfsrouter")
remotes::install_github ("UrbanAnalyst/gtfsrouter")

To load the package and check the version:

library (gtfsrouter)
packageVersion ("gtfsrouter")
## [1] '0.0.5.158'

Main functions

The main functions can be demonstrated with sample data included with the package from Berlin (the “Verkehrverbund Berlin Brandenburg”, or VBB). GTFS data are always stored as .zip files, and these sample data can be written to the temporary directory (tempdir()) of the current R session with the function berlin_gtfs_to_zip().

filename <- berlin_gtfs_to_zip ()
print (filename)
## [1] "/tmp/RtmpeXCbTq/vbb.zip"

For normal package use, filename will specify the name of a local GTFS .zip file.

gtfs_route

Given the name of a GTFS .zip file, filename, routing is as simple as the following code:

gtfs <- extract_gtfs (filename)
gtfs <- gtfs_timetable (gtfs, day = "Wed") # A pre-processing step to speed up queries
gtfs_route (gtfs,
    from = "Tegel",
    to = "Berlin Hauptbahnhof",
    start_time = 12 * 3600 + 120
) # 12:02 in seconds
route_name trip_name stop_name arrival_time departure_time
U8 U Paracelsus-Bad U Schonleinstr. (Berlin) 12:04:00 12:04:00
U8 U Paracelsus-Bad U Kottbusser Tor (Berlin) 12:06:00 12:06:00
U8 U Paracelsus-Bad U Moritzplatz (Berlin) 12:08:00 12:08:00
U8 U Paracelsus-Bad U Heinrich-Heine-Str. (Berlin) 12:09:30 12:09:30
U8 U Paracelsus-Bad S+U Jannowitzbrucke (Berlin) 12:10:30 12:10:30
S5 S Westkreuz S+U Jannowitzbrucke (Berlin) 12:15:24 12:15:54
S5 S Westkreuz S+U Alexanderplatz Bhf (Berlin) 12:17:24 12:18:12
S5 S Westkreuz S Hackescher Markt (Berlin) 12:19:24 12:19:54
S5 S Westkreuz S+U Friedrichstr. Bhf (Berlin) 12:21:24 12:22:12
S5 S Westkreuz S+U Berlin Hauptbahnhof 12:24:06 12:24:42

gtfs_traveltimes

The gtfs_traveltimes() function` calculates minimal travel times from any nominated stop to all other stops within a feed. It requires the two parameters of start station, and a vector of two values specifying earliest and latest desired start times. The following code returns the fastest travel times to all stations within the feed for services which leave the nominated station (“Alexanderplatz”) between 12:00 and 13:00 on a Monday:

gtfs <- extract_gtfs (filename)
gtfs <- gtfs_timetable (gtfs, day = "Monday")
x <- gtfs_traveltimes (gtfs,
    from = "Alexanderplatz",
    start_time_limits = c (12, 13) * 3600
)

The function returns a simple table detailing all stations reachable with services departing from the nominated station and start times:

head (x)
start_time duration ntransfers stop_id stop_name stop_lon stop_lat
12:00:42 00:14:42 1 060003102223 S Bellevue (Berlin) 13.34710 52.51995
12:00:42 00:08:36 0 060003102224 S Bellevue (Berlin) 13.34710 52.51995
12:00:42 00:15:06 1 060003103233 S Tiergarten (Berlin) 13.33624 52.51396
12:00:42 00:10:42 0 060003103234 S Tiergarten (Berlin) 13.33624 52.51396
12:00:42 00:14:18 1 060003201213 S+U Berlin Hauptbahnhof 13.36892 52.52585
12:00:42 00:05:54 0 060003201214 S+U Berlin Hauptbahnhof 13.36892 52.52585

Further details are provided in a separate vignette.

gtfs_transfer_table

Feeds should include a “transfers.txt” table detailing all possible transfers between nearby stations, yet many feeds omit these tables, rendering them unusable for routing because transfers between services can not be calculated. The gtfsrouter package also includes a function, gtfs_transfer_table(), which can calculate a transfer table for a given feed, with transfer times calculated either using straight-line distances (the default), or using more realistic pedestrian times routed through the underlying street network.

This function can also be used to enable routing through multiple adjacent or overlapping GTFS feeds. The feeds need simply be merged through binding the rows of all tables, and the resultant aggregate feed submitted to the gtfs_transfer_table() function. This transfer table will retain all transfers specified in the original feeds, yet be augmented by all possible transfers between the multiple systems up to a user-specified maximal distance. Further details of this function are also provided in another separate vignette.

Additional Functionality

There are many ways to construct GTFS feeds. For background information, see gtfs.org, and particularly their GTFS Examples. Feeds may include a “frequencies.txt” table which defines “service periods”, and overrides any schedule information during the specified times. The gtfsrouter package includes a function, frequencies_to_stop_times(), to convert “frequencies.txt” tables to equivalent “stop_times.txt” entries, to enable the feed to be used for routing.

Contributors

All contributions to this project are gratefully acknowledged using the allcontributors package following the all-contributors specification. Contributions of any kind are welcome!

Code


mpadge

AlexandraKapp

stmarcin

dhersz

polettif

Issue Authors


sridharraman

orlandombaa

Maxime2506

chinhqho

federicotallis

rafapereirabr

dcooley

bernd886

stefan-overkamp

luukvdmeer

szaboildi

cseveren

jh0ker

zamirD123

viajerus

jmertic

5balls

pteridin

FlxPo

Issue Contributors


tbuckl

tuesd4y

Robinlovelace

loanho23

abyrd

hansmib

gtfsrouter's People

Contributors

alexandrakapp avatar dhersz avatar mpadge avatar polettif avatar stmarcin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gtfsrouter's Issues

Headway of trips (including transfers)

How often does a connection go from Place A to Place B?

  • you can compute the headway for a stop
  • you can compute the routing for an origin-destination
    For computing the headway of a route from place A to place B (which are not on the same line) all possible connections within a given time interval need to be calculated.

@mpadge as discussed, I created this as an issue

Crash with specified date

Running the following code with a fairly simple feed crashes RStudio:

# devtools::install_github("ATFutures/gtfs-router")
library(gtfsrouter)
download.file("https://github.com/polettif/gtfs-test-feeds/raw/master/zip/routing.zip", "routing.zip")
gtfs = extract_gtfs("routing.zip")
timetbl <- gtfs_timetable(gtfs, date = 20181001)

Screenshot

I can't really tell where the issue is, transfers.txt looks like this:

from_stop_id,to_stop_id,transfer_type,min_transfer_time
stop1a,stop1b,2,10
stop1b,stop1a,2,10
stop3a,stop3b,2,10
stop3b,stop3a,2,10
stop8a,stop8b,2,10
stop8b,stop8a,2,10

Or maybe it's an issue with the date. I don't know how dates are extracted in gtfsrouter. In my understanding of gtfs_timetable's doc, the date parameter is only applied to calendar_dates.txt since

Some systems do not specify days of the week within their 'calendar' table; rather they provide full timetables for specified calendar dates via a 'calendar_date' table.

Compare to tidytransit's approach where a date_service_table is calculated to see which services (and thus trips) run on which date.

# install.packages("tidytransit")
library(tidytransit)
gtfs = read_gtfs("https://github.com/polettif/gtfs-test-feeds/raw/master/zip/routing.zip")
gtfs$calendar
#> # A tibble: 4 x 10
#>   service_id monday tuesday wednesday thursday friday saturday sunday start_date
#>   <chr>       <int>   <int>     <int>    <int>  <int>    <int>  <int> <date>    
#> 1 WEEK            1       1         1        1      1        0      0 2018-10-01
#> 2 EXPR            0       0         0        0      0        0      0 2018-10-01
#> 3 WEND            0       0         0        0      0        1      1 2018-10-01
#> 4 EMPT            1       0         1        1      0        1      0 2018-10-01
#> # … with 1 more variable: end_date <date>
gtfs$calendar_dates
#> # A tibble: 5 x 3
#>   service_id date       exception_type
#>   <chr>      <date>              <int>
#> 1 WEEK       2018-10-06              2
#> 2 WEEK       2018-10-07              2
#> 3 EXPR       2018-10-05              1
#> 4 EMPT       2018-10-02              1
#> 5 EMPT       2018-10-01              2

gtfs <- set_date_service_table(gtfs)
gtfs$.$date_service_table
#> # A tibble: 586 x 2
#>    date       service_id
#>    <date>     <chr>     
#>  1 2018-10-01 WEEK      
#>  2 2018-10-02 WEEK      
#>  3 2018-10-03 WEEK      
#>  4 2018-10-03 EMPT      
#>  5 2018-10-04 WEEK      
#>  6 2018-10-04 EMPT      
#>  7 2018-10-05 WEEK      
#>  8 2018-10-06 WEND      
#>  9 2018-10-06 EMPT      
#> 10 2018-10-07 WEND      
#> # … with 576 more rows
filtered_stop_times = filter_stop_times(gtfs, "2018-10-01", 0, 24*3600)

Created on 2020-06-25 by the reprex package (v0.3.0)

Index out of bound when GTFS does not include optional trasnfer.txt

library(gtfsrouter)
path <- "F:/Project/GTFS"
filename <- list.files (path, full.names = TRUE, pattern = "GTFS.zip")

gt <- extract_gtfs(filename)
#> Warning: This feed contains no transfers.txt
summary(gt)
#> A gtfs object with the following tables and respective numbers of entries in each:
#> calendar calendar_dates routes stops stop_times
#> 1930 25264 6648 44501 4602181
#> trips
#> 155901
#> Note: This feed contains no transfers.txt table
gtfsrouter::gtfs_route(gt,
from = "Central",
to = "Newtown")
#> Day not specified; extracting timetable for Monday
#> Error in rcpp_csa(gtfs$timetable, gtfs$transfers, nrow(gtfs$stop_ids), : Index out of bounds: [index='from_stop_id'].

Routes blended with many options with the OD has many route alternatives

Hi Developers,

I ran the gtfsrouter and had the table below with the 3 route options between this OD:

  • Route 1: get in 141, transferring to 765n, then to B1 and, T9
  • Route 2: get in 144, transferring B1 then T9
  • Route 3: get in 170x, tranferring to B1 then T9 (this option appears to have an issue that is the time getting off 170x at Wynyard Station, York St, Stand M 7:56, while the time to get in at the first of T9 at Wynyard Station, Platform 3 is 7:52)

I interpreted these 3 routes based on my knowledge of Sydney, but I believe you have better idea how to classify and select appropriate routes from the source code.

I have 2 questions:

  1. How can I separate these 3 route options? in your function scripts, is there any way to add route classification?
  2. How can I eliminate inappropriate route like the Route 3 from the beginning, so the gtfsrouter doesn't create that route?

Thank you very much.

gtfsrouter::gtfs_route (gtfswithtransfersprep, include_ids = FALSE,
from = as.character("Sydney Rd At Austin St"),
to = as.character("Central Station"),
start_time = 7 * 3600 + 60*14,
day = "tu")

  route_name trip_name stop_name arrival_time departure_time
5 141 Belrose Sydney Rd At Austin St 7:17:02 7:17:02
6 141 Belrose Sydney Rd After Hill St 7:17:57 7:17:57
8 141 Belrose Sydney Rd Before Condamine St 7:19:00 7:19:00
13 141 Belrose Sydney Rd At Woodland St 7:20:41 7:20:41
17 141 Belrose Sydney Rd At West St 7:22:39 7:22:39
18 141 Belrose Sydney Rd At Wanganella St 7:23:57 7:23:57
1 144 Chatswood Sydney Rd At Austin St 7:15:00 7:15:00
2 144 Chatswood Sydney Rd After Hill St 7:16:00 7:16:00
4 144 Chatswood Sydney Rd Before Condamine St 7:17:00 7:17:00
10 144 Chatswood Sydney Rd At Woodland St 7:19:00 7:19:00
12 144 Chatswood Sydney Rd At West St 7:20:00 7:20:00
15 144 Chatswood Sydney Rd At Wanganella St 7:21:00 7:21:00
20 144 Chatswood Sydney Rd At Coral St 7:24:00 7:24:00
23 144 Chatswood Manly Rd At Heaton Av 7:26:00 7:26:00
26 144 Chatswood Manly Rd At Avona Cres 7:27:00 7:27:00
27 144 Chatswood Spit East Reserve, Spit Rd 7:29:00 7:29:00
29 144 Chatswood Spit Rd Opp Medusa St 7:33:00 7:33:00
31 144 Chatswood Spit Rd Opp Bickell Rd 7:35:00 7:35:00
34 144 Chatswood Spit Junction B-Line, Spit Rd 7:38:00 7:38:00
3 170X Sydney Sydney Rd At Austin St 7:17:00 7:17:00
7 170X Sydney Sydney Rd After Hill St 7:18:00 7:18:00
9 170X Sydney Sydney Rd Before Condamine St 7:19:00 7:19:00
11 170X Sydney Sydney Rd At Woodland St 7:20:00 7:20:00
14 170X Sydney Sydney Rd At West St 7:21:00 7:21:00
16 170X Sydney Sydney Rd At Wanganella St 7:22:00 7:22:00
19 170X Sydney Sydney Rd At Coral St 7:24:00 7:24:00
22 170X Sydney Manly Rd At Heaton Av 7:26:00 7:26:00
25 170X Sydney Manly Rd At Avona Cres 7:27:00 7:27:00
41 170X Sydney Wynyard Station, York St, Stand M 7:56:00 7:56:00
21 765n Milsons Point Manly Rd At Heaton Av 7:25:00 7:25:00
24 765n Milsons Point Manly Rd At Avona Cres 7:26:00 7:26:00
28 765n Milsons Point Spit East Reserve, Spit Rd 7:29:00 7:29:00
30 765n Milsons Point Spit Rd Opp Medusa St 7:33:00 7:33:00
32 765n Milsons Point Spit Rd Opp Bickell Rd 7:35:00 7:35:00
36 765n Milsons Point Spit Junction B-Line, Spit Rd 7:39:00 7:39:00
33 767n Milsons Point Spit Rd Opp Bickell Rd 7:36:00 7:36:00
35 767n Milsons Point Spit Junction B-Line, Spit Rd 7:38:00 7:38:00
37 B1 Sydney Spit Junction B-Line, Spit Rd 7:39:00 7:39:00
38 B1 Sydney Neutral Bay Junction, Military Rd, Stand A 7:44:00 7:44:00
39 B1 Sydney Wynyard Station, York St, Stand M 7:51:00 7:51:00
40 T9 Central Station Wynyard Station, Platform 3 7:52:54 7:53:54
42 T9 Central Station Town Hall Station, Platform 2 7:56:00 7:57:00
43 T9 Central Station Central Station, Platform 18 8:00:00 8:00:00

I really appreciate your development of this package which is very useful to create route options from the whole timetable.
Loan

Error while reading feed

I have a GTFS zip file that is read fine by tidytransit. But when I try to read it using gtfsrouter, I get the following error:

Error in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : Internal error: sampleLines(101) > allocnrow(0) In addition: Warning messages: 1: This feed contains no transfers.txt 2: In data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File '/tmp/RtmpAnhFlA/file167d63e3f0bb' has size 0. Returning a NULL data.table.

I understand that transfers.txt is optional. But I am unable to understand what the other error is.

Routing result

Thank you for fixing routing with character ids in #2! I now have a question about the routing result. I've run the following code with a test feed. (I did use this feed for other calibrations of sorts and I can't see anything wrong with it but there might still be an error somewhere).

gtfs <- gtfsrouter::extract_gtfs("routing.zip")
route <- gtfsrouter::gtfs_route(gtfs, "One", "Four", 7*3600)
print(route)
#>    route  stop departure_time arrival_time
#> 1 Line B   One       07:10:00     07:10:00
#> 2 Line B Three       07:29:00     07:28:00
#> 3 Line B  Four       07:37:00     07:37:00
#> 4 Line A   One       07:00:00     07:00:00
#> 5 Line A   Two       07:05:00     07:04:00
#> 6 Line A Three       07:12:00     07:11:00
#> 7 Line A  Four       07:40:00     07:40:00

Created on 2019-02-20 by the reprex package (v0.2.1)

Is this the route to take or are these multiple possible routes since One appears twice? What I'd expect is the following route:

#>    route  stop   departure_time arrival_time
#> 1 Line D  One    07:17:00       -
#> 2 Line D  Three  -              07:23:00
#> 3 Line B  Three  07:29:00       -
#> 3 Line B  Four   -              07:37:00

which is optimised for earliest arrival, then minimal travel time. Though there might be other optimisation criteria like number of transfers.

for some stops still too many transfers

## Example of too many transfers
# S Grunewald to Berlin, Koenigin-Luise-Str./Clayallee

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(gtfsrouter)

timetable <- readRDS("timetable_vbb.Rds")

# gtfs_route returns correct amount of transfers: 1
gtfs_route(timetable, start_time = 8*3600, "S Grunewald", "nigin-Luise-Str")
#>   route_name                trip_name                               stop_name
#> 1        186      S Lichterfelde Süd                    S Grunewald (Berlin)
#> 2        186      S Lichterfelde Süd                      Berlin, Hagenplatz
#> 3        186      S Lichterfelde Süd            Berlin, Richard-Strauss-Str.
#> 4        186      S Lichterfelde Süd              Berlin, Hubertusbader Str.
#> 5        186      S Lichterfelde Süd         Berlin, Roseneck/Teplitzer Str.
#> 6        X10 Teltow, Rammrath-Brücke         Berlin, Roseneck/Teplitzer Str.
#> 7        X10 Teltow, Rammrath-Brücke Berlin, Brücke-Museum/Kunsthaus Dahlem
#> 8        X10 Teltow, Rammrath-Brücke   Berlin, Königin-Luise-Str./Clayallee
#>   arrival_time departure_time
#> 1     08:10:00       08:10:00
#> 2     08:12:00       08:12:00
#> 3     08:14:00       08:14:00
#> 4     08:15:00       08:15:00
#> 5     08:15:30       08:15:30
#> 6     08:24:00       08:24:00
#> 7     08:27:00       08:27:00
#> 8     08:28:00       08:28:00


# with gtfs_isochrone 3 transfers are returned
iso <- gtfs_isochrone(timetable, "S Grunewald", start_time = 8 * 3600, end_time = 8 * 3600 + 30*60)
#> Loading required namespace: geodist
#> Loading required namespace: lwgeom
iso$end_points%>% filter(grepl("igin-Luise-Str", stop_name))
#> Simple feature collection with 0 features and 6 fields
#> bbox:           xmin: NA ymin: NA xmax: NA ymax: NA
#> geographic CRS: WGS 84
#> [1] stop_name stop_id   departure arrival   duration  transfers geometry 
#> <0 rows> (or 0-length row.names)
iso$mid_points%>% filter(grepl("igin-Luise-Str", stop_name))
#> Simple feature collection with 1 feature and 6 fields
#> geometry type:  POINT
#> dimension:      XY
#> bbox:           xmin: 13.27476 ymin: 52.46009 xmax: 13.27476 ymax: 52.46009
#> geographic CRS: WGS 84
#>                               stop_name      stop_id departure  arrival
#> 1 Berlin, Königin-Luise-Str./Clayallee 070101001743  08:06:00 08:28:00
#>   duration transfers                  geometry
#> 1 00:22:00         3 POINT (13.27476 52.46009)

# get isotrips: debug gtfs_isochrone and store isotrips in temp.Rds
isotrips <- readRDS("temp.Rds")

for (i in 1:198) {
  r <- isotrips[[1]][[i]] %>% filter(grepl("igin-Luise-Str", stop_name))
  if (nrow(r) > 0){
    print (i)
    index <- i
  }
}
#> [1] 37
print(isotrips[[1]][index])
#> [[1]]
#>         stop_id                               stop_name parent_station stop_lon
#> 1  070101002370                    S Grunewald (Berlin)   900000048101 13.26194
#> 2  070101002920                  Berlin, Taubertstraße   900000048158 13.26798
#> 3  070101001409                      Berlin, Hagenplatz   900000048107 13.26591
#> 4  070101001410            Berlin, Richard-Strauss-Str.   900000048159 13.27158
#> 5  070101001411              Berlin, Hubertusbader Str.   900000048160 13.27560
#> 6  070101001248         Berlin, Roseneck/Teplitzer Str.   900000046354 13.28048
#> 7  070101002445         Berlin, Roseneck/Teplitzer Str.   900000046354 13.28048
#> 8  070101003809 Berlin, Brücke-Museum/Kunsthaus Dahlem   900000051259 13.27730
#> 9  070101001743   Berlin, Königin-Luise-Str./Clayallee   900000051204 13.27476
#> 10 070101000017                Berlin, Alliiertenmuseum   900000051255 13.27366
#> 11 070101000018                      Berlin, Hüttenweg   900000051256 13.27224
#>    stop_lat  route_id   trip_id            trip_headsign earliest_arrival
#> 1  52.48868 17445_700 141829991            U Mehringdamm            29160
#> 2  52.48460 17445_700 141829991            U Mehringdamm            29280
#> 3  52.48332 17341_700 141792572      S Lichterfelde Süd            29280
#> 4  52.47995 17341_700 141792572      S Lichterfelde Süd            29640
#> 5  52.47841 17341_700 141792572      S Lichterfelde Süd            29700
#> 6  52.47749 17341_700 141792572      S Lichterfelde Süd            29730
#> 7  52.47749 17529_700 141867473 Teltow, Rammrath-Brücke            29730
#> 8  52.46473 17529_700 141867473 Teltow, Rammrath-Brücke            30420
#> 9  52.46009 17529_700 141867473 Teltow, Rammrath-Brücke            30480
#> 10 52.45648 17299_700 141775970 Berlin, Neuruppiner Str.            30720
#> 11 52.45352 17299_700 141775970 Berlin, Neuruppiner Str.            30780

Created on 2020-10-27 by the reprex package (v0.3.0)

Fix timetable

The list of stations created in the C++ code should match the stops table.

All Contributors

Hi All! This repository uses the allcontributor package to acknowledge all contributions on the main README This issue has been automatically generated by the addcontributors function in order to ping you that you've been acknowledged. Thank you all:

@AlexandraKapp
@stmarcin
@polettif
@tbuckl
@sridharraman
@tuesd4y
@luukvdmeer
@Robinlovelace
@orlandoandradeb
@Maxime2506
@chinhqho
@federicotallis
@rafapereirabr
@loanho23

(Issue may be closed immediately, and will be re-opened each time new contributors are added when running the addcontributors function.)

cache

Cache the whole timetable calculation when feed is first read. Maybe?

Isochrones

Add extra time_range argument that returns all end stations reachable from nominated station within specified time range

Filter by route

Routes generally have identifying patterns distinguishing subway from train from tram from whatever. It would be useful to be able to filter a feed down to only specified forms of transport, and this could be easily done by implementing a grep-able parameter in the gtfs_timetable() function, along the lines of current code used to generate test data.

accept stop_id as well as stop_name

plus solve this issue:

library(gtfsrouter)
gtfs <- extract_gtfs ("vbb.zip") # local Berlin VBB feed
gtfs <- gtfs_timetable (gtfs)
#> Day not specified; extracting timetable for Wednesday
set.seed (3)
from <- sample (gtfs$stops$stop_name, 1)
to <- sample (gtfs$stops$stop_name, 1)
message (from, " -> ", to)
#> Frankfurt (Oder), EuroCamp -> Groß Fredenwalde
gtfs_route (gtfs, from = from, to = to)
#> Error in station_name_to_ids(from, gtfs_cp): Frankfurt (Oder), EuroCamp does not match any stations

Created on 2020-06-17 by the reprex package (v0.3.0)

It's in the stops table, so has to be recongised as a station.

gtfs_home/work fns

Make generic functions to read a local feed and use local envvars defining "home" and "work" stations so gtfs_home() will screen-dump the next available service from work -> home, and gtfs_to_work() will dump the reverse direction.

This will require construction and local storage of a timetable. Reading back just the timetable part of the Berlin VBB data (4.5 million entries) still takes ~0.4s, so the function will need to be cleverly optimised to perform well. Maybe write a separate C++ routine to just read the timetable data directly from disk line-by-line without having to load it into local memory?

consider calendar_dates

some GTFS Feeds (e.g. Paris or Osnabrück) use calendar_dates for the regular schedule. Those are not considered in the timetable construction.

grafik

Not sure if this can be integrated in the current logic, where only weekdays are considered of if it needs to be switched to a logic where actual dates are used.

Unable to read gtfs nor reproduce an example

Hello,
Unfortunately I am not able to reproduce an example from vignette:

library(gtfsrouter)
berlin_gtfs_to_zip()
#> Warning in system2(zip, args, input = input, invisible = TRUE): '"zip"' not
#> found
tempfiles <- list.files (tempdir (), full.names = TRUE)
filename <- tempfiles [grep ("vbb.zip", tempfiles)]
filename
#> character(0)

Created on 2020-04-16 by the reprex package (v0.3.0)

I am not able to read this gtfs feed :

library(gtfsrouter)
download.file("https://mkuran.pl/feed/ztm/ztm-latest.zip", "gtfs.zip")
gtfs <- extract_gtfs("gtfs.zip")
#> Warning: This feed contains no transfers.txt
#> Warning in (if (.Platform$OS.type == "unix") system else shell)
#> (paste0("(", : '(unzip -p gtfs.zip "calendar_dates.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c64af4fb9' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c64af4fb9' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else shell)
#> (paste0("(", : '(unzip -p gtfs.zip "attributions.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c4e9d1e4e' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c4e9d1e4e' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else shell)
#> (paste0("(", : '(unzip -p gtfs.zip "frequencies.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c46701221' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c46701221' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else
#> shell)(paste0("(", : '(unzip -p gtfs.zip "shapes.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c53ae785f' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c53ae785f' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else
#> shell)(paste0("(", : '(unzip -p gtfs.zip "agency.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c20bc155a' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c20bc155a' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else
#> shell)(paste0("(", : '(unzip -p gtfs.zip "trips.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c676e6bd8' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c676e6bd8' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else
#> shell)(paste0("(", : '(unzip -p gtfs.zip "stops.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c6f452fd8' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c6f452fd8' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else shell)
#> (paste0("(", : '(unzip -p gtfs.zip "feed_info.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c12434871' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c12434871' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else
#> shell)(paste0("(", : '(unzip -p gtfs.zip "routes.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c25c321b9' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c25c321b9' has size 0.
#> Returning a NULL data.table.
#> Warning in (if (.Platform$OS.type == "unix") system else shell)
#> (paste0("(", : '(unzip -p gtfs.zip "stop_times.txt") > C:
#> \Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c4eb956d6' execution failed
#> with error code 1
#> Warning in data.table::fread(cmd = paste0("unzip -p ", filename, " \"", : File
#> 'C:\Users\stepniak\AppData\Local\Temp\RtmpcdC2YK\file95c4eb956d6' has size 0.
#> Returning a NULL data.table.
#> Error in extract_gtfs("gtfs.zip"): gtfs.zip does not appear to be a GTFS file; it must minimally contain
#>   routes, stops, stop_times, trips

Created on 2020-04-16 by the reprex package (v0.3.0)

I attach my systemInfo:

sessionInfo()
#> R version 3.6.3 (2020-02-29)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows 10 x64 (build 18362)
#> 
#> Matrix products: default
#> 
#> locale:
#> [1] LC_COLLATE=English_United Kingdom.1252 
#> [2] LC_CTYPE=English_United Kingdom.1252   
#> [3] LC_MONETARY=English_United Kingdom.1252
#> [4] LC_NUMERIC=C                           
#> [5] LC_TIME=English_United Kingdom.1252    
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#>  [1] compiler_3.6.3   magrittr_1.5     tools_3.6.3      htmltools_0.4.0 
#>  [5] yaml_2.2.1       Rcpp_1.0.4.6     stringi_1.4.6    rmarkdown_2.1   
#>  [9] highr_0.8        knitr_1.28       stringr_1.4.0    xfun_0.13       
#> [13] digest_0.6.25    rlang_0.4.5.9000 evaluate_0.14

Created on 2020-04-16 by the reprex package (v0.3.0)
And this:

packageVersion("gtfsrouter")
#> [1] '0.0.1.3'

Created on 2020-04-16 by the reprex package (v0.3.0)

It looks like I am missing something in my R settings but no idea what can it be. Do you have any hint about what should I look for? Thanks

gtfs_bounding_box function

Develop a function to reduce a GTFS feed to within a defined bounding box, through removing all routes which do not pass within the bounding box at all.

transfers.txt optional

When I try to run extract_gtfs("sample-feed-fixed.zip") with this sample feed I get the error because transfers.txt is missing:

Error in extract_gtfs("sample-feed-fixed.zip") : 
  sample-feed-fixed.zip does not appear to be a GTFS file; it must minimally contain
  calendar, routes, stop_times, transfers, trips

While I'm aware that routing on a feed without transfers might not yield very usable results, transfers.txt is not a required file for a gtfs feed.

error handling - column headings

Working with Melbourne's transit feed is not always straight forward, and this morning I ran into this particular issue which tripped me up for a few hours, where the column heading has a non-Ascii symbol in it.

So my request is, is it worth adding in a 'clean column names' -type function when extracting the feed to try and handle this?

Here's the exmaple

library(data.table)
library(gtfsrouter)

url <- "http://data.ptv.vic.gov.au/downloads/gtfs.zip"

temp_dir <- tempdir()
download.file(url, destfile = paste0(temp_dir, "/gtfs.zip") )
list.files( temp_dir )

unzip( paste0(temp_dir, "/gtfs.zip"), exdir = paste0(temp_dir) )

## Melbourne GTFS is saved in folders numbered 1:11 for different modes
## <sigh>
list.files( temp_dir )
## 3 == tram
list.files(paste0(temp_dir, "/3"))
gtfs_tram <- extract_gtfs( paste0(temp_dir, "/3/google_transit.zip") )
# unlink(temp_dir)

I found this issue when running gtfsrouter:::join_service_id_to_stops(), as it gave me all NAs for trip_id

tram_stop_service <- gtfsrouter:::join_service_id_to_stops( gtfs_tram )
unique( tram_stop_service$services )
# [1] NA

So diving into the stop_times object I found the issue

dt_stoptimes <- copy( gtfs_tram$stop_times )
dput( dt_stoptimes[1, ] )

Copying this output back into my script highlighted the rogue character

Screen Shot 2020-11-05 at 10 05 04 am

This is fixed by the iconv() command.

setnames(
  gtfs_tram$stop_times
  , names( gtfs_tram$stop_times )
  , iconv( names( gtfs_tram$stop_times ), "latin1", "ASCII", sub = "" )
)

tram_stop_service <- gtfsrouter:::join_service_id_to_stops( gtfs_tram )
head(tram_stop_service )

# stop_id services
# 1:   19725    T0+a6
# 2:   19372    T0+a6
# 3:   19371    T0+a6
# 4:   19370    T0+a6
# 5:   19369    T0+a6
# 6:   18184    T0+a6

Is something like this worth adding to gtfsrouter?

Error with ids using characters

I tried to run the router on the Swiss GTFS feed and received the following error:

Error in rcpp_make_timetable(gtfs$stop_times) : 
  Not compatible with requested type: [type=character; target=integer].

I guess there's a problem is with the ids (stops or trips) using characters. For example, a typical trip id is 63.TA.18-26-j19-1.25.R. AFAIK the gtfs spec doesn't state that ids have to be numeric?

column name 'trip_headsign' not found error

Sorry for the possibly spammy issues but I had a look at this package again today and I've just run into these. If I try to run the router on this test feed I get the following error.

gtfs <- gtfsrouter::extract_gtfs("routing.zip")
gtfs <- gtfsrouter::gtfs_timetable(gtfs)
#> Day not specified; extracting timetable for Friday
gtfsrouter::gtfs_route(gtfs, from = "One", to = "Four", start_time = 7 * 3600)
#> Error in `[.data.table`(gtfs$trips, index, trip_headsign): j (the 2nd argument inside [...]) is a single symbol but column name 'trip_headsign' is not found. Perhaps you intended DT[, ..trip_headsign]. This difference to data.frame is deliberate and explained in FAQ 1.1.

Created on 2019-05-10 by the reprex package (v0.2.1)

It appears that gtfsrouter needs the optional trip_headsign column to work? Is there a way around that or should I simply add the column to the feed.

Distance between stops

Hello

I would like to know if is possible to get data such the distance from a certrain stop to another stop. The table generate in the example gives the route followed incluiding the stops and the times but not the distance.

Thank you

Service's descriptions in Calendar_dates aren't taken into account

Hello,

I'm working on a GTFS (RATP - subway in Paris, France) which doesn't define the weekly services by default in Calendar, but defines it day-by-day in Calendar_dates.
The function filter_by_day is only looking at Calendar and stops with an error (no service selected)

. The other functions are calling filter_by_day and doesn't work either.
Did I miss something?

Maxime

PS : GTFS elements and command

ratp$calendar

A tibble: 4,926 x 10

service_id monday tuesday wednesday thursday friday saturday sunday start_date end_date

1 1132941 0 0 0 0 0 0 0 2019-10-03 2019-12-31
2 12755436 0 0 0 0 0 0 0 2019-10-28 2019-10-28
3 12773209 0 0 0 0 0 0 0 2019-10-07 2019-12-30
4 12773210 0 0 0 0 0 0 0 2019-11-02 2019-11-11
5 12773214 0 0 0 0 0 0 0 2019-10-22 2019-12-27
6 12773215 0 0 0 0 0 0 0 2019-12-31 2019-12-31
7 12773216 0 0 0 0 0 0 0 2019-10-04 2019-12-20
8 12773217 0 0 0 0 0 0 0 2019-10-06 2019-12-29
9 12773219 0 0 0 0 0 0 0 2019-10-05 2019-12-21
10 12773221 0 0 0 0 0 0 0 2020-01-01 2020-01-01

ratp$calendar_dates

A tibble: 60,420 x 3

service_id date exception_type

1 1132941 2019-10-03 1
2 1132941 2019-10-04 1
3 1132941 2019-10-07 1
4 1132941 2019-10-08 1
5 1132941 2019-10-09 1
6 1132941 2019-10-10 1
7 1132941 2019-10-11 1
8 1132941 2019-10-14 1
9 1132941 2019-10-15 1
10 1132941 2019-10-16 1

console :

gtfs_timetable(ratp, day = 4)
Error in !attr(gtfs_cp, "filtered") : invalid argument type
attr (ratp, "filtered") <- FALSE
gtfs_timetable(ratp, day = 4)
Error in get(i) : object 'wednesday' not found
traceback()
11: get(i)
10: check_names_df(j, x)
9: [.tbl_df(gtfs$calendar, , get(i))
8: NextMethod([)
7: [.spec_tbl_df(gtfs$calendar, , get(i))
6: gtfs$calendar[, get(i)]
5: which(gtfs$calendar[, get(i)] == 1)
4: FUN(X[[i]], ...)
3: lapply(day, function(i) which(gtfs$calendar[, get(i)] == 1))
2: filter_by_day(gtfs_cp, day, quiet = quiet)
1: gtfs_timetable(ratp, day = 4)

gtfs_isochrone returns too many stops

I opened another issue on the previously stated problem, because I think this is not related to the transfers issue.

I think the problem is due to this line:

https://github.com/ATFutures/gtfs-router/blob/44f8e43df3dd85c7488e66e33e789967e021dcf6/src/csa-isochrone.cpp#L86

If the actual_end_time never gets updated in line 110 then the break point in line 91 is never reached.

I tried instead to initialize with

int actual_start_time = start_time, actual_end_time = end_time;

and then it seems to work. Not 100% that I'm missing sth else then...


Originally posted by @AlexandraKapp in #14 (comment)

another issue that popped up with the custom transfers.txt:

for some stops and times all stops are within reach of 5 minutes. Though, only with the custom transfers.txt, not with the original one:

E.g. with the VBB Feed:

gtfs <- extract_gtfs ("VBB_gtfs.zip")

# this works as expected:
i <- gtfs_isochrone(gtfs, "Boxhagener Platz", day = "Monday", start_time = 8*3600 + 5*60, end_time = 8*3600 + 10*60)

# isochrone with custom transfers
gtfs_cp <- copy(gtfs)
gtfs_cp$stops <- gtfs_cp$stops %>% select(stop_id, stop_lat, stop_lon, stop_name, parent_station) # workaround for bug: # find_xy_cols(obj) :   Unable to determine longitude and latitude columns; perhaps try re-naming columns. "
transfers <- gtfsrouter::gtfs_transfer_table (gtfs_cp, network_times = FALSE)
gtfs_cp$transfers <- transfers

# this produces the implausible isochrone:
i_cust_trans <- gtfs_isochrone(gtfs_cp, "Boxhagener Platz", day = "Monday", start_time = 8*3600 + 5*60, end_time = 8*3600 + 10*60)

nrow(i$mid_points) # returns 6
nrow(i_cust_trans$mid_points) # returns 122233

# with 5 minutes earlier start time this works just fine:
i_cust_trans2 <- gtfs_isochrone(gtfs_cp, "Boxhagener Platz", day = "Monday", start_time = 8*3600, end_time = 8*3600 + 5*60)
nrow(i_cust_trans2$mid_points) # returns 13

max_transfers does not work as expected

library (gtfsrouter)
gtfs <- extract_gtfs("vbb.zip") # full Berlin VBB feed
#> ▶ 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 = "thurs")
from <- "Alexanderplatz"
to <- "Berlin, Helene-Weigel-Platz"

r1 <- gtfs_route (gtfs, from = "Alexanderplatz", to = to,
                  start_time = 9 * 3600,
                  earliest_arrival = TRUE)
r2 <- gtfs_route (gtfs, from = "Alexanderplatz", to = to,
                  start_time = 9 * 3600,
                  earliest_arrival = FALSE)
r1
#>    route_name                       trip_name                       stop_name
#> 1          S7               S Ahrensfelde Bhf S+U Alexanderplatz Bhf (Berlin)
#> 2          S7               S Ahrensfelde Bhf    S+U Jannowitzbrücke (Berlin)
#> 3          S7               S Ahrensfelde Bhf           S Ostbahnhof (Berlin)
#> 4          S7               S Ahrensfelde Bhf    S+U Warschauer Str. (Berlin)
#> 5          S7               S Ahrensfelde Bhf         S Ostkreuz Bhf (Berlin)
#> 6          S7               S Ahrensfelde Bhf         S Nöldnerplatz (Berlin)
#> 7          S7               S Ahrensfelde Bhf    S+U Lichtenberg Bhf (Berlin)
#> 8          S7               S Ahrensfelde Bhf  S Friedrichsfelde Ost (Berlin)
#> 9          S7               S Ahrensfelde Bhf          S Springpfuhl (Berlin)
#> 10         M8 Berlin, Ahrensfelde/Stadtgrenze          S Springpfuhl (Berlin)
#> 11         M8 Berlin, Ahrensfelde/Stadtgrenze     Berlin, Helene-Weigel-Platz
#>    arrival_time departure_time
#> 1      09:04:36       09:05:24
#> 2      09:06:54       09:07:24
#> 3      09:09:06       09:09:54
#> 4      09:11:36       09:12:12
#> 5      09:13:54       09:14:42
#> 6      09:16:12       09:16:42
#> 7      09:18:12       09:18:48
#> 8      09:20:42       09:21:12
#> 9      09:23:48       09:24:54
#> 10     09:30:00       09:30:00
#> 11     09:31:00       09:31:00

That route has only one transfer, and leaves at 09:04. In comparison, the route generated with earliest_arrival = FALSE (see #46) gives:

r2
#>    route_name                       trip_name                       stop_name
#> 1          S3                    S Erkner Bhf S+U Alexanderplatz Bhf (Berlin)
#> 2          S3                    S Erkner Bhf    S+U Jannowitzbrücke (Berlin)
#> 3          S3                    S Erkner Bhf           S Ostbahnhof (Berlin)
#> 4          S3                    S Erkner Bhf    S+U Warschauer Str. (Berlin)
#> 5          S3                    S Erkner Bhf         S Ostkreuz Bhf (Berlin)
#> 6          S7               S Ahrensfelde Bhf         S Nöldnerplatz (Berlin)
#> 7          S7               S Ahrensfelde Bhf    S+U Lichtenberg Bhf (Berlin)
#> 8          S7               S Ahrensfelde Bhf  S Friedrichsfelde Ost (Berlin)
#> 9          S7               S Ahrensfelde Bhf          S Springpfuhl (Berlin)
#> 10         M8 Berlin, Ahrensfelde/Stadtgrenze          S Springpfuhl (Berlin)
#> 11         M8 Berlin, Ahrensfelde/Stadtgrenze     Berlin, Helene-Weigel-Platz
#>    arrival_time departure_time
#> 1      09:01:36       09:02:24
#> 2      09:03:54       09:04:24
#> 3      09:06:06       09:07:24
#> 4      09:09:06       09:09:42
#> 5      09:11:24       09:12:12
#> 6      09:16:12       09:16:42
#> 7      09:18:12       09:18:48
#> 8      09:20:42       09:21:12
#> 9      09:23:48       09:24:54
#> 10     09:30:00       09:30:00
#> 11     09:31:00       09:31:00

Setting max_transfers = 1 should therefore yield the first of these routes, and yet it returns the second:

gtfs_route (gtfs, from = "Alexanderplatz", to = "Boschpoler Str",
            start_time = 9 * 3600,
            max_transfers = 1,
            earliest_arrival = FALSE)
#>    route_name                       trip_name                       stop_name
#> 1          S3                    S Erkner Bhf S+U Alexanderplatz Bhf (Berlin)
#> 2          S3                    S Erkner Bhf    S+U Jannowitzbrücke (Berlin)
#> 3          S3                    S Erkner Bhf           S Ostbahnhof (Berlin)
#> 4          S3                    S Erkner Bhf    S+U Warschauer Str. (Berlin)
#> 5          S3                    S Erkner Bhf         S Ostkreuz Bhf (Berlin)
#> 6          S7               S Ahrensfelde Bhf         S Nöldnerplatz (Berlin)
#> 7          S7               S Ahrensfelde Bhf    S+U Lichtenberg Bhf (Berlin)
#> 8          S7               S Ahrensfelde Bhf  S Friedrichsfelde Ost (Berlin)
#> 9          S7               S Ahrensfelde Bhf          S Springpfuhl (Berlin)
#> 10         M8 Berlin, Ahrensfelde/Stadtgrenze          S Springpfuhl (Berlin)
#> 11         M8 Berlin, Ahrensfelde/Stadtgrenze     Berlin, Helene-Weigel-Platz
#> 12         M8 Berlin, Ahrensfelde/Stadtgrenze         Berlin, Boschpoler Str.
#>    arrival_time departure_time
#> 1      09:01:36       09:02:24
#> 2      09:03:54       09:04:24
#> 3      09:06:06       09:07:24
#> 4      09:09:06       09:09:42
#> 5      09:11:24       09:12:12
#> 6      09:16:12       09:16:42
#> 7      09:18:12       09:18:48
#> 8      09:20:42       09:21:12
#> 9      09:23:48       09:24:54
#> 10     10:00:00       10:00:00
#> 11     10:01:00       10:01:00
#> 12     10:02:00       10:02:00

Created on 2020-10-12 by the reprex package (v0.3.0)

Fix that!

vbb.zip does not appear to be a GTFS file while it contains all the tables required

Appear there is an issue with the dev version which through me an error "the vbb.zip does not appear to be a GTFS file. "
filename <- list.files (getwd(), full.names = TRUE, pattern = "vbb.zip")
filename #"M:/Projects/GTFS/gtfsRouter/vbb.zip"
g <- extract_gtfs(filename)
'got error here: Error in extract_gtfs(filename) : M:/Projects/GTFS/gtfsRouter/vbb.zip does not appear to be a GTFS file; it must minimally contain routes, stops, stop_times, trips

Enable route_pattern to also exclude selection

Currently only works as a positive grep match. Should also add an invert_match = FALSE parameter that, when TRUE, uses grep(..., invert = TRUE) to exclude the matched items. What should it be called?

  • invert_match to match the invert parameter of grep itself, which is in turn called that because that just adds the -v flag to the grep library call which is described as "invert call".
  • exclude_match because that is perhaps more directly informative

ping @AlexandraKapp

Routes have too many transfers

Example:

library(gtfsrouter)
packageVersion ("gtfsrouter")
#> [1] '0.0.4.8'
file.info ("vbb.zip")$mtime
#> [1] "2019-02-14 13:48:16 CET"
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 = "Monday")
from <- "Berlin, Amalienstr"
to <- "Berlin, Heesestr"
start_time <- 11 * 3600
gtfs_route (gtfs, from = from, to = to, start_time = start_time)
#>   route_name                            trip_name
#> 1        284                 S+U Rathaus Steglitz
#> 2        284                 S+U Rathaus Steglitz
#> 3        284                 S+U Rathaus Steglitz
#> 4        284                 S+U Rathaus Steglitz
#> 5        X83 Berlin, Königin-Luise-Str./Clayallee
#> 6        284                 S+U Rathaus Steglitz
#> 7        284                 S+U Rathaus Steglitz
#> 8        284                 S+U Rathaus Steglitz
#> 9        284                 S+U Rathaus Steglitz
#>                                  stop_name arrival_time departure_time
#> 1                      Berlin, Amalienstr.     11:04:00       11:04:00
#> 2 Berlin, Kaiser-Wilhelm-Str./Seydlitzstr.     11:05:00       11:05:00
#> 3                      Berlin, Dillgesstr.     11:06:00       11:06:00
#> 4                  Berlin, Lankwitz Kirche     11:08:00       11:08:00
#> 5                      S Lankwitz (Berlin)     11:11:00       11:11:00
#> 6     Berlin, Steglitzer Damm/Bismarckstr.     11:16:00       11:16:00
#> 7                 Berlin, Neue Filandastr.     11:17:00       11:17:00
#> 8                      Berlin, Breite Str.     11:18:00       11:18:00
#> 9                        Berlin, Heesestr.     11:19:00       11:19:00

Created on 2020-10-25 by the reprex package (v0.3.0)

That route should remain on route_name 284 the whole way, but changes to X83 for one stop before changing back again. That happens because the timetable for that section has the entry for the X83 service prior to the appropriate entry for the 284, and the route simply connects with first available service at all times. Function has to be fixed to avoid unnecessary transfers. Ping @AlexandraKapp

gtfs_summary fn

Lots of details could be usefully summarised in a series of single numbers (most likely as a simple named vector). Numbers of routes, stations, trips, providers, transfers, everything. Ping @tbuckl, @polettif thinking this is the context of tidytransit - some heavy back-end stuff already in-place for numbers of journeys between station pairs and the like, so this function should be pretty easy to implement.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.