【问题标题】:Change background map for contextily根据上下文更改背景图
【发布时间】:2019-10-26 19:26:00
【问题描述】:

我有这个代码:

import pandas as pd
import numpy as np
from geopandas import GeoDataFrame
import geopandas
from shapely.geometry import LineString, Point
import matplotlib.pyplot as plt
import contextily

''' Do Something'''

df = start_stop_df.drop('track', axis=1)
crs = {'init': 'epsg:4326'}
gdf = GeoDataFrame(df, crs=crs, geometry=geometry)

ax = gdf.plot()
contextily.add_basemap(ax)
ax.set_axis_off()
plt.show()

基本上,这会生成一个位于新加坡的背景地图。但是,当我运行它时,我收到以下错误:HTTPError: Tile URL resulted in a 404 error. Double-check your tile url:http://tile.stamen.com/terrain/29/268436843/268435436.png 但是,它仍然会生成此图像:

如何更改磁贴 URL?我仍然希望将新加坡地图作为基础图层。

编辑
还尝试将此参数包含在 add_basemap 中:
url ='https://www.openstreetmap.org/#map=12/1.3332/103.7987'
哪个产生了这个错误:
OSError: cannot identify image file <_io.BytesIO object at 0x000001CC3CC4BC50>

【问题讨论】:

    标签: python python-3.x geopandas contextily


    【解决方案1】:

    首先确保您的 GeoDataframe 在 Web Mercator 投影 (epsg=3857) 中。一旦您的地理数据框被正确地地理参考,您可以通过 Geopandas 重投影来实现这一点:

    df = df.to_crs(epsg=3857)
    

    完成此操作后,您可以轻松选择任何受支持的地图样式。在撰写本文时,可以在 contextily.sources 模块中找到完整列表:

    ### Tile provider sources ###
    
    ST_TONER = 'http://tile.stamen.com/toner/tileZ/tileX/tileY.png'
    ST_TONER_HYBRID = 'http://tile.stamen.com/toner-hybrid/tileZ/tileX/tileY.png'
    ST_TONER_LABELS = 'http://tile.stamen.com/toner-labels/tileZ/tileX/tileY.png'
    ST_TONER_LINES = 'http://tile.stamen.com/toner-lines/tileZ/tileX/tileY.png'
    ST_TONER_BACKGROUND = 'http://tile.stamen.com/toner-background/tileZ/tileX/tileY.png'
    ST_TONER_LITE = 'http://tile.stamen.com/toner-lite/tileZ/tileX/tileY.png'
    
    ST_TERRAIN = 'http://tile.stamen.com/terrain/tileZ/tileX/tileY.png'
    ST_TERRAIN_LABELS = 'http://tile.stamen.com/terrain-labels/tileZ/tileX/tileY.png'
    ST_TERRAIN_LINES = 'http://tile.stamen.com/terrain-lines/tileZ/tileX/tileY.png'
    ST_TERRAIN_BACKGROUND = 'http://tile.stamen.com/terrain-background/tileZ/tileX/tileY.png'
    
    ST_WATERCOLOR = 'http://tile.stamen.com/watercolor/tileZ/tileX/tileY.png'
    
    # OpenStreetMap as an alternative
    OSM_A = 'http://a.tile.openstreetmap.org/tileZ/tileX/tileY.png'
    OSM_B = 'http://b.tile.openstreetmap.org/tileZ/tileX/tileY.png'
    OSM_C = 'http://c.tile.openstreetmap.org/tileZ/tileX/tileY.png'
    

    请记住,您不应在磁贴 URL 中添加实际的 x、y、z 磁贴编号(就像您在“编辑”示例中所做的那样)。 ctx 会处理这一切。

    您可以在 GeoPandas docs 找到一个可复制的工作示例和更多信息。

    import contextily as ctx
    
    # Dataframe you want to plot
    gdf = GeoDataFrame(df, crs= {"init": "epsg:4326"}) # Create a georeferenced dataframe  
    gdf = gdf.to_crs(epsg=3857) # reproject it in Web mercator
    ax = gdf.plot()
    
    # choose any of the supported maps from ctx.sources
    ctx.add_basemap(ax, url=ctx.sources.ST_TERRAIN)
    ax.set_axis_off()
    plt.show()
    

    【讨论】:

    • 我遇到了同样的问题并按照您的示例进行操作,但似乎无法解决问题。我通过 .to_crs(epsg=3857) 从 epsg=4326 转换了 gdf,但我仍然得到 HTTPError: Tile URL resulted in a 404 error. Double-check your tile url: http://tile.stamen.com/terrain-background/23/4194302/4194300.png
    • 我不确定您是否可以将缩放级别提高到 23... 通常只能达到 20。(maps.stamen.com/toner/#20/37.80802/-122.32054)。也许你应该把地图缩小一点。
    • 我的坐标系有问题,还是没能解决。 (所以我看到的只是海洋)即便如此,为了简单地避免由于上面解释的缩放级别而出现错误,我正在编码:contextily.add_basemap(ax, zoom=18)
    • 我也有一个HTTPError: Tile URL resulted in a 404 error. Double-check your tile url: https://stamen-tiles-a.a.ssl.fastly.net/terrain/14/8383/5485.png,但发现这是一些 Stamen 地图图块提供商 (github.com/stamen/maps.stamen.com/issues/107) 的问题。一旦我更换到另一个地图提供商,例如ctx.add_basemap(ax, alpha=0.8, source=ctx.providers.OpenStreetMap.Mapnik)问题似乎解决了
    【解决方案2】:

    我太新了,无法添加评论,但我想指出那些在 cmets 中说他们收到 404 错误的人。检查你的大写字母等。 Stamen 的网址是专门针对此的。例如,没有全大写电话。它只是将第一个字母大写。例如:

    ctx.add_basemap(ax=ax,url=ctx.providers.Stamen.Toner, zoom=10)

    【讨论】:

      【解决方案3】:

      Contextily 的默认 crs 是 epsg:3857。但是,您的数据框位于不同的 CRS 中。使用以下,参考手册here:

      ctx.add_basemap(ax, crs='epsg:4326', source=ctx.providers.Stamen.TonerLite)
      

      请参阅此link 以使用不同的来源,例如Stamen.TonerStamen.Terrain 等(默认使用Stamen.Terrain)。

      此外,您可以使用 df.to_crs() 将数据框转换为 EPSG:3857。在这种情况下,您应该跳过 ctx.add_basemap() 函数中的 crs 参数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-19
        • 2015-12-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多