<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/data-from-public-bicycle-hire-systems/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://ropensci.org/blog/blog/2017/10/17/bikedata"> rOpenSci Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>A new rOpenSci package provides access to data to which users may already have directly contributed, and for which contribution is fun, keeps you fit, and <a rel="nofollow" href="http://www.bmj.com/content/357/bmj.j1456" target="_blank">helps made the world a better place</a>. The data come from using public bicycle hire schemes, and the package is called <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a>. Public bicycle hire systems operate in many cities throughout the world, and most systems collect (generally anonymous) data, minimally consisting of the times and locations at which every single bicycle trip starts and ends. The <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a> package provides access to data from all cities which openly publish these data, currently including <a rel="nofollow" href="https://tfl.gov.uk/modes/cycling/santander-cycles" target="_blank">London, U.K.</a>, and in the U.S.A., <a rel="nofollow" href="https://www.citibikenyc.com/" target="_blank">New York</a>, <a rel="nofollow" href="https://bikeshare.metro.net/" target="_blank">Los Angeles</a>, <a rel="nofollow" href="https://www.rideindego.com/" target="_blank">Philadelphia</a>, <a rel="nofollow" href="https://www.divvybikes.com/" target="_blank">Chicago</a>, <a rel="nofollow" href="https://www.thehubway.com/" target="_blank">Boston</a>, and <a rel="nofollow" href="https://www.capitalbikeshare.com/" target="_blank">Washington DC</a>. The package will expand as more cities openly publish their data (with the newly enormously expanded San Francisco system <a rel="nofollow" href="https://github.com/ropensci/bikedata/issues/2" target="_blank">next on the list</a>).</p>
<h1>Why bikedata?</h1>
<p>The short answer to that question is that the package provides access to what is arguably one of the most spatially and temporally detailed databases of finely-scaled human movement throughout several of the world's most important cities. Such data are likely to prove invaluable in the increasingly active and well-funded attempt to develop a science of cities. Such a science does not yet exist in any way comparable to most other well-established scientific disciplines, but the importance of developing a science of cities is indisputable, and reflected in such enterprises as the NYU-based <a rel="nofollow" href="http://cusp.nyu.edu/" target="_blank">Center for Urban Science and Progress</a>, or the UCL-based <a rel="nofollow" href="https://www.ucl.ac.uk/bartlett/casa/" target="_blank">Centre for Advanced Spatial Analysis</a>.</p>
<p>People move through cities, yet at present anyone faced with the seemingly fundamental question of how, when, and where people do so would likely have to draw on some form of private data (typically operators of transport systems or mobile phone providers). There are very few open, public data providing insight into this question. The <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a> package aims to be one contribution towards filling this gap. The data accessed by the package are entirely open, and are constantly updated, typically on a monthly basis. The package thus provides ongoing insight into the dynamic changes and reconfigurations of these cities. Data currently available via the package amounts to several tens of Gigabytes, and will expand rapidly both with time, and with the inclusion of more cities.</p>
<h2>Why are these data published?</h2>
<p>In answer to that question, all credit must rightfully go to <a rel="nofollow" href="http://www.theregister.co.uk/2011/01/11/transport_for_london_foi/" target="_blank">Adrian Short</a>, who submitted a Freedom of Information request in 2011 to Transport for London for usage statistics from the relatively new, and largely publicly-funded, bicycle scheme. This request from one individual ultimately resulted in the data being openly published on an ongoing basis. All U.S. systems included in <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a> commenced operation subsequent to that point in time, and many of them have openly published their data from the very beginning. The majority of the world's public bicycle hire systems (<a rel="nofollow" href="https://en.wikipedia.org/wiki/List_of_bicycle-sharing_systems" target="_blank">see list here</a>) nevertheless do not openly publish data, notably including very large systems in China, France, and Spain. One important aspiration of the <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a> package is to demonstrate the positive benefit for the cities themselves of openly and easily facilitating complex analyses of usage data, which brings us to …</p>
<h2>What's important about these data?</h2>
<p>As mentioned, the data really do provide uniquely valuable insights into the movement patterns and behaviour of people within some of the world's major cities. While the more detailed explorations below demonstrate the kinds of things that can be done with the package, the variety of insights these data facilitate is best demonstrated through considering the work of other people, exemplified by <a rel="nofollow" href="http://toddwschneider.com/posts/a-tale-of-twenty-two-million-citi-bikes-analyzing-the-nyc-bike-share-system/" target="_blank">Todd Schneider's high-profile blog piece</a> on the New York City system. Todd's analyses clearly demonstrate how these data can provide insight into where and when people move, into inter-relationships between various forms of transport, and into relationships with broader environmental factors such as weather. As cities evolve, and public bicycle hire schemes along with them, data from these systems can play a vital role in informing and guiding the ongoing processes of urban development. The <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a> package greatly facilitates analysing such processes, not only through making data access and aggregation enormously easier, but through enabling analyses from any one system to be immediately applied to, and compared with, any other systems.</p>
<h1>How it works</h1>
<p>The package currently focusses on the data alone, and provides functionality for downloading, storage, and aggregation. The data are stored in an <code>SQLite3</code> database, enabling newly published data to be continually added, generally with one simple line of code. It's as easy as:</p>
<div>
<pre><code data-lang="r"><span></span>store_bikedata <span>(</span>city <span>=</span> <span>&quot;chicago&quot;</span><span>,</span> bikedb <span>=</span> <span>&quot;bikedb&quot;</span><span>)</span>
</code></pre>
</div>
<p>If the nominated database (<code>bikedb</code>) already holds data for Chicago, only new data will be added, otherwise all historical data will be downloaded and added. All bicycle hire systems accessed by <code>bikedata</code> have fixed docking stations, and the primary means of aggregation is in terms of &quot;trip matrices&quot;, which are square matrices of numbers of trips between all pairs of stations, extracted with:</p>
<div>
<pre><code data-lang="r"><span></span>trips <span>&lt;-</span> bike_tripmat <span>(</span>bikedb <span>=</span> <span>&quot;bikedb&quot;</span><span>,</span> city <span>=</span> <span>&quot;chi&quot;</span><span>)</span>
</code></pre>
</div>
<p>Note that most parameters are highly flexible in terms of formatting, so pretty much anything starting with <code>&quot;ch&quot;</code> will be recognised as Chicago. Of course, if the database only contains data for Chicago, the <code>city</code> parameter may be omitted entirely. Trip matrices may be filtered by time, through combinations of year, month, day, hour, minute, or even second, as well as by demographic characteristics such as gender or date of birth for those systems which provide such data. (These latter data are freely provided by users of the systems, and there can be no guarantee of their accuracy.) These can all be combined in calls like the following, which further demonstrates the highly flexible ways of specifying the various parameters:</p>
<div>
<pre><code data-lang="r"><span></span>trips <span>&lt;-</span> bike_tripmat <span>(</span><span>&quot;bikedb&quot;</span><span>,</span> city <span>=</span> <span>&quot;london, innit&quot;</span><span>,</span>
                       start_date <span>=</span> <span>20160101</span><span>,</span> end_date <span>=</span> <span>&quot;16,02,28&quot;</span><span>,</span>
                       start_time <span>=</span> <span>6</span><span>,</span> end_time <span>=</span> <span>24</span><span>,</span>
                       birth_year <span>=</span> <span>1980</span><span>:</span><span>1990</span><span>,</span> gender <span>=</span> <span>&quot;f&quot;</span><span>)</span>
