缩放时如何调整 bins/pixels 的大小

How to resize of bins/pixels when zooming

我目前正在尝试借助数据着色器和散景将数据集(柏林 public 交通点)投影到地图图块上。在某种程度上它工作得很好,但仍然存在三个问题:

  1. 当放大数据时,像素仍然相当大并且是 没有重新排列 - 如何做到这一点?
  2. 如何让投影数据半透明后仍能看到下面的地图?
  3. 散景工具栏的 "save" 功能消失了,因为合并了地图图块。如何取回?

感谢任何意见!

编写的(远非完美的)代码:

import numpy as np
import pandas as pd
import geopandas as gp
import datashader as ds
import datashader.transfer_functions as tf
from datashader.utils import export_image
from datashader.utils import lnglat_to_meters as webm
from datashader.colors import Hot
import dask.dataframe as dd
import multiprocessing as mp
from functools import partial
from IPython.core.display import HTML, display
import matplotlib.pyplot as plt
import holoviews as hv
from holoviews.operation.datashader import datashade, dynspread
hv.extension("bokeh", "matplotlib")
from bokeh.io import output_file, output_notebook, show
from bokeh.plotting import figure, show
from holoviews import dim, opts
import geoviews as gv
from colorcet import palette, fire

#get official data of bus/subway stops in Berlin
# -> https://www.vbb.de/media/download/2035
#read data
df = pd.read_csv('UMBW.CSV', engine= 'python', sep=';', usecols=['Y-Koordinate', 'X-Koordinate'])

##some formatting
##replace comma by point
df = df.apply(lambda x: x.str.replace(',','.'))
#delete rows witn NaN -> pandas.DataFrame.dropna
df = df.dropna()
#entries were objects - need to convert to floats
df['X-Koordinate']=pd.to_numeric(df['X-Koordinate'])
df['Y-Koordinate']=pd.to_numeric(df['Y-Koordinate'])

# Project longitude and latitude onto web mercator plane.
df.loc[:, 'easting'], df.loc[:, 'northing'] = webm(df['X-Koordinate'],df['Y-Koordinate'])

# Getting range/box of latitude and longitude for plotting later.
# drop the points lying on the border
y_range_min = df['Y-Koordinate'].quantile(0.01)
y_range_max = df['Y-Koordinate'].quantile(0.99)
x_range_min = df['X-Koordinate'].quantile(0.01)
x_range_max = df['X-Koordinate'].quantile(0.99)

#cornerspots for canvas
sw = webm(x_range_min,y_range_min)#southwest
ne = webm(x_range_max,y_range_max)#northeast
SF = zip(sw, ne)

dask_df = dd.from_pandas(df, npartitions=mp.cpu_count())
dask_df = dask_df.compute()

display(HTML("<style>.container { width:100% !important; }</style>"))

plot_width = int(3600)
plot_height = int(3600)
cvs = ds.Canvas(plot_width, plot_height, *SF)
agg = cvs.points(dask_df, 'easting', 'northing')

#dynamic map tiles -> https://wiki.openstreetmap.org/wiki/Tile_servers
#url="http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{Z}/{Y}/{X}.png"
url="https://a.tile.openstreetmap.org/{Z}/{X}/{Y}.png"
geomap = gv.WMTS(url)

#manipulate pixelsize for zoom
dynspread.max_px=1
dynspread.threshold=0.1

points = hv.Points(gv.Dataset(dask_df, kdims=['easting', 'northing']))
bvg_stops = dynspread(datashade(points, cmap=Hot).opts(height=640,width=640))
fig = geomap * bvg_stops
hv.save(fig, 'berlin.html', backend='bokeh')

初始散景图的示例输出和放大版本(科特布斯市周围)。

  1. “当放大数据时,像素仍然相当大并且没有重新排列 - 如何做到这一点?”

    Datashader 是一个 Python 程序,它在给定数据结构时生成栅格化值数组。在这里,它根据请求呈现您的数据,然后您使用 hv.save 将其输出保存到 HTML 文件。一旦你这样做,你将拥有一个永远不会更新的数字。您将放大 HTML 页面,导致浏览器的 JavaScript 代码向 Python 请求更新,但 Python 不是 运行 并且无法响应要求更新数字。如果您想要将可缩放图像导出到 HTML,您需要指定更高的初始分辨率,例如 datashade(..., dynamic=False, height=4000, width=4000)(这会产生较大的文件大小并且最初看起来可能不太好,但是将允许一定程度的缩放),或者以多种不同的分辨率生成一整套数据图块(由 Datashader 支持,但尚未得到充分记录),或者(为了充分发挥作用)使用 Bokeh 服务器提供 Python 过程伴随 HTML/JavaScript 代码。即,要么最初生成更多数据,预先生成所有数据组合,要么提供可以按需重新生成它们的服务器。如果没有这些方法中的任何一种,您不应该期望在初始渲染之外有任何可用数据。

  2. 如何让投影数据半透明后还能看到下面的地图?

    bvg_stops.opts(alpha=0.5)。您还可以考虑使用 Panel.pyviz.org 为地图和数据添加一些不透明度小部件,以便您以交互方式打开和关闭它们;有关示例,请参阅 examples.pyviz.org。

  3. 随着地图图块的合并,散景工具栏的“保存”功能消失了。如何取回?

    不幸的是,这是由浏览器的安全模型引起的限制,不是 Bokeh 或此处的任何其他工具可以覆盖的。地图图块来自单独的服务器,浏览器禁止导出此类“跨源”内容以避免某些安全问题 ()。