In [1]:
# Allow to import without installing
import sys
sys.path.insert(0, "..")

%matplotlib inline
import matplotlib.pyplot as plt

import numpy as np
import pandas as pd
import geopandas as gpd

How to build a GeoDataFrame

We firstly explore how to do this by using the GeoJSON schema.

It's then as simple as this...


In [2]:
point_features = [{"geometry": {
               "type": "Point",
               "coordinates": [102.0, 0.5]
            },
           "properties": {
               "prop0": "value0", "prop1": "value1"
           }
       }]

point_data = gpd.GeoDataFrame.from_features(point_features)
point_data


Out[2]:
geometry prop0 prop1
0 POINT (102 0.5) value0 value1

In [3]:
point_data.ix[0].geometry


Out[3]:

In [4]:
line_features = [{"geometry": {
               "type": "LineString",
               "coordinates": [[102.0, 0.5], [104, 3], [103, 2]]
           },
           "properties": {
               "prop3": "value3"
           }
       }]

line_data = gpd.GeoDataFrame.from_features(line_features)
line_data


Out[4]:
geometry prop3
0 LINESTRING (102 0.5, 104 3, 103 2) value3

In [5]:
line_data.ix[0].geometry


Out[5]:

In [6]:
polygon_features = [{"geometry": {
               "type": "Polygon",
               "coordinates": [[[102.0, 0.5], [104, 3], [102, 2], [102,0.5]]]
           },
           "properties": {
               "prop4": "value4", "prop1": "value1"
           }
       }]

data = gpd.GeoDataFrame.from_features(polygon_features)
data


Out[6]:
geometry prop1 prop4
0 POLYGON ((102 0.5, 104 3, 102 2, 102 0.5)) value1 value4

In [7]:
data.plot()


Out[7]:
<matplotlib.axes._subplots.AxesSubplot at 0x15de5663198>

In [8]:
data.ix[0].geometry


Out[8]:

In [9]:
features = []
features.extend(point_features)
features.extend(line_features)
features.extend(polygon_features)
gpd.GeoDataFrame.from_features(features)


Out[9]:
geometry prop0 prop1 prop3 prop4
0 POINT (102 0.5) value0 value1 NaN NaN
1 LINESTRING (102 0.5, 104 3, 103 2) NaN NaN value3 NaN
2 POLYGON ((102 0.5, 104 3, 102 2, 102 0.5)) NaN value1 NaN value4

Notes

Some things that jumped out at me as I read the GeoJSON spec:

  • Coordinates are always in the order: longitude, latitude.
  • A "Polygon" is allowed to contain holes. The "outer" edge should be ordered counter-clockwise, and each "inner" edge (i.e. a "hole") should be clockwise.
  • If a polygon contains more than one array of points, then the first array is the outer edge, and the rest inner edges.
  • Lines crossing the anti-meridian need to be split. (I wonder what OSM does?)

Via using shapely

Under the hood, geopandas uses the shapely library, and we can alternatively build data frames by directly building shapely objects


In [10]:
type(point_data.geometry[0]), type(line_data.geometry[0]), type(data.geometry[0])


Out[10]:
(shapely.geometry.point.Point,
 shapely.geometry.linestring.LineString,
 shapely.geometry.polygon.Polygon)

In [11]:
import shapely.geometry

In [12]:
pts = shapely.geometry.LineString([shapely.geometry.Point(0,0), shapely.geometry.Point(1,0), shapely.geometry.Point(1,1)])
df = gpd.GeoDataFrame({"geometry": [pts], "key1":["value1"], "key2":["value2"]})
df


Out[12]:
geometry key1 key2
0 LINESTRING (0 0, 1 0, 1 1) value1 value2

In [13]:
df.ix[0].geometry


Out[13]:

Support in the library


In [14]:
import osmdigest.geometry as geometry
import osmdigest.sqlite as sq

import os
filename = os.path.join("..", "..", "..", "Data", "california-latest.db")

