A Ruby Gem for GTFS to GeoJSON Conversion
I published my first Ruby gem: gtfs-geojson! You can view the source on GitHub. gtfs-geojson is a Ruby utility to convert a GTFS feed to a GeoJSON file. It’s a simple endeavor, for sure, but I’m pleased with what I learned along the way.
Let’s start out with some before-and-after views of the data. These images were created using QGIS, OpenStreetMap, Transfort’s GTFS feed, and the gtfs-geojson library.
As with most transit projects, the input to gtfs-geojson is a GTFS feed. GTFS is the standard format published by transit agencies worldwide to make their routes, stops, and even fares usable by developers. The data is a series of comma-separated text files. To validate a GTFS feed, I used an existing gem. gtfs will fail gracefully if the shapes.txt file is not present, which is the only file I actually need for the conversion to GeoJSON.
gtfs-geojson implements the same algorithm as the “Points to path” QGIS tool I used when looking at Transfort bus data. The main trick is that the points within each route ID must be sorted by their point sequence value. Several other QGIS plugins I tried did not do this correctly, so don’t forget this if implementing this yourself!
While QGIS tools output shapefiles, gtfs-geojson produces a GeoJSON file, which is a JSON stream with geospatial points and polylines data served up in a standard format. I have previously loaded GeoJSON files in Mapbox applications, and they are also useful in a GIS context. The following three lines will load the library, validate the GTFS feed, convert its shapes.txt file to GeoJSON format, and write the GeoJSON to a file.
require 'gtfs-geojson'
geojson = GTFS::GeoJSON.generate("gtfs.zip")
File.open("gtfs.geojson",'w') do { |f| f.write(geojson) }
That’s it! Let me know if you have any suggestions! The README
on the GitHub repo gives installation instructions.
The most valuable tip I learned while creating this gem was the use of the $RUBYLIB
environment variable. This isn’t necessary when installing a gem onto your system using bundler, but it is extremely helpful during development. $RUBYLIB
lets you specify the path searched when the require
keyword is used. To add paths dynamically to $RUBYLIB
, you can push items to the $:
array. $:
is shorthand for $LOAD_PATH
within a Ruby program. My require_relative
days are over!
If you are considering writing your own gem, I highly recommend RubyGems.org’s “Make Your Own Gem” guide. It is comprehensive and just generally fantastic.
I plan to use gtfs-geojson in a Rails project in the future. And speaking of gems, I’ve also been dabbling on a Ruby API client for Transitland. I hope to have more to share on both fronts soon!
Until then, ride on!
Have any transit projects to share? Let me know!