I know I can add custom background maps to a geopandas data frame like below
ax = df_wm.plot(figsize=(10, 10), alpha=0.5, edgecolor='k')
cx.add_basemap(ax, source=cx.providers.Stamen.TonerLite)
ax.set_axis_off()
How could I use other map tiles. For example, USGS topo tiles like those from the national map below? https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/7/46/26
To get webmap tiles for your maps' background from a standard sources, you need to identify url
and layer
and use them in your code. Here is a demo script that uses cartopy to request the services.
Map tiles are generally produced in web-mercator
projection (ccrs.epsg(3857)). If you want to use them as is you must plot your map on that projection or mercator projection.
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import os
os.environ['USE_PYGEOS'] = '0'
import geopandas as gpd
url = "https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/WMTS/1.0.0/WMTSCapabilities.xml"
layer = "USGSTopo"
mercator = ccrs.Mercator() #ccrs.epsg(3857)
nonproj = ccrs.PlateCarree()
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1, projection=mercator)
# The requested maps will appear as data that
# matplotlib can plot on its `ax`
ax.add_wmts(url, layer)
ax.set_extent([20, 25, 35, 40], crs=nonproj)
# Plot a linestring using long/lat in degrees
ax.plot([20.1, 22.7, 24.5], [35.5, 37.2, 39.2], transform=nonproj ,zorder=15)
# Plot Geopandas cities data
city_pnts = gpd.read_file(gpd.datasets.get_path("naturalearth_cities"))
# Geometries in Geodataframes have CRS transformed
# to Mercator projection and plotted here
cty2 = city_pnts.to_crs(mercator.proj4_init)
cty2.plot(ax=ax, color="red", zorder=20)
ax.gridlines(draw_labels=True)
ax.set_title('USGSTopo WMTS')
plt.show()