{"id":26984346,"url":"https://github.com/transitland/mapzen-gtfs","last_synced_at":"2025-04-03T17:37:11.883Z","repository":{"id":28125123,"uuid":"31624192","full_name":"transitland/mapzen-gtfs","owner":"transitland","description":"Python library for reading and writing GTFS feeds","archived":false,"fork":false,"pushed_at":"2018-12-07T02:18:12.000Z","size":135,"stargazers_count":29,"open_issues_count":4,"forks_count":7,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-05-16T19:02:49.232Z","etag":null,"topics":["gtfs","python","transit"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/transitland.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-03T22:11:08.000Z","updated_at":"2023-07-01T02:08:22.000Z","dependencies_parsed_at":"2022-09-26T17:21:35.240Z","dependency_job_id":null,"html_url":"https://github.com/transitland/mapzen-gtfs","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transitland%2Fmapzen-gtfs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transitland%2Fmapzen-gtfs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transitland%2Fmapzen-gtfs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transitland%2Fmapzen-gtfs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/transitland","download_url":"https://codeload.github.com/transitland/mapzen-gtfs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247050646,"owners_count":20875512,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gtfs","python","transit"],"created_at":"2025-04-03T17:37:11.260Z","updated_at":"2025-04-03T17:37:11.872Z","avatar_url":"https://github.com/transitland.png","language":"Python","funding_links":[],"categories":["Producing Data","Uncategorized"],"sub_categories":["GTFS","Uncategorized"],"readme":"# Mapzen GTFS\n\n[![Circle CI](https://circleci.com/gh/transitland/mapzen-gtfs.png?style=badge)](https://circleci.com/gh/transitland/mapzen-gtfs)\n\nA simple GTFS library.\n\nBenefits:\n\n * Fast parser\n * Reads directly from zip archives\n * Entity generators, read tables line-by-line\n * Entity graph structure\n * Built-in basic validator\n\n## Installation\n\nInstallation using pip:\n\n```\npip install mzgtfs\n```\n\nAlternatively, [download from PyPi](https://pypi.python.org/pypi/mzgtfs) or clone this repository, and install using setup.py:\n\n```\npython ./setup.py install\n```\n\nThe dependency [unicodecsv](https://pypi.python.org/pypi/unicodecsv) will be automatically installed using the above methods.\n\n## Opening a GTFS Feed\n\nThe `mzgtfs.feed.Feed` class is the main entry point for reading and writing schedule data. A feed can be read from either a GTFS zip file, or a directory of CSV files. The validation and write methods are discussed later in this document.\n\n| Feed method | Description |\n|-------------|-------------|\n| init(filename=None, path=None) | Open a feed, given a GTFS zip file or directory\n| preload() | Load the entire feed and entity relationships\n| read(table) | Return a list of entities from a table; e.g. `feed.read('stops')`\n| iterread(table) | Entity generator\n| write(filename, entities, sortkey=None, columns=None) | Write a CSV file\n| make_zip(filename, files=None, path=None, clone=None) | Create a GTFS zip archive                  \n| validate() | Validate feed\n| validate_feedvalidator() | Validate using external feedvalidator.py\n\nThe GTFS CSV files are mapped to the following Entity classes:\n\n| Feed method                   | GTFS file           | Entity class\n|-------------------------------|---------------------|-----------------|\n| agencies(), agency(agency_id) | agency.txt          | Agency\n| routes(), route(route_id)     | routes.txt          | Route\n| trips(), trip(trip_id)        | trips.txt           | Trip\n| stops(), stop(stop_id)        | stops.txt           | Stop\n| stop_times()                  | stop_times.txt      | StopTime\n| shape_line(shape_id)          | shapes.txt          | ShapeLine\n| service_periods(), service_period(service_id) | calendar.txt | ServicePeriod\n| service_exceptions()          | calendar_dates.txt  | ServiceDate\n| fares(), fare(fare_id)        | fare_attributes.txt | FareAttribute\n| fare_rules()                  | fare_rules.txt      | FareRule\n| transfers()                   | transfers.txt       | Transfer\n| frequencies()                 | frequencies.txt     | Frequency\n| feed_infos()                  | feed_info.txt       | FeedInfo\n\n```\n\u003e\u003e\u003e import mzgtfs.feed\n\u003e\u003e\u003e gtfs_feed = mzgtfs.feed.Feed(filename='current.zip') # alt., path=\u003cdir\u003e\n\u003e\u003e\u003e gtfs_feed.routes()\n[\u003cRoute BFC\u003e, \u003cRoute CITY\u003e, \u003cRoute STBA\u003e, \u003cRoute AB\u003e, \u003cRoute AAMV\u003e]\n\u003e\u003e\u003e gtfs_feed.stops()\n[\u003cStop NANAA\u003e, \u003cStop BULLFROG\u003e, \u003cStop FUR_CREEK_RES\u003e, \u003cStop BEATTY_AIRPORT\u003e, \u003cStop EMSI\u003e, \u003cStop DADAN\u003e, \u003cStop NADAV\u003e, \u003cStop STAGECOACH\u003e, \u003cStop AMV\u003e]\n\u003e\u003e\u003e gtfs_feed.stop('NANAA').json()\n{'name': u'North Ave / N A Ave', ... }\n```\n\n## GTFS Graph\n\nFeeds are built on relations between entities; for instance, each agency has a number of routes, these routes have trips, and so on. A convenient way to work with a feed is the `preload()` method, which loads the entire feed and constructs a graph of entities. This provides quick access, such as finding all of the routes and stops associated with an agency.\n\n```\n\u003e\u003e\u003e gtfs_feed.preload() # Load all tables and create relationships\n\u003e\u003e\u003e gtfs_feed.agencies()\n[\u003cAgency DTA\u003e, \u003cAgency ATD\u003e]\n\u003e\u003e\u003e dta = gtfs_feed.agency('DTA')\n\u003e\u003e\u003e len(dta.routes())\n5\n\u003e\u003e\u003e len(dta.stops())\n9\n\u003e\u003e\u003e dta.routes()\nset([\u003cRoute STBA\u003e, \u003cRoute CITY\u003e, \u003cRoute AB\u003e, \u003cRoute AAMV\u003e, \u003cRoute BFC\u003e])\n\u003e\u003e\u003e dta.route('CITY').stops()\nset([\u003cStop EMSI\u003e, \u003cStop DADAN\u003e, \u003cStop NANAA\u003e, \u003cStop NADAV\u003e, \u003cStop STAGECOACH\u003e])\n```\n\n## Entity generator\n\nEach of the access methods in the above table will read the CSV file and cache the resulting entities. If you want to read a table line-by-line with lower overhead, you can use `iterread(table)`. This is especially useful with stop_times.txt, which may have millions of rows.\n\n```\n\u003e\u003e\u003e gtfs_feed.iterread('routes')\n\u003cgenerator object iterread at 0x101cd86e0\u003e\n\u003e\u003e\u003e for route in gtfs_feed.iterread('routes'): print route\n\u003cRoute AB\u003e\n\u003cRoute BFC\u003e\n\u003cRoute STBA\u003e\n\u003cRoute CITY\u003e\n\u003cRoute AAMV\u003e\n```\n\n## Entity methods\n\nThe base Entity class provides the following methods.\n\n| Entity method | Description |\n|---------------|-------------|\n| get(key, default=None) | Get a GTFS attribute\n| entity[key] | Get a GTFS attribute\n| len(entity) | Number of attributes\n| key in entity | Attribute exists in entity\n| keys() | List attributes\n| items() | Attribute keys, values\n| set(key, value) | Set an attribute\n| id() | GTFS entity ID, e.g. agency_id, stop_id, etc.\n| name() | A reasonable entity name or description\n| point() | A point geometry, if one exists\n| bbox() | Entity bounding box\n| geometry() | A GeoJSON geometry\n| children() | Entity children (e.g. agency -\u003e routes)\n| add_child(child) | Add a child entity\n| parents() | Entity parents (e.g. route -\u003e agencies)\n| add_parent(parent) | Add a parent entity\n| validate() | Validate entity; you may pass in a reported\n| validate_feed() | Validate entity relationships\n| json() | JSON representation\n| Entity.from_json(data, feed) | Class method; create Entity from JSON\n| Entity.from_row(data, feed) | Class method; create Entity from CSV row\n\n## Validating a Feed\n\nThis library contains a basic GTFS validator. It validates required and optional attributes and their values, foreign keys, and requirements such as stop sequences.\n\nAdditionally, a wrapper to Google's Transitfeed `feedvalidator.py` is provided, if it is available on your system. This provides additional checks, as well as warnings for common feed problems such as date ranges, stop spacing, bus speeds, etc. However, this is currently only supported on zip'd feeds; if you have made any changes, you will have to write out a zip file first.\n\n```\n\u003e\u003e\u003e import mzgtfs.feed\n\u003e\u003e\u003e import mzgtfs.validation\n\u003e\u003e\u003e report = mzgtfs.validation.ValidationReport()\n\u003e\u003e\u003e gtfs_feed = mzgtfs.feed.Feed('current.zip')\n\u003e\u003e\u003e gtfs_feed.validate(validator=report)\n\u003e\u003e\u003e gtfs_feed.validate_feedvalidator(validator=report)\n\u003e\u003e\u003e report.report()\nValidation report:\n\u003cFeed .//mzgtfs/examples/sample-feed.zip\u003e: Errors reported by feedvalidator.py; see report.html for details\n```\n\n## Writing data\n\nWriting out GTFS CSV files and creating new zip archives is also supported.\n\n```\n\u003e\u003e\u003e import mzgtfs.feed\n\u003e\u003e\u003e gtfs_feed = mzgtfs.feed.Feed('original.zip')\n\u003e\u003e\u003e for stop in gtfs_feed.stops(): stop.set('zone_id', '1')\n\u003e\u003e\u003e # Write out a stops.txt table with our updated stops, sorting on 'stop_id'\n\u003e\u003e\u003e gtfs_feed.write('stops.txt', gtfs_feed.stops(), sortkey='stop_id')\n\u003e\u003e\u003e # Create \"new.zip\", merging our stops table and the original feed.\n\u003e\u003e\u003e gtfs_feed.make_zip('new.zip', files=['stops.txt'], clone='original.zip')\n```\n\n## Running tests\n\nThe library's test suite uses Python unittest. To run the test suite:\n\n```\npython -m unittest discover\n```\n\n## Contributing\n\nPlease [open a Github issue](https://github.com/transitland/mapzen-gtfs/issues/new) with as much of the following information as you're able to specify, or [contact us](#contact) for assistance.\n\n## Contact\n\nTransitland is sponsored by [Mapzen](http://mapzen.com). Contact us with your questions, comments, or suggests: [hello@mapzen.com](mailto:hello@mapzen.com).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftransitland%2Fmapzen-gtfs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftransitland%2Fmapzen-gtfs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftransitland%2Fmapzen-gtfs/lists"}