├── .gitignore ├── figures ├── hex.png └── plot-1.png ├── docs ├── favicon.ico ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── reference │ ├── Rplot001.png │ ├── figures │ │ └── hex.png │ ├── data │ │ ├── station_status.rds │ │ ├── system_alerts.rds │ │ ├── system_hours.rds │ │ ├── system_regions.rds │ │ ├── free_bike_status.rds │ │ ├── system_calendar.rds │ │ ├── station_information.rds │ │ ├── system_information.rds │ │ └── system_pricing_plans.rds │ ├── gbfs_data │ │ ├── station_status.rds │ │ ├── system_alerts.rds │ │ ├── system_hours.rds │ │ ├── system_regions.rds │ │ ├── free_bike_status.rds │ │ ├── system_calendar.rds │ │ ├── station_information.rds │ │ ├── system_information.rds │ │ └── system_pricing_plans.rds │ ├── kc_gbfs │ │ └── station_status.rds │ ├── slcbikes │ │ ├── station_status.rds │ │ ├── system_regions.rds │ │ ├── station_information.rds │ │ ├── system_information.rds │ │ └── system_pricing_plans.rds │ ├── get_gbfs_cities.html │ ├── index.html │ ├── get_system_pricing_plans.html │ ├── gbfs.html │ ├── get_system_hours.html │ ├── get_system_alerts.html │ ├── get_system_calendar.html │ ├── get_which_gbfs_feeds.html │ └── get_system_regions.html ├── apple-touch-icon-120x120.png ├── apple-touch-icon-152x152.png ├── apple-touch-icon-180x180.png ├── apple-touch-icon-60x60.png ├── apple-touch-icon-76x76.png ├── pkgdown.yml ├── link.svg ├── sitemap.xml ├── bootstrap-toc.css ├── docsearch.js ├── jquery.sticky-kit.min.js ├── pkgdown.js ├── articles │ └── index.html ├── bootstrap-toc.js ├── 404.html ├── authors.html ├── CONTRIBUTING.html └── pkgdown.css ├── tests ├── testthat.R └── testthat │ ├── test-static-feeds.R │ ├── test-wrapper.R │ ├── test-dynamic-feeds.R │ └── test-utils.R ├── man ├── figures │ └── hex.png ├── get_gbfs_cities.Rd ├── get_which_gbfs_feeds.Rd ├── get_system_pricing_plans.Rd ├── get_system_hours.Rd ├── get_system_calendar.Rd ├── get_system_alerts.Rd ├── get_station_information.Rd ├── get_free_bike_status.Rd ├── gbfs.Rd ├── get_station_status.Rd ├── get_system_regions.Rd ├── get_system_information.Rd └── get_gbfs.Rd ├── pkgdown └── favicon │ ├── favicon.ico │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── apple-touch-icon.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ └── apple-touch-icon-180x180.png ├── cran-comments.md ├── .Rbuildignore ├── codecov.yml ├── gbfs.Rproj ├── NAMESPACE ├── DESCRIPTION ├── CONTRIBUTING.md ├── .github └── workflows │ └── R-CMD-check.yaml ├── R ├── get_dynamic_feeds.R ├── gbfs_description.R ├── get_gbfs.R └── get_static_feeds.R ├── NEWS.md └── README.Rmd /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | -------------------------------------------------------------------------------- /figures/hex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/figures/hex.png -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /figures/plot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/figures/plot-1.png -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(gbfs) 3 | 4 | test_check("gbfs") 5 | -------------------------------------------------------------------------------- /man/figures/hex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/man/figures/hex.png -------------------------------------------------------------------------------- /docs/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/favicon-16x16.png -------------------------------------------------------------------------------- /docs/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/favicon-32x32.png -------------------------------------------------------------------------------- /docs/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /docs/reference/figures/hex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/figures/hex.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /docs/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: '3.2' 2 | pkgdown: 2.1.0 3 | pkgdown_sha: ~ 4 | articles: {} 5 | last_built: 2025-01-13T16:19Z 6 | -------------------------------------------------------------------------------- /docs/reference/data/station_status.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/station_status.rds -------------------------------------------------------------------------------- /docs/reference/data/system_alerts.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/system_alerts.rds -------------------------------------------------------------------------------- /docs/reference/data/system_hours.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/system_hours.rds -------------------------------------------------------------------------------- /docs/reference/data/system_regions.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/system_regions.rds -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /docs/reference/data/free_bike_status.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/free_bike_status.rds -------------------------------------------------------------------------------- /docs/reference/data/system_calendar.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/system_calendar.rds -------------------------------------------------------------------------------- /docs/reference/data/station_information.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/station_information.rds -------------------------------------------------------------------------------- /docs/reference/data/system_information.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/system_information.rds -------------------------------------------------------------------------------- /docs/reference/gbfs_data/station_status.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/station_status.rds -------------------------------------------------------------------------------- /docs/reference/gbfs_data/system_alerts.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/system_alerts.rds -------------------------------------------------------------------------------- /docs/reference/gbfs_data/system_hours.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/system_hours.rds -------------------------------------------------------------------------------- /docs/reference/gbfs_data/system_regions.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/system_regions.rds -------------------------------------------------------------------------------- /docs/reference/kc_gbfs/station_status.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/kc_gbfs/station_status.rds -------------------------------------------------------------------------------- /docs/reference/slcbikes/station_status.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/slcbikes/station_status.rds -------------------------------------------------------------------------------- /docs/reference/slcbikes/system_regions.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/slcbikes/system_regions.rds -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /docs/reference/data/system_pricing_plans.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/data/system_pricing_plans.rds -------------------------------------------------------------------------------- /docs/reference/gbfs_data/free_bike_status.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/free_bike_status.rds -------------------------------------------------------------------------------- /docs/reference/gbfs_data/system_calendar.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/system_calendar.rds -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /docs/reference/gbfs_data/station_information.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/station_information.rds -------------------------------------------------------------------------------- /docs/reference/gbfs_data/system_information.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/system_information.rds -------------------------------------------------------------------------------- /docs/reference/slcbikes/station_information.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/slcbikes/station_information.rds -------------------------------------------------------------------------------- /docs/reference/slcbikes/system_information.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/slcbikes/system_information.rds -------------------------------------------------------------------------------- /docs/reference/slcbikes/system_pricing_plans.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/slcbikes/system_pricing_plans.rds -------------------------------------------------------------------------------- /docs/reference/gbfs_data/system_pricing_plans.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/simonpcouch/gbfs/HEAD/docs/reference/gbfs_data/system_pricing_plans.rds -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## gbfs 2 | 3 | There were no ERRORs, WARNINGs, or NOTEs in checks. 4 | 5 | The package currently has no reverse dependencies. 6 | 7 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | docs/ 4 | ^README.Rmd 5 | ^README.md 6 | NEWS.Rmd 7 | figures/ 8 | ^codecov\.yml$ 9 | ^CRAN-RELEASE$ 10 | CONTRIBUTING.md 11 | ^pkgdown 12 | ^\.github$ 13 | ^cran-comments\.md$ 14 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: 2 | layout: "reach, diff, flags, files" 3 | behavior: default 4 | require_changes: false # if true: only post the comment if coverage changes 5 | require_base: no # [yes :: must have a base report to post] 6 | require_head: yes # [yes :: must have a head report to post] 7 | branches: null 8 | -------------------------------------------------------------------------------- /gbfs.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(get_free_bike_status) 4 | export(get_gbfs) 5 | export(get_gbfs_cities) 6 | export(get_station_information) 7 | export(get_station_status) 8 | export(get_system_alerts) 9 | export(get_system_calendar) 10 | export(get_system_hours) 11 | export(get_system_information) 12 | export(get_system_pricing_plans) 13 | export(get_system_regions) 14 | export(get_which_gbfs_feeds) 15 | importFrom(dplyr,"%>%") 16 | -------------------------------------------------------------------------------- /tests/testthat/test-static-feeds.R: -------------------------------------------------------------------------------- 1 | context("static feeds") 2 | 3 | 4 | test_that("static feeds work", { 5 | 6 | skip_if_offline(host = "r-project.org") 7 | 8 | get_station_information("https://gbfs.lyft.com/gbfs/1.1/pdx/en/station_information.json") 9 | 10 | get_system_alerts("https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_alerts.json") 11 | 12 | get_system_calendar("https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_calendar.json") 13 | 14 | get_system_hours("https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_hours.json") 15 | 16 | get_system_information("https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_information.json") 17 | 18 | get_system_regions("https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_regions.json") 19 | }) 20 | -------------------------------------------------------------------------------- /man/get_gbfs_cities.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_gbfs.R 3 | \name{get_gbfs_cities} 4 | \alias{get_gbfs_cities} 5 | \title{Get table of all cities releasing GBFS feeds} 6 | \source{ 7 | North American Bikeshare Association, General Bikeshare Feed Specification 8 | \url{https://raw.githubusercontent.com/MobilityData/gbfs/master/systems.csv} 9 | } 10 | \usage{ 11 | get_gbfs_cities() 12 | } 13 | \value{ 14 | A \code{data.frame} of all cities issuing GBFS feeds. The `Auto-Discovery URL` 15 | column supplies the relevant .json feeds, while the entries in the `URL` column 16 | take the user to the public-facing webpage of the programs. 17 | } 18 | \description{ 19 | Get table of all cities releasing GBFS feeds 20 | } 21 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: gbfs 2 | Type: Package 3 | Title: Interface with Live Bikeshare Data 4 | Version: 1.3.10.9000 5 | Authors@R: c( 6 | person("Simon P.", "Couch", , "simonpatrickcouch@gmail.com", c("aut", "cre")), 7 | person("Kaelyn", "Rosenberg", , "kaerosenberg@gmail.com", c("aut")), 8 | person("Mark", "Padgham", , "mark.padgham@email.com", c("ctb"))) 9 | Description: Supplies a set of functions to interface with bikeshare data 10 | following the General Bikeshare Feed Specification, allowing users to query 11 | and accumulate tidy datasets for specified cities/bikeshare programs. 12 | License: CC0 13 | Imports: 14 | dplyr, 15 | readr, 16 | stringr, 17 | jsonlite, 18 | lubridate, 19 | httr, 20 | purrr, 21 | curl 22 | Encoding: UTF-8 23 | RoxygenNote: 7.3.0 24 | Suggests: 25 | knitr, 26 | rmarkdown, 27 | testthat (>= 2.1.0), 28 | covr 29 | URL: https://github.com/simonpcouch/gbfs 30 | BugReports: https://github.com/simonpcouch/gbfs/issues 31 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | /404.html 3 | /CONTRIBUTING.html 4 | /articles/index.html 5 | /articles/kc_bikeshare.html 6 | /authors.html 7 | /index.html 8 | /news/index.html 9 | /reference/gbfs.html 10 | /reference/get_free_bike_status.html 11 | /reference/get_gbfs.html 12 | /reference/get_gbfs_cities.html 13 | /reference/get_station_information.html 14 | /reference/get_station_status.html 15 | /reference/get_system_alerts.html 16 | /reference/get_system_calendar.html 17 | /reference/get_system_hours.html 18 | /reference/get_system_information.html 19 | /reference/get_system_pricing_plans.html 20 | /reference/get_system_regions.html 21 | /reference/get_which_gbfs_feeds.html 22 | /reference/index.html 23 | 24 | 25 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 6 | 7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 8 | 9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, issues, and other contributions that are not aligned to this Code of Conduct. 10 | 11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 12 | 13 | This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at https://www.contributor-covenant.org/version/1/0/0/code-of-conduct.html 14 | -------------------------------------------------------------------------------- /man/get_which_gbfs_feeds.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_gbfs.R 3 | \name{get_which_gbfs_feeds} 4 | \alias{get_which_gbfs_feeds} 5 | \title{Get dataframe of bikeshare feeds released by a city} 6 | \source{ 7 | North American Bikeshare Association, General Bikeshare Feed 8 | Specification \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 9 | } 10 | \usage{ 11 | get_which_gbfs_feeds(city) 12 | } 13 | \arguments{ 14 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 15 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 16 | also attempt to match to the URL of an active .json feed or city name.} 17 | } 18 | \value{ 19 | A \code{data.frame} containing the feeds supplied by 20 | a city. . The `feed` column supplies the name of the relevant .json feeds, 21 | while the entries in the `URL` column supply the feeds themselves. 22 | } 23 | \description{ 24 | Of the different types of feeds supplied by the gbfs, 25 | some are required, some are conditionally required, and some are 26 | optional. This function grabs a list of each of the feeds supplied 27 | by a given city, as well as the URLs to access them. 28 | } 29 | \examples{ 30 | # grab all of the feeds released by portland 31 | \donttest{get_which_gbfs_feeds(city = "biketown_pdx")} 32 | 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v3 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - uses: r-lib/actions/check-r-package@v2 48 | with: 49 | upload-snapshots: true 50 | -------------------------------------------------------------------------------- /tests/testthat/test-wrapper.R: -------------------------------------------------------------------------------- 1 | context("wrapper") 2 | 3 | # grab the feed for portland's biketown... these feeds 4 | # change regularly, so test failures might result from 5 | # changes in the operation model of biketown rather than 6 | # failure of the software 7 | 8 | biketown <- tryCatch( 9 | get_gbfs("biketown_pdx"), 10 | error = function(e) {e} 11 | ) 12 | 13 | if (inherits(biketown, "error")) { 14 | skip("no internet connection or deprecated bikeshare system") 15 | } 16 | 17 | bike_itau <- tryCatch( 18 | get_gbfs("santiago"), 19 | error = function(e) {e} 20 | ) 21 | 22 | if (inherits(bike_itau, "error")) { 23 | skip("no internet connection or deprecated bikeshare system") 24 | } 25 | 26 | chicago_url <- "https://gbfs.divvybikes.com/gbfs/2.3/gbfs.json" 27 | 28 | if (url_exists(chicago_url)) { 29 | chicago <- tryCatch( 30 | get_gbfs(chicago_url), 31 | error = function(e) {e} 32 | ) 33 | 34 | if (inherits(chicago, "error")) { 35 | skip("deprecated bikeshare system") 36 | } 37 | } else { 38 | skip("no internet connection") 39 | } 40 | 41 | test_that("main wrapper works", { 42 | 43 | skip_if_offline(host = "r-project.org") 44 | 45 | expect_equal(class(biketown), "list") 46 | expect_equal(class(bike_itau), "list") 47 | expect_equal(class(chicago), "list") 48 | 49 | }) 50 | 51 | test_that("argument checking works", { 52 | 53 | skip_if_offline(host = "r-project.org") 54 | 55 | # no directory supplied but user wants to save 56 | expect_error(get_gbfs("biketown_pdx", 57 | output = "save"), 58 | "The argument to output suggests") 59 | 60 | }) 61 | -------------------------------------------------------------------------------- /tests/testthat/test-dynamic-feeds.R: -------------------------------------------------------------------------------- 1 | context("dynamic feeds") 2 | 3 | 4 | test_that("dynamic feeds work", { 5 | 6 | skip_if_offline(host = "r-project.org") 7 | 8 | get_station_status("biketown_pdx") 9 | 10 | get_free_bike_status("biketown_pdx") 11 | 12 | }) 13 | 14 | test_that("file saving and overwriting works", { 15 | 16 | skip("row-binding trips up on GHA") 17 | 18 | # make a temporary directory 19 | dir <- tempdir() 20 | 21 | # save the file to a subdirectory of it 22 | get_station_status("biketown_pdx", paste0(dir, "/test")) 23 | 24 | # ...and then append to it 25 | get_station_status("biketown_pdx", paste0(dir, "/test")) 26 | 27 | }) 28 | 29 | test_that("row binding checks work", { 30 | 31 | skip_if_offline(host = "r-project.org") 32 | 33 | # make a temporary directory 34 | dir <- tempdir() 35 | 36 | # grab some data to work with 37 | pdx_status <- get_station_status("biketown_pdx", dir, output = "both") 38 | 39 | # try to overwrite it, but... 40 | 41 | # ... with a column pulled off 42 | pdx_status_ <- pdx_status %>% 43 | dplyr::select(-station_id) 44 | 45 | expect_error(datasets_can_be_row_binded( 46 | pdx_status_, 47 | paste0(dir, "/station_status.rds")), 48 | "columns, while") 49 | 50 | # ... or a column name changed 51 | pdx_status_ <- pdx_status %>% 52 | dplyr::rename(stationId = station_id) 53 | 54 | expect_error(datasets_can_be_row_binded( 55 | pdx_status_, 56 | paste0(dir, "/station_status.rds")), 57 | "has different column names") 58 | 59 | # ... or different column types 60 | pdx_status_ <- pdx_status %>% 61 | dplyr::mutate(station_id = as.factor(station_id)) 62 | 63 | expect_error(datasets_can_be_row_binded( 64 | pdx_status_, 65 | paste0(dir, "/station_status.rds")), 66 | "has different column types") 67 | 68 | }) 69 | -------------------------------------------------------------------------------- /man/get_system_pricing_plans.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_static_feeds.R 3 | \name{get_system_pricing_plans} 4 | \alias{get_system_pricing_plans} 5 | \title{Grab the system_pricing_plans feed.} 6 | \usage{ 7 | get_system_pricing_plans( 8 | city, 9 | directory = NULL, 10 | file = "system_pricing_plans.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | feed, a dataframe object, or both. 36 | } 37 | \description{ 38 | \code{get_system_pricing_plans} grabs and tidies the system_pricing_plans 39 | feed for a given city. Metadata for this dataset can be found at: 40 | \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 41 | } 42 | \seealso{ 43 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 44 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 45 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 46 | are released by a given city. 47 | } 48 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /man/get_system_hours.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_static_feeds.R 3 | \name{get_system_hours} 4 | \alias{get_system_hours} 5 | \title{Grab the system_hours feed.} 6 | \usage{ 7 | get_system_hours( 8 | city, 9 | directory = NULL, 10 | file = "system_hours.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | feed, a dataframe object, or both. 36 | } 37 | \description{ 38 | \code{get_system_hours} grabs and tidies the system_hours 39 | feed for a given city. Metadata for this 40 | dataset can be found at: 41 | \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 42 | } 43 | \examples{ 44 | # grab the system hours feed for portland, oregon 45 | \donttest{get_system_hours(city = 46 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_hours.json", 47 | output = "return")} 48 | 49 | } 50 | \seealso{ 51 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 52 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 53 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 54 | are released by a given city. 55 | } 56 | -------------------------------------------------------------------------------- /man/get_system_calendar.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_static_feeds.R 3 | \name{get_system_calendar} 4 | \alias{get_system_calendar} 5 | \title{Grab the system_calendar feed.} 6 | \usage{ 7 | get_system_calendar( 8 | city, 9 | directory = NULL, 10 | file = "system_calendar.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | feed, a dataframe object, or both. 36 | } 37 | \description{ 38 | \code{get_system_calendar} grabs and tidies the system_calendar feed 39 | for a given city. Metadata for this dataset can be found at: 40 | \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 41 | } 42 | \examples{ 43 | # grab the system calendar feed for portland, oregon 44 | \donttest{get_system_calendar(city = 45 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_calendar.json", 46 | output = "return")} 47 | 48 | 49 | } 50 | \seealso{ 51 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 52 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 53 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 54 | are released by a given city. 55 | } 56 | -------------------------------------------------------------------------------- /man/get_system_alerts.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_static_feeds.R 3 | \name{get_system_alerts} 4 | \alias{get_system_alerts} 5 | \title{Grab the system_alerts feed.} 6 | \usage{ 7 | get_system_alerts( 8 | city, 9 | directory = NULL, 10 | file = "system_alerts.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | feed, a dataframe object, or both. 36 | } 37 | \description{ 38 | \code{get_system_alerts} grabs and tidies the system_alerts feed for a given city. 39 | This feed informs users about changes to normal operation. Metadata for this 40 | dataset can be found at: \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 41 | } 42 | \examples{ 43 | # grab the system alerts feed for portland, oregon 44 | \donttest{get_system_alerts(city = 45 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_alerts.json", 46 | output = "return")} 47 | 48 | } 49 | \seealso{ 50 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 51 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 52 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 53 | are released by a given city. 54 | } 55 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /R/get_dynamic_feeds.R: -------------------------------------------------------------------------------- 1 | #' Grab the free_bike_status feed. 2 | #' 3 | #' Grab a dataframe giving the geographic location and other metadata of 4 | #' bikeshare bikes not parked at bikeshare stations. Metadata for this dataset 5 | #' can be found at: \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 6 | #' 7 | #' @inherit get_station_information params seealso 8 | #' 9 | #' @return The output of this function depends on the argument to \code{output} 10 | #' and \code{directory}. Either a saved .rds object generated from the current 11 | #' station_information feed, a dataframe object, or both. If a saved feed of 12 | #' the same type already exists at the filepath, the feed will be appended to 13 | #' rather than overwritten. 14 | #' 15 | #' @examples 16 | #' # grab the free bike status feed for portland, oregon's bikeshare program 17 | #' \donttest{get_free_bike_status(city = 18 | #' "https://gbfs.lyft.com/gbfs/1.1/pdx/en/free_bike_status.json", 19 | #' output = "return")} 20 | #' 21 | #' @export 22 | get_free_bike_status <- function(city, directory = NULL, file = "free_bike_status.rds", output = NULL) { 23 | 24 | get_gbfs_dataset_(city, directory, file, output, feed = "free_bike_status") 25 | 26 | } 27 | 28 | #' Grab the station_status feed. 29 | #' 30 | #' Grab a dataframe giving the geographic location and other metadata of 31 | #' bikeshare bikes parked at bikeshare stations. Metadata for this dataset 32 | #' can be found at: \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 33 | #' 34 | #' @inherit get_station_information params seealso 35 | #' 36 | #' @inherit get_free_bike_status return 37 | #' 38 | #' @examples 39 | #' # we can grab the free bike status feed for portland, 40 | #' # oregon's bikeshare program in several ways! the most 41 | #' # straightforward way is just to supply the `city` argument 42 | #' # as a string: 43 | #' \donttest{get_station_status(city = "biketown_pdx")} 44 | #' 45 | #' # the `city` argument can also be supplied as an 46 | #' # actual URL to an active .json feed 47 | #' \donttest{get_station_status(city = 48 | #' "https://gbfs.lyft.com/gbfs/1.1/pdx/en/station_status.json")} 49 | 50 | #' 51 | #' @export 52 | get_station_status <- function(city, directory = NULL, file = "station_status.rds", output = NULL) { 53 | 54 | get_gbfs_dataset_(city, directory, file, output, feed = "station_status") 55 | 56 | } 57 | -------------------------------------------------------------------------------- /man/get_station_information.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_static_feeds.R 3 | \name{get_station_information} 4 | \alias{get_station_information} 5 | \title{Grab the station_information feed.} 6 | \usage{ 7 | get_station_information( 8 | city, 9 | directory = NULL, 10 | file = "station_information.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | feed, a dataframe object, or both. 36 | } 37 | \description{ 38 | \code{get_station_information} grabs and tidies the station_information feed for a given city. 39 | This dataset contains locations, capacity, and other information about bikeshare stations. 40 | Metadata for this dataset can be found at: 41 | \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 42 | } 43 | \examples{ 44 | # grab the free bike status feed for portland, oreoon's bikeshare program 45 | \donttest{get_station_information(city = 46 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/station_information.json", 47 | output = "return")} 48 | 49 | } 50 | \seealso{ 51 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 52 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 53 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 54 | are released by a given city. 55 | } 56 | -------------------------------------------------------------------------------- /man/get_free_bike_status.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_dynamic_feeds.R 3 | \name{get_free_bike_status} 4 | \alias{get_free_bike_status} 5 | \title{Grab the free_bike_status feed.} 6 | \usage{ 7 | get_free_bike_status( 8 | city, 9 | directory = NULL, 10 | file = "free_bike_status.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on the argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | station_information feed, a dataframe object, or both. If a saved feed of 36 | the same type already exists at the filepath, the feed will be appended to 37 | rather than overwritten. 38 | } 39 | \description{ 40 | Grab a dataframe giving the geographic location and other metadata of 41 | bikeshare bikes not parked at bikeshare stations. Metadata for this dataset 42 | can be found at: \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 43 | } 44 | \examples{ 45 | # grab the free bike status feed for portland, oregon's bikeshare program 46 | \donttest{get_free_bike_status(city = 47 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/free_bike_status.json", 48 | output = "return")} 49 | 50 | } 51 | \seealso{ 52 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 53 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 54 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 55 | are released by a given city. 56 | } 57 | -------------------------------------------------------------------------------- /R/gbfs_description.R: -------------------------------------------------------------------------------- 1 | #' Package: gbfs 2 | #' 3 | #' The \code{gbfs} package allows users to query tidy datasets about bikeshare 4 | #' programs around the world by supplying a set of functions to interface with 5 | #' .json feeds following the General Bikeshare Feed Specification, a standard 6 | #' data release format developed by the North American Bikeshare Association. 7 | #' 8 | #' @details 9 | #' 10 | #' The main function exported by this package is \code{get_gbfs()}, which 11 | #' grabs every feed released by a city. Alternatively, the user can just 12 | #' grab information on specific feeds (or groups of feeds). 13 | #' 14 | #' Each of the feeds described below can be queried with the \code{get_suffix()} 15 | #' function, where \code{suffix} is replaced with the name of the relevant feed. 16 | #' 17 | #' Although all of the feeds are livestreamed, only a few of the datasets 18 | #' change often: 19 | #' 20 | #' \describe{ 21 | #' \item{\code{station_status:}}{ Supplies the number of available bikes and 22 | #' docks at each station as well as station availability} 23 | #' \item{\code{free_bike_status:}}{ Gives the coordinates and metadata on 24 | #' available bikes that are parked, but not at a station.} 25 | #' } 26 | #' 27 | #' In this package, these two datasets are considered "dynamic", and can be 28 | #' specified as desired datasets by setting `\code{feeds = "dynamic"} in the 29 | #' main wrapper function in the package, \code{get_gbfs}. 30 | #' 31 | #' Much of the data supplied in this specification can be considered static. 32 | #' If you want to grab all of these for a given city, set \code{feeds = "static"} 33 | #' when calling \code{get_gbfs}. Static feeds include: 34 | #' 35 | #' \describe{ 36 | #' \item{\code{system_information:}}{ Basic metadata about the bikeshare program} 37 | #' \item{\code{station_information:}}{ Information on the capacity and coordinates of stations} 38 | #' \item{Several optional feeds:}{ \code{system_hours}, \code{system_calendar}, 39 | #' \code{system_regions}, \code{system_pricing_plans}, and \code{system_alerts}} 40 | #' } 41 | #' 42 | #' 43 | #' @docType package 44 | #' @name gbfs 45 | #' @importFrom dplyr %>% 46 | "_PACKAGE" 47 | 48 | utils::globalVariables( 49 | c(".", "Location", "Name", "last_reported", "last_updated", 50 | "num_bikes_available", "num_bikes_disabled", "num_docks_available", 51 | "num_docks_disabled", "is_installed", "is_renting", "is_returning", 52 | "station_id", "city", "gbfs_feeds", "name", "type", 53 | "Auto-Discovery URL", "System ID")) 54 | -------------------------------------------------------------------------------- /man/gbfs.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gbfs_description.R 3 | \docType{package} 4 | \name{gbfs} 5 | \alias{gbfs-package} 6 | \alias{gbfs} 7 | \title{Package: gbfs} 8 | \description{ 9 | The \code{gbfs} package allows users to query tidy datasets about bikeshare 10 | programs around the world by supplying a set of functions to interface with 11 | .json feeds following the General Bikeshare Feed Specification, a standard 12 | data release format developed by the North American Bikeshare Association. 13 | } 14 | \details{ 15 | The main function exported by this package is \code{get_gbfs()}, which 16 | grabs every feed released by a city. Alternatively, the user can just 17 | grab information on specific feeds (or groups of feeds). 18 | 19 | Each of the feeds described below can be queried with the \code{get_suffix()} 20 | function, where \code{suffix} is replaced with the name of the relevant feed. 21 | 22 | Although all of the feeds are livestreamed, only a few of the datasets 23 | change often: 24 | 25 | \describe{ 26 | \item{\code{station_status:}}{ Supplies the number of available bikes and 27 | docks at each station as well as station availability} 28 | \item{\code{free_bike_status:}}{ Gives the coordinates and metadata on 29 | available bikes that are parked, but not at a station.} 30 | } 31 | 32 | In this package, these two datasets are considered "dynamic", and can be 33 | specified as desired datasets by setting `\code{feeds = "dynamic"} in the 34 | main wrapper function in the package, \code{get_gbfs}. 35 | 36 | Much of the data supplied in this specification can be considered static. 37 | If you want to grab all of these for a given city, set \code{feeds = "static"} 38 | when calling \code{get_gbfs}. Static feeds include: 39 | 40 | \describe{ 41 | \item{\code{system_information:}}{ Basic metadata about the bikeshare program} 42 | \item{\code{station_information:}}{ Information on the capacity and coordinates of stations} 43 | \item{Several optional feeds:}{ \code{system_hours}, \code{system_calendar}, 44 | \code{system_regions}, \code{system_pricing_plans}, and \code{system_alerts}} 45 | } 46 | } 47 | \seealso{ 48 | Useful links: 49 | \itemize{ 50 | \item \url{https://github.com/simonpcouch/gbfs} 51 | \item Report bugs at \url{https://github.com/simonpcouch/gbfs/issues} 52 | } 53 | 54 | } 55 | \author{ 56 | \strong{Maintainer}: Simon P. Couch \email{simonpatrickcouch@gmail.com} 57 | 58 | Authors: 59 | \itemize{ 60 | \item Kaelyn Rosenberg \email{kaerosenberg@gmail.com} 61 | } 62 | 63 | Other contributors: 64 | \itemize{ 65 | \item Mark Padgham \email{mark.padgham@email.com} [contributor] 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /man/get_station_status.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_dynamic_feeds.R 3 | \name{get_station_status} 4 | \alias{get_station_status} 5 | \title{Grab the station_status feed.} 6 | \usage{ 7 | get_station_status( 8 | city, 9 | directory = NULL, 10 | file = "station_status.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on the argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | station_information feed, a dataframe object, or both. If a saved feed of 36 | the same type already exists at the filepath, the feed will be appended to 37 | rather than overwritten. 38 | } 39 | \description{ 40 | Grab a dataframe giving the geographic location and other metadata of 41 | bikeshare bikes parked at bikeshare stations. Metadata for this dataset 42 | can be found at: \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 43 | } 44 | \examples{ 45 | # we can grab the free bike status feed for portland, 46 | # oregon's bikeshare program in several ways! the most 47 | # straightforward way is just to supply the `city` argument 48 | # as a string: 49 | \donttest{get_station_status(city = "biketown_pdx")} 50 | 51 | # the `city` argument can also be supplied as an 52 | # actual URL to an active .json feed 53 | \donttest{get_station_status(city = 54 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/station_status.json")} 55 | 56 | } 57 | \seealso{ 58 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 59 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 60 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 61 | are released by a given city. 62 | } 63 | -------------------------------------------------------------------------------- /man/get_system_regions.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_static_feeds.R 3 | \name{get_system_regions} 4 | \alias{get_system_regions} 5 | \title{Grab the system_regions feed.} 6 | \usage{ 7 | get_system_regions( 8 | city, 9 | directory = NULL, 10 | file = "system_regions.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | feed, a dataframe object, or both. 36 | } 37 | \description{ 38 | \code{get_system_regions} grabs and tidies the system_regions feed for 39 | a given city. Metadata for this dataset can be found at: 40 | \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 41 | } 42 | \examples{ 43 | # we can grab the system regions feed for portland, 44 | # oregon in one of several ways! first, supply the `city` 45 | # argument as a URL, and save to file by leaving output 46 | # set to it's default. usually, we would supply a character 47 | # string (like "pdx", maybe,) for the `directory` argument 48 | # instead of `tempdir`. 49 | \donttest{get_system_regions(city = 50 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_regions.json", 51 | directory = tempdir())} 52 | 53 | # or, instead, just supply the name of 54 | # the city as a string and return the output 55 | # as a dataframe 56 | \donttest{get_system_regions(city = "biketown_pdx", 57 | output = "return")} 58 | } 59 | \seealso{ 60 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 61 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 62 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 63 | are released by a given city. 64 | } 65 | -------------------------------------------------------------------------------- /man/get_system_information.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_static_feeds.R 3 | \name{get_system_information} 4 | \alias{get_system_information} 5 | \title{Grab the system_information feed.} 6 | \usage{ 7 | get_system_information( 8 | city, 9 | directory = NULL, 10 | file = "system_information.rds", 11 | output = NULL 12 | ) 13 | } 14 | \arguments{ 15 | \item{city}{A character string that can be matched to a gbfs feed. The recommended 16 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 17 | also attempt to match to the URL of an active .json feed or city name.} 18 | 19 | \item{directory}{Optional. Path to a folder (or folder to be 20 | created) where the feed will be saved.} 21 | 22 | \item{file}{Optional. The name of the file to be saved (if \code{output} 23 | is set to \code{"save"} or \code{"both"}), as a character string. 24 | Must end in \code{".rds"}.} 25 | 26 | \item{output}{Optional. The type of output method. If left as default, this 27 | argument is inferred from the \code{directory} argument. If 28 | \code{output = "save"}, the object will be saved as an .rds object at 29 | # the given path. If \code{output = "return"}, the output will be returned 30 | as a dataframe object. Setting \code{output = "both"} will do both.} 31 | } 32 | \value{ 33 | The output of this function depends on argument to \code{output} 34 | and \code{directory}. Either a saved .rds object generated from the current 35 | feed, a dataframe object, or both. 36 | } 37 | \description{ 38 | \code{get_system_information} grabs and tidies the system_information 39 | feed for a given city. Metadata for this dataset can be found at: 40 | \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 41 | } 42 | \examples{ 43 | # we can grab the free bike status feed for portland, 44 | # oregon's bikeshare program in several ways! first, supply the `city` 45 | # argument as a URL, and save to file by leaving output 46 | # set to it's default. usually, we would supply a character 47 | # string (like "pdx", maybe,) for the `directory` argument 48 | # instead of `tempdir`. 49 | \donttest{get_system_information(city = 50 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_information.json", 51 | directory = tempdir())} 52 | 53 | # or, instead, just supply the name of 54 | # the city as a string and return the output as a dataframe 55 | \donttest{get_system_information(city = "biketown_pdx", 56 | output = "return")} 57 | } 58 | \seealso{ 59 | [get_gbfs()] for a wrapper to call each of the \code{get_feed} 60 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 61 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 62 | are released by a given city. 63 | } 64 | -------------------------------------------------------------------------------- /docs/jquery.sticky-kit.min.js: -------------------------------------------------------------------------------- 1 | /* Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | */ 2 | /* 3 | Source: https://github.com/leafo/sticky-kit 4 | License: MIT 5 | */ 6 | (function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); 7 | if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, 8 | u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), 10 | a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", 11 | y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n max_length) { 29 | max_length = length; 30 | pos = i; 31 | } 32 | } 33 | 34 | // Add class to parent
  • , and enclosing
  • if in dropdown 35 | if (pos >= 0) { 36 | var menu_anchor = $(links[pos]); 37 | menu_anchor.parent().addClass("active"); 38 | menu_anchor.closest("li.dropdown").addClass("active"); 39 | } 40 | }); 41 | 42 | function paths(pathname) { 43 | var pieces = pathname.split("/"); 44 | pieces.shift(); // always starts with / 45 | 46 | var end = pieces[pieces.length - 1]; 47 | if (end === "index.html" || end === "") 48 | pieces.pop(); 49 | return(pieces); 50 | } 51 | 52 | // Returns -1 if not found 53 | function prefix_length(needle, haystack) { 54 | if (needle.length > haystack.length) 55 | return(-1); 56 | 57 | // Special case for length-0 haystack, since for loop won't run 58 | if (haystack.length === 0) { 59 | return(needle.length === 0 ? 0 : -1); 60 | } 61 | 62 | for (var i = 0; i < haystack.length; i++) { 63 | if (needle[i] != haystack[i]) 64 | return(i); 65 | } 66 | 67 | return(haystack.length); 68 | } 69 | 70 | /* Clipboard --------------------------*/ 71 | 72 | function changeTooltipMessage(element, msg) { 73 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 74 | element.setAttribute('data-original-title', msg); 75 | $(element).tooltip('show'); 76 | element.setAttribute('data-original-title', tooltipOriginalTitle); 77 | } 78 | 79 | if(ClipboardJS.isSupported()) { 80 | $(document).ready(function() { 81 | var copyButton = ""; 82 | 83 | $("div.sourceCode").addClass("hasCopyButton"); 84 | 85 | // Insert copy buttons: 86 | $(copyButton).prependTo(".hasCopyButton"); 87 | 88 | // Initialize tooltips: 89 | $('.btn-copy-ex').tooltip({container: 'body'}); 90 | 91 | // Initialize clipboard: 92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 93 | text: function(trigger) { 94 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); 95 | } 96 | }); 97 | 98 | clipboardBtnCopies.on('success', function(e) { 99 | changeTooltipMessage(e.trigger, 'Copied!'); 100 | e.clearSelection(); 101 | }); 102 | 103 | clipboardBtnCopies.on('error', function() { 104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 105 | }); 106 | }); 107 | } 108 | })(window.jQuery || window.$) 109 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # gbfs (development version) 2 | 3 | # gbfs 1.3.10 4 | 5 | - Transitioned from deprecated `testthat::with_mock()` to 6 | `testthat::with_mocked_bindings()` in package tests (#12). 7 | 8 | # gbfs 1.3.9 9 | 10 | - Fixed bug where non-english feeds couldn't be accessed using the top-level 11 | gbfs feed URL (#10). 12 | - Update URLs to reflect the transition of the gbfs source from the NABSA 13 | GitHub organization to MobilityData (#9). 14 | - Update URLs in examples and unit tests to reflect bikeshare systems 15 | adjusting operations. 16 | - Address CRAN check NOTEs related to help-file formatting. 17 | 18 | # gbfs 1.3.8 19 | 20 | - Changed default development branch name from `master` to `main`. 21 | - Fixed HTML5 NOTEs on R devel checks. 22 | 23 | # gbfs 1.3.7 24 | 25 | - Update URLs in examples and unit tests to reflect bikeshare systems 26 | adjusting operations due to COVID-19 27 | - Catch errors while fetching .json data and return a more informative 28 | message on timeout and HTTP 400 errors 29 | 30 | # gbfs 1.3.6 31 | 32 | - Introduce support for the new system ID key to improve stability of 33 | argument matching. This is now the recommended method for specifying the 34 | system of interest! 35 | - Switch from Travis to GitHub Actions for continuous integration 36 | - Update URLs in examples and unit tests to reflect bikeshare systems 37 | adjusting operations due to COVID-19 38 | 39 | # gbfs 1.3.5 40 | 41 | - Update URLs in examples and unit tests to reflect bikeshare systems 42 | adjusting operations due to COVID-19 43 | 44 | # gbfs 1.3.4 45 | 46 | - Update URLs in examples and unit tests to reflect bikeshare systems 47 | adjusting operations due to COVID-19 48 | 49 | # gbfs 1.3.3 50 | 51 | - Catch errors while fetching .json data and return a more informative 52 | message on timeout and HTTP 400 errors 53 | - Update URLs in examples and unit tests to reflect bikeshare systems 54 | adjusting operations due to COVID-19 55 | 56 | # gbfs 1.3.2 57 | 58 | - Several fixes for bugs arising from NABSA’s update to the gbfs spec 59 | (gbfs 1.1-RC) 60 | - Improved error message for multiple cities matching the supplied 61 | string 62 | - Accomodate valid json URLs with no .json file extension 63 | 64 | # gbfs 1.3.1 65 | 66 | - All package functions requiring internet access now immediately 67 | check the internet connection upon being called, raising a message 68 | and returning an empty list if an internet connection is not 69 | available. 70 | 71 | # gbfs 1.3.0 72 | 73 | - The main wrapper function, `get_gbfs`, can now return its output as 74 | a named list, where each entry is a GBFS dataframe. 75 | - Results will now be returned by default (note that these changes are 76 | non-breaking–the new default settings would error out in previous 77 | versions, and previously valid arguments still return results in the 78 | same way.) 79 | - Added a `get_which_gbfs_feeds` function, which supplies a table 80 | giving all of the available feeds for a city\! 81 | - Extended flexibility of the `city` argument–in addition to a string 82 | that matches the city name, the package can now find the appropriate 83 | feed given any subfeed of a bikeshare system. 84 | - Extend argument checking. 85 | - Make error messages more informative. 86 | - Documentation improvements. 87 | - Code refactoring. 88 | 89 | # gbfs 1.2.0 90 | 91 | - Addressed errors arising from new columns types introduced in the 92 | new NABSA GBFS guidelines. 93 | - Added the `output` argument, allowing users to either save the 94 | outputs as `.Rds` files or return them as list or dataframe objects. 95 | As a result, the directory argument is no longer required if `output 96 | = "return"` 97 | - Minor bug fixes and documentation improvements 98 | 99 | # gbfs 1.1.0 100 | 101 | - Thanks to Mark Padgham (@mpadge), we’ve introduced a new function 102 | `get_gbfs_cities` that lists all of the cities currently releasing 103 | feeds\! This function will help inform users who do not have a 104 | specific city already in mind. 105 | - Add functionality for new column types introduced in the new NABSA 106 | GBFS guidelines. 107 | - Minor bug fixes (unused imports, vignette errors, etc.) 108 | -------------------------------------------------------------------------------- /tests/testthat/test-utils.R: -------------------------------------------------------------------------------- 1 | context("utils") 2 | 3 | 4 | test_that("argument checking works", { 5 | 6 | skip_if_offline(host = "r-project.org") 7 | 8 | # bad argument to `output` 9 | expect_error(check_return_arguments(directory_ = NULL, 10 | file_ = "gbfs.Rds", 11 | output_ = "bad"), 12 | "Please supply one of") 13 | 14 | # user wants to save, but not dir provided 15 | expect_error(check_return_arguments(directory_ = NULL, 16 | file_ = "gbfs.Rds", 17 | output_ = "save"), 18 | "You have not supplied a folder") 19 | 20 | # bad url 21 | expect_error(city_to_url(city_ = "beep_bop_station_information.json", 22 | feed_ = "station_information"), 23 | "but the webpage doesn") 24 | 25 | # lower-level url for top-level feed with non-json file extension 26 | hon <- "https://hon.publicbikesystem.net/ube/gbfs/v1/en/system_pricing_plans" 27 | expect_error(city_to_url(city_ = hon, 28 | feed_ = "gbfs"), 29 | "No supported cities") 30 | 31 | # bad url for top-level 32 | expect_error(city_to_url(city_ = "beep_bop_gbfs.json", 33 | feed_ = "gbfs"), 34 | "The supplied argument for") 35 | 36 | # no matching cities 37 | expect_error(city_to_url(city_ = "wldojglkwefpoimf", 38 | feed_ = "gbfs"), 39 | "No supported cities matched") 40 | 41 | # one matching city, non top-level feed 42 | # no matching cities 43 | expect_equal(city_to_url(city_ = "biketown_pdx", 44 | feed_ = "station_information"), 45 | "https://gbfs.lyft.com/gbfs/2.3/pdx/en/station_information.json") 46 | 47 | # several matching cities 48 | expect_error(city_to_url(city_ = "los angeles", 49 | feed_ = "gbfs"), 50 | "Several cities matched") 51 | 52 | # feeds argument is valid 53 | expect_error(process_feeds_argument("bop"), 54 | "argument is \"bop\", but it needs") 55 | 56 | }) 57 | 58 | test_that("find feed from top level works", { 59 | 60 | skip_if_offline(host = "r-project.org") 61 | 62 | expect_equal(find_feed_from_top_level( 63 | "https://gbfs.lyft.com/gbfs/1.1/pdx/gbfs.json", 64 | "station_information"), 65 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/station_information.json") 66 | 67 | expect_error(find_feed_from_top_level( 68 | "https://gbfs.lyft.com/gbfs/1.1/pdx/gbfs.json", 69 | "weird_feed"), 70 | "webpage for the weird_feed .json") 71 | 72 | expect_equal(find_feed_from_top_level( 73 | "https://gbfs.lyft.com/gbfs/1.1/pdx/gbfs.json", 74 | "gbfs"), 75 | "https://gbfs.lyft.com/gbfs/1.1/pdx/gbfs.json") 76 | 77 | }) 78 | 79 | test_that("determine output type works", { 80 | expect_equal(determine_output_types("biketown_pdx", 81 | "both"), 82 | c(TRUE, TRUE)) 83 | 84 | expect_equal(determine_output_types("biketown_pdx", 85 | NULL), 86 | c(TRUE, FALSE)) 87 | 88 | expect_equal(determine_output_types(NULL, 89 | "return"), 90 | c(FALSE, TRUE)) 91 | 92 | expect_message(determine_output_types("biketown_pdx", 93 | "return"), 94 | "and only returning the output") 95 | 96 | expect_error(determine_output_types("biketown_pdx", 97 | "bad"), 98 | "argument doesn't match any of") 99 | 100 | }) 101 | 102 | test_that("no internet connection message works", { 103 | # "pretend" that the internet connection doesn't work 104 | with_mocked_bindings(connected_to_internet = function() FALSE, { 105 | # try it on all of the different functions that test internet connection 106 | expect_message(get_gbfs("biketown_pdx")) 107 | 108 | expect_message(get_gbfs_dataset_( 109 | "biketown_pdx", 110 | NULL, 111 | NULL, 112 | "return", 113 | "station_information" 114 | )) 115 | 116 | expect_message(get_which_gbfs_feeds("biketown_pdx")) 117 | 118 | expect_message(get_gbfs_cities()) 119 | 120 | expect_equal(get_gbfs_cities(), list()) 121 | }) 122 | }) 123 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Articles • gbfs 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 41 | 42 | 43 | 44 | 45 | 46 |
    47 |
    48 | 99 | 100 | 101 |
    102 | 103 |
    104 |
    105 | 108 | 109 |
    110 |

    All vignettes

    111 |

    112 | 113 | 116 |
    117 |
    118 |
    119 | 120 |
    121 | 124 | 125 |
    126 |

    Site built with pkgdown.

    127 |
    128 | 129 |
    130 |
    131 | 132 | 133 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Page not found (404) • gbfs 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | 28 | 29 |
    30 |
    67 | 68 | 69 | 70 | 71 |
    72 |
    73 | 76 | 77 | Content not found. Please use links in the navbar. 78 | 79 |
    80 | 81 | 85 | 86 |
    87 | 88 | 89 | 90 |
    94 | 95 |
    96 |

    97 |

    Site built with pkgdown 2.1.0.

    98 |
    99 | 100 |
    101 |
    102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | Authors and Citation • gbfs 6 | 7 | 8 |
    9 |
    40 | 41 | 42 | 43 |
    44 |
    45 |
    46 | 49 | 50 | 51 |
    • 52 |

      Simon P. Couch. Author, maintainer. 53 |

      54 |
    • 55 |
    • 56 |

      Kaelyn Rosenberg. Author. 57 |

      58 |
    • 59 |
    • 60 |

      Mark Padgham. Contributor. 61 |

      62 |
    • 63 |
    64 |
    65 |
    66 |

    Citation

    67 | Source: DESCRIPTION 68 |
    69 |
    70 | 71 | 72 |

    Couch S, Rosenberg K (2025). 73 | gbfs: Interface with Live Bikeshare Data. 74 | R package version 1.3.10, https://github.com/simonpcouch/gbfs. 75 |

    76 |
    @Manual{,
     77 |   title = {gbfs: Interface with Live Bikeshare Data},
     78 |   author = {Simon P. Couch and Kaelyn Rosenberg},
     79 |   year = {2025},
     80 |   note = {R package version 1.3.10},
     81 |   url = {https://github.com/simonpcouch/gbfs},
     82 | }
    83 | 84 |
    85 | 86 |
    87 | 88 | 89 | 90 |
    93 | 94 |
    95 |

    Site built with pkgdown 2.1.0.

    96 |
    97 | 98 |
    99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /docs/reference/get_gbfs_cities.html: -------------------------------------------------------------------------------- 1 | 2 | Get table of all cities releasing GBFS feeds — get_gbfs_cities • gbfs 6 | 7 | 8 |
    9 |
    40 | 41 | 42 | 43 |
    44 |
    45 | 50 | 51 |
    52 |

    Get table of all cities releasing GBFS feeds

    53 |
    54 | 55 |
    56 |
    get_gbfs_cities()
    57 |
    58 | 59 |
    60 |

    Source

    61 |

    North American Bikeshare Association, General Bikeshare Feed Specification 62 | https://raw.githubusercontent.com/MobilityData/gbfs/master/systems.csv

    63 |
    64 |
    65 |

    Value

    66 |

    A data.frame of all cities issuing GBFS feeds. The `Auto-Discovery URL` 67 | column supplies the relevant .json feeds, while the entries in the `URL` column 68 | take the user to the public-facing webpage of the programs.

    69 |
    70 | 71 |
    72 | 75 |
    76 | 77 | 78 |
    81 | 82 |
    83 |

    Site built with pkgdown 2.1.0.

    84 |
    85 | 86 |
    87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.html: -------------------------------------------------------------------------------- 1 | 2 | Contributor Code of Conduct • gbfs 6 | 7 | 8 |
    9 |
    40 | 41 | 42 | 43 |
    44 |
    45 | 48 | 49 |
    50 | 51 |

    As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.

    52 |

    We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.

    53 |

    Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.

    54 |

    Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, issues, and other contributions that are not aligned to this Code of Conduct.

    55 |

    Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.

    56 |

    This Code of Conduct is adapted from the Contributor Covenant, version 1.0.0, available at https://www.contributor-covenant.org/version/1/0/0/code-of-conduct.html

    57 |
    58 | 59 |
    60 | 61 | 64 | 65 |
    66 | 67 | 68 | 69 |
    72 | 73 |
    74 |

    Site built with pkgdown 2.1.0.

    75 |
    76 | 77 |
    78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /R/get_gbfs.R: -------------------------------------------------------------------------------- 1 | #' Get table of all cities releasing GBFS feeds 2 | #' 3 | #' @return A \code{data.frame} of all cities issuing GBFS feeds. The `Auto-Discovery URL` 4 | #' column supplies the relevant .json feeds, while the entries in the `URL` column 5 | #' take the user to the public-facing webpage of the programs. 6 | #' @source North American Bikeshare Association, General Bikeshare Feed Specification 7 | #' \url{https://raw.githubusercontent.com/MobilityData/gbfs/master/systems.csv} 8 | #' @export 9 | get_gbfs_cities <- function() { 10 | 11 | # test internet connection 12 | if (!connected_to_internet()) { 13 | return(message_no_internet()) 14 | } 15 | 16 | # specify column types 17 | systems_cols <- readr::cols( 18 | `Country Code` = readr::col_character(), 19 | "Name" = readr::col_character(), 20 | "Location" = readr::col_character(), 21 | `System ID` = readr::col_character(), 22 | `URL` = readr::col_character(), 23 | `Auto-Discovery URL` = readr::col_character() 24 | ) 25 | 26 | # grab the data 27 | readr::read_csv("https://raw.githubusercontent.com/MobilityData/gbfs/master/systems.csv", 28 | col_types = systems_cols) 29 | } 30 | 31 | 32 | 33 | #' Get dataframe of bikeshare feeds released by a city 34 | #' 35 | #' @description Of the different types of feeds supplied by the gbfs, 36 | #' some are required, some are conditionally required, and some are 37 | #' optional. This function grabs a list of each of the feeds supplied 38 | #' by a given city, as well as the URLs to access them. 39 | #' 40 | #' @param city A character string that can be matched to a gbfs feed. The recommended 41 | #' argument is a system ID supplied in the output of [get_gbfs_cities()], but will 42 | #' also attempt to match to the URL of an active .json feed or city name. 43 | #' 44 | #' @return A \code{data.frame} containing the feeds supplied by 45 | #' a city. . The `feed` column supplies the name of the relevant .json feeds, 46 | #' while the entries in the `URL` column supply the feeds themselves. 47 | #' 48 | #' @source North American Bikeshare Association, General Bikeshare Feed 49 | #' Specification \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 50 | #' 51 | #' @examples 52 | #' # grab all of the feeds released by portland 53 | #' \donttest{get_which_gbfs_feeds(city = "biketown_pdx")} 54 | #' 55 | #' @export 56 | get_which_gbfs_feeds <- function(city) { 57 | 58 | # test internet connection 59 | if (!connected_to_internet()) { 60 | return(message_no_internet()) 61 | } 62 | 63 | # convert the city argument to a URL 64 | url <- city_to_url(city, "gbfs") 65 | 66 | # grab the relevant data 67 | gbfs <- tryCatch(jsonlite::fromJSON(txt = url), 68 | error = report_connection_issue) 69 | 70 | # pull out the dataset 71 | gbfs_feeds <- gbfs[["data"]][[1]][[1]] 72 | 73 | # ...and return it! 74 | return(gbfs_feeds) 75 | 76 | } 77 | 78 | #' Grab bikeshare data 79 | #' 80 | #' \code{get_gbfs} grabs bikeshare data supplied in the General Bikeshare 81 | #' Feed Specification format for a given city. By default, the function returns 82 | #' the results as a named list of dataframes, but to make accumulation of 83 | #' datasets over time straightforward, the user can also save the results 84 | #' as .Rds files that will be automatically row-binded. 85 | #' Metadata for each dataset can be found at: 86 | #' \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 87 | #' 88 | #' @param city A character string that can be matched to a city or a url to an 89 | #' active gbfs.json feed. See \code{get_gbfs_cities} for a current list of available cities. 90 | #' @param feeds Optional. A character string specifying which feeds should be saved. 91 | #' Options are \code{"all"}, \code{"static"}, and \code{"dynamic"}. 92 | #' @param directory Optional. Path to a folder (or folder to be created) where 93 | #' the feed will will be saved. 94 | #' @param output Optional. The type of output method. By default, output method 95 | #' will be inferred from the \code{directory} argument. If \code{output = "save"}, 96 | #' the dataframes will be saved as .rds objects in the given folder. If 97 | #' \code{output = "return"}, the results will be returned as a named list of 98 | #' dataframes. Setting \code{output = "both"} will do both. If both are left 99 | #' as NULL, the result will be returned and not saved to file. 100 | #' @return The output of this function depends on the arguments supplied to 101 | #' \code{output} and \code{directory}. Either a folder of .rds dataframes saved 102 | #' at the given path, a returned named list of dataframes, or both. 103 | #' The function will raise an error if the \code{directory} and \code{output} 104 | #' arguments seem to conflict. 105 | #' @examples 106 | #' # grab all of the feeds released by portland's 107 | #' # bikeshare program and return them as a 108 | #' # named list of dataframes 109 | #' \donttest{get_gbfs(city = "biketown_pdx")} 110 | #' 111 | #' # if, rather than returning the data, we wanted to save it: 112 | #' \donttest{get_gbfs(city = "biketown_pdx", directory = tempdir())} 113 | #' 114 | #' # note that, usually, we'd supply a character string 115 | #' # (like "pdx", maybe,) to the directory argument 116 | #' # instead of `tempdir()`. 117 | #' 118 | #' # if we're having trouble specifying the correct feed, 119 | #' # we can also supply the actual URL to the feed 120 | #' \donttest{get_gbfs(city = "https://gbfs.lyft.com/gbfs/1.1/pdx/gbfs.json")} 121 | #' 122 | #' # the examples above grab every feed that portland releases. 123 | #' # if, instead, we just wanted the dynamic feeds 124 | #' \donttest{get_gbfs(city = "biketown_pdx", feeds = "dynamic")} 125 | #' @export 126 | get_gbfs <- function(city, feeds = "all", directory = NULL, output = NULL) { 127 | 128 | # test internet connection 129 | if (!connected_to_internet()) { 130 | return(message_no_internet()) 131 | } 132 | 133 | # check the "feeds" argument 134 | feeds <- process_feeds_argument(feeds) 135 | 136 | # figure out how to output the resulting object 137 | output_types <- determine_output_types(directory, output) 138 | 139 | # check that, if the user said to save the file, they also 140 | # supplied a directory 141 | if (output_types[1] & is.null(directory)) { 142 | stop(sprintf(c("The argument to output suggests that the resulting", 143 | " data should be saved, but a directory to save the", 144 | " outputs in hasn't been supplied. Please supply", 145 | " an argument to directory or leave the output argument", 146 | " as default."))) 147 | } 148 | 149 | # convert the city argument to a top-level gbfs url 150 | url <- city_to_url(city, "gbfs") 151 | 152 | # figure out which feeds are available 153 | available_feeds <- get_which_gbfs_feeds(city = url) 154 | 155 | # ...and then figure out which of them to grab 156 | relevant_feeds <- available_feeds %>% 157 | dplyr::left_join(all_feeds, by = "name") %>% 158 | dplyr::filter(type %in% feeds) %>% 159 | dplyr::select(name) %>% 160 | dplyr::pull() 161 | 162 | # grab all of the relevant feeds! note that this will save each 163 | # of the datasets in the directory folder if directory is 164 | # something other than NULL 165 | data <- suppressMessages( 166 | purrr::map2(paste0(relevant_feeds, ".Rds"), 167 | relevant_feeds, 168 | get_gbfs_dataset_, 169 | city = url, 170 | directory = directory, 171 | output = NULL) 172 | ) 173 | 174 | # name each of the elements so that they're more easily accessible 175 | names(data) <- relevant_feeds 176 | 177 | # output the datasets as desired :-) 178 | if (output_types[2]) { 179 | return(data) 180 | } 181 | } 182 | 183 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | ```{r, echo = FALSE, message = FALSE} 6 | knitr::opts_chunk$set( 7 | collapse = TRUE, 8 | comment = "#>", 9 | fig.path = "figures/" 10 | ) 11 | devtools::load_all() 12 | ``` 13 | 14 | # General Bikeshare Feed Specification A hexagonal logo with a black border and white background showing a green bicycle icon. 15 | 16 | [![CRAN status](https://www.r-pkg.org/badges/version/gbfs)](https://cran.r-project.org/package=gbfs) 17 | [![R build status](https://github.com/simonpcouch/gbfs/workflows/R-CMD-check/badge.svg)](https://github.com/simonpcouch/gbfs/actions) 18 | [![CRAN Downloads](https://cranlogs.r-pkg.org/badges/grand-total/gbfs)](https://cran.r-project.org/package=gbfs) 19 | 20 | The `gbfs` package supplies a set of functions to interface with General 21 | Bikeshare Feed Specification .json feeds in R, allowing users to save 22 | and accumulate tidy .rds datasets for specified cities/bikeshare programs. 23 | The North American Bikeshare Association's [gbfs](https://github.com/MobilityData/gbfs) 24 | is a standardized data release format for live information on the status 25 | of bikeshare programs, as well as metadata, including counts of bikes at 26 | stations, ridership costs, and geographic locations of stations and 27 | parked bikes. 28 | 29 | __Features__ 30 | 31 | * Get bikeshare data by specifying city name or supplying url of feed 32 | * All feeds for a city can be saved with a single function 33 | * New information from dynamic feeds can be appended to existing datasets 34 | 35 | ## Installation 36 | 37 | We're on CRAN! Install the latest release with: 38 | 39 | ```{r cran-installation, eval = FALSE} 40 | install.packages("gbfs") 41 | library(gbfs) 42 | ``` 43 | 44 | You can install the developmental version of `gbfs` from GitHub with: 45 | 46 | ```{r gh-installation, eval = FALSE} 47 | # install.packages("devtools") 48 | devtools::install_github("simonpcouch/gbfs") 49 | ``` 50 | 51 | ## Background 52 | 53 | The `gbfs` is a standardized data feed describing the current status of a 54 | bikeshare program. 55 | 56 | Although all of the data is live, only a few of the datasets change often: 57 | 58 | * `station_status`: Supplies the number of available bikes and 59 | docks at each station as well as station availability 60 | * `free_bike_status`: Gives the coordinates and metadata on available 61 | bikes that are parked, but not at a station. 62 | 63 | In this package, these two datasets are considered "dynamic", and can be 64 | specified as desired datasets by setting `feeds = "dynamic"` in the 65 | main wrapper function in the package, `get_gbfs`. 66 | 67 | Much of the data supplied in this specification can be considered static. If you 68 | want to grab all of these for a given city, set `feeds = "static"` when calling 69 | `get_gbfs`. Static feeds include: 70 | 71 | * `system_information`: Basic metadata about the bikeshare program 72 | * `station_information`: Information on the capacity and coordinates of stations 73 | * Several optional feeds: `system_hours`, `system_calendar`, `system_regions`, 74 | `system_pricing_plans`, and `system_alerts` 75 | 76 | Each of the above feeds can be queried with the `get_suffix` function, where 77 | `suffix` is replaced with the name of the relevant feed. 78 | 79 | For more details on the official `gbfs` spec, see 80 | [this document](https://github.com/MobilityData/gbfs/blob/master/gbfs.md). 81 | 82 | ## Example 83 | 84 | In this example, we'll grab data from Portland, Oregon's Biketown bikeshare 85 | program and visualize some of the different datasets. 86 | 87 | ```{r, warning = FALSE, message = FALSE} 88 | # load necessary packages 89 | library(tidyverse) 90 | ``` 91 | 92 | 93 | First, we'll grab some information on the stations. 94 | 95 | ```{r} 96 | # grab portland station information and return it as a dataframe 97 | pdx_station_info <- 98 | get_station_information("https://gbfs.lyft.com/gbfs/1.1/pdx/gbfs.json") 99 | 100 | # check it out! 101 | glimpse(pdx_station_info) 102 | ``` 103 | 104 | ...as well as the number of bikes at each station. 105 | 106 | ```{r} 107 | # grab current capacity at each station and return it as a dataframe 108 | pdx_station_status <- 109 | get_station_status("https://gbfs.lyft.com/gbfs/1.1/pdx/gbfs.json") 110 | 111 | # check it out! 112 | glimpse(pdx_station_status) 113 | ``` 114 | 115 | Just like that, we have two tidy datasets containing information about 116 | Portland's bikeshare program. 117 | 118 | Joining these datasets, we can get the capacity at each station, along with each 119 | station's metadata. 120 | 121 | ```{r} 122 | # full join these two datasets on station_id and select a few columns 123 | pdx_stations <- full_join(pdx_station_info, 124 | pdx_station_status, 125 | by = "station_id") %>% 126 | # just select columns we're interested in visualizing 127 | select(id = station_id, 128 | lon, 129 | lat, 130 | num_bikes_available, 131 | num_docks_available) %>% 132 | mutate(type = "docked") 133 | ``` 134 | 135 | Finally, before we plot, lets grab the locations of the bikes parked in 136 | Portland that are not docked at a station, 137 | 138 | ```{r} 139 | # grab data on free bike status and save it as a dataframe 140 | pdx_free_bikes <- 141 | get_free_bike_status("https://gbfs.lyft.com/gbfs/1.1/pdx/gbfs.json", 142 | output = "return") %>% 143 | # just select columns we're interested in visualizing 144 | select(id = bike_id, lon, lat) %>% 145 | # make columns analogous to station_status for row binding 146 | mutate(num_bikes_available = 1, 147 | num_docks_available = NA, 148 | type = "free") 149 | ``` 150 | 151 | ...and bind these dataframes together! 152 | 153 | ```{r} 154 | # row bind stationed and free bike info 155 | pdx_full <- bind_rows(pdx_stations, pdx_free_bikes) 156 | ``` 157 | 158 | Now, plotting, 159 | 160 | ```{r plot} 161 | # filter out stations with 0 available bikes 162 | pdx_plot <- pdx_full %>% 163 | filter(num_bikes_available > 0) %>% 164 | # plot the geospatial distribution of bike counts 165 | ggplot() + 166 | aes(x = lon, 167 | y = lat, 168 | size = num_bikes_available, 169 | col = type) + 170 | geom_point() + 171 | # make aesthetics slightly more cozy 172 | theme_minimal() + 173 | scale_color_brewer(type = "qual") 174 | ``` 175 | 176 | ```{r print-plot, eval = FALSE} 177 | pdx_plot 178 | ``` 179 | 180 | 181 | 182 | Folks who have spent a significant amount of time in Portland might be able to 183 | pick out the Willamette River running Northwest/Southeast through the city. 184 | With a few lines of `gbfs`, `dplyr`, and `ggplot2`, we can put together a 185 | meaningful visualization to help us better understand how bikeshare bikes 186 | are distributed throughout Portland. 187 | 188 | Some other features worth playing around with in `gbfs` that weren't touched 189 | on in this example: 190 | 191 | * The main wrapper function in the package, `get_gbfs`, will grab every 192 | dataset for a given city. (We call the functions to grab individual datasets 193 | above for clarity.) 194 | * In the above lines, we output the datasets as returned dataframes. If you'd 195 | rather save the output to your local files, check out the `directory` and 196 | `return` arguments. 197 | * When the `output` argument is left as default in `get_free_bike_status` and 198 | `get_station_status` (the functions for the `dynamic` dataframes,) 199 | and a dataframe already exists at the given path, `gbfs` will row bind the 200 | dataframes, allowing for the capability to accumulate large datasets over time. 201 | * If you're not sure if your city supplies `gbfs` feeds, you might find the 202 | `get_gbfs_cities` and `get_which_gbfs_feeds` functions useful. 203 | 204 | ## Contributing 205 | 206 | Please note that the `gbfs` R package is released with a [Contributor Code of Conduct](CONTRIBUTING.md). By contributing to this project, you agree to abide by its terms. 207 | -------------------------------------------------------------------------------- /R/get_static_feeds.R: -------------------------------------------------------------------------------- 1 | #' Grab the station_information feed. 2 | #' 3 | #' \code{get_station_information} grabs and tidies the station_information feed for a given city. 4 | #' This dataset contains locations, capacity, and other information about bikeshare stations. 5 | #' Metadata for this dataset can be found at: 6 | #' \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 7 | #' 8 | #' @param city A character string that can be matched to a gbfs feed. The recommended 9 | #' argument is a system ID supplied in the output of [get_gbfs_cities()], but will 10 | #' also attempt to match to the URL of an active .json feed or city name. 11 | #' @param directory Optional. Path to a folder (or folder to be 12 | #' created) where the feed will be saved. 13 | #' @param file Optional. The name of the file to be saved (if \code{output} 14 | #' is set to \code{"save"} or \code{"both"}), as a character string. 15 | #' Must end in \code{".rds"}. 16 | #' @param output Optional. The type of output method. If left as default, this 17 | #' argument is inferred from the \code{directory} argument. If 18 | #' \code{output = "save"}, the object will be saved as an .rds object at 19 | #' # the given path. If \code{output = "return"}, the output will be returned 20 | #' as a dataframe object. Setting \code{output = "both"} will do both. 21 | #' 22 | #' @return The output of this function depends on argument to \code{output} 23 | #' and \code{directory}. Either a saved .rds object generated from the current 24 | #' feed, a dataframe object, or both. 25 | #' 26 | #' @seealso [get_gbfs()] for a wrapper to call each of the \code{get_feed} 27 | #' functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 28 | #' functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 29 | #' are released by a given city. 30 | #' 31 | #' @examples 32 | #' # grab the free bike status feed for portland, oreoon's bikeshare program 33 | #' \donttest{get_station_information(city = 34 | #' "https://gbfs.lyft.com/gbfs/1.1/pdx/en/station_information.json", 35 | #' output = "return")} 36 | #' 37 | #' @export 38 | get_station_information <- function(city, directory = NULL, file = "station_information.rds", output = NULL) { 39 | 40 | get_gbfs_dataset_(city, directory, file, output, feed = "station_information") 41 | 42 | } 43 | 44 | #' Grab the system_alerts feed. 45 | #' 46 | #' \code{get_system_alerts} grabs and tidies the system_alerts feed for a given city. 47 | #' This feed informs users about changes to normal operation. Metadata for this 48 | #' dataset can be found at: \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 49 | #' 50 | #' @inherit get_station_information params return seealso 51 | #' 52 | #' @examples 53 | #' # grab the system alerts feed for portland, oregon 54 | #' \donttest{get_system_alerts(city = 55 | #' "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_alerts.json", 56 | #' output = "return")} 57 | #' 58 | #' @export 59 | 60 | get_system_alerts <- function (city, directory = NULL, file = "system_alerts.rds", output = NULL) { 61 | 62 | get_gbfs_dataset_(city, directory, file, output, feed = "system_alerts") 63 | 64 | } 65 | 66 | #' Grab the system_calendar feed. 67 | #' 68 | #' \code{get_system_calendar} grabs and tidies the system_calendar feed 69 | #' for a given city. Metadata for this dataset can be found at: 70 | #' \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 71 | #' 72 | #' @inherit get_station_information params return seealso 73 | #' 74 | #' @examples 75 | #' # grab the system calendar feed for portland, oregon 76 | #' \donttest{get_system_calendar(city = 77 | #' "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_calendar.json", 78 | #' output = "return")} 79 | #' 80 | #' 81 | #' @export 82 | 83 | get_system_calendar <- function (city, directory = NULL, file = "system_calendar.rds", output = NULL) { 84 | 85 | get_gbfs_dataset_(city, directory, file, output, feed = "system_calendar") 86 | 87 | } 88 | 89 | #' Grab the system_hours feed. 90 | #' 91 | #' \code{get_system_hours} grabs and tidies the system_hours 92 | #' feed for a given city. Metadata for this 93 | #' dataset can be found at: 94 | #' \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 95 | #' 96 | #' @inherit get_station_information params return seealso 97 | #' 98 | #' @examples 99 | #' # grab the system hours feed for portland, oregon 100 | #' \donttest{get_system_hours(city = 101 | #' "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_hours.json", 102 | #' output = "return")} 103 | #' 104 | #' @export 105 | 106 | get_system_hours <- function (city, directory = NULL, file = "system_hours.rds", output = NULL) { 107 | 108 | get_gbfs_dataset_(city, directory, file, output, feed = "system_hours") 109 | 110 | } 111 | 112 | #' Grab the system_information feed. 113 | #' 114 | #' \code{get_system_information} grabs and tidies the system_information 115 | #' feed for a given city. Metadata for this dataset can be found at: 116 | #' \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 117 | #' 118 | #' @inherit get_station_information params return seealso 119 | #' 120 | #' @examples 121 | #' # we can grab the free bike status feed for portland, 122 | #' # oregon's bikeshare program in several ways! first, supply the `city` 123 | #' # argument as a URL, and save to file by leaving output 124 | #' # set to it's default. usually, we would supply a character 125 | #' # string (like "pdx", maybe,) for the `directory` argument 126 | #' # instead of `tempdir`. 127 | #' \donttest{get_system_information(city = 128 | #' "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_information.json", 129 | #' directory = tempdir())} 130 | #' 131 | #' # or, instead, just supply the name of 132 | #' # the city as a string and return the output as a dataframe 133 | #'\donttest{get_system_information(city = "biketown_pdx", 134 | #' output = "return")} 135 | #' @export 136 | 137 | get_system_information <- function(city, directory = NULL, file = "system_information.rds", output = NULL){ 138 | 139 | get_gbfs_dataset_(city, directory, file, output, feed = "system_information") 140 | 141 | } 142 | 143 | #' Grab the system_pricing_plans feed. 144 | #' 145 | #' \code{get_system_pricing_plans} grabs and tidies the system_pricing_plans 146 | #' feed for a given city. Metadata for this dataset can be found at: 147 | #' \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 148 | #' 149 | #' @inherit get_station_information params return seealso 150 | #' 151 | #' @export 152 | 153 | get_system_pricing_plans <- function(city, directory = NULL, file = "system_pricing_plans.rds", output = NULL) { 154 | 155 | get_gbfs_dataset_(city, directory, file, output, feed = "system_pricing_plans") 156 | 157 | } 158 | 159 | #' Grab the system_regions feed. 160 | #' 161 | #' \code{get_system_regions} grabs and tidies the system_regions feed for 162 | #' a given city. Metadata for this dataset can be found at: 163 | #' \url{https://github.com/MobilityData/gbfs/blob/master/gbfs.md} 164 | #' 165 | #' @inherit get_station_information params return seealso 166 | #' 167 | #' @examples 168 | #' # we can grab the system regions feed for portland, 169 | #' # oregon in one of several ways! first, supply the `city` 170 | #' # argument as a URL, and save to file by leaving output 171 | #' # set to it's default. usually, we would supply a character 172 | #' # string (like "pdx", maybe,) for the `directory` argument 173 | #' # instead of `tempdir`. 174 | #' \donttest{get_system_regions(city = 175 | #' "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_regions.json", 176 | #' directory = tempdir())} 177 | #' 178 | #' # or, instead, just supply the name of 179 | #' # the city as a string and return the output 180 | #' # as a dataframe 181 | #'\donttest{get_system_regions(city = "biketown_pdx", 182 | #' output = "return")} 183 | #' @export 184 | get_system_regions <- function(city, directory = NULL, file = "system_regions.rds", output = NULL) { 185 | 186 | get_gbfs_dataset_(city, directory, file, output, feed = "system_regions") 187 | 188 | } 189 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | Package index • gbfs 6 | 7 | 8 |
    9 |
    40 | 41 | 42 | 43 |
    44 |
    45 | 48 | 49 | 53 | 56 | 57 | 60 | 61 | 64 | 65 | 68 | 69 | 72 | 73 | 76 | 77 | 80 | 81 | 84 | 85 | 88 | 89 | 92 | 93 | 96 | 97 | 100 | 101 | 104 | 105 |
    50 |

    All functions

    51 |

    52 |
    54 |

    gbfs-package gbfs

    55 |

    Package: gbfs

    58 |

    get_free_bike_status()

    59 |

    Grab the free_bike_status feed.

    62 |

    get_gbfs()

    63 |

    Grab bikeshare data

    66 |

    get_gbfs_cities()

    67 |

    Get table of all cities releasing GBFS feeds

    70 |

    get_station_information()

    71 |

    Grab the station_information feed.

    74 |

    get_station_status()

    75 |

    Grab the station_status feed.

    78 |

    get_system_alerts()

    79 |

    Grab the system_alerts feed.

    82 |

    get_system_calendar()

    83 |

    Grab the system_calendar feed.

    86 |

    get_system_hours()

    87 |

    Grab the system_hours feed.

    90 |

    get_system_information()

    91 |

    Grab the system_information feed.

    94 |

    get_system_pricing_plans()

    95 |

    Grab the system_pricing_plans feed.

    98 |

    get_system_regions()

    99 |

    Grab the system_regions feed.

    102 |

    get_which_gbfs_feeds()

    103 |

    Get dataframe of bikeshare feeds released by a city

    106 | 107 | 110 |
    111 | 112 | 113 |
    116 | 117 |
    118 |

    Site built with pkgdown 2.1.0.

    119 |
    120 | 121 |
    122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body { 21 | position: relative; 22 | } 23 | 24 | body > .container { 25 | display: flex; 26 | height: 100%; 27 | flex-direction: column; 28 | } 29 | 30 | body > .container .row { 31 | flex: 1 0 auto; 32 | } 33 | 34 | footer { 35 | margin-top: 45px; 36 | padding: 35px 0 36px; 37 | border-top: 1px solid #e5e5e5; 38 | color: #666; 39 | display: flex; 40 | flex-shrink: 0; 41 | } 42 | footer p { 43 | margin-bottom: 0; 44 | } 45 | footer div { 46 | flex: 1; 47 | } 48 | footer .pkgdown { 49 | text-align: right; 50 | } 51 | footer p { 52 | margin-bottom: 0; 53 | } 54 | 55 | img.icon { 56 | float: right; 57 | } 58 | 59 | /* Ensure in-page images don't run outside their container */ 60 | .contents img { 61 | max-width: 100%; 62 | height: auto; 63 | } 64 | 65 | /* Fix bug in bootstrap (only seen in firefox) */ 66 | summary { 67 | display: list-item; 68 | } 69 | 70 | /* Typographic tweaking ---------------------------------*/ 71 | 72 | .contents .page-header { 73 | margin-top: calc(-60px + 1em); 74 | } 75 | 76 | dd { 77 | margin-left: 3em; 78 | } 79 | 80 | /* Section anchors ---------------------------------*/ 81 | 82 | a.anchor { 83 | display: none; 84 | margin-left: 5px; 85 | width: 20px; 86 | height: 20px; 87 | 88 | background-image: url(./link.svg); 89 | background-repeat: no-repeat; 90 | background-size: 20px 20px; 91 | background-position: center center; 92 | } 93 | 94 | h1:hover .anchor, 95 | h2:hover .anchor, 96 | h3:hover .anchor, 97 | h4:hover .anchor, 98 | h5:hover .anchor, 99 | h6:hover .anchor { 100 | display: inline-block; 101 | } 102 | 103 | /* Fixes for fixed navbar --------------------------*/ 104 | 105 | .contents h1, .contents h2, .contents h3, .contents h4 { 106 | padding-top: 60px; 107 | margin-top: -40px; 108 | } 109 | 110 | /* Navbar submenu --------------------------*/ 111 | 112 | .dropdown-submenu { 113 | position: relative; 114 | } 115 | 116 | .dropdown-submenu>.dropdown-menu { 117 | top: 0; 118 | left: 100%; 119 | margin-top: -6px; 120 | margin-left: -1px; 121 | border-radius: 0 6px 6px 6px; 122 | } 123 | 124 | .dropdown-submenu:hover>.dropdown-menu { 125 | display: block; 126 | } 127 | 128 | .dropdown-submenu>a:after { 129 | display: block; 130 | content: " "; 131 | float: right; 132 | width: 0; 133 | height: 0; 134 | border-color: transparent; 135 | border-style: solid; 136 | border-width: 5px 0 5px 5px; 137 | border-left-color: #cccccc; 138 | margin-top: 5px; 139 | margin-right: -10px; 140 | } 141 | 142 | .dropdown-submenu:hover>a:after { 143 | border-left-color: #ffffff; 144 | } 145 | 146 | .dropdown-submenu.pull-left { 147 | float: none; 148 | } 149 | 150 | .dropdown-submenu.pull-left>.dropdown-menu { 151 | left: -100%; 152 | margin-left: 10px; 153 | border-radius: 6px 0 6px 6px; 154 | } 155 | 156 | /* Sidebar --------------------------*/ 157 | 158 | #pkgdown-sidebar { 159 | margin-top: 30px; 160 | position: -webkit-sticky; 161 | position: sticky; 162 | top: 70px; 163 | } 164 | 165 | #pkgdown-sidebar h2 { 166 | font-size: 1.5em; 167 | margin-top: 1em; 168 | } 169 | 170 | #pkgdown-sidebar h2:first-child { 171 | margin-top: 0; 172 | } 173 | 174 | #pkgdown-sidebar .list-unstyled li { 175 | margin-bottom: 0.5em; 176 | } 177 | 178 | /* bootstrap-toc tweaks ------------------------------------------------------*/ 179 | 180 | /* All levels of nav */ 181 | 182 | nav[data-toggle='toc'] .nav > li > a { 183 | padding: 4px 20px 4px 6px; 184 | font-size: 1.5rem; 185 | font-weight: 400; 186 | color: inherit; 187 | } 188 | 189 | nav[data-toggle='toc'] .nav > li > a:hover, 190 | nav[data-toggle='toc'] .nav > li > a:focus { 191 | padding-left: 5px; 192 | color: inherit; 193 | border-left: 1px solid #878787; 194 | } 195 | 196 | nav[data-toggle='toc'] .nav > .active > a, 197 | nav[data-toggle='toc'] .nav > .active:hover > a, 198 | nav[data-toggle='toc'] .nav > .active:focus > a { 199 | padding-left: 5px; 200 | font-size: 1.5rem; 201 | font-weight: 400; 202 | color: inherit; 203 | border-left: 2px solid #878787; 204 | } 205 | 206 | /* Nav: second level (shown on .active) */ 207 | 208 | nav[data-toggle='toc'] .nav .nav { 209 | display: none; /* Hide by default, but at >768px, show it */ 210 | padding-bottom: 10px; 211 | } 212 | 213 | nav[data-toggle='toc'] .nav .nav > li > a { 214 | padding-left: 16px; 215 | font-size: 1.35rem; 216 | } 217 | 218 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 219 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 220 | padding-left: 15px; 221 | } 222 | 223 | nav[data-toggle='toc'] .nav .nav > .active > a, 224 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 225 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 226 | padding-left: 15px; 227 | font-weight: 500; 228 | font-size: 1.35rem; 229 | } 230 | 231 | /* orcid ------------------------------------------------------------------- */ 232 | 233 | .orcid { 234 | font-size: 16px; 235 | color: #A6CE39; 236 | /* margins are required by official ORCID trademark and display guidelines */ 237 | margin-left:4px; 238 | margin-right:4px; 239 | vertical-align: middle; 240 | } 241 | 242 | /* Reference index & topics ----------------------------------------------- */ 243 | 244 | .ref-index th {font-weight: normal;} 245 | 246 | .ref-index td {vertical-align: top; min-width: 100px} 247 | .ref-index .icon {width: 40px;} 248 | .ref-index .alias {width: 40%;} 249 | .ref-index-icons .alias {width: calc(40% - 40px);} 250 | .ref-index .title {width: 60%;} 251 | 252 | .ref-arguments th {text-align: right; padding-right: 10px;} 253 | .ref-arguments th, .ref-arguments td {vertical-align: top; min-width: 100px} 254 | .ref-arguments .name {width: 20%;} 255 | .ref-arguments .desc {width: 80%;} 256 | 257 | /* Nice scrolling for wide elements --------------------------------------- */ 258 | 259 | table { 260 | display: block; 261 | overflow: auto; 262 | } 263 | 264 | /* Syntax highlighting ---------------------------------------------------- */ 265 | 266 | pre, code, pre code { 267 | background-color: #f8f8f8; 268 | color: #333; 269 | } 270 | pre, pre code { 271 | white-space: pre-wrap; 272 | word-break: break-all; 273 | overflow-wrap: break-word; 274 | } 275 | 276 | pre { 277 | border: 1px solid #eee; 278 | } 279 | 280 | pre .img, pre .r-plt { 281 | margin: 5px 0; 282 | } 283 | 284 | pre .img img, pre .r-plt img { 285 | background-color: #fff; 286 | } 287 | 288 | code a, pre a { 289 | color: #375f84; 290 | } 291 | 292 | a.sourceLine:hover { 293 | text-decoration: none; 294 | } 295 | 296 | .fl {color: #1514b5;} 297 | .fu {color: #000000;} /* function */ 298 | .ch,.st {color: #036a07;} /* string */ 299 | .kw {color: #264D66;} /* keyword */ 300 | .co {color: #888888;} /* comment */ 301 | 302 | .error {font-weight: bolder;} 303 | .warning {font-weight: bolder;} 304 | 305 | /* Clipboard --------------------------*/ 306 | 307 | .hasCopyButton { 308 | position: relative; 309 | } 310 | 311 | .btn-copy-ex { 312 | position: absolute; 313 | right: 0; 314 | top: 0; 315 | visibility: hidden; 316 | } 317 | 318 | .hasCopyButton:hover button.btn-copy-ex { 319 | visibility: visible; 320 | } 321 | 322 | /* headroom.js ------------------------ */ 323 | 324 | .headroom { 325 | will-change: transform; 326 | transition: transform 200ms linear; 327 | } 328 | .headroom--pinned { 329 | transform: translateY(0%); 330 | } 331 | .headroom--unpinned { 332 | transform: translateY(-100%); 333 | } 334 | 335 | /* mark.js ----------------------------*/ 336 | 337 | mark { 338 | background-color: rgba(255, 255, 51, 0.5); 339 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 340 | padding: 1px; 341 | } 342 | 343 | /* vertical spacing after htmlwidgets */ 344 | .html-widget { 345 | margin-bottom: 10px; 346 | } 347 | 348 | /* fontawesome ------------------------ */ 349 | 350 | .fab { 351 | font-family: "Font Awesome 5 Brands" !important; 352 | } 353 | 354 | /* don't display links in code chunks when printing */ 355 | /* source: https://stackoverflow.com/a/10781533 */ 356 | @media print { 357 | code a:link:after, code a:visited:after { 358 | content: ""; 359 | } 360 | } 361 | 362 | /* Section anchors --------------------------------- 363 | Added in pandoc 2.11: https://github.com/jgm/pandoc-templates/commit/9904bf71 364 | */ 365 | 366 | div.csl-bib-body { } 367 | div.csl-entry { 368 | clear: both; 369 | } 370 | .hanging-indent div.csl-entry { 371 | margin-left:2em; 372 | text-indent:-2em; 373 | } 374 | div.csl-left-margin { 375 | min-width:2em; 376 | float:left; 377 | } 378 | div.csl-right-inline { 379 | margin-left:2em; 380 | padding-left:1em; 381 | } 382 | div.csl-indent { 383 | margin-left: 2em; 384 | } 385 | -------------------------------------------------------------------------------- /docs/reference/get_system_pricing_plans.html: -------------------------------------------------------------------------------- 1 | 2 | Grab the system_pricing_plans feed. — get_system_pricing_plans • gbfs 8 | 9 | 10 |
    11 |
    42 | 43 | 44 | 45 |
    46 |
    47 | 52 | 53 |
    54 |

    get_system_pricing_plans grabs and tidies the system_pricing_plans 55 | feed for a given city. Metadata for this dataset can be found at: 56 | https://github.com/MobilityData/gbfs/blob/master/gbfs.md

    57 |
    58 | 59 |
    60 |
    get_system_pricing_plans(
     61 |   city,
     62 |   directory = NULL,
     63 |   file = "system_pricing_plans.rds",
     64 |   output = NULL
     65 | )
    66 |
    67 | 68 |
    69 |

    Arguments

    70 | 71 | 72 |
    city
    73 |

    A character string that can be matched to a gbfs feed. The recommended 74 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 75 | also attempt to match to the URL of an active .json feed or city name.

    76 | 77 | 78 |
    directory
    79 |

    Optional. Path to a folder (or folder to be 80 | created) where the feed will be saved.

    81 | 82 | 83 |
    file
    84 |

    Optional. The name of the file to be saved (if output 85 | is set to "save" or "both"), as a character string. 86 | Must end in ".rds".

    87 | 88 | 89 |
    output
    90 |

    Optional. The type of output method. If left as default, this 91 | argument is inferred from the directory argument. If 92 | output = "save", the object will be saved as an .rds object at 93 | # the given path. If output = "return", the output will be returned 94 | as a dataframe object. Setting output = "both" will do both.

    95 | 96 |
    97 |
    98 |

    Value

    99 |

    The output of this function depends on argument to output 100 | and directory. Either a saved .rds object generated from the current 101 | feed, a dataframe object, or both.

    102 |
    103 |
    104 |

    See also

    105 |

    [get_gbfs()] for a wrapper to call each of the get_feed 106 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 107 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 108 | are released by a given city.

    109 |
    110 | 111 |
    112 | 115 |
    116 | 117 | 118 |
    121 | 122 |
    123 |

    Site built with pkgdown 2.1.0.

    124 |
    125 | 126 |
    127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /docs/reference/gbfs.html: -------------------------------------------------------------------------------- 1 | 2 | Package: gbfs — gbfs • gbfs 9 | 10 | 11 |
    12 |
    43 | 44 | 45 | 46 |
    47 |
    48 | 53 | 54 |
    55 |

    The gbfs package allows users to query tidy datasets about bikeshare 56 | programs around the world by supplying a set of functions to interface with 57 | .json feeds following the General Bikeshare Feed Specification, a standard 58 | data release format developed by the North American Bikeshare Association.

    59 |
    60 | 61 | 62 |
    63 |

    Details

    64 |

    The main function exported by this package is get_gbfs(), which 65 | grabs every feed released by a city. Alternatively, the user can just 66 | grab information on specific feeds (or groups of feeds).

    67 |

    Each of the feeds described below can be queried with the get_suffix() 68 | function, where suffix is replaced with the name of the relevant feed.

    69 |

    Although all of the feeds are livestreamed, only a few of the datasets 70 | change often:

    71 |
    station_status:
    72 |

    Supplies the number of available bikes and 73 | docks at each station as well as station availability

    74 | 75 |
    free_bike_status:
    76 |

    Gives the coordinates and metadata on 77 | available bikes that are parked, but not at a station.

    78 | 79 | 80 |

    In this package, these two datasets are considered "dynamic", and can be 81 | specified as desired datasets by setting `feeds = "dynamic" in the 82 | main wrapper function in the package, get_gbfs.

    83 |

    Much of the data supplied in this specification can be considered static. 84 | If you want to grab all of these for a given city, set feeds = "static" 85 | when calling get_gbfs. Static feeds include:

    86 |
    system_information:
    87 |

    Basic metadata about the bikeshare program

    88 | 89 |
    station_information:
    90 |

    Information on the capacity and coordinates of stations

    91 | 92 |
    Several optional feeds:
    93 |

    system_hours, system_calendar, 94 | system_regions, system_pricing_plans, and system_alerts

    95 | 96 | 97 |
    98 |
    99 |

    See also

    100 | 103 |
    104 |
    105 |

    Author

    106 |

    Maintainer: Simon P. Couch simonpatrickcouch@gmail.com

    107 |

    Authors:

    Other contributors:

    110 | 111 |
    112 | 115 |
    116 | 117 | 118 |
    121 | 122 |
    123 |

    Site built with pkgdown 2.1.0.

    124 |
    125 | 126 |
    127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /docs/reference/get_system_hours.html: -------------------------------------------------------------------------------- 1 | 2 | Grab the system_hours feed. — get_system_hours • gbfs 9 | 10 | 11 |
    12 |
    43 | 44 | 45 | 46 |
    47 |
    48 | 53 | 54 |
    55 |

    get_system_hours grabs and tidies the system_hours 56 | feed for a given city. Metadata for this 57 | dataset can be found at: 58 | https://github.com/MobilityData/gbfs/blob/master/gbfs.md

    59 |
    60 | 61 |
    62 |
    get_system_hours(
     63 |   city,
     64 |   directory = NULL,
     65 |   file = "system_hours.rds",
     66 |   output = NULL
     67 | )
    68 |
    69 | 70 |
    71 |

    Arguments

    72 | 73 | 74 |
    city
    75 |

    A character string that can be matched to a gbfs feed. The recommended 76 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 77 | also attempt to match to the URL of an active .json feed or city name.

    78 | 79 | 80 |
    directory
    81 |

    Optional. Path to a folder (or folder to be 82 | created) where the feed will be saved.

    83 | 84 | 85 |
    file
    86 |

    Optional. The name of the file to be saved (if output 87 | is set to "save" or "both"), as a character string. 88 | Must end in ".rds".

    89 | 90 | 91 |
    output
    92 |

    Optional. The type of output method. If left as default, this 93 | argument is inferred from the directory argument. If 94 | output = "save", the object will be saved as an .rds object at 95 | # the given path. If output = "return", the output will be returned 96 | as a dataframe object. Setting output = "both" will do both.

    97 | 98 |
    99 |
    100 |

    Value

    101 |

    The output of this function depends on argument to output 102 | and directory. Either a saved .rds object generated from the current 103 | feed, a dataframe object, or both.

    104 |
    105 |
    106 |

    See also

    107 |

    [get_gbfs()] for a wrapper to call each of the get_feed 108 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 109 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 110 | are released by a given city.

    111 |
    112 | 113 |
    114 |

    Examples

    115 |
    # grab the system hours feed for portland, oregon
    116 | get_system_hours(city = 
    117 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_hours.json",  
    118 |                  output = "return")
    119 | #> data frame with 0 columns and 0 rows
    120 | 
    121 | 
    122 |
    123 |
    124 | 127 |
    128 | 129 | 130 |
    133 | 134 |
    135 |

    Site built with pkgdown 2.1.0.

    136 |
    137 | 138 |
    139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /docs/reference/get_system_alerts.html: -------------------------------------------------------------------------------- 1 | 2 | Grab the system_alerts feed. — get_system_alerts • gbfs 8 | 9 | 10 |
    11 |
    42 | 43 | 44 | 45 |
    46 |
    47 | 52 | 53 |
    54 |

    get_system_alerts grabs and tidies the system_alerts feed for a given city. 55 | This feed informs users about changes to normal operation. Metadata for this 56 | dataset can be found at: https://github.com/MobilityData/gbfs/blob/master/gbfs.md

    57 |
    58 | 59 |
    60 |
    get_system_alerts(
     61 |   city,
     62 |   directory = NULL,
     63 |   file = "system_alerts.rds",
     64 |   output = NULL
     65 | )
    66 |
    67 | 68 |
    69 |

    Arguments

    70 | 71 | 72 |
    city
    73 |

    A character string that can be matched to a gbfs feed. The recommended 74 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 75 | also attempt to match to the URL of an active .json feed or city name.

    76 | 77 | 78 |
    directory
    79 |

    Optional. Path to a folder (or folder to be 80 | created) where the feed will be saved.

    81 | 82 | 83 |
    file
    84 |

    Optional. The name of the file to be saved (if output 85 | is set to "save" or "both"), as a character string. 86 | Must end in ".rds".

    87 | 88 | 89 |
    output
    90 |

    Optional. The type of output method. If left as default, this 91 | argument is inferred from the directory argument. If 92 | output = "save", the object will be saved as an .rds object at 93 | # the given path. If output = "return", the output will be returned 94 | as a dataframe object. Setting output = "both" will do both.

    95 | 96 |
    97 |
    98 |

    Value

    99 |

    The output of this function depends on argument to output 100 | and directory. Either a saved .rds object generated from the current 101 | feed, a dataframe object, or both.

    102 |
    103 |
    104 |

    See also

    105 |

    [get_gbfs()] for a wrapper to call each of the get_feed 106 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 107 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 108 | are released by a given city.

    109 |
    110 | 111 |
    112 |

    Examples

    113 |
    # grab the system alerts feed for portland, oregon
    114 | get_system_alerts(city = 
    115 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_alerts.json",  
    116 |                   output = "return")
    117 | #> data frame with 0 columns and 0 rows
    118 |  
    119 | 
    120 |
    121 |
    122 | 125 |
    126 | 127 | 128 |
    131 | 132 |
    133 |

    Site built with pkgdown 2.1.0.

    134 |
    135 | 136 |
    137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /docs/reference/get_system_calendar.html: -------------------------------------------------------------------------------- 1 | 2 | Grab the system_calendar feed. — get_system_calendar • gbfs 8 | 9 | 10 |
    11 |
    42 | 43 | 44 | 45 |
    46 |
    47 | 52 | 53 |
    54 |

    get_system_calendar grabs and tidies the system_calendar feed 55 | for a given city. Metadata for this dataset can be found at: 56 | https://github.com/MobilityData/gbfs/blob/master/gbfs.md

    57 |
    58 | 59 |
    60 |
    get_system_calendar(
     61 |   city,
     62 |   directory = NULL,
     63 |   file = "system_calendar.rds",
     64 |   output = NULL
     65 | )
    66 |
    67 | 68 |
    69 |

    Arguments

    70 | 71 | 72 |
    city
    73 |

    A character string that can be matched to a gbfs feed. The recommended 74 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 75 | also attempt to match to the URL of an active .json feed or city name.

    76 | 77 | 78 |
    directory
    79 |

    Optional. Path to a folder (or folder to be 80 | created) where the feed will be saved.

    81 | 82 | 83 |
    file
    84 |

    Optional. The name of the file to be saved (if output 85 | is set to "save" or "both"), as a character string. 86 | Must end in ".rds".

    87 | 88 | 89 |
    output
    90 |

    Optional. The type of output method. If left as default, this 91 | argument is inferred from the directory argument. If 92 | output = "save", the object will be saved as an .rds object at 93 | # the given path. If output = "return", the output will be returned 94 | as a dataframe object. Setting output = "both" will do both.

    95 | 96 |
    97 |
    98 |

    Value

    99 |

    The output of this function depends on argument to output 100 | and directory. Either a saved .rds object generated from the current 101 | feed, a dataframe object, or both.

    102 |
    103 |
    104 |

    See also

    105 |

    [get_gbfs()] for a wrapper to call each of the get_feed 106 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 107 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 108 | are released by a given city.

    109 |
    110 | 111 |
    112 |

    Examples

    113 |
    # grab the system calendar feed for portland, oregon
    114 | get_system_calendar(city = 
    115 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_calendar.json",  
    116 |                     output = "return")
    117 | #>   start_month end_day end_month start_day
    118 | #> 1           1      31        12         1
    119 | 
    120 | 
    121 | 
    122 |
    123 |
    124 | 127 |
    128 | 129 | 130 |
    133 | 134 |
    135 |

    Site built with pkgdown 2.1.0.

    136 |
    137 | 138 |
    139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /docs/reference/get_which_gbfs_feeds.html: -------------------------------------------------------------------------------- 1 | 2 | Get dataframe of bikeshare feeds released by a city — get_which_gbfs_feeds • gbfs 9 | 10 | 11 |
    12 |
    43 | 44 | 45 | 46 |
    47 |
    48 | 53 | 54 |
    55 |

    Of the different types of feeds supplied by the gbfs, 56 | some are required, some are conditionally required, and some are 57 | optional. This function grabs a list of each of the feeds supplied 58 | by a given city, as well as the URLs to access them.

    59 |
    60 | 61 |
    62 |
    get_which_gbfs_feeds(city)
    63 |
    64 | 65 |
    66 |

    Source

    67 |

    North American Bikeshare Association, General Bikeshare Feed 68 | Specification https://github.com/MobilityData/gbfs/blob/master/gbfs.md

    69 |
    70 |
    71 |

    Arguments

    72 | 73 | 74 |
    city
    75 |

    A character string that can be matched to a gbfs feed. The recommended 76 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 77 | also attempt to match to the URL of an active .json feed or city name.

    78 | 79 |
    80 |
    81 |

    Value

    82 |

    A data.frame containing the feeds supplied by 83 | a city. . The `feed` column supplies the name of the relevant .json feeds, 84 | while the entries in the `URL` column supply the feeds themselves.

    85 |
    86 | 87 |
    88 |

    Examples

    89 |
    # grab all of the feeds released by portland
     90 | get_which_gbfs_feeds(city = "biketown_pdx")
     91 | #>                                                                url
     92 | #> 1                     https://gbfs.lyft.com/gbfs/2.3/pdx/gbfs.json
     93 | #> 2    https://gbfs.lyft.com/gbfs/2.3/pdx/en/system_information.json
     94 | #> 3   https://gbfs.lyft.com/gbfs/2.3/pdx/en/station_information.json
     95 | #> 4        https://gbfs.lyft.com/gbfs/2.3/pdx/en/station_status.json
     96 | #> 5      https://gbfs.lyft.com/gbfs/2.3/pdx/en/free_bike_status.json
     97 | #> 6          https://gbfs.lyft.com/gbfs/2.3/pdx/en/system_hours.json
     98 | #> 7       https://gbfs.lyft.com/gbfs/2.3/pdx/en/system_calendar.json
     99 | #> 8        https://gbfs.lyft.com/gbfs/2.3/pdx/en/system_regions.json
    100 | #> 9  https://gbfs.lyft.com/gbfs/2.3/pdx/en/system_pricing_plans.json
    101 | #> 10        https://gbfs.lyft.com/gbfs/2.3/pdx/en/system_alerts.json
    102 | #> 11        https://gbfs.lyft.com/gbfs/2.3/pdx/en/gbfs_versions.json
    103 | #> 12        https://gbfs.lyft.com/gbfs/2.3/pdx/en/vehicle_types.json
    104 | #>                    name
    105 | #> 1                  gbfs
    106 | #> 2    system_information
    107 | #> 3   station_information
    108 | #> 4        station_status
    109 | #> 5      free_bike_status
    110 | #> 6          system_hours
    111 | #> 7       system_calendar
    112 | #> 8        system_regions
    113 | #> 9  system_pricing_plans
    114 | #> 10        system_alerts
    115 | #> 11        gbfs_versions
    116 | #> 12        vehicle_types
    117 | 
    118 | 
    119 |
    120 |
    121 | 124 |
    125 | 126 | 127 |
    130 | 131 |
    132 |

    Site built with pkgdown 2.1.0.

    133 |
    134 | 135 |
    136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /docs/reference/get_system_regions.html: -------------------------------------------------------------------------------- 1 | 2 | Grab the system_regions feed. — get_system_regions • gbfs 8 | 9 | 10 |
    11 |
    42 | 43 | 44 | 45 |
    46 |
    47 | 52 | 53 |
    54 |

    get_system_regions grabs and tidies the system_regions feed for 55 | a given city. Metadata for this dataset can be found at: 56 | https://github.com/MobilityData/gbfs/blob/master/gbfs.md

    57 |
    58 | 59 |
    60 |
    get_system_regions(
     61 |   city,
     62 |   directory = NULL,
     63 |   file = "system_regions.rds",
     64 |   output = NULL
     65 | )
    66 |
    67 | 68 |
    69 |

    Arguments

    70 | 71 | 72 |
    city
    73 |

    A character string that can be matched to a gbfs feed. The recommended 74 | argument is a system ID supplied in the output of [get_gbfs_cities()], but will 75 | also attempt to match to the URL of an active .json feed or city name.

    76 | 77 | 78 |
    directory
    79 |

    Optional. Path to a folder (or folder to be 80 | created) where the feed will be saved.

    81 | 82 | 83 |
    file
    84 |

    Optional. The name of the file to be saved (if output 85 | is set to "save" or "both"), as a character string. 86 | Must end in ".rds".

    87 | 88 | 89 |
    output
    90 |

    Optional. The type of output method. If left as default, this 91 | argument is inferred from the directory argument. If 92 | output = "save", the object will be saved as an .rds object at 93 | # the given path. If output = "return", the output will be returned 94 | as a dataframe object. Setting output = "both" will do both.

    95 | 96 |
    97 |
    98 |

    Value

    99 |

    The output of this function depends on argument to output 100 | and directory. Either a saved .rds object generated from the current 101 | feed, a dataframe object, or both.

    102 |
    103 |
    104 |

    See also

    105 |

    [get_gbfs()] for a wrapper to call each of the get_feed 106 | functions, [get_gbfs_cities()] for a dataframe of cities releasing gbfs 107 | functions, and [get_which_gbfs_feeds()] for a dataframe of which feeds 108 | are released by a given city.

    109 |
    110 | 111 |
    112 |

    Examples

    113 |
    # we can grab the system regions feed for portland, 
    114 | # oregon in one of several ways! first, supply the `city` 
    115 | # argument as a URL, and save to file by leaving output 
    116 | # set to it's default. usually, we would supply a character 
    117 | # string (like "pdx", maybe,) for the `directory` argument 
    118 | # instead of `tempdir`.
    119 | get_system_regions(city = 
    120 | "https://gbfs.lyft.com/gbfs/1.1/pdx/en/system_regions.json",  
    121 |                    directory = tempdir())
    122 |                     
    123 | # or, instead, just supply the name of 
    124 | # the city as a string and return the output
    125 | # as a dataframe
    126 | get_system_regions(city = "biketown_pdx",  
    127 |                    output = "return")
    128 | #>   name region_id
    129 | #> 1  PDX       PDX
    130 | 
    131 |
    132 |
    133 | 136 |
    137 | 138 | 139 |
    148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | --------------------------------------------------------------------------------