When plotting subplots of different countries, the axis ratios are not the same among subplots, showing the countries with incorrect sizes.
Kenya is much bigger than the others but shows as big as the others.
GeoJson files can be accessed here: https://file.io/v7fuma1EXwEa
strCountries = ["ghana", "kenya", "zimbabwe"]
admin1Countries = []
for country in strCountries:
regions = gpd.read_file(f"../data/admin1{country}.geojson")
admin1Countries.append(regions)
# real size in one plot
fig, ax = plt.subplots()
for regions in admin1Countries:
regions.plot(ax=ax)
plt.show()
fig, ax = plt.subplots(1, 3, figsize=(15, 5))
for i, regions in enumerate(admin1Countries):
regions.plot(ax=ax[i])
ax[i].set_title(strCountries[i].capitalize())
ax[i].set_axis_off()
plt.show()
I tried changing the CRS to those corresponding to the regions of the countries. Nothing changed. I also tried with axs[i].set_aspect('equal')
You need to set the axis range of all subplots to the same value. Don't forget to draw the figure before getting the actual axis limits.
import geopandas as gpd
import matplotlib.pyplot as plt
strCountries = ["GHA", "KEN", "ZWE"]
admin1Countries = []
for country in strCountries:
regions = gpd.read_file(f"https://raw.githubusercontent.com/johan/world.geo.json/master/countries/{country}.geo.json")
admin1Countries.append(regions)
fig, axes = plt.subplots(1, len(admin1Countries), figsize=(15, 5))
for region, ax, country in zip(admin1Countries, axes, strCountries):
region.plot(ax=ax)
ax.set_title(country)
ax.set_axis_off()
ax.set_aspect('equal')
fig.draw_without_rendering()
max_range = 0
centers = []
for ax in axes:
range = ax.get_ylim()
centers.append((range[0] + range[1]) / 2)
if range[1] - range[0] > max_range:
max_range = range[1] - range[0]
for center, ax in zip(centers, axes):
ax.set_ylim(center - max_range / 2, center + max_range / 2)
Update (see comment):
The above is not generally correct: the countries will be shown with different heights for the same y-range in order to fit into the space reserved for the Axes considering the aspect ratio (you can see it if you leave the axes visible, especially when you set ax.set_adjustable('datalim')
).
To fix this you'll need to reserve space for the Axes according to their proportions:
import geopandas as gpd
import matplotlib.pyplot as plt
strCountries = ["GHA", "CIV", "BFA", "TGO"]
admin1Countries = []
for country in strCountries:
regions = gpd.read_file(f"https://raw.githubusercontent.com/johan/world.geo.json/master/countries/{country}.geo.json")
admin1Countries.append(regions)
width_ratios = []
for region in admin1Countries:
bounds = region.geometry.values.bounds[0]
width_ratios.append(bounds[2] - bounds[0])
fig, axes = plt.subplots(1, len(admin1Countries), figsize=(15, 5), width_ratios=width_ratios)
for region, ax, country in zip(admin1Countries, axes, strCountries):
region.plot(ax=ax)
ax.set_title(country)
ax.set_axis_off()
ax.set_aspect('equal')
fig.draw_without_rendering()
max_range = 0
centers = []
for ax in axes:
range = ax.get_ylim()
centers.append((range[0] + range[1]) / 2)
if range[1] - range[0] > max_range:
max_range = range[1] - range[0]
for center, ax in zip(centers, axes):
ax.set_ylim(center - max_range / 2, center + max_range / 2)
Update 2
Another way is to first translate
all the countries to a common center (e.g. Point(0, 0)
) and then use shared Axes for display:
import geopandas as gpd
import matplotlib.pyplot as plt
strCountries = ["GHA", "CIV", "BFA", "TGO"]
admin1Countries = []
for country in strCountries:
regions = gpd.read_file(f"https://raw.githubusercontent.com/johan/world.geo.json/master/countries/{country}.geo.json")
center = regions.geometry.values[0].centroid
admin1Countries.append(regions.set_geometry(regions.geometry.translate(-center.x, -center.y)))
fig, axes = plt.subplots(1, len(admin1Countries), figsize=(15, 5), sharey=True, sharex=True)
for region, ax in zip(admin1Countries, axes):
region.plot(ax=ax)
ax.set(title=region.loc[0, 'name'], aspect='equal')
ax.set_axis_off()