I have a geopandas.geodataframe.GeoDataFrame with 3 columns: the_geom, Property Crime Rate, Year. Note that the_geom here is just a polygon of Virginia. I want to show this crime rate change over time. Here's what I have so far:
sns.set_style("white")
fig, axs = plt.subplots(nrows=3, ncols=4, sharex=True, sharey=True, figsize=(10,5))
fig.tight_layout(pad=3.0)
i = 0
for year in range(1994, 2015, 2):
subdf = c7[c7['Year']==year]
divider = make_axes_locatable(axs[i//4, i%4])
cax = divider.append_axes("right", size="5%", pad=0)
axs[i//4, i%4].set_title(str(year))
subdf.plot(ax=axs[i//4, i%4],
column='Property crime rate',
cmap='RdBu_r',
cax=cax,
legend=True
)
axs[i//4, i%4].axis('off')
i+=1
axs[i//4, i%4].axis('off')
The problem is that all the states are the same color because their legends on the right are using different scales. I want them all to share the same scale so you can see the color changes over time. Something like sns.FacetGrid() seems like it could work, but I can't get it to work with GeoDataFrames. When I use plt.plot below, it doesn't show the polygon:
g = sns.FacetGrid(c7, col="Year", hue="Property crime rate")
g = (g.map(plt.plot, "Property crime rate").add_legend())
When I try replacing plt.plot with gpd.GeoDataFrame.plot I get the following error:
g = sns.FacetGrid(c7, col="Year", hue="Property crime rate")
g = (g.map(gpd.GeoDataFrame.plot, "Property crime rate").add_legend())
AttributeError: 'Series' object has no attribute 'geometry'
Can anyone help?
Well I found the solution after a lot of tinkering. I didn't try @martinfleis vmin and vmax, so that might work too. I abandoned plt.legend() and went with plt.colorbar(), which seemed to work great.
import matplotlib
import matplotlib.cm as cm #color mapping function
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
import seaborn as sns
%matplotlib inline
sns.set_style("white")
# c7 is my geodataframe
va = c7[c7.State=='Virginia'].sort_values(by='Year').copy(deep=True)
va.reset_index(drop=True, inplace=True)
minima = min(va["Property crime rate"])
maxima = max(va["Property crime rate"])
norm = matplotlib.colors.Normalize(vmin=minima, vmax=maxima, clip=True)
mapper = cm.ScalarMappable(norm=norm, cmap=cm.cool)
fig, ax = plt.subplots(1, 1, figsize=(15,8))
ax.axis('off')
axinset1 = inset_axes(ax, loc='center right', borderpad=-7, # negative value borderpad pushes it out
width="2%", height="40%") # width/height = X% of parent_bbox width/height
cb = plt.colorbar(cax=axinset1, mappable=mapper)
cb.set_label("Property Crime Rate", labelpad=20)
fig.suptitle('Virginia\'s Property Crime Rate Over Time', y=1, fontsize=20) # y<1 brings down, y>1 brings up
for idx, row in va.iterrows():
ax = fig.add_subplot(3, 4, idx+1)
ax.set_title("{}".format(row.Year))
va[va.Year == row.Year].plot(ax=ax, color=mapper.to_rgba(row["Property crime rate"]))
ax.axis('off')
ax.axis('off')
plt.show()