</code></pre>
</div>
<p>The second mode of aggregation is as daily time series, via the <code>bike_daily_trips()</code> function. See <a rel="nofollow" href="https://ropensci.github.io/bikedata/articles/bikedata.html" target="_blank">the vignette</a> for further details.</p>
<h1>What can be done with these data?</h1>
<p>Lots of things. How about examining how far people ride. This requires getting the distances between all pairs of docking stations as routed through the street network, to yield a distance matrix corresponding to the trip matrix. The latest version of <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a> has a brand new function to perform exactly that task, so it's as easy as</p>
<div>
<pre><code data-lang="r"><span></span>devtools<span>::</span>install_github <span>(</span><span>&quot;ropensci/bikedata&quot;</span><span>)</span> <span># to install latest version</span>
dists <span>&lt;-</span> bike_distmat <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> <span>&quot;chicago&quot;</span><span>)</span>
</code></pre>
</div>
<p>These are distances as routed through the underlying street network, with street types prioritised for bicycle travel. The network is extracted from OpenStreetMap using the <a rel="nofollow" href="https://github.com/ropensci/osmdata" target="_blank">rOpenSci <code>osmdata</code> package</a>, and the distances are calculated using a brand new package called <a rel="nofollow" href="https://cran.r-project.org/package=dodgr" target="_blank"><code>dodgr</code></a> (Distances on Directed Graphs). (Disclaimer: It's my package, and this is a shameless plug for it – please use it!)</p>
<p>The distance matrix extracted with <code>bike_distmat</code> is between all stations listed for a given system, which <code>bike_tripmat</code> will return trip matrices only between those stations in operation over a specified time period. Because systems expand over time, the two matrices will generally not be directly comparable, so it is necessary to submit both to the <code>bikedata</code> function <code>match_matrices()</code>:</p>
<div>
<pre><code data-lang="r"><span></span>dim <span>(</span>trips<span>);</span> dim <span>(</span>dists<span>)</span>
</code></pre>
</div>
<div>
<pre><code data-lang="text"><span></span>## [1] 581 581

## [1] 636 636
</code></pre>
</div>
<div>
<pre><code data-lang="r"><span></span>mats <span>&lt;-</span> match_matrices <span>(</span>trips<span>,</span> dists<span>)</span>
trips <span>&lt;-</span> mats<span>$</span>trip
dists <span>&lt;-</span> mats<span>$</span>dist
dim <span>(</span>trips<span>);</span> dim <span>(</span>dists<span>)</span>
</code></pre>
</div>
<div>
<pre><code data-lang="text"><span></span>## [1] 581 581

## [1] 581 581
</code></pre>
</div>
<div>
<pre><code data-lang="r"><span></span>identical <span>(</span>rownames <span>(</span>trips<span>),</span> rownames <span>(</span>dists<span>))</span>
</code></pre>
</div>
<div>
<pre><code data-lang="text"><span></span>## [1] TRUE
</code></pre>
</div>
<p>Distances can then be visually related to trip numbers to reveal their distributional form. These matrices contain too many values to plot directly, so the <code>hexbin</code> package is used here to aggregate in a <code>ggplot</code>.</p>
<div>
<pre><code data-lang="r"><span></span><span>library</span> <span>(</span>hexbin<span>)</span>
<span>library</span> <span>(</span>ggplot2<span>)</span>
dat <span>&lt;-</span> <span>data.frame</span> <span>(</span>distance <span>=</span> as.vector <span>(</span>dmat<span>),</span>
                   number <span>=</span> as.vector <span>(</span>trips<span>))</span>
ggplot <span>(</span>dat<span>,</span> aes <span>(</span>x <span>=</span> distance<span>,</span> y <span>=</span> number<span>))</span> <span>+</span>
    stat_binhex<span>(</span>aes<span>(</span>fill <span>=</span> log <span>(</span><span>..</span>count..<span>)))</span> <span>+</span>
    scale_x_log10 <span>(</span>breaks <span>=</span> <span>c</span> <span>(</span><span>0.1</span><span>,</span> <span>0.5</span><span>,</span> <span>1</span><span>,</span> <span>2</span><span>,</span> <span>5</span><span>,</span> <span>10</span><span>,</span> <span>20</span><span>),</span>
                   labels <span>=</span> <span>c</span> <span>(</span><span>&quot;0.1&quot;</span><span>,</span> <span>&quot;0.5&quot;</span><span>,</span> <span>&quot;1&quot;</span><span>,</span> <span>&quot;2&quot;</span><span>,</span> <span>&quot;5&quot;</span><span>,</span> <span>&quot;10&quot;</span><span>,</span> <span>&quot;20&quot;</span><span>))</span> <span>+</span>
    scale_y_log10 <span>(</span>breaks <span>=</span> <span>c</span> <span>(</span><span>10</span><span>,</span> <span>100</span><span>,</span> <span>1000</span><span>))</span> <span>+</span>
    scale_fill_gradientn<span>(</span>colours <span>=</span> <span>c</span><span>(</span><span>&quot;seagreen&quot;</span><span>,</span><span>&quot;goldenrod1&quot;</span><span>),</span>
                         name <span>=</span> <span>&quot;Frequency&quot;</span><span>,</span> na.value <span>=</span> <span>NA</span><span>)</span> <span>+</span>
    guides <span>(</span>fill <span>=</span> <span>FALSE</span><span>)</span>
</code></pre>
</div>
<p><img alt="" src="https://i0.wp.com/ropensci.org/assets/blog-images/2017-10-17-bikedata/chicago.png?w=456" data-recalc-dims="1"></p>
<p>The central region of the graph (yellow hexagons) reveals that numbers of trips generally decrease roughly exponentially with increasing distance (noting that scales are logarithmic), with most trip distances lying below 5km. What is the &quot;average&quot; distance travelled in Chicago? The easiest way to calculate this is as a weighted mean,</p>
<div>
<pre><code data-lang="r"><span></span>sum <span>(</span>as.vector <span>(</span>dmat<span>)</span> <span>*</span> as.vector <span>(</span>trips<span>)</span> <span>/</span> sum <span>(</span>trips<span>),</span> na.rm <span>=</span> <span>TRUE</span><span>)</span>
</code></pre>
</div>
<div>
<pre><code data-lang="text"><span></span>## [1] 2.510285
</code></pre>
</div>
<p>giving a value of just over 2.5 kilometres. We could also compare differences in mean distances between cyclists who are registered with a system and causal users. These two categories may be loosely considered to reflect &quot;residents&quot; and &quot;non-residents&quot;. Let's wrap this in a function so we can use it for even cooler stuff in a moment.</p>
<div>
<pre><code data-lang="r"><span></span>dmean <span>&lt;-</span> <span>function</span> <span>(</span>bikedb <span>=</span> <span>&quot;bikedb&quot;</span><span>,</span> city <span>=</span> <span>&quot;chicago&quot;</span><span>)</span>
<span>{</span>
    tm <span>&lt;-</span> bike_tripmat <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> city<span>)</span>
    tm_memb <span>&lt;-</span> bike_tripmat <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> city<span>,</span> member <span>=</span> <span>TRUE</span><span>)</span>
    tm_nomemb <span>&lt;-</span> bike_tripmat <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> city<span>,</span> member <span>=</span> <span>FALSE</span><span>)</span>
    stns <span>&lt;-</span> bike_stations <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> city<span>)</span>
    dists <span>&lt;-</span> bike_distmat <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> city<span>)</span>
    mats <span>&lt;-</span> match_mats <span>(</span>dists<span>,</span> tm_memb<span>)</span>
    tm_memb <span>&lt;-</span> mats<span>$</span>trip
    mats <span>&lt;-</span> match_mats <span>(</span>dists<span>,</span> tm_nomemb<span>)</span>
    tm_nomemb <span>&lt;-</span> mats<span>$</span>trip
    mats <span>&lt;-</span> match_mats <span>(</span>dists<span>,</span> tm<span>)</span>
    tm <span>&lt;-</span> mats<span>$</span>trip
    dists <span>&lt;-</span> mats<span>$</span>dists

    d0 <span>&lt;-</span> sum <span>(</span>as.vector <span>(</span>dists<span>)</span> <span>*</span> as.vector <span>(</span>tm<span>)</span> <span>/</span> sum <span>(</span>tm<span>),</span> na.rm <span>=</span> <span>TRUE</span><span>)</span>
    dmemb <span>&lt;-</span> sum <span>(</span>as.vector <span>(</span>dists<span>)</span> <span>*</span> as.vector <span>(</span>tmemb<span>)</span> <span>/</span> sum <span>(</span>t_memb<span>),</span> na.rm <span>=</span> <span>TRUE</span><span>)</span>
    dnomemb <span>&lt;-</span> sum <span>(</span>as.vector <span>(</span>dists<span>)</span> <span>*</span> as.vector <span>(</span>tm_nomemb<span>)</span> <span>/</span> sum <span>(</span>tm_nomemb<span>),</span> na.rm <span>=</span> <span>TRUE</span><span>)</span>
    res <span>&lt;-</span> <span>c</span> <span>(</span>d0<span>,</span> dmemb <span>/</span> dnomemb<span>)</span>
    names <span>(</span>res<span>)</span> <span>&lt;-</span> <span>c</span> <span>(</span><span>&quot;dmean&quot;</span><span>,</span> <span>&quot;ratio_memb_non&quot;</span><span>)</span>
    <span>return</span> <span>(</span>res<span>)</span>
