Python >> Tutoriel Python >  >> Python Tag >> Matplotlib

Tracer de grands fichiers de formes avec matplotlib

Ce n'est pas un problème de Matplotlib mais de votre script et du module que vous utilisez pour lire les shapefiles

1) Vous savez qu'il y a des points dans les géométries du shapefile Polygon donc éliminez try... except

2) vous chargez et lisez le shapefile deux fois pour x et y (mémoire)

for shape in shp.shapeRecords():
   xy = [i for i in shape.shape.points[:]]
   x = [i[0] for i in xy]
   y = [i[1] for i in xy]

ou directement

 for shape in shp.shapeRecords():       
       xy = [i for i in shape.shape.points[:]]
       x,y = zip(*[(j[0],j[1]) for j in xy])

3) Vous pouvez également utiliser la Geo_interface (regardez Plot shapefile avec matplotlib)

 for shape in shp.shapeRecords():
     poly = shape.shape.__geo_interface__
     print(poly)
 {'type': 'Polygon', 'coordinates': (((203602.55736766502, 89867.47994546698), (204061.86095852466, 89822.92064187612), (203983.02526755622, 89322.48538616339), (203684.82069737124, 89031.13609345393), (203280.35932631575, 89260.78788888374), (203184.3854416585, 89624.11759508614), (203602.55736766502, 89867.47994546698)),)}

Et vous avez la représentation GeoJSON de la géométrie (Polygon). Vous pouvez tracer le polygone comme dans la référence

L'anneau linéaire du polygone

 x,y = zip(*[(i[0],i[1]) for i in poly['coordinates'][0]])

Et les nœuds du Polygone

4) Le problème de Pyshp (shapefile) est qu'il charge le shapefile complet en mémoire et si le shapefile est trop gros...
Vous pouvez utiliser un générateur (lire la couche une entité par une entité)

def records(filename):  
  # generator 
  reader = shapefile.Reader(filename)   
  for sr in reader.shapeRecords():  
      geom = sr.shape.__geo_interface__  
      yield geom

  features  = records("a_polygon.shp")
  features.next()
  {'type': 'Polygon', 'coordinates': (((203602.55736766502, 89867.47994546698), (204061.86095852466, 89822.92064187612), (203983.02526755622, 89322.48538616339), (203684.82069737124, 89031.13609345393), (203280.35932631575, 89260.78788888374), (203184.3854416585, 89624.11759508614), (203602.55736766502, 89867.47994546698)),)}

Ou directement

  shapes = shapefile.Reader('a_polygon.shp')
  shapes.iterShapes().next().__geo_interface__
  {'type': 'Polygon', 'coordinates': (((203602.55736766502, 89867.47994546698), (204061.86095852466, 89822.92064187612), (203983.02526755622, 89322.48538616339), (203684.82069737124, 89031.13609345393), (203280.35932631575, 89260.78788888374), (203184.3854416585, 89624.11759508614), (203602.55736766502, 89867.47994546698)),)}

5) Soit utiliser un module Python qui utilise directement les générateurs/itérateurs :Fiona

import fiona
shapes = fiona.open("a_polygon.shp")
first = shapes.next() # for for feature in shapes
print(first)
{'geometry': {'type': 'Polygon', 'coordinates': [[(203602.55736766502, 89867.47994546698), (204061.86095852466, 89822.92064187612), (203983.02526755622, 89322.48538616339), (203684.82069737124, 89031.13609345393), (203280.35932631575, 89260.78788888374), (203184.3854416585, 89624.11759508614), (203602.55736766502, 89867.47994546698)]]}, 'type': 'Feature', 'id': '0', 'properties': OrderedDict([(u'id', None)])}
 print(first['geometry']['coordinates']
 [[(203602.55736766502, 89867.47994546698), (204061.86095852466, 89822.92064187612), (203983.02526755622, 89322.48538616339), (203684.82069737124, 89031.13609345393), (203280.35932631575, 89260.78788888374), (203184.3854416585, 89624.11759508614), (203602.55736766502, 89867.47994546698)]]

Vous pouvez utiliser des géopandas pour tracer comme indiqué dans cette réponse.

Vous pouvez également utiliser pyshp comme dans le code suivant

from descartes import PolygonPatch
import shapefile
sf=shapefile.Reader('shapefile')
fig = plt.figure() 
ax = fig.gca() 
for poly in sf.shapes():
    poly_geo=poly.__geo_interface__
    ax.add_patch(PolygonPatch(poly_geo, fc='#ffffff', ec='#000000', alpha=0.5, zorder=2 ))

ax.axis('scaled')
plt.show()

Utilisation de geopandas , le code ressemblerait à :

import geopandas
df = geopandas.read_file(shpFilePath)
df.plot()

et cela devrait également être plus rapide (au moins à partir de geopandas 0.3.0)