Search code examples
geopandasosmnx

Error during momepy.preprocess while generating tessellation based on OpenStreemap


I am working through the Morphological Measuring in Python (momepy) toolkit tutorial and have run into a problem when I step away from the instructions slightly.

When using momepy.preprocess, I have consistently been returned the error "ValueError: Must have equal len keys and value when setting with an iterable."

This only occurs when I try to run momepy.preprocess on an area different than the tutorial - so far that includes Champaign, Urbana, and Peoria, Illinois, USA; Oxford, England; and Jena, Germany. When run on Kahla, Germany (the location featured in the tutorial), the process runs correctly. The osmnx process of pulling the afore mentioned cities seems to work correctly, as does plotting them via plt.subplots. Therefore, I am reasonably confident the problem originates with momepy.preprocess.

The documentation states that momepy.preprocess is "experimental," but due to my own inexperience and lack of expertise, I suspect the problem is mine.

Thank you in advance for any assistance given - I'm very excited about learning more about this powerful set of tools!


Solution

  • The geodataframe fed into momepy.preprocess can contain only polygons. Sometimes OSM returns non-polygon elements in the "buildings" layer. Extracting the polygons from the original geodataframe solved the problem, but in order to avoid removing MultiPolygon geometries which may be valuable, you should use explode before doing so. It is likely necessary to reset_index after using explode and extracting the polygons due to a bug in geopandas.

    Note: the reset index function returns a new GeoDataFrame, it doesn’t alter the original one, so you need to assign it back.

    Here is how my code ended up looking:

    #Get building geometries from OSM
    gdf = ox.geometries.geometries_from_place('Main Quad, Champaign,Illinois', tags={'building':True}, buffer_dist=1000)
    
    gdf_projected = ox.projection.project_gdf(gdf)
    
    #Explode muti-part geometries into multiple single geometries. 
    gdf_exploded = gdf_projected.explode()
    
    #Strip out polygons from exploded gdf
    gdf_exploded_poly = gdf_exploded.loc[gdf_exploded.geometry.type=='Polygon',:]
    
    #Reset index
    gdf_exploded_poly = gdf_exploded_poly.reset_index()
    
    #Run momepy.preprocess
    buildings = momepy.preprocess(gdf_exploded_poly, size=30, compactness=0.2, islands=True)