In [15]:
db = sq.OSM_SQLite(filename)
way = db.complete_way(33088737)
series = geometry.geoseries_from_way(way)
series


Out[15]:
geometry    LINESTRING (-122.244191 37.819027, -122.244287...
osm_id                                               33088737
dtype: object

In [16]:
gpd.GeoDataFrame(series).T.plot()


Out[16]:
<matplotlib.axes._subplots.AxesSubplot at 0x15de5b8d940>

In [17]:
way = db.complete_way(285549437)
series = geometry.geoseries_from_way(way)
series


Out[17]:
addr:city                                                    Piedmont
addr:housenumber                                                  344
addr:postcode                                                   94611
addr:street                                           Highland Avenue
amenity                                                          bank
building                                                          yes
geometry            LINESTRING (-122.2314666 37.8246631, -122.2313...
name                                                      Wells Fargo
osm_id                                                      285549437
dtype: object

In [18]:
df = gpd.GeoDataFrame(series).T
df


Out[18]:
addr:city addr:housenumber addr:postcode addr:street amenity building geometry name osm_id
0 Piedmont 344 94611 Highland Avenue bank yes LINESTRING (-122.2314666 37.8246631, -122.2313... Wells Fargo 285549437

In [19]:
df.plot()


Out[19]:
<matplotlib.axes._subplots.AxesSubplot at 0x15de5bb5f98>

For relations

We can build a geo data frame with the raw data from a relation.


In [20]:
relation = db.complete_relation(2866485)
geometry.geodataframe_from_relation(relation)


Out[20]:
barrier geometry members name note osm_id place population role source wikidata wikipedia
0 NaN None [(node, 2155598516, admin_centre), (node, 2155... Palm Springs Areas listed as city by county, not city's sph... 2866485 city 44552 NaN RCTLMA_GIS Q488004 en:Palm Springs, California
1 NaN POINT (-116.540303 33.8246269) NaN Palm Springs NaN 2155598516 city 44552 admin_centre Wikipedia NaN en:Palm Springs, California
2 NaN POINT (-116.540303 33.8246269) NaN Palm Springs NaN 2155598516 city 44552 label Wikipedia NaN en:Palm Springs, California
3 NaN LINESTRING (-116.4771365 33.7724258, -116.4755... NaN NaN NaN 301016136 NaN NaN outer NaN NaN NaN
4 NaN LINESTRING (-116.4776487 33.7724256, -116.4771... NaN NaN NaN 301016103 NaN NaN outer NaN NaN NaN
5 NaN LINESTRING (-116.4776496 33.7721148, -116.4776... NaN NaN NaN 301016104 NaN NaN outer NaN NaN NaN
6 NaN LINESTRING (-116.4779212 33.7710789, -116.4778... NaN NaN NaN 301016134 NaN NaN outer NaN NaN NaN
7 NaN LINESTRING (-116.4782632 33.7705517, -116.4780... NaN NaN NaN 301016125 NaN NaN outer NaN NaN NaN
8 NaN LINESTRING (-116.4801208 33.7667125, -116.4784... NaN NaN NaN 301016128 NaN NaN outer NaN NaN NaN
9 NaN LINESTRING (-116.480614 33.7656544, -116.48012... NaN NaN NaN 301016110 NaN NaN outer NaN NaN NaN
10 NaN LINESTRING (-116.4814603 33.7624376, -116.4812... NaN NaN NaN 216274692 NaN NaN outer NaN NaN NaN
11 NaN LINESTRING (-116.4821181 33.7615081, -116.4816... NaN NaN NaN 301016127 NaN NaN outer NaN NaN NaN
12 NaN LINESTRING (-116.4813274 33.7605874, -116.4821... NaN NaN NaN 301016116 NaN NaN outer NaN NaN NaN
13 NaN LINESTRING (-116.4811359 33.7605569, -116.4813... NaN NaN NaN 301006748 NaN NaN outer NaN NaN NaN
14 NaN LINESTRING (-116.4782206 33.7595696, -116.4811... NaN NaN NaN 301006782 NaN NaN outer NaN NaN NaN
15 wall LINESTRING (-116.477768 33.7594163, -116.47822... NaN NaN NaN 301006724 NaN NaN outer NaN NaN NaN
16 NaN LINESTRING (-116.4776832 33.7593876, -116.4777... NaN NaN NaN 301006719 NaN NaN outer NaN NaN NaN
17 NaN LINESTRING (-116.4776856 33.7583431, -116.4776... NaN NaN NaN 301006739 NaN NaN outer NaN NaN NaN
18 NaN LINESTRING (-116.4776871 33.7576554, -116.4776... NaN NaN NaN 301006733 NaN NaN outer NaN NaN NaN
19 NaN LINESTRING (-116.47769 33.7568412, -116.477687... NaN NaN NaN 301006721 NaN NaN outer NaN NaN NaN
20 NaN LINESTRING (-116.4776919 33.7563197, -116.4776... NaN NaN NaN 301006716 NaN NaN outer NaN NaN NaN
21 NaN LINESTRING (-116.4776926 33.7561084, -116.4776... NaN NaN NaN 216274693 NaN NaN outer NaN NaN NaN
22 NaN LINESTRING (-116.4777134 33.7501669, -116.4776... NaN NaN NaN 295884024 NaN NaN outer NaN NaN NaN
23 NaN LINESTRING (-116.4777316 33.7431726, -116.4777... NaN NaN NaN 295884029 NaN NaN outer NaN NaN NaN
24 NaN LINESTRING (-116.4603213 33.74316, -116.477731... NaN NaN NaN 295884048 NaN NaN outer NaN NaN NaN
25 NaN LINESTRING (-116.4602821 33.728644, -116.46032... NaN NaN NaN 295884062 NaN NaN outer NaN NaN NaN
26 NaN LINESTRING (-116.4602508 33.7140741, -116.4602... NaN NaN NaN 216302383 NaN NaN outer NaN NaN NaN
27 NaN LINESTRING (-116.4602508 33.7140741, -116.4601... NaN NaN NaN 216302381 NaN NaN outer NaN NaN NaN
28 NaN LINESTRING (-116.4428115 33.6415993, -116.4428... NaN NaN NaN 216302370 NaN NaN outer NaN NaN NaN
29 NaN LINESTRING (-116.4428115 33.6415993, -116.4601... NaN NaN NaN 216302379 NaN NaN outer NaN NaN NaN
30 NaN LINESTRING (-116.4601592 33.6124671, -116.4775... NaN NaN NaN 216302388 NaN NaN outer NaN NaN NaN
31 NaN LINESTRING (-116.5302458 33.7139949, -116.5128... NaN NaN NaN 216302362 NaN NaN outer NaN NaN NaN
32 NaN LINESTRING (-116.6145628 33.8302599, -116.6146... NaN NaN NaN 216302387 NaN NaN outer NaN NaN NaN
33 NaN LINESTRING (-116.684479 33.8877169, -116.66682... NaN NaN NaN 216302374 NaN NaN outer NaN NaN NaN
34 NaN LINESTRING (-116.6729974 33.9224601, -116.6726... NaN NaN NaN 216302384 NaN NaN outer NaN NaN NaN
35 NaN LINESTRING (-116.6325463 33.9211813, -116.6321... NaN NaN NaN 216302369 NaN NaN outer NaN NaN NaN
36 NaN LINESTRING (-116.5835006 33.9247907, -116.5802... NaN NaN NaN 216302386 NaN NaN outer NaN NaN NaN
37 NaN LINESTRING (-116.5540107 33.9248192, -116.5540... NaN NaN NaN 216302382 NaN NaN outer NaN NaN NaN
38 NaN LINESTRING (-116.5453116 33.9175915, -116.5453... NaN NaN NaN 216302375 NaN NaN outer NaN NaN NaN

In [21]:
geometry.geodataframe_from_relation( db.complete_relation(63222) )


Out[21]:
bridge colour electrified frequency from gauge geometry layer members name ... osm_id railway ref role route route_master to tunnel type voltage
0 NaN #FAA635 contact_line 0 NaN 1435 None NaN [(relation, 2877693, ), (relation, 3433311, )] J-Church ... 63222 light_rail J NaN NaN light_rail NaN NaN route_master 600
1 NaN #FAA635 NaN NaN Balboa Park Station NaN None NaN [(way, 247320917, ), (way, 159785611, ), (way,... J-Church: Inbound to Downtown ... 2877693 NaN J light_rail NaN Embarcadero Station NaN route NaN
2 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.446833 37.7209604, -122.44679... NaN NaN Muni Metro ... 247320917 light_rail NaN NaN NaN NaN NaN NaN 600
3 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4458288 37.7219202, -122.4457... NaN NaN Muni J ... 159785611 light_rail NaN NaN NaN NaN NaN NaN 600
4 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4446761 37.7230291, -122.4443... NaN NaN Muni J ... 159791118 light_rail NaN NaN NaN NaN NaN NaN 600
5 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4385522 37.7298607, -122.4384... NaN NaN Muni J ... 160279679 light_rail NaN NaN NaN NaN NaN NaN 600
6 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4353891 37.7311316, -122.4351... -1 NaN Muni J ... 309010742 light_rail NaN NaN NaN NaN yes NaN 600
7 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4350813 37.7316453, -122.4350... NaN NaN Muni J ... 309010734 light_rail NaN NaN NaN NaN NaN NaN 600
8 yes NaN contact_line 0 NaN 1435 LINESTRING (-122.4326384 37.7329369, -122.4320... 2 NaN Muni J ... 159798877 light_rail NaN NaN NaN NaN NaN NaN 600
9 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4320284 37.7332331, -122.4312... NaN NaN Muni J ... 160268072 light_rail NaN NaN NaN NaN NaN NaN 600
10 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.423347 37.742122, -122.423337... NaN NaN Muni J ... 160272613 light_rail NaN NaN NaN NaN NaN NaN 600
11 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4265292 37.7423202, -122.4265... NaN NaN Muni J ... 160272583 light_rail NaN NaN NaN NaN NaN NaN 600
12 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4277179 37.7546853, -122.4277... NaN NaN Muni J ... 160270943 light_rail NaN NaN NaN NaN NaN NaN 600
13 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4283697 37.7614531, -122.4284... NaN NaN Muni J ... 142843532 light_rail NaN NaN NaN NaN NaN NaN 600
14 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4289267 37.7672859, -122.4289... NaN NaN Muni J ... 27145509 light_rail NaN NaN NaN NaN NaN NaN 600
15 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.428885 37.7694495, -122.42884... NaN NaN Muni Metro ... 27145527 light_rail NaN NaN NaN NaN NaN NaN 600
16 NaN NaN NaN NaN NaN NaN LINESTRING (-122.4271746 37.7695516, -122.4264... NaN NaN NaN ... 252221514 light_rail NaN NaN NaN NaN yes NaN NaN
17 NaN NaN NaN NaN NaN NaN LINESTRING (-122.4259714 37.769864, -122.42613... -1 NaN Muni Metro ... 160306978 light_rail NaN NaN NaN NaN yes NaN NaN
18 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.3969324 37.792879, -122.40120... -1 NaN Muni Metro ... 340366203 light_rail NaN NaN NaN NaN yes NaN 600
19 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.3958183 37.7937502, -122.3969... -1 NaN Muni Metro ... 160333986 light_rail NaN NaN NaN NaN yes NaN 600
20 NaN #FAA635 NaN NaN Embarcadero Station NaN None NaN [(way, 160333986, ), (way, 340366203, ), (way,... J-Church: Outbound to Balboa Park ... 3433311 NaN J light_rail NaN Balboa Park Station NaN route NaN
21 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.3958183 37.7937502, -122.3969... -1 NaN Muni Metro ... 160333986 light_rail NaN NaN NaN NaN yes NaN 600
22 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.3969324 37.792879, -122.40120... -1 NaN Muni Metro ... 340366203 light_rail NaN NaN NaN NaN yes NaN 600
23 NaN NaN NaN NaN NaN NaN LINESTRING (-122.4259714 37.769864, -122.42610... -1 NaN Muni Metro ... 160307216 light_rail NaN NaN NaN NaN yes NaN NaN
24 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4271777 37.769586, -122.42861... NaN NaN Muni Metro ... 216045932 light_rail NaN NaN NaN NaN NaN NaN 600
25 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.428928 37.7694799, -122.42899... NaN NaN Muni J ... 160281860 light_rail NaN NaN NaN NaN NaN NaN 600
26 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4289627 37.7672876, -122.4288... NaN NaN Muni J ... 160272608 light_rail NaN NaN NaN NaN NaN NaN 600
27 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4284093 37.7614511, -122.4284... NaN NaN Muni J ... 160272584 light_rail NaN NaN NaN NaN NaN NaN 600
28 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4277519 37.7546832, -122.4269... NaN NaN Muni J ... 160272598 light_rail NaN NaN NaN NaN NaN NaN 600
29 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4265677 37.742319, -122.42655... NaN NaN Muni J ... 160272626 light_rail NaN NaN NaN NaN NaN NaN 600
30 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.42342 37.7420698, -122.423704... NaN NaN Muni J ... 160272619 light_rail NaN NaN NaN NaN NaN NaN 600
31 yes NaN contact_line 0 NaN 1435 LINESTRING (-122.4320798 37.7332618, -122.4326... 2 NaN Muni J ... 160272602 light_rail NaN NaN NaN NaN NaN NaN 600
32 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4326883 37.7329691, -122.4328... NaN NaN Muni J ... 309010756 light_rail NaN NaN NaN NaN NaN NaN 600
33 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4351319 37.7316664, -122.4351... -1 NaN Muni J ... 309010747 light_rail NaN NaN NaN NaN yes NaN 600
34 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4354583 37.7311016, -122.4354... NaN NaN Muni J ... 309010759 light_rail NaN NaN NaN NaN NaN NaN 600
35 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4385742 37.7298829, -122.4389... NaN NaN Muni J ... 160279678 light_rail NaN NaN NaN NaN NaN NaN 600
36 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.4447109 37.7230433, -122.4447... NaN NaN Muni J ... 159791122 light_rail NaN NaN NaN NaN NaN NaN 600
37 NaN NaN contact_line 0 NaN 1435 LINESTRING (-122.447138 37.7226667, -122.44716... NaN NaN Muni Metro ... 159785610 light_rail NaN NaN NaN NaN NaN NaN 600

38 rows × 25 columns

Looking at relations

These are harder to compute automatically, because the exact interpretation of the sub-elements depends upon context. However, most relations which have "interesting" geometry (as opposed to giving contextual information on other elements) are of "multi-polygon" type, and can be recognised by the presence of ways with the "role" of "inner" or "outer".

I found that using the shapely library itself was the easiest way to conver the geometry.

There are some cases of geometry which shapely cannot handle. For example:


In [264]:
gen = db.relations()
for _ in range(15):
    next(gen)

relation = next(gen)
print(relation)
series = geometry.geoseries_from_relation(db.complete_relation(relation))
series


Relation(22601 ->  [Member(type='way', ref=25774607, role='outer'), Member(type='way', ref=25790915, role='inner')] {'name': 'Charles W. Davidson College of Engineering', 'type': 'multipolygon', 'source': 'survey', 'website': 'http://www.engr.sjsu.edu/', 'building': 'university'})
Out[264]:
building                                           university
geometry    POLYGON ((-121.8819651 37.3363975, -121.881993...
name               Charles W. Davidson College of Engineering
osm_id                                                  22601
source                                                 survey
type                                             multipolygon
website                             http://www.engr.sjsu.edu/
dtype: object

In [265]:
gpd.GeoDataFrame(series).T.plot()


Out[265]:
<matplotlib.axes._subplots.AxesSubplot at 0x15de9b8bf98>