<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title></title>
      <link>https://www.jmspae.se</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://www.jmspae.se/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Fri, 14 Feb 2025 00:00:00 +0000</lastBuildDate>
      <item>
          <title>&quot;The closer to the train station, the worse the kebab&quot; - A &quot;Study&quot;</title>
          <pubDate>Fri, 14 Feb 2025 00:00:00 +0000</pubDate>
          <author>James Pae</author>
          <link>https://www.jmspae.se/write-ups/kebabs-train-stations/</link>
          <guid>https://www.jmspae.se/write-ups/kebabs-train-stations/</guid>
          <description xml:base="https://www.jmspae.se/write-ups/kebabs-train-stations/">&lt;p&gt;&lt;em&gt;This write-up was originally posted &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;gis&#x2F;comments&#x2F;1iph0yy&#x2F;the_closer_to_the_railway_station_the_less_tasty&#x2F;&quot;&gt;on reddit&lt;&#x2F;a&gt;, though I&#x27;ve cleaned things up specifically for this post. Due to reasons discussed towards the end of this post, I&#x27;m not entirely happy with the results and intend to take another shot at it in the near future.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;a class=&quot;zola-anchor&quot; href=&quot;#introduction&quot; aria-label=&quot;Anchor link for: introduction&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I came across &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;gis&#x2F;comments&#x2F;1iopp56&#x2F;anyone_motivated_to_prove_that_the_closer_from&#x2F;&quot;&gt;this post&lt;&#x2F;a&gt; sharing a hypothesis from a French subreddit;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The closer to the train station, the worse the kebab.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The original French post gained a decent amount of traction compared to the subreddit&#x27;s relatively small size, indicating a certain amount of agreement among its members. There were some detractors in the comments, however, sharing experiences which ran contrary to the stated hypothesis.&lt;&#x2F;p&gt;
&lt;p&gt;Thus, I figured I had nothing better to do, being a burned-out, unemployed drop-out with a newly-obtained autism diagnosis, so I figured I&#x27;d sacrifice my time for a worthy cause and perform this informal &lt;em&gt;&quot;study&quot;&lt;&#x2F;em&gt;. I&#x27;ll be expecting my Nobel peace prize in the postbox and several job offers in my DMs within the next 3 working days.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;method&quot;&gt;Method&lt;a class=&quot;zola-anchor&quot; href=&quot;#method&quot; aria-label=&quot;Anchor link for: method&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;I assumed the best study area to be Paris, France since;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;The original post was French&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;I haven&#x27;t personally heard of this hypothesis in my home country (Sweden, also home to many a kebab-serving restaurant) so I figured I&#x27;d assume this to be a French phenomenon for the purpose of this informal &quot;Study&quot;.&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Density&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The inner city is &lt;em&gt;&lt;strong&gt;dense&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt; with dozens of train&#x2F;metro stations and god knows how many kebab shops. I knew early on that this would make my life pretty miserable, but at least it&#x27;d provide plenty of sample data.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;network-data&quot;&gt;Network Data&lt;a class=&quot;zola-anchor&quot; href=&quot;#network-data&quot; aria-label=&quot;Anchor link for: network-data&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I used OSMnx to download and save a navigation network. Given the public transit-centric nature of the French subreddit, I though it&#x27;d make sense to stick to walking distance (eg. footpaths, side-walks) thus i set the OSMnx &lt;code&gt;network_type&lt;&#x2F;code&gt; to &lt;code&gt;&quot;walk&quot;&lt;&#x2F;code&gt;. Given the location (and that OSMnx used this CRS automatically when none was provided), all data was projected to EPSG:32631 (UTM zone 31N).&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;py&quot; style=&quot;background-color:#fafafa;color:#383a42;&quot; class=&quot;language-py &quot;&gt;&lt;code class=&quot;language-py&quot; data-lang=&quot;py&quot;&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;osmnx &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;ox
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;from &lt;&#x2F;span&gt;&lt;span&gt;geopandas &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;GeoDataFrame
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a0a1a7;&quot;&gt;#EPSG
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;PROJECTION &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;32631
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;graph &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ox.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;graph_from_place&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;#39;Paris, FR&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;network_type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;walk&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;graph &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ox.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;project_graph&lt;&#x2F;span&gt;&lt;span&gt;(graph, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_crs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;PROJECTION&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;ox.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;save_graphml&lt;&#x2F;span&gt;&lt;span&gt;(graph, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;filepath&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;network.graphml&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-1.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-1.c53f23b9b1fd351c.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

