如何使用datashader设置地理投影?

问题描述 投票:0回答:2

我用 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)

enter image description here

python mapping geospatial datashader
2个回答
3
投票

那是一只好看的阿米巴原虫! :-)

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 上的高级界面覆盖到地图上,这将强制采用地理纵横比。


0
投票

如果您投影了坐标,则根据纬度/经度距离计算纵横比相对容易:

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

enter image description here

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.