Как объединить карту хороплета с затененным растром в Python? - PullRequest
0 голосов
/ 07 марта 2020

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

Доступны карты высокого разрешения для разделения населенных пунктов и даже плотности внутри них. Код Python, приведенный ниже, создает растр, окрашенный в соответствии со средней такой плотностью для каждого пикселя.

Однако, что мне действительно нужно, так это раскраска с картограммы той же области (почтовые индексы Венгрии в это случай), но окраска влияет только на точки, которые все равно будут отображаться в растре. Растр может определять только гамму пикселя (или, может быть, высоту в каком-то трехмерном аналоге). Какой хороший способ go по этому поводу?

A rasterio.mask.mask как-нибудь?

(Кстати, наложение с границами почтового индекса также было бы неплохо, но у меня есть лучшее понимание того, как это может работать с GeoViews.)

import rasterio
import os
import datashader as ds
from datashader import transfer_functions as tf
import xarray as xr
from matplotlib.cm import viridis

# download a GeoTIFF from this location: https://data.humdata.org/dataset/hungary-high-resolution-population-density-maps-demographic-estimates
data_path = '~/Downloads/'
file_name = 'HUN_youth_15_24.tif'  # young people
file_path = os.path.join(data_path, file_name)
src = rasterio.open(file_path)
da = xr.open_rasterio(file_path)
cvs = ds.Canvas(plot_width=5120, plot_height=2880)
img = tf.shade(cvs.raster(da,layer=1), cmap=viridis)
ds.utils.export_image(img, "map", export_path=data_path, fmt=".png")

1 Ответ

1 голос
/ 08 марта 2020

Datashader позволит вам объединять данные многих типов в общую растровую форму, где вы можете делать все, что вам угодно, создавая или фильтруя, используя операции xarray на основе NumPy. Например, вы можете визуализировать хороплет как полигоны, а затем замаскировать необитаемые регионы. Как нормализовать по области зависит от вас, и это может быть очень сложным, но должно быть выполнимо, когда вы точно определите, что вы собираетесь делать. См. transform код в https://examples.pyviz.org/nyc_taxi/nyc_taxi.html для примеров того, как это сделать, например:

def transform(overlay):
    picks = overlay.get(0).redim(pickup_x='x', pickup_y='y')
    drops = overlay.get(1).redim(dropoff_x='x', dropoff_y='y')
    pick_agg = picks.data.Count.data
    drop_agg = drops.data.Count.data
    more_picks = picks.clone(picks.data.where(pick_agg>drop_agg))
    more_drops = drops.clone(drops.data.where(drop_agg>pick_agg))
    return (hd.shade(more_drops, cmap=['lightcyan', "blue"]) *
            hd.shade(more_picks, cmap=['mistyrose', "red"]))

picks = hv.Points(df, ['pickup_x',  'pickup_y'])
drops = hv.Points(df, ['dropoff_x', 'dropoff_y'])
((hd.rasterize(picks) * hd.rasterize(drops))).apply(transform).opts(
    bgcolor='white', xaxis=None, yaxis=None, width=900, height=500)

Здесь на самом деле ничего не маскируется, но, надеюсь, вы увидите, как маскирование должно сработать; просто возьмите какой-нибудь растеризованный объект, затем выполните математическую операцию, используя другой растеризованный объект. Здесь все шаги выполняются в функции с использованием объектов HoloViews, чтобы вы могли иметь интерактивный интерактивный график, но вы, вероятно, захотите разработать подход, используя более базовый код c на datashader.org, где вам нужно только иметь дело с объектами xarray, а не с конвейером HoloViews; затем вы можете перевести то, что вы сделали для одного xarray, в конвейер HoloViews, который затем обеспечит полное интерактивное использование с панорамированием, масштабированием, осями и т. д. c.

...