<span>}</span>
</code></pre>
</div>
<p>Differences in distances ridden between &quot;resident&quot; and &quot;non-resident&quot; cyclists can then be calculated with</p>
<div>
<pre><code data-lang="r"><span></span>dmean <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> <span>&quot;ch&quot;</span><span>)</span>
</code></pre>
</div>
<div>
<pre><code data-lang="text"><span></span>##          dmean ratio_memb_non
##       2.510698       1.023225
</code></pre>
</div>
<p>And system members cycle slightly longer distances than non-members. (Do not at this point ask about statistical tests – these comparisons are made between millions–often tens of millions–of points, and statistical significance may always be assumed to be negligibly small.) Whatever the reason for this difference between &quot;residents&quot; and others, we can use this exact same code to compare equivalent distances for all cities which record whether users are members or not (which is all cities except London and Washington DC).</p>
<div>
<pre><code data-lang="r"><span></span>cities <span>&lt;-</span> <span>c</span> <span>(</span><span>&quot;ny&quot;</span><span>,</span> <span>&quot;ch&quot;</span><span>,</span> <span>&quot;bo&quot;</span><span>,</span> <span>&quot;la&quot;</span><span>,</span> <span>&quot;ph&quot;</span><span>)</span> <span># NYC, Chicago, Boston, LA, Philadelphia</span>
sapply <span>(</span>cities<span>,</span> <span>function</span> <span>(</span>i<span>)</span> dmean <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> i<span>))</span>
</code></pre>
</div>
<div>
<pre><code data-lang="text"><span></span>##                       ny       ch       bo       la       ph
## dmean          2.8519131 2.510285 2.153918 2.156919 1.702372
## ratio_memb_non 0.9833729 1.023385 1.000635 1.360099 1.130929
</code></pre>
</div>
<p>And we thus discover that Boston manifests the greatest equality in terms of distances cycled between residents and non-residents, while LA manifests the greatest difference. New York City is the only one of these five in which non-members of the system actually cycle further than members. (And note that these two measures can't be statistically compared in any direct way, because mean distances are also affected by relative numbers of member to non-member trips.) These results likely reflect a host of (scientifically) interesting cultural and geo-spatial differences between these cities, and demonstrate how the <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a> package (combined with <a rel="nofollow" href="https://github.com/gmost/dodgr" target="_blank"><code>dodgr</code></a> and <a rel="nofollow" href="https://github.com/ropensci/osmdata" target="_blank"><code>osmdata</code></a>) can provide unique insight into differences in human behaviour between some of the most important cities in the U.S.</p>
<h1>visualisation</h1>
<p>Many users are likely to want to visualise how people use a given bicycle system, and in particular are likely to want to produce maps. This is also readily done with the <a rel="nofollow" href="https://github.com/gmost/dodgr" target="_blank"><code>dodgr</code> package</a>, which can route and aggregate transit flows for a particular mode of transport throughout a street network. Let's plot bicycle flows for the Indego System of Philadelphia PA. First get the trip matrix, along with the coordinates of all bicycle stations.</p>
<div>
<pre><code data-lang="r"><span></span>devtools<span>::</span>install_github <span>(</span><span>&quot;gmost/dodgr&quot;</span><span>)</span> <span># to install latest version</span>
city <span>&lt;-</span> <span>&quot;ph&quot;</span>
<span># store_bikedata (bikedb = bikedb, city = city) # if not already done</span>
trips <span>&lt;-</span> bike_tripmat <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> city<span>)</span>
stns <span>&lt;-</span> bike_stations <span>(</span>bikedb <span>=</span> bikedb<span>,</span> city <span>=</span> city<span>)</span>
xy <span>&lt;-</span> stns <span>[,</span> which <span>(</span>names <span>(</span>stns<span>)</span> <span>%in%</span> <span>c</span> <span>(</span><span>&quot;longitude&quot;</span><span>,</span> <span>&quot;latitude&quot;</span><span>))]</span>
</code></pre>
</div>
<p>Flows of cyclists are calculated between those <code>xy</code>points, so the <code>trips</code> table has to match the <code>stns</code> table:</p>
<div>
<pre><code data-lang="r"><span></span>indx <span>&lt;-</span> match <span>(</span>stns<span>$</span>stn_id<span>,</span> rownames <span>(</span>trips<span>))</span>
trips <span>&lt;-</span> trips <span>[</span>indx<span>,</span> indx<span>]</span>
</code></pre>
</div>
<p>The <a rel="nofollow" href="https://github.com/gmost/dodgr" target="_blank"><code>dodgr</code> package</a> can be used to extract the underlying street network surrounding those <code>xy</code> points (expanded here by 50%):</p>
<div>
<pre><code data-lang="r"><span></span>net <span>&lt;-</span> dodgr_streetnet <span>(</span>pts <span>=</span> xy<span>,</span> expand <span>=</span> <span>0.5</span><span>)</span> <span>%>%</span>
    weight_streetnet <span>(</span>wt_profile <span>=</span> <span>&quot;bicycle&quot;</span><span>)</span>
