RubeRad
RubeRad

Reputation: 417

Jupyter/Geopandas plot order breaks figsize

I've got a notebook (github link) where I'm using geopandas to draw maps with various countries colored. Depending on the order of the plots, sometimes it doesn't respect the figsize() I specify. I'm seeing this behavior repeatably in jupyter running locally in Ubuntu 20.04 and Firefox, and both Binder and Colab running in Chromium.

Can somebody help me understand what's going on? Is this a bug or am I controlling geopandas/matplotlib wrong?

import matplotlib.pyplot as plt
import geopandas as gpd

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
sixc = world[ world['continent'] != 'Antarctica' ]
asia = world[ world['continent'] == 'Asia' ]
noam = world[ world['continent'] == 'North America']
swed = world[ world['iso_a3'] == 'SWE' ] 

# This works, makes a 2x1 landscapey aspect
axes = sixc.plot(figsize=(8,4), color='lightgrey')
asia.plot(ax=axes, color='green')
noam.plot(ax=axes, color='purple')

# Plotting swed at the end breaks figsize, makes it squareish
axes = sixc.plot(figsize=(8,4), color='lightgrey')
asia.plot(ax=axes, color='green')
noam.plot(ax=axes, color='purple')
swed.plot(ax=axes, color='yellow')

# Plotting swed in the middle makes it ok again
axes = sixc.plot(figsize=(8,4), color='lightgrey')
asia.plot(ax=axes, color='green')
swed.plot(ax=axes, color='yellow')  
noam.plot(ax=axes, color='purple')

(Also, for some (but not all!) of my students, that broken plot also has no lightgray background countries. Is that likely a result/side-effect of whatever is causing the aspect problem?)

Upvotes: 3

Views: 775

Answers (2)

swatchai
swatchai

Reputation: 18782

With geopandas v 0.8.1 you are using, the default aspect ratio of the plot commands you use is auto. Thus, the output plots you obtained will have unpredictable value of aspect ratio. Try

print(axes.get_aspect()) 

for each plot. In previous version of geopandas, one will get equal as output, and the plots are correct. But in your case, you will get values that do not represent equal aspect.

For a simple fix of your problem, you can add this line of code:

 axes.set_aspect('equal')

after the last plot statement.

Upvotes: 6

David Erickson
David Erickson

Reputation: 16683

This is a great answer regarding how aspect ratio works in matplotlib; however, although the concepts are helpful, GeoSeries.plot is built on top of matplotlib, so that answer might not help in terms of the code that would solve the problem.

The easiest thing to do is to pass aspect='equal' to each GeoSeries.plot as default is 'auto' for "aspect" in link).

As for your other issue, I cannot reproduce, and I would have those students upgrade to the latest versions or use a different IDE. This works for me in a Jupyter Notebook.

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
sixc = world[ world['continent'] != 'Antarctica' ]
asia = world[ world['continent'] == 'Asia' ]
noam = world[ world['continent'] == 'North America']
swed = world[ world['iso_a3'] == 'SWE' ] 

# This works, makes a 2x1 landscapey aspect
axes = sixc.plot(figsize=(8,4), color='lightgrey', aspect='equal')
asia.plot(ax=axes, color='green', aspect='equal')
noam.plot(ax=axes, color='purple', aspect='equal')

# Plotting swed at the end breaks figsize, makes it squareish
axes = sixc.plot(figsize=(8,4), color='lightgrey', aspect='equal')
asia.plot(ax=axes, color='green', aspect='equal')
noam.plot(ax=axes, color='purple', aspect='equal')
swed.plot(ax=axes, color='yellow', aspect='equal')

# Plotting swed in the middle makes it ok again
axes = sixc.plot(figsize=(8,4), color='lightgrey', aspect='equal')
asia.plot(ax=axes, color='green', aspect='equal')
swed.plot(ax=axes, color='yellow', aspect='equal')
noam.plot(ax=axes, color='purple', aspect='equal')

enter image description here

Also, as a sidenote that dataset has some irregularities with 99 as the ISO code. I believe it is getting fixed in an update (see https://github.com/geopandas/geopandas/issues/1041).... you can use the below code to fix them manually:

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
world.loc[world['name'] == 'France', 'iso_a3'] = 'FRA'
world.loc[world['name'] == 'Norway', 'iso_a3'] = 'NOR'
world.loc[world['name'] == 'Somaliland', 'iso_a3'] = 'SOM'
world.loc[world['name'] == 'Kosovo', 'iso_a3'] = 'RKS'

Upvotes: 1

Related Questions