&lt;em&gt;Figure 1: The study area and network&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Next up is the various train&#x2F;metro stations. Given the nature of the original French sub, I figured it&#x27;d make sense to include both the long-distance central stations along with the countless metro stations. This was also rather trivial with OSMnx, filtering by &lt;code&gt;railway=subway_entrance&lt;&#x2F;code&gt; or &lt;code&gt;railway=train_station_entrance.&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;py&quot; style=&quot;background-color:#fafafa;color:#383a42;&quot; class=&quot;language-py &quot;&gt;&lt;code class=&quot;language-py&quot; data-lang=&quot;py&quot;&gt;&lt;span&gt;stations: GeoDataFrame &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ox.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;features_from_place&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;#39;Paris, FR&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;tags &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;railway&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;: [&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;subway_entrance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;train_station_entrance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;})
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a0a1a7;&quot;&gt;# Filter results to points
&lt;&#x2F;span&gt;&lt;span&gt;station_nodes: GeoDataFrame &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;stations.loc[stations.geom_type&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;Point&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;station_nodes &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;station_nodes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_crs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;epsg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;PROJECTION&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;station_nodes.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;train_station_entrances.gpkg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I saved outputs religiously so I could easily inspect them in QGIS. I did attempt to get python notebooks working with my NeoVIM setup, but it was all for naught.&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-2.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-2.51f0e47dcd63c0a8.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

&lt;em&gt;Figure 2: Rail&#x2F;metro entrances... Please ignore the airport iconography.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;... And there we have the first half of the data, now for the restaurants.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;restaurant-data&quot;&gt;Restaurant Data&lt;a class=&quot;zola-anchor&quot; href=&quot;#restaurant-data&quot; aria-label=&quot;Anchor link for: restaurant-data&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The Google Places API (and their respective reviews) seemed like a reasonable choice. Google reviews are naturally far from perfect and subject to their fair share of botting and the like, but it&#x27;s the best I could think of at the time. There are alternatives such as Yelp, but their API is horrifically expensive for poor old me, and I was not in the mood to build a web scraper (it has the same soul-sucking effect on me as prompting an LLM). The $200 of free credit was also enticing.&lt;&#x2F;p&gt;
&lt;p&gt;However, as I started exploring the API... I realised that the Places API doesn&#x27;t seem to have any way to search within a polygon, only within a point radius. Thank you, Mr. publicly owned mega-corporation. How Fun.&lt;&#x2F;p&gt;
&lt;p&gt;It also didn&#x27;t help that autocomplete for the &lt;code&gt;googlemaps&lt;&#x2F;code&gt; library wasn&#x27;t working. Python&#x27;s a fine language, but its tooling does like to test my patience a little too often. And whilst I&#x27;m still complaining... The Google Cloud dashboard is likely the slowest &quot;website&quot; I&#x27;ve ever had the displeasure of interacting with.&lt;&#x2F;p&gt;
&lt;p&gt;So... This meant I&#x27;d have to perform some sort of grid search of the whole of Paris, crossing my fingers that I wouldn&#x27;t bust my free usage. This, along with a couple interesting questions;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;What is... &lt;em&gt;A kebab?&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;When I search for &quot;kebab&quot; (no further context necessary)... How does Google decide what restaurant serves kebab?&lt;&#x2F;p&gt;
&lt;p&gt;After some perusing, it didn&#x27;t seem to be as deep as I thought. Plenty of restaurants simply had &quot;kebab&quot; in the name, some were designated as &quot;Mediterranean&quot; (Kebab has its origins in Turkey, Persia, middle east in general) and others had a fair few reviews simply mentioning &quot;kebab.&quot; Good enough for me.&lt;&#x2F;p&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;Trouble in query-land&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;It turns out that when you query for places within a given radius, it&#x27;s only a &quot;bias.&quot; It&#x27;s not a hard cut-off that&#x27;ll help narrow-down our data harvesting and reduce unnecessary requests. It was becoming increasingly clear that google isn&#x27;t really a fan of people doing this.&lt;&#x2F;p&gt;
&lt;p&gt;Now with all of that preamble out of the way, I needed to prepare my search.&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-3.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-3.605c84ffddad8323.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

