Как построить карту различий с помощью геопанд и mapclassify?

У меня есть GeoDataFrame со столбцом «различия», в котором хранится дельта между двумя числами. Иногда эти числа бывают положительными, отрицательными или нулевыми, если нет разницы. Мне нужно создать картограмму, которая имеет некоторую расходящуюся цветовую карту с 0 (или некоторым средним буфером) в качестве средней точки и несимметричной цветовой полосой, например [-0.02, -0.01, 0., 0.01, 0.02, 0.03]. Я экспериментировал с

class MidPointNormalize(mp.colors.Normalize):
    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        self.midpoint = midpoint
        mp.colors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
        return np.ma.masked_array(np.interp(value, x, y), np.isnan(value))

norm = MidPointNormalize(midpoint=0,vmin=diff_merge_co["diff"].min(),
                         vmax=diff_merge_co["diff"].max())
diff_merge_co.plot(ax=ax, column="diff", cmap="coolwarm", norm=norm,
                   legend=True)

а также установка norm на некоторые подобранные вручную значения:

bounds = np.array([-0.02, -0.01, 0., 0.01, 0.02, 0.03])
norm = colors.BoundaryNorm(boundaries=bounds, ncolors=256) 

но с этим связано множество технических проблем (в том числе то, что шкала палитры не удерживается вверх, и очевидное уродство подбора значений вручную).

Итак, мой вопрос: как бы вы нарисовали карту с расходящимся масштабом, используя geopandas.GeoDataFrame.plot(), и какой mapclassify метод вы бы использовали?


person Dervin Thunk    schedule 14.04.2019    source источник
comment
См. Также комментарий к проблеме с github.   -  person ImportanceOfBeingErnest    schedule 15.04.2019


Ответы (1)


Возможно, я не понимаю, в чем проблема, но обе идеи должны работать нормально. Например:

import geopandas as gpd
print(gpd.__version__)   ## 0.4.1
import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt 
import matplotlib.colors as mcolors

class MidPointNormalize(mcolors.Normalize):
    def __init__(self, vmin=None, vmax=None, midpoint=None, clip=False):
        self.midpoint = midpoint
        mcolors.Normalize.__init__(self, vmin, vmax, clip)

    def __call__(self, value, clip=None):
        x, y = [self.vmin, self.midpoint, self.vmax], [0, 0.5, 1]
        return np.ma.masked_array(np.interp(value, x, y), np.isnan(value))

## Some data file from ## http://biogeo.ucdavis.edu/data/diva/adm/USA_adm.zip    
gdf = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) 
quant = np.random.rand(len(gdf))*0.05-0.02
gdf['quant']=quant
print(gdf.head())


fig, (ax, ax2) = plt.subplots(2, figsize=(7,6))

norm=MidPointNormalize(-0.02, 0.03, 0)
gdf.plot(column='quant', cmap='RdBu', norm=norm, ax=ax)
fig.colorbar(ax.collections[0], ax=ax)


bounds = np.array([-0.02, -0.01, 0., 0.01, 0.02, 0.03])
norm2 = mcolors.BoundaryNorm(boundaries=bounds, ncolors=256) 
gdf.plot(column='quant', cmap='RdBu', norm=norm2, ax=ax2)
fig.colorbar(ax2.collections[0], ax=ax2)


plt.show()

введите здесь описание изображения

person ImportanceOfBeingErnest    schedule 14.04.2019