我用 datashader 绘制了一张地理地图。一切正常,但地理投影似乎不正确。长度和长宽比不匹配,可能是因为没有设置地理投影? 我的代码如下所示:
agg = ds.Canvas().points(df, 'lon',"lat")
karte=ds.tf.set_background(ds.tf.shade(agg, cmap=cc.fire,how="log"), "black")
utils.export_image(img=karte,filename='output', fmt=".png", background=None)
那是一只好看的阿米巴原虫! :-)
Datashader 是一种通用工具,不以任何方式与地理数据绑定。特别是,如果您希望将数据投影到其他坐标系中,则需要在调用Datashader之前进行投影; Datashader 所做的只是渲染它所给出的内容。
Datashader 确实包含一个实用程序函数,用于将经度/纬度数据投影到 Web 墨卡托 (datashader.utils.lnglat_to_meters) 的特殊情况,以方便使用 Web 墨卡托映射图块的绘图库,但如果您要单独可视化数据(未覆盖在地图上)您甚至不需要该实用程序;裸经/纬度值应该没问题。
如果你想要一些特定的宽高比,你可以通过 Canvas 构造函数的参数来确定它。具体来说,将
plot_height
和 plot_width
设置为您想要的任何图像大小,然后将 x_range 和 y_range 设置为该图像大小中您想要的数据空间范围(例如,像 xrange=(270, 290), yrange=(30,40)
这样的经度和纬度范围)。
或者您可以使用 hvplot.holoviz.org 或 holoviews.org 上的高级界面覆盖到地图上,这将强制采用地理纵横比。
如果您投影了坐标,则根据纬度/经度距离计算纵横比相对容易:
def bounds(x_range, y_range):
x,y = lnglat_to_meters(x_range, y_range)
return dict(x_range=x, y_range=y)
Earth = ((-180.00, 180.00), (-59.00, 74.00))
France = (( -12.00, 16.00), ( 41.26, 51.27))
Berlin = (( 12.843018, 14.149704), ( 52.274880, 52.684292))
Dresden = (( 13.415680, 14.703827), ( 50.740090, 51.194905))
USA = (( -126, -64), ( 24.92, 49.35))
Paris = (( 2.05, 2.65), ( 48.76, 48.97))
DE = (( 4.605469, 15.372070), ( 46.697243, 55.065885))
def plot(x_range, y_range, plot_width: int = None):
"""Plot df using tf-shade()
Calculates aspect ratio based on
web mercator distance ratio lat/lng
"""
if plot_width is None:
plot_width = 1000
lng_width = x_range[1]-x_range[0]
lat_height = y_range[1]-y_range[0]
plot_height = int(((plot_width * lat_height) / lng_width)*1.5)
cvs = ds.Canvas(plot_width=plot_width, plot_height=plot_height, **bounds(x_range, y_range))
with diag.ProgressBar(), diag.Profiler() as prof, diag.ResourceProfiler(0.5) as rprof:
agg = cvs.points(df, x='x', y='y')
return tf.shade(agg, cmap=["lightblue","darkblue"])
def save_image(img, output_name, return_img: bool = True, ):
"""Saves image as PNG"""
ds.utils.export_image(
img=img, filename= str(OUTPUT / output_name), fmt=".png", background='white')
if return_img:
return img
save_image(plot(*DE), output_name='DE_map')