Matplotlib provides several normalization schemes. Unfortunately, there are no ready-made schemes for normalizing quantiles or user-defined lists of numbers. To create your own normalization scheme, you need to create your own class that inherits from the Normalize class. Such a class is not provided. The class requires a list of stop values of the color gradient to be specified. In this way, you can build any normalization scheme. The quantile scheme can be obtained using the histogram equalization function.
import numpy as np
import pandas as pd
import geopandas as gpd
import matplotlib.pyplot as plt
import matplotlib.colors as clt
import gc
class customNorm(clt.Normalize):
def __init__(self,stops,vmin=-np.inf,vmax=np.inf,clip=False):
super().__init__(vmin, vmax, clip)
self.stops = np.asarray(stops)
self.mapable = np.linspace(0,1,len(self.stops))
self.vmin=vmin
self.vmax=vmax
def __call__(self,value,clip=None):
return np.ma.masked_array(np.interp(value,self.stops,self.mapable,
left=self.vmin, right=self.vmax))
def inverse(self,value):
return np.interp(value,self.mapable,self.stops,
left=0, right=1)
Normalization of the histogram, that is, adjusting the empirical distribution to a uniform distribution.
def histogramEq(y,nbins=256):
histogram = np.histogram(y,nbins)[0]
cdf = np.cumsum(histogram)
eq = ((cdf-cdf.min())/(cdf.max()-cdf.min()))*(nbins-1)
hst = np.linspace(y.min(),y.max(),nbins)
f = np.interp(np.arange(nbins),eq,hst) # linear interpolation
return f
The chorophlet function creates a composition built from a map of the continental US and submaps of Alaska and Hawaii. The function normalizes colors, overlays county, and state boundary lines. Submaps are added using the inset_axes method. The ranges of individual submaps are defined by the set_(xy)lim method.
def chorophlet(gdf,serie,states,ax=None,map_kws=None,ticks=None):
ct = gdf.join(serie)
column = serie.name
ax = ax or plt.gca()
legend_kwds = dict(ticks=ticks,shrink=0.5)
#legend_kwds = {"loc":"lower right"}
ct.plot(column=column,ax=ax,legend=True,legend_kwds=legend_kwds, **map_kws)
#ct.plot(column=column,ax=ax,legend=False, **map_kws)
states.plot(facecolor="none", edgecolor="#222222",linewidth=0.3,ax=ax)
ax.set_xlim(-2500000,2300000)
ax.set_ylim(-1500000,1800000)
ax.axis('off')
ax_alaska = ax.inset_axes([0,0,0.3,0.3])
ct.plot(column=column,ax=ax_alaska,**map_kws)
ax_alaska.set_xlim(-4000000,-2200000)
ax_alaska.set_ylim(2200000,4600000)
ax_alaska.axis('off')
#
ax_havaii = ax.inset_axes([0.3,0.01,0.1,0.15])
ax_havaii.axis('off')
ct.plot(column=column,ax=ax_havaii,**map_kws)
ax_havaii.set_xlim(-6300000,-5900000)
ax_havaii.set_ylim(-80000,500000)
counties = pd.read_pickle("data/counties.p")
states = pd.read_pickle("data/states.p")
explanatory = pd.read_pickle("data/explanatory.p")
Main loop:
For each variable in the list of variables:
- calculate quantile intervals
- round
- build the figure
- build the norm
- build the list of parameters passed to the plot geopandas method
- call main function
- add title
- change the range of the plot
- save the figure
- close the figure
- clear the memory (memory leak)
for var in explanatory.columns:
q = np.quantile(explanatory[var],q=np.linspace(0,1,7))
q = np.round(q,2)
fig,ax = plt.subplots(figsize=(12,8),dpi=150)
norm = customNorm(q,vmin=0,vmax=1)
map_kws_exp = dict(cmap="rainbow",edgecolor="gray",linewidth=0.1,norm=norm)
chorophlet(counties,explanatory[var],states,ax=ax,map_kws=map_kws_exp,ticks=q)
ax.set_title(varnames.loc[var].colname,fontsize=25)
plt.subplots_adjust(left=0.05, right=0.95, top=0.97, bottom=0.01)
fig.savefig("OGH/vars/"+var+".png")
fig.close()
gc.collect()