&lt;em&gt;Figure 3. Original admin boundaries&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Paris&#x27; administrative boundary contains a couple of large green spaces. To the west, a park and to the east, some sort of sports institute.&lt;&#x2F;p&gt;
&lt;p&gt;After perusing these rather large spaces in Google maps, they seemed to contain a distinct lack of kebab-serving establishments. Thus, they were a burden on our API budget and needed to go.&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-4.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-4.b360881962350eea.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

&lt;em&gt;Figure 4. Adjusted admin boundaries w&#x2F; network&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I figured keeping the network and stations wouldn&#x27;t do any harm, so they went unmodified.&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-5.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-5.eedb86cb4c85e12c.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

&lt;em&gt;Figure 5. Sampling points, later projected to WGS84 for harvesting purposes&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To maximise data-harvesting, I decided to go with a hex layout with a vertical spacing of 1 km. This should give us a search radius of 500m * √3 ~= 866 meters. Plenty of overlap, sure, but we shouldn&#x27;t be getting any holes anywhere. I&#x27;m not sure why I was spending this much time ensuring &quot;data integrity&quot; when that might just have flown the window courtesy of Google, but it&#x27;s the illusion of control that counts.&lt;&#x2F;p&gt;
&lt;p&gt;This give us 99 sample points which... Should be enough?&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, here&#x27;s how my 3AM python turned out:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;py&quot; style=&quot;background-color:#fafafa;color:#383a42;&quot; class=&quot;language-py &quot;&gt;&lt;code class=&quot;language-py&quot; data-lang=&quot;py&quot;&gt;&lt;span style=&quot;color:#a0a1a7;&quot;&gt;# Already projected to WGS84
&lt;&#x2F;span&gt;&lt;span&gt;sample_points: GeoDataFrame &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;GeoDataFrame.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;from_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;samples.gpkg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;gmaps: googlemaps.Client &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;googlemaps.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;#39;get-your-own&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;output &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;point &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;sample_points.geometry:
&lt;&#x2F;span&gt;&lt;span&gt;    lat, lon &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;point.y, point.x
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    next_page_token &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;None
&lt;&#x2F;span&gt;&lt;span&gt;    num_fetches &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;3
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;while &lt;&#x2F;span&gt;&lt;span&gt;num_fetches &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;        result &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;{}
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;next_page_token &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            result &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;gmaps.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;places&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;kebab&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;location&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;(lat, lon),
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;radius&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;866&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;            )
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;else&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            result &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;gmaps.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;places&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;page_token&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;next_page_token
&lt;&#x2F;span&gt;&lt;span&gt;            )
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        next_page_token &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;result.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;next_page_token&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;print&lt;&#x2F;span&gt;&lt;span&gt;(result[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;status&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;], next_page_token)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;p &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;result[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;results&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]:
&lt;&#x2F;span&gt;&lt;span&gt;            output[p[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;place_id&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;p
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;next_page_token &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span&gt;:
&lt;&#x2F;span&gt;&lt;span&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;break
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        num_fetches &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;-= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;1
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;json_out &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;json.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;dumps&lt;&#x2F;span&gt;&lt;span&gt;(output)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;output.json&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;w&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;file:
&lt;&#x2F;span&gt;&lt;span&gt;    file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(json_out)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This worked quite well. Initially I skipped paging, resulting in 322 results. However, I noticed that a few establishments were missing in the results compared to my explorations in Google Maps.&lt;&#x2F;p&gt;
&lt;p&gt;After implementing paging and re-running, this gave us a grand total of 400 kebab-serving establishments. I was likely over-zealous with the paging considering how few additional results were retrieved. That, and that the API doesn&#x27;t cap the search radius (again, it&#x27;s only a bias) likely led to a fair few redundant API calls.&lt;&#x2F;p&gt;
&lt;p&gt;The raw Google Places API-output also needed to be clipped to the study area, projected to the local UTM zone as well as converted to a geospatial format;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;py&quot; style=&quot;background-color:#fafafa;color:#383a42;&quot; class=&quot;language-py &quot;&gt;&lt;code class=&quot;language-py&quot; data-lang=&quot;py&quot;&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;pandas &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;pd
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;with &lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;open&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;output.json&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;r&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;file:
&lt;&#x2F;span&gt;&lt;span&gt;    data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;json.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(file)
&lt;&#x2F;span&gt;&lt;span&gt;    file.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;close&lt;&#x2F;span&gt;&lt;span&gt;()
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;id &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;data:
&lt;&#x2F;span&gt;&lt;span&gt;        place &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        point &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;place[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;geometry&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;location&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;lng&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;point[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;lng&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;lat&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;point[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;lat&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;del &lt;&#x2F;span&gt;&lt;span&gt;data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;][&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;geometry&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;pd.DataFrame.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;from_dict&lt;&#x2F;span&gt;&lt;span&gt;(data).T
&lt;&#x2F;span&gt;&lt;span&gt;    data.rating &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;pd.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_numeric&lt;&#x2F;span&gt;&lt;span&gt;(data.rating)
&lt;&#x2F;span&gt;&lt;span&gt;    data.user_ratings_total &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;pd.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_numeric&lt;&#x2F;span&gt;&lt;span&gt;(data.user_ratings_total)
&lt;&#x2F;span&gt;&lt;span&gt;    data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;data[data[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;user_ratings_total&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a0a1a7;&quot;&gt;# Cleanup was added after the screenshot below was taken
&lt;&#x2F;span&gt;&lt;span&gt;    data &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;data.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;drop&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;columns&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;[
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;icon&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;icon_background_color&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;icon_mask_base_uri&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;plus_code&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;reference&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;photos&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;opening_hours&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;    ])
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    gdata &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;GeoDataFrame&lt;&#x2F;span&gt;&lt;span&gt;(
&lt;&#x2F;span&gt;&lt;span&gt;        data, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;geometry&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;geopandas.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;points_from_xy&lt;&#x2F;span&gt;&lt;span&gt;(data.lng, data.lat),
&lt;&#x2F;span&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;crs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;4326
&lt;&#x2F;span&gt;&lt;span&gt;    )
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    gdata: GeoDataFrame &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;gdata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_crs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;PROJECTION&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a0a1a7;&quot;&gt;# Modified boundaries from Figure 4.
&lt;&#x2F;span&gt;&lt;span&gt;    paris &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;GeoDataFrame.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;from_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;mod_bounary.gpkg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    gdata: GeoDataFrame &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;gdata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;clip&lt;&#x2F;span&gt;&lt;span&gt;(paris)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    gdata.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;establishments.gpkg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-6.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-6.1eab106a30493ee2.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

