2

我想在地图上绘制区域的特征,但人口密度非常不均匀,较大的瓷砖会误导性地吸引注意力。想想邮政编码的平均值(比如考试成绩)。

高分辨率地图可用于区分有人居住的地区,甚至是其中的密度。下面的 Python 代码确实根据每个像素的平均密度生成了一个彩色栅格。

但是,我真正需要的是从同一区域的等值线地图(在这种情况下为匈牙利的邮政编码)着色,但着色只影响无论如何都会出现在栅格上的点。光栅只能确定像素的伽玛(或者可能是某些 3D 模拟中的高度)。什么是解决这个问题的好方法?

不知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")
4

2 回答 2

2

Datashader 将让您将多种类型的数据组合成一个通用的栅格形状,您可以在其中使用基于 NumPy 的 xarray 操作进行任何您喜欢的制作或过滤。例如,您可以将 choropleth 渲染为多边形,然后掩盖无人居住的区域。如何按区域进行标准化取决于您,并且可能会变得非常复杂,但是一旦您准确定义了您打算做什么,就应该是可行的。有关如何执行此操作的示例,请参见https://examples.pyviz.org/nyc_taxi/nyc_taxi.htmltransform中的代码,如下所示:

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 对象的函数中完成的,这样您就可以获得实时交互式绘图,但您可能希望使用 datashader.org 上的更基本代码来解决该方法,您只需处理 xarray 对象而不是 HoloViews 管道;然后,您可以将您对单个 xarray 所做的转换到 HoloViews 管道中,然后允许完全交互式使用平移、缩放、轴等。

于 2020-03-08T17:07:48.307 回答
2

我不确定我是否理解,所以如果我弄错了,请告诉我。如果我理解得很好,你可以只使用 numpy 来实现你想要的(我相信将它翻译成 xarray 会很容易):

# ---- snipped code already in the question -----
import numpy as np
import matplotlib.pyplot as plt

#  fake a choropleth in a dirty, fast way
height, width = 2880, 5120
choropleth = np.empty((height, width, 3,), dtype=np.uint8)
CHUNKS = 10
x_size = width // CHUNKS
for x_step, x in enumerate(range(0, width, width // CHUNKS)):
    y_size = height // CHUNKS
    for y_step, y in enumerate(range(0, height, height // CHUNKS)):
        choropleth[y: y+y_size, x: x+x_size] = (255-x_step*255//CHUNKS,
                                                0, y_step*255//CHUNKS)
plt.figure("Fake Choropleth")
plt.imshow(choropleth)

# Option 1: play with alpha only
outimage = np.empty((height, width, 4,), dtype=np.uint8)  # RGBA image
outimage[:, :, 3] = img  # Set alpha channel
outimage[:, :, :3] = choropleth  # Set color
plt.figure("Alpha filter only")
plt.imshow(outimage)

# Option 2: clear the empty points
outimage[img == 0, :3] = 0  # White. use 0 for black
plt.figure("Points erased")
plt.imshow(outimage[:,:,:3])  # change to 'outimage' to see the image with alpha

结果:虚拟 choroplet 合唱团

阿尔法过滤图 仅 alpha 过滤器

黑色背景,无 alpha 滤镜 没有阿尔法过滤器 请注意,由于matplotlib' 抗锯齿,图像可能看起来不同。

于 2022-02-06T03:46:17.460 回答