</code></pre>
</div>
<p>We then need to align the bicycle station coordinates in <code>xy</code> to the nearest points (or &quot;vertices&quot;) in the street network:</p>
<div>
<pre><code data-lang="r"><span></span>verts <span>&lt;-</span> dodgr_vertices <span>(</span>net<span>)</span>
pts <span>&lt;-</span> verts<span>$</span>id <span>[</span>match_pts_to_graph <span>(</span>verts<span>,</span> xy<span>)]</span>
</code></pre>
</div>
<p>Flows between these points can then mapped onto the underlying street network with:</p>
<div>
<pre><code data-lang="r"><span></span>flow <span>&lt;-</span> dodgr_flows <span>(</span>net<span>,</span> from <span>=</span> pts<span>,</span> to <span>=</span> pts<span>,</span> flow <span>=</span> trips<span>)</span> <span>%>%</span>
    merge_directed_flows <span>()</span>
net <span>&lt;-</span> net <span>[</span>flow<span>$</span>edge_id<span>,</span> <span>]</span>
net<span>$</span>flow <span>&lt;-</span> flow<span>$</span>flow
</code></pre>
</div>
<p>See the <a rel="nofollow" href="https://github.com/gmost/dodgr" target="_blank"><code>dodgr</code> documentation</a> for further details of how this works. We're now ready to plot those flows, but before we do, let's overlay them on top of the rivers of Philadelphia, extracted with rOpenSci's <a rel="nofollow" href="https://github.com/ropensci/osmdata" target="_blank"><code>osmdata</code> package</a>.</p>
<div>
<pre><code data-lang="r"><span></span>q <span>&lt;-</span> opq <span>(</span><span>&quot;Philadelphia pa&quot;</span><span>)</span>
rivers1 <span>&lt;-</span> q <span>%>%</span>
    add_osm_feature <span>(</span>key <span>=</span> <span>&quot;waterway&quot;</span><span>,</span> value <span>=</span> <span>&quot;river&quot;</span><span>,</span> value_exact <span>=</span> <span>FALSE</span><span>)</span> <span>%>%</span>
    osmdata_sf <span>(</span>quiet <span>=</span> <span>FALSE</span><span>)</span>