&lt;em&gt;Figure 6. We&#x27;re in f###ing business&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;routing-and-distance&quot;&gt;Routing and Distance&lt;a class=&quot;zola-anchor&quot; href=&quot;#routing-and-distance&quot; aria-label=&quot;Anchor link for: routing-and-distance&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Finally, the fun part. I need to get the distance to the nearest station entrance for each establishment.&lt;&#x2F;p&gt;
&lt;p&gt;I could&#x27;ve absolutely just routed to every single entrance for every single restaurant to get the nearest... But that would&#x27;ve taken several decades. I needed to build some sort of spatial index and route to the nearest ~3 or something along those lines. Since Paris is so dense with plenty of routing options, I figured I wouldn&#x27;t need to perform too many routing operations.&lt;&#x2F;p&gt;
&lt;p&gt;After some googling and dredging through API docs, however, it seemed GeoPandas was nice enough to do that for us with &lt;code&gt;sindex&lt;&#x2F;code&gt;. Although it didn&#x27;t have the same &quot;return nearest N&quot; like my beloved r-tree rust library I was all too used to, it did allow me to search within a certain radius (1 km was large enough) and go from there. The query results weren&#x27;t sorted, so I had to sort the indexes by distance and cut it down to size.&lt;&#x2F;p&gt;
&lt;p&gt;The network analysis was relatively straight-forward thanks to NetworkX, and after a couple of hours I managed to cobble together the following;&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;py&quot; style=&quot;background-color:#fafafa;color:#383a42;&quot; class=&quot;language-py &quot;&gt;&lt;code class=&quot;language-py&quot; data-lang=&quot;py&quot;&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;networkx &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;nx
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;import &lt;&#x2F;span&gt;&lt;span&gt;shapely &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;as &lt;&#x2F;span&gt;&lt;span&gt;shp
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;establishments: GeoDataFrame &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;GeoDataFrame.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;from_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;establishments.gpkg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;entrances: GeoDataFrame &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;GeoDataFrame.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;from_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;entrances.gpkg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;graph &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ox.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;load_graphml&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;network.graphml&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;graph &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ox.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;project_graph&lt;&#x2F;span&gt;&lt;span&gt;(graph, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_crs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;PROJECTION&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a0a1a7;&quot;&gt;# Ensure the same CRS
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;(establishments.crs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;!= &lt;&#x2F;span&gt;&lt;span&gt;entrances.crs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;!= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;PROJECTION&lt;&#x2F;span&gt;&lt;span&gt;):
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;100&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a0a1a7;&quot;&gt;# Helper function to get the distance between a graph node and establishment geometry
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;def &lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;node_geom_dist&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;node_id&lt;&#x2F;span&gt;&lt;span&gt;: int, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;geom&lt;&#x2F;span&gt;&lt;span&gt;: shp.Point):
&lt;&#x2F;span&gt;&lt;span&gt;    node &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;graph.nodes[node_id]
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span&gt;math.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;sqrt&lt;&#x2F;span&gt;&lt;span&gt;((geom.x &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;node[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;#39;x&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;2 &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span&gt;(geom.y &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;- &lt;&#x2F;span&gt;&lt;span&gt;node[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;#39;y&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;** &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;distances: list[float] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;id&lt;&#x2F;span&gt;&lt;span&gt;, establishment) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;establishments.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;iterrows&lt;&#x2F;span&gt;&lt;span&gt;():
&lt;&#x2F;span&gt;&lt;span&gt;    establishment_geom: shp.Point &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;establishment.geometry
&lt;&#x2F;span&gt;&lt;span&gt;    establishment_node: int &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ox.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;nearest_nodes&lt;&#x2F;span&gt;&lt;span&gt;(graph, establishment_geom.x, establishment_geom.y)
&lt;&#x2F;span&gt;&lt;span&gt;    establishment_dist_to_node: float &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;node_geom_dist&lt;&#x2F;span&gt;&lt;span&gt;(establishment_node, establishment_geom)
&lt;&#x2F;span&gt;&lt;span&gt;    
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a0a1a7;&quot;&gt;# Spatial index for rail entrances
&lt;&#x2F;span&gt;&lt;span&gt;    index: shp.STRtree &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;entrances.sindex
&lt;&#x2F;span&gt;&lt;span&gt;    nearest_q &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;index.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;query&lt;&#x2F;span&gt;&lt;span&gt;(establishment_geom, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;predicate&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;dwithin&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;distance &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;1000&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;span&gt;    nearest_entrances: list[tuple[int, float]] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;nearest_q:
&lt;&#x2F;span&gt;&lt;span&gt;        ent &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;entrances.iloc[i]
&lt;&#x2F;span&gt;&lt;span&gt;        ent_geom: shp.Point &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ent.geometry
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;        dist &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;ent_geom.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;distance&lt;&#x2F;span&gt;&lt;span&gt;(establishment.geometry)
&lt;&#x2F;span&gt;&lt;span&gt;        
&lt;&#x2F;span&gt;&lt;span&gt;        nearest_entrances.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;((i, dist))
&lt;&#x2F;span&gt;&lt;span&gt;     
&lt;&#x2F;span&gt;&lt;span&gt;    nearest_entrances &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;sorted&lt;&#x2F;span&gt;&lt;span&gt;(nearest_entrances, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;key &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= lambda &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span&gt;: e[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;])[:&lt;&#x2F;span&gt;&lt;span style=&quot;color:#c18401;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;]
&lt;&#x2F;span&gt;&lt;span&gt;    entrance_geom: list[shp.Point] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[entrances.iloc[i].geometry &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;_&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;nearest_entrances]
&lt;&#x2F;span&gt;&lt;span&gt;    entrance_nodes: list[int] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[ox.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;nearest_nodes&lt;&#x2F;span&gt;&lt;span&gt;(graph, point.x, point.y) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;point &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;entrance_geom]
&lt;&#x2F;span&gt;&lt;span&gt;    entrance_geom_dist_to_node: list[float] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;node_geom_dist&lt;&#x2F;span&gt;&lt;span&gt;(entrance_nodes[i], entrance_geom[i]) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;i &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;range&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span&gt;(nearest_entrances))]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    result_paths &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[nx.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;shortest_path&lt;&#x2F;span&gt;&lt;span&gt;(graph, establishment_node, dest_node, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;weight&lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;length&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;dest_node &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span&gt;entrance_nodes]
&lt;&#x2F;span&gt;&lt;span&gt;    result_lengths: list[float] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;[nx.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;path_weight&lt;&#x2F;span&gt;&lt;span&gt;(graph, path, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;length&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span&gt;entrance_geom_dist_to_node[i] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;+ &lt;&#x2F;span&gt;&lt;span&gt;establishment_dist_to_node &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span&gt;(i, path) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;in &lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span&gt;(result_paths)]
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;    distances.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;append&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#0184bc;&quot;&gt;min&lt;&#x2F;span&gt;&lt;span&gt;(result_lengths))
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;establishments[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;distance&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color:#a626a4;&quot;&gt;= &lt;&#x2F;span&gt;&lt;span&gt;distances 
&lt;&#x2F;span&gt;&lt;span&gt;establishments.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#e45649;&quot;&gt;to_file&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#50a14f;&quot;&gt;&amp;quot;establishment_results.gpkg&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;)
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Not exactly my finest work. The sheer amount of list comprehension is perhaps a little terrifying, but it works.&lt;&#x2F;p&gt;
&lt;p&gt;After some prodding around in QGIS with the resulting data and networks (and many print() statements), I was confident in the accuracy of the results.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;results&quot;&gt;Results&lt;a class=&quot;zola-anchor&quot; href=&quot;#results&quot; aria-label=&quot;Anchor link for: results&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;Now with all of this data, it is time to settle the question of whether or not the kebabs are less tasty the closer they are to a train&#x2F;metro station...&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-7.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-7.1ff7f2b316a90f62.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

&lt;em&gt;Figure 7. Hmmmmm....&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;With a mighty Pearson&#x27;s correlation of 0.091, the data indicates that this could be true! If you ignore the fact that the correlation is so weak that calling it &#x27;statistically insignificant&#x27; would be quite generous.&lt;&#x2F;p&gt;
&lt;p&gt;Outliers can have an outsized impact on a Pearson&#x27;s correlation, so after ridding the dataset of some outliers via IQR fencing...&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-8.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-8.af2b5c5cacb7b32d.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

&lt;em&gt;Figure 8. Removed outliers&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;... This increased the coefficient to a whopping 0.098.&lt;&#x2F;p&gt;
&lt;p&gt;This was a bit of a bummer (though hardly surprising) and figuring I had nothing to lose from messing around a little, I tried filtering out metro stations in case my original assumption of the metro being included in the original hypothesis was incorrect.&lt;&#x2F;p&gt;
&lt;p&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;www.jmspae.se&#x2F;write-ups&#x2F;kebabs-train-stations&#x2F;fig-9.webp&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;www.jmspae.se&amp;#x2F;processed_images&amp;#x2F;fig-9.3427bdea5242e0b1.jpg&quot; &#x2F;&gt;&lt;&#x2F;a&gt;

*Figure 9. Not much better, eh? Correction: &quot;... Nearest train station entrance.&quot;&lt;&#x2F;p&gt;
&lt;p&gt;With an even worse coefficient of 0.001, I think It&#x27;s time to hang up the towel.&lt;&#x2F;p&gt;
&lt;p&gt;Whilst there are some minor indications that the hypothesis &lt;em&gt;could&lt;&#x2F;em&gt; be correct (eg. Many of the absolute worst restaurants being some of the closest) the correlation is simply too weak.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;discussion&quot;&gt;Discussion&lt;a class=&quot;zola-anchor&quot; href=&quot;#discussion&quot; aria-label=&quot;Anchor link for: discussion&quot;&gt;🔗&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;- Are Google reviews an objective measurement of how tasty the kebabs are?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Absolutely the f### not. This was a rather subjective observation from the very beginning and Google reviews aren&#x27;t exactly a good measure of &quot;is the food good?&quot; There are many aspects of the dining experience that could hypothetically impact a review score. The staff, cleanliness, the surrounding environment, etc. Not to mention online skulduggery and review manipulation.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;- Can tourism have an impact?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It absolutely could. I don&#x27;t want to make any definitive assumptions, but I can absolutely imagine the local regulars being harsher than the massive tourist population, or even vice-versa.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;- Were the Google results accurate?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;To an extent, yes. From what I could gather, every location from the query seemed to serve kebab in some form. There were a few weird outliers and nuances, such as Pizza Hut which likely only serves kebab pizza rather than the multitude of different forms in which kebab could possibly be consumed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;- Why not restaurants in general?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Because the initial hypothesis was too comically hyper-specific for me to give up on.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;- What about review count?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This could very well have an effect, though I was not entirely certain how to properly implement this metric into the analysis at the time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;- Gib Data&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not quite comfortable in doing so, mostly due to potential breaches of Google&#x27;s TOS. I don&#x27;t think they would care about me harvesting some 400 POIs for this little experiment, I&#x27;m not quite willing to gamble sharing the data with others.&lt;&#x2F;p&gt;
&lt;p&gt;Besides, I gave you the code. Go burn some of your own credits.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;- Are you Ok?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;... I guess? Are you?&lt;&#x2F;p&gt;
&lt;p&gt;In conclusion, this was actually quite fun. I wrote this as the project went on (otherwise I would likely never have found the motivation) and I would encourage others to do other silly explorations like this, even if the results end up slightly depressing.&lt;&#x2F;p&gt;
&lt;p&gt;... &lt;em&gt;However&lt;&#x2F;em&gt;, after some additional discussion, I decided I wasn&#x27;t quite done.&lt;&#x2F;p&gt;
&lt;p&gt;As stated earlier, there were a few detracting comments on the original French post. Interestingly, many of the provided examples of good kebab restaurants next to train stations just so happened to be in Paris.&lt;&#x2F;p&gt;
&lt;p&gt;The user who originally posted the French post for the sub in English provided some &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;imgur.com&#x2F;gallery&#x2F;kebab-railway-stations-wuYG9D2&quot;&gt;examples&lt;&#x2F;a&gt; which seem to strengthen the hypothesis. It could very well be that whatever conditions affect Paris restaurants (whether it be higher rent, wages, tourism, population density...) had a larger impact than I initially suspected.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Stay tuned for part 2... Whenever I get around to doing it!&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
