10

Unfortunately geopandas plotting is extremely slow and takes a lot of resources, hence I would like to use instead matplotlib for plotting.

When I use pure Fiona to open and read the shapefile I have no trouble to extract the Polygons as matplotlib patches but now I would like to use as starting point the geopandas dataframe to get my matplotlib Polygons.

I am currently using something like:

with FI.open(df_map_elements, 'r') as layer:
    for element in layer:
        key = int(element['id'])
        if key not in dict_mapindex_mpl_polygon.keys():
            dict_mapindex_mpl_polygon[key]=[]
        for tp in element['geometry']['coordinates']:
            q = np.array(tp)
            polygon = Polygon(q) # matplotlib Polygon NOT Shapely

For plotting polygons with matplotlib:

from matplotlib import pyplot as plt
from matplotlib.patches import Polygon
from matplotlib.collections import PatchCollection
9

There is a Python module for that: Descartes (look at Plot shapefile with matplotlib for example)

from geopandas import GeoDataFrame
test = GeoDataFrame.from_file('poly1.shp')
test.set_index('id', inplace=True)
test.sort()
test['geometry']
testid
0    POLYGON ((1105874.411110075 -6125459.381061088...
1    POLYGON ((1106076.359169902 -6125875.557806003...
2    POLYGON ((1106260.568548799 -6125410.258560049...
3    POLYGON ((1105747.511315724 -6125864.64169466,...
Name: geometry, dtype: object

The type of the geometry is a shapely polygon:

 type(test['geometry'][2])
 shapely.geometry.polygon.Polygon

Now you can use Descartes to directly plot a shapely polygon

import matplotlib.pyplot as plt 
from descartes import PolygonPatch
BLUE = '#6699cc'
poly= test['geometry'][2]
fig = plt.figure() 
ax = fig.gca() 
ax.add_patch(PolygonPatch(poly, fc=BLUE, ec=BLUE, alpha=0.5, zorder=2 ))
ax.axis('scaled')
plt.show()

enter image description here

5

After the simple and understandable answer, I came up myself with a straightforward way to plot a whole shp with matplotlib. I feel geopandas should just update their plotting function because this one is simple but so much faster including the full flexibility of matplotlib - adding legend, title, etc.

from descartes import PolygonPatch
import geopandas as gp
import pysal as ps
import numpy as np

# Import libraries for visualization
from matplotlib import pyplot as plt
from matplotlib.patches import Polygon as mpl_Polygon
from matplotlib.collections import PatchCollection

shapefile = 'raw_data/shapefile/yourshapefile.shp'
df_map_elements = gp.GeoDataFrame.from_file(shapefile)

df_map_elements["mpl_polygon"] = np.nan
df_map_elements['mpl_polygon'] = df_map_elements['mpl_polygon'].astype(object)
for self_index, self_row_df in df_map_elements.iterrows():
    m_polygon = self_row_df['geometry']
    poly=[]
    if m_polygon.geom_type == 'MultiPolygon':
        for pol in m_polygon:
            poly.append(PolygonPatch(pol))
    else:
        poly.append(PolygonPatch(m_polygon))
    df_map_elements.set_value(self_index, 'mpl_polygon', poly)

dict_mapindex_mpl_polygon = df_map_elements['mpl_polygon'].to_dict()

And for plotting:

fig, ax = plt.subplots()
for c_l ,patches in dict_mapindex_mpl_polygon.items():
    p = PatchCollection(patches,color='white',lw=.3,edgecolor='k')
    ax.add_collection(p)
ax.autoscale_view()

plt.show()

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.