Datashader:GeoDataFrames 的分类颜色映射

Posted

技术标签:

【中文标题】Datashader:GeoDataFrames 的分类颜色映射【英文标题】:Datashader: categorical colormapping of GeoDataFrames 【发布时间】:2021-09-22 06:20:26 【问题描述】:

已安装的包

datashader 0.13.0、holoviews 1.14.4、geoviews 1.9.1.、bokeh 2.3.2.

我要做什么

我正在尝试使用 Datashader 重新创建一个等值线图,其中一种颜色映射到大型 GeoDataFrame 中的一个类别,遵循管道页面中的this 示例和this 以及this SO,它们都不同它们的语法略有不同,并且都使用点作为示例,而不是多边形。

可重现的代码示例

下面是完整数据集的一个小样本。

import pandas as pd
import geopandas as gpd
from spatialpandas import GeoDataFrame
import datashader as ds
import datashader.transfer_functions as tf


d = 'geometry': 0: 'POLYGON ((13.80961103741604 51.04076975651729, 13.80965521888065 51.04079016168103, 13.80963851766593 51.04080454197601, 13.80959433642561 51.04078412781548, 13.80961103741604 51.04076975651729))',
  1729: 'POLYGON ((13.80839606906416 51.03845025070634, 13.80827635138927 51.03836030644977, 13.80840483855695 51.03829244374037, 13.80852462026795 51.03838211873356, 13.80839606906416 51.03845025070634))',
  2646: 'POLYGON ((13.80894179055831 51.04544128170094, 13.80952887156242 51.0450399782091, 13.80954152432486 51.04504668985658, 13.80896834397535 51.04545611172818, 13.80894179055831 51.04544128170094))',
 'category': 0: 'Within_500m', 1729: 'Outside_500m', 2646: 'River/stream'

gdf = gpd.GeoDataFrame(pd.DataFrame(d), geometry=gpd.GeoSeries.from_wkt(pd.DataFrame(d)['geometry']), crs="EPSG:4326")

gdf['category'] = gdf['category'].astype('category')

spatialpdGDF = GeoDataFrame(gdf)

color_key = 'Within_500m': 'red', 'Outside_500m': 'lightgrey', 'River/stream': 'lightblue'
canvas = ds.Canvas(plot_width=1000, plot_height=1000)
agg = canvas.polygons(spatialpdGDF, 'geometry', agg=ds.count_cat('category'))
tf.shade(agg, color_key=color_key)

预期行为

我希望所有多边形都被光栅化并以每个类别的单一颜色显示。

观察到的行为

完整数据集的图像几乎是白色的,一些轮廓非常隐约可见。

如果我改变背景颜色,一些多边形会更加突出,尽管标题也只是隐约可见。

tf.Images(tf.set_background(tf.shade(agg, color_key=color_key, name="Custom color key"), "black"))

这是否与 Datashader 计算有关,正如 Pipeline notebook 中提到的,“根据每个类别对该像素的贡献,每个像素的透明度和颜色”?但是由于每个类别都是每个像素的唯一贡献者(即在这种情况下与其他类别没有空间重叠),为什么 alpha 似乎设置得如此之低以至于看不到任何东西?我还尝试了agg=ds.by('category') 聚合器,结果相同。

顺便说一句,如果我删除“类别”列(否则会导致“输入必须是数字”错误)并将 GeoViews 与 HoloViews rasterize 结合使用,我可以使用 one 可视化多边形颜色没有问题,但我还没有弄清楚如何使用这种方法在同一个散景/或 mpl 图上绘制具有不同颜色映射的多个数据着色 GDF(通常的 HoloViews“叠加乘法”在这种情况下不起作用)。

import geoviews as gv
from holoviews.operation.datashader import rasterize

gv.extension('bokeh')

del gdf['category']

rasterize(gv.Polygons(gdf)).opts(cmap=['red'])

【问题讨论】:

我无法立即发现为什么在这种情况下情节如此轻松。我同意这不应该是由于颜色混合,如果每个像素只有一个类别。对于 HoloViews 版本,请尝试 datashade 而不是 rasterize;目前只能从datashade 获得分类着色。 examples.pyviz.org/nyc_buildings 是否有帮助? 哦,也许可以试试agg=ds.by('category', ds.any()),它会忽略重叠,以防你有一些重叠。 ds.by 与 ds.count_cat 相同,但泛化为处理任何类型的聚合(不仅仅是计数),计数为默认值。 agg=ds.by('category', ds.any()) 是票!太感谢了!如果我尝试datashade(agg, color_key=color_key) 我会得到“'DataArray' 对象没有属性'apply'”。我将查看 NYC Buildings 示例,因为它非常接近我的用例 - 太糟糕了,这不在 datashader 页面上(或者我太盲目了,看不到它)! 很高兴听到这个消息!在这种情况下,可能发生的情况是您有一些形状重叠了一些微小的量,导致 1 或 2 个明亮像素(重叠该像素的 2 个形状的计数)和所有其余暗像素(重叠的 1 个形状的计数那个像素)。 ds.any() 忽略计数,但至少现在您知道存在一些重叠(即使只是几个像素)!我似乎再也无法使用 geopandas 构建环境,或者我会尝试您的其他问题。是的,nyc_buildings 示例是新的,我们希望看到关于 datashader 文档的 PR 来添加它! 【参考方案1】:

试试agg=ds.by('category', ds.any()),它将忽略在任何像素中重叠的多边形。 ds.count_cat('category') 现在是 ds.by('category', ds.count()) 的别名,但从 Datashader 0.12.1 开始,您不再仅限于 count,并且可以例如使用any 丢弃有关重叠的信息。

【讨论】:

以上是关于Datashader:GeoDataFrames 的分类颜色映射的主要内容,如果未能解决你的问题,请参考以下文章