|
| 1 | +{ |
| 2 | +"cells": [ |
| 3 | + { |
| 4 | +"cell_type":"markdown", |
| 5 | +"metadata": {}, |
| 6 | +"source": [ |
| 7 | +"## GeoJSON Example - Stations\n", |
| 8 | +"\n", |
| 9 | +"In this Python snippet we use stations (geographic) from the Swiss public transportation and convert the data to a GeoJSON (http://geojson.org/) file.\n", |
| 10 | +"\n", |
| 11 | +"\n", |
| 12 | +"- Donwload the _'bfkoordgeo.csv'_ file, https://opentransportdata.swiss/en/dataset/bhlist/resource/b92a372f-7843-4ddd-b1c6-c9c6397e1097\n", |
| 13 | +"- Convert the file from ISO-8859-1 to UTF-8\n", |
| 14 | +"\n", |
| 15 | +"```\n", |
| 16 | +"iconv -f ISO-8859-1 -t UTF-8 bfkoordgeo.csv > out.csv\n", |
| 17 | +"```\n", |
| 18 | +"\n", |
| 19 | +"\n", |
| 20 | +"> __Note:__ The data is from the _Open Data Platform Swiss Public Transport_, https://opentransportdata.swiss/en/\n", |
| 21 | +"\n", |
| 22 | +"\n", |
| 23 | +"### Required libraries\n", |
| 24 | +"- pandas, http://pandas.pydata.org/\n", |
| 25 | +"- geojson, https://pypi.python.org/pypi/geojson/\n" |
| 26 | + ] |
| 27 | + }, |
| 28 | + { |
| 29 | +"cell_type":"markdown", |
| 30 | +"metadata": {}, |
| 31 | +"source": [ |
| 32 | +"### Load the data\n", |
| 33 | +"First let's load the data with pandas. The data frame contains the stations from the public transportations from Switzerland and some from adjoining countries. We have the columns:\n", |
| 34 | +"- StationID\n", |
| 35 | +"- Longitude\n", |
| 36 | +"- Latitude\n", |
| 37 | +"- Height\n", |
| 38 | +"- Remark\n", |
| 39 | +"\n", |
| 40 | +"Longitude and Latitude should be _WGS 84_ coordinates." |
| 41 | + ] |
| 42 | + }, |
| 43 | + { |
| 44 | +"cell_type":"code", |
| 45 | +"execution_count":4, |
| 46 | +"metadata": { |
| 47 | +"collapsed":false |
| 48 | + }, |
| 49 | +"outputs": [ |
| 50 | + { |
| 51 | +"data": { |
| 52 | +"text/html": [ |
| 53 | +"<div>\n", |
| 54 | +"<table border=\"1\" class=\"dataframe\">\n", |
| 55 | +" <thead>\n", |
| 56 | +" <tr style=\"text-align: right;\">\n", |
| 57 | +" <th></th>\n", |
| 58 | +" <th>StationID</th>\n", |
| 59 | +" <th>Longitude</th>\n", |
| 60 | +" <th>Latitude</th>\n", |
| 61 | +" <th>Height</th>\n", |
| 62 | +" <th>Remark</th>\n", |
| 63 | +" </tr>\n", |
| 64 | +" </thead>\n", |
| 65 | +" <tbody>\n", |
| 66 | +" <tr>\n", |
| 67 | +" <th>0</th>\n", |
| 68 | +" <td>6</td>\n", |
| 69 | +" <td>7.549783</td>\n", |
| 70 | +" <td>47.216111</td>\n", |
| 71 | +" <td>441</td>\n", |
| 72 | +" <td>St. Katharinen</td>\n", |
| 73 | +" </tr>\n", |
| 74 | +" <tr>\n", |
| 75 | +" <th>1</th>\n", |
| 76 | +" <td>7</td>\n", |
| 77 | +" <td>9.733756</td>\n", |
| 78 | +" <td>46.922368</td>\n", |
| 79 | +" <td>744</td>\n", |
| 80 | +" <td>Fideris</td>\n", |
| 81 | +" </tr>\n", |
| 82 | +" <tr>\n", |
| 83 | +" <th>2</th>\n", |
| 84 | +" <td>11</td>\n", |
| 85 | +" <td>7.389462</td>\n", |
| 86 | +" <td>47.191804</td>\n", |
| 87 | +" <td>467</td>\n", |
| 88 | +" <td>Grenchen Nord</td>\n", |
| 89 | +" </tr>\n", |
| 90 | +" <tr>\n", |
| 91 | +" <th>3</th>\n", |
| 92 | +" <td>16</td>\n", |
| 93 | +" <td>6.513937</td>\n", |
| 94 | +" <td>46.659019</td>\n", |
| 95 | +" <td>499</td>\n", |
| 96 | +" <td>La Sarraz, Couronne</td>\n", |
| 97 | +" </tr>\n", |
| 98 | +" <tr>\n", |
| 99 | +" <th>4</th>\n", |
| 100 | +" <td>22</td>\n", |
| 101 | +" <td>7.589551</td>\n", |
| 102 | +" <td>47.547405</td>\n", |
| 103 | +" <td>277</td>\n", |
| 104 | +" <td>Basel SBB</td>\n", |
| 105 | +" </tr>\n", |
| 106 | +" </tbody>\n", |
| 107 | +"</table>\n", |
| 108 | +"</div>" |
| 109 | + ], |
| 110 | +"text/plain": [ |
| 111 | +" StationID Longitude Latitude Height Remark\n", |
| 112 | +"0 6 7.549783 47.216111 441 St. Katharinen\n", |
| 113 | +"1 7 9.733756 46.922368 744 Fideris\n", |
| 114 | +"2 11 7.389462 47.191804 467 Grenchen Nord\n", |
| 115 | +"3 16 6.513937 46.659019 499 La Sarraz, Couronne\n", |
| 116 | +"4 22 7.589551 47.547405 277 Basel SBB" |
| 117 | + ] |
| 118 | + }, |
| 119 | +"execution_count":4, |
| 120 | +"metadata": {}, |
| 121 | +"output_type":"execute_result" |
| 122 | + } |
| 123 | + ], |
| 124 | +"source": [ |
| 125 | +"import pandas as pd\n", |
| 126 | +"\n", |
| 127 | +"df = pd.read_csv('data/bfkoordgeo_utf8.csv')\n", |
| 128 | +"df.head()" |
| 129 | + ] |
| 130 | + }, |
| 131 | + { |
| 132 | +"cell_type":"markdown", |
| 133 | +"metadata": {}, |
| 134 | +"source": [ |
| 135 | +"Now we do some data cleaning and remove all rows where _Longitude_ and _Latitude_ are _'null'_." |
| 136 | + ] |
| 137 | + }, |
| 138 | + { |
| 139 | +"cell_type":"code", |
| 140 | +"execution_count":5, |
| 141 | +"metadata": { |
| 142 | +"collapsed":false, |
| 143 | +"scrolled":true |
| 144 | + }, |
| 145 | +"outputs": [], |
| 146 | +"source": [ |
| 147 | +"df = df[df['Longitude'].notnull()]\n", |
| 148 | +"df = df[df['Latitude'].notnull()]\n", |
| 149 | +"\n", |
| 150 | +"# will display all rows that have null values\n", |
| 151 | +"#df[df.isnull().any(axis=1)]" |
| 152 | + ] |
| 153 | + }, |
| 154 | + { |
| 155 | +"cell_type":"markdown", |
| 156 | +"metadata": {}, |
| 157 | +"source": [ |
| 158 | +"### Convert pandas data frame to GeoJSON\n", |
| 159 | +"Next we convert the panda data frame to geosjon objects (_FeatureCollection/Feature/Point_)." |
| 160 | + ] |
| 161 | + }, |
| 162 | + { |
| 163 | +"cell_type":"code", |
| 164 | +"execution_count":6, |
| 165 | +"metadata": { |
| 166 | +"collapsed":false |
| 167 | + }, |
| 168 | +"outputs": [ |
| 169 | + { |
| 170 | +"ename":"ImportError", |
| 171 | +"evalue":"No module named geojson", |
| 172 | +"output_type":"error", |
| 173 | +"traceback": [ |
| 174 | +"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
| 175 | +"\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)", |
| 176 | + "\u001b[0;32m<ipython-input-6-24a9a6f30e7a>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mgeojson\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mgeojson\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mvalues\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'Longitude'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'Latitude'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdf\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'Remark'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mpoints\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mgeojson\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mFeature\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgeometry\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mgeojson\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mPoint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mproperties\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m{\u001b[0m\u001b[0;34m'name'\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m}\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", |
| 177 | +"\u001b[0;31mImportError\u001b[0m: No module named geojson" |
| 178 | + ] |
| 179 | + } |
| 180 | + ], |
| 181 | +"source": [ |
| 182 | +"import geojson as geojson\n", |
| 183 | +"\n", |
| 184 | +"values = zip(df['Longitude'], df['Latitude'], df['Remark'])\n", |
| 185 | +"points = [geojson.Feature(geometry=geojson.Point((v[0], v[1])), properties={'name': v[2]}) for v in values]\n", |
| 186 | +"\n", |
| 187 | +"geo_collection = geojson.FeatureCollection(points)\n", |
| 188 | +"\n", |
| 189 | +"print(points[0])" |
| 190 | + ] |
| 191 | + }, |
| 192 | + { |
| 193 | +"cell_type":"markdown", |
| 194 | +"metadata": {}, |
| 195 | +"source": [ |
| 196 | +"### Save the GeoJSON (FeatureCollection) to a file\n", |
| 197 | +"Finally we dump the GeoJSON objects to a file." |
| 198 | + ] |
| 199 | + }, |
| 200 | + { |
| 201 | +"cell_type":"code", |
| 202 | +"execution_count":1, |
| 203 | +"metadata": { |
| 204 | +"collapsed":false |
| 205 | + }, |
| 206 | +"outputs": [ |
| 207 | + { |
| 208 | +"ename":"NameError", |
| 209 | +"evalue":"name 'geojson' is not defined", |
| 210 | +"output_type":"error", |
| 211 | +"traceback": [ |
| 212 | +"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
| 213 | +"\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", |
| 214 | + "\u001b[0;32m<ipython-input-1-49573f81a20e>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdump\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mgeojson\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdumps\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mgeo_collection\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msort_keys\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m '''\n\u001b[1;32m 4\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'stations.geojson'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'w'\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mfile\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mfile\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mwrite\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdump\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
| 215 | +"\u001b[0;31mNameError\u001b[0m: name 'geojson' is not defined" |
| 216 | + ] |
| 217 | + } |
| 218 | + ], |
| 219 | +"source": [ |
| 220 | +"dump = geojson.dumps(geo_collection, sort_keys=True)\n", |
| 221 | +"\n", |
| 222 | +"'''\n", |
| 223 | +"with open('stations.geojson', 'w') as file:\n", |
| 224 | +" file.write(dump)\n", |
| 225 | +"'''" |
| 226 | + ] |
| 227 | + }, |
| 228 | + { |
| 229 | +"cell_type":"markdown", |
| 230 | +"metadata": {}, |
| 231 | +"source": [ |
| 232 | +"### Result\n", |
| 233 | +"You can find the resulat (GeoJSON file) from this snippet here\n", |
| 234 | +"- [stations.geojson](stations.geojson)" |
| 235 | + ] |
| 236 | + } |
| 237 | + ], |
| 238 | +"metadata": { |
| 239 | +"kernelspec": { |
| 240 | +"display_name":"Python 2", |
| 241 | +"language":"python", |
| 242 | +"name":"python2" |
| 243 | + }, |
| 244 | +"language_info": { |
| 245 | +"codemirror_mode": { |
| 246 | +"name":"ipython", |
| 247 | +"version":2 |
| 248 | + }, |
| 249 | +"file_extension":".py", |
| 250 | +"mimetype":"text/x-python", |
| 251 | +"name":"python", |
| 252 | +"nbconvert_exporter":"python", |
| 253 | +"pygments_lexer":"ipython2", |
| 254 | +"version":"2.7.12" |
| 255 | + } |
| 256 | + }, |
| 257 | +"nbformat":4, |
| 258 | +"nbformat_minor":2 |
| 259 | +} |