rivers2 <span>&lt;-</span> q <span>%>%</span>
    add_osm_feature <span>(</span>key <span>=</span> <span>&quot;natural&quot;</span><span>,</span> value <span>=</span> <span>&quot;water&quot;</span><span>)</span> <span>%>%</span>
    osmdata_sf <span>(</span>quiet <span>=</span> <span>FALSE</span><span>)</span>
rivers <span>&lt;-</span> <span>c</span> <span>(</span>rivers1<span>,</span> rivers2<span>)</span>
</code></pre>
</div>
<p>And finally plot the map, using rOpenSci's <a rel="nofollow" href="https://github.com/ropensci/osmplotr" target="_blank"><code>osmplotr</code> package</a> to prepare a base map with the underlying rivers, and the <code>ggplot2::geom_segment()</code> function to add the line segments with colours and widths weighted by bicycle flows.</p>
<div>
<pre><code data-lang="r"><span></span><span>#gtlibrary (osmplotr)</span>
<span>require</span> <span>(</span>ggplot2<span>)</span>
bb <span>&lt;-</span> get_bbox <span>(</span><span>c</span> <span>(</span><span>-75.22</span><span>,</span> <span>39.91</span><span>,</span> <span>-75.10</span><span>,</span> <span>39.98</span><span>))</span>
cols <span>&lt;-</span> colorRampPalette <span>(</span><span>c</span> <span>(</span><span>&quot;lawngreen&quot;</span><span>,</span> <span>&quot;red&quot;</span><span>))</span> <span>(</span><span>30</span><span>)</span>
map <span>&lt;-</span> osm_basemap <span>(</span>bb<span>,</span> bg <span>=</span> <span>&quot;gray10&quot;</span><span>)</span> <span>%>%</span>
    add_osm_objects <span>(</span>rivers<span>$</span>osm_multipolygons<span>,</span> col <span>=</span> <span>&quot;gray20&quot;</span><span>)</span> <span>%>%</span>
    add_osm_objects <span>(</span>rivers<span>$</span>osm_lines<span>,</span> col <span>=</span> <span>&quot;gray20&quot;</span><span>)</span> <span>%>%</span>
    add_colourbar <span>(</span>zlims <span>=</span> range <span>(</span>net<span>$</span>flow <span>/</span> <span>1000</span><span>),</span> col <span>=</span> cols<span>)</span>
