2

我目前正在尝试在数据着色器和散景的帮助下将数据集(柏林公共交通站点)投影到地图瓷砖上。在一定程度上它运作良好,但仍然存在三个问题:

  1. 放大数据时,像素仍然很大并且没有重新排列 - 如何做到这一点?
  2. 如何使投影数据半透明以仍然看到下面的地图?
  3. 随着地图图块的合并,散景工具栏的“保存”功能消失了。怎么找回来?

感谢您的任何意见!

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

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')

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

数据集的散景图(未缩放) 数据集的散景图(放大)

4

1 回答 1

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

    Datashader 是一个 Python 程序,它在给定数据结构时生成一个光栅化值数组。在这里,它根据请求呈现您的数据,然后您将其输出保存到 HTML 文件中,使用hv.save. 一旦你这样做了,你将拥有一个永远不会更新的数字。您将放大 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 或此处的任何其他工具都无法覆盖。地图图块来自单独的服务器,浏览器禁用导出此类“跨域”内容以避免某些安全问题(Can't Save Bokeh Plot with Panel from PyViz Example)。

于 2020-03-01T13:50:18.823 回答