Integración de Datashader para polígonos en el mapbox de Plotly.
Estoy utilizando Scattermapbox de plotly para superponer un mapa con una imagen sombreada de polígonos creada por la función shade de datashader (basada en https://plotly.com/python/datashader/), pero las proyecciones no parecen coincidir, vea la imagen a continuación. ¿Algún consejo sobre cómo puedo solucionar este problema utilizando Scattermapbox y datashader de plotly?
Ejemplo reproducible:
import geopandas as gpd
import plotly.graph_objects as go
import spatialpandas as spd
import datashader as ds
from colorcet import fire
import datashader.transfer_functions as tf
# cargar datos
world = gpd.read_file(
gpd.datasets.get_path('naturalearth_lowres')
)
# convertir proyección
world = world.to_crs(epsg=3857)
# crear DataFrame de spatialpandas
df_world = spd.GeoDataFrame(world)
# crear canvas de datashader y agregar
cvs = ds.Canvas(plot_width=1000, plot_height=1000)
agg = cvs.polygons(df_world, geometry='geometry', agg=ds.mean('pop_est'))
# crear imagen sombreada
tf.shade(agg, cmap=fire)
# crear imagen sombreada y convertirla en una imagen de Python
img = tf.shade(agg, cmap=fire)[::-1].to_pil()
coords_lat, coords_lon = agg.coords['y'].values, agg.coords['x'].values
# Esquinas de la imagen, que deben pasarse a mapbox
coordinates = [
[coords_lon[0], coords_lat[0]],
[coords_lon[-1], coords_lat[0]],
[coords_lon[-1], coords_lat[-1]],
[coords_lon[0], coords_lat[-1]],
]
fig = go.Figure(go.Scattermapbox())
fig.update_layout(
mapbox_style="open-street-map",
mapbox_layers=[
{
"sourcetype": "image",
"source": img,
"coordinates": coordinates,
}
]
)
fig.show()
Leí que Scattermapbox solo admite la proyección de Mercator, lo cual me resultó confuso ya que los ejemplos en la documentación de plotly parecen estar en formato de longitud/latitud, pero intenté convertir las coordenadas del GeoDataFrame a epsg 3857, vea:
world = world.to_crs(epsg=3857)
El resultado es que la imagen sombreada se vuelve invisible. Cualquier ayuda sería muy apreciada.
davy.ai
Es probable que las proyecciones de datashader y Scattermapbox no estén coincidiendo, de ahí el desalineamiento de la imagen sombreada y el mapa.
Una forma de solucionar este problema es reproyectar el GeoDataFrame a la proyección Mercator antes de crear el lienzo de datashader, en lugar de convertir las coordenadas a EPSG 3857. De esta manera, las coordenadas en el lienzo de datashader estarán en la misma proyección que la gráfica Scattermapbox, y la imagen sombreada debería alinearse perfectamente con el mapa.
Para hacer esto, puedes utilizar el método
to_crs()
del GeoDataFrame para reproyectar a la proyección Mercator, de la siguiente manera:Con este código, la imagen sombreada debería alinearse perfectamente con el mapa.