map <span>&lt;-</span> map <span>+</span> geom_segment <span>(</span>data <span>=</span> net<span>,</span> size <span>=</span> net<span>$</span>flow <span>/</span> <span>50000</span><span>,</span>
                           aes <span>(</span>x <span>=</span> from_lon<span>,</span> y <span>=</span> from_lat<span>,</span> xend <span>=</span> to_lon<span>,</span> yend <span>=</span> to_lat<span>,</span>
                                colour <span>=</span> flow<span>,</span> size <span>=</span> flow<span>))</span> <span>+</span>
    scale_colour_gradient <span>(</span>low <span>=</span> <span>&quot;lawngreen&quot;</span><span>,</span> high <span>=</span> <span>&quot;red&quot;</span><span>,</span> guide <span>=</span> <span>&quot;none&quot;</span><span>)</span>
print_osm_map <span>(</span>map<span>)</span>
</code></pre>
</div>
<p><img alt="" src="https://i0.wp.com/ropensci.org/assets/blog-images/2017-10-17-bikedata/ph.png?w=456" data-recalc-dims="1"></p>
<p>The colour bar on the right shows thousands of trips, with the map revealing the relatively enormous numbers crossing the South Street Bridge over the Schuylkill River, leaving most other flows coloured in the lower range of green or yellows. This map thus reveals that anyone wanting to see Philadelphia's Indego bikes in action without braving the saddle themselves would be best advised to head straight for the South Street Bridge.</p>
<h1>Future plans</h1>
<p>Although the <a rel="nofollow" href="https://github.com/gmost/dodgr" target="_blank"><code>dodgr</code> package</a> greatly facilitates the production of such maps, the code is nevertheless rather protracted, and it would probably be very useful to convert much of the code in the preceding section to an internal <a rel="nofollow" href="https://github.com/ropensci/bikedata" target="_blank"><code>bikedata</code></a> function to map trips between pairs of stations onto corresponding flows through the underlying street networks.</p>
<p>Beyond that point, and the list of currently open issues awaiting development on the <a rel="nofollow" href="https://github.com/ropensci/bikedata/issues" target="_blank">github repository</a>, future development is likely to depend very much on how users use the package, and on what extra features people might want. How can you help? A great place to start might be the official <a rel="nofollow" href="https://ropensci.org/blog/blog/2017/10/02/hacktoberfest" target="_blank">Hacktoberfest issue</a>, helping to import the next lot of data from <a rel="nofollow" href="https://github.com/ropensci/bikedata/issues/34" target="_blank">San Francisco</a>. Or just use the package, and open up a new issue in response to any ideas that might pop up, no matter how minor they might seem. See the <a rel="nofollow" href="https://github.com/ropensci/bikedata/blob/master/CONTRIBUTING.md" target="_blank">contributing guidelines</a> for general advice.</p>
<h1>Acknowledgements</h1>
<p>Finally, this package wouldn't be what it is without my co-author <a rel="nofollow" href="https://github.com/richardellison" target="_blank">Richard Ellison</a>, who greatly accelerated development through encouraging C rather than C++ code for the SQL interfaces. <a rel="nofollow" href="https://github.com/maelle" target="_blank">Maëlle Salmon</a> majestically guided the entire review process, and made the transformation of the package to its current polished form a joy and a pleasure. I remain indebted to both <a rel="nofollow" href="https://github.com/chucheria" target="_blank">Bea Hernández</a> and <a rel="nofollow" href="https://github.com/eamcvey" target="_blank">Elaine McVey</a> for offering their time to extensively test and <a rel="nofollow" href="https://github.com/ropensci/onboarding/issues/116" target="_blank">review the package</a> as part of rOpenSci's onboarding process. The review process has made the package what it is, and for that I am grateful to all involved!</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://ropensci.org/blog/blog/2017/10/17/bikedata"> rOpenSci Blog</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/GpoYCSf2HOc" height="1"></a></div>