As shown below, map A is created using plotly.express and map B using plotly.graph_objects.'

I’d like to ask to align and overlap map A on top of map B while keeping the animation on map A.

  1. map A (left) animates two typhoon paths near Japan, and map B (right) shows 3 solar farms in Japan: enter image description here

  2. code to create the dataframe:

import polars as pl
import plotly.express as px
import plotly.graph_objects as go

# create df for solar farms
data_solar_farms = {
    "name"          : ["Setouchi Kirei", "Eurus Rokkasho", "Tomatoh Abira"],
    "capacity_mw"   : [235, 148, 111],
    "latitude"      : [34.6, 40.9, 42.7],
    "longitude"     : [134.1, 141.3, 141.7],
    "state"         : ["Okayama", "Aomori", "Hokkaido"],
    "city"          : ["Setouchi", "Rokkasho", "Abira"],
    "year_operation": [2018, 2015, 2015],
}
df_solar_farms = pl.DataFrame(data_solar_farms)

# create df for typhoon paths
data_typhoon = {
    'name'            : ['Lan',  'Lan',  'Lan',  'Guc',  'Guc',  'Guc'],
    'idx'             : [230701, 230702, 230703, 220301, 220302, 220303],
    'latitude'        : [31.1,   36.6,   41.0,   31.8,   36.6,   37.8],
    'longitude'       : [137.3,  133.0,  135.8,  128.4,  135.0,  142.2],
    'date_time'       : [
        '2022-08-07 00:00:00',
        '2022-08-07 06:00:00',
        '2022-08-07 12:00:00',
        '2023-06-06 18:00:00',
        '2023-06-07 00:00:00',
        '2023-06-07 06:00:00',
    ],
    'grade'           : [1, 3, 2, 4, 6, 5]
}
df_typhoon = pl.DataFrame(data_typhoon)
  1. code for map A:
fig_typhoon = px.line_mapbox(
    df_typhoon,
    lat='latitude',
    lon='longitude',
    color='name',
    animation_frame='name',
)

fig_typhoon.update_layout(
    mapbox_style="carto-darkmatter",
    mapbox_center_lat=36,
    mapbox_center_lon=138,
    mapbox_zoom=3,
)

fig_typhoon.show()
  1. code for map B:
fig_solar_farms = go.Figure(
    go.Scattermapbox(
        lat = df_solar_farms['latitude'],
        lon = df_solar_farms['longitude'],
        mode = 'markers',
        marker = go.scattermapbox.Marker(
            size=df_solar_farms['capacity_mw']/10
        ),
    )
)

fig_solar_farms.update_layout(
    mapbox_style="carto-darkmatter",
    mapbox=dict(
        center=go.layout.mapbox.Center(
            lat=36,
            lon=138
        ),
        zoom=3
    ),
)

fig_solar_farms.show()

I've tried the following:

fig_merged = go.Figure()
fig_merged.add_traces(fig_solar_farms, fig_typhoon)
fig_merged.show()

...but got the following error:

ValueError: 
    Invalid element(s) received for the 'data' property of 
        Invalid elements include: [Figure({
    'data': [{'lat': array([34.6, 40.9, 42.7]),
              'lon': array([134.1, 141.3, 141.7]),
              'marker': {'size': array([23.5, 14.8, 11.1])},
              'mode': 'markers',
              'type': 'scattermapbox'}],
    'layout': {'mapbox': {'center': {'lat': 36, 'lon': 138}, 'style': 'carto-darkmatter', 'zoom': 3}, 'template': '...'}
})]

    The 'data' property is a tuple of trace instances
    that may be specified as:
      - A list or tuple of trace instances
        (e.g. [Scatter(...), Bar(...)])
      - A single trace instance
        (e.g. Scatter(...), Bar(...), etc.)
      - A list or tuple of dicts of string/value properties where:
        - The 'type' property specifies the trace type
            One of: ['bar', 'barpolar', 'box', 'candlestick',
                     'carpet', 'choropleth', 'choroplethmapbox',
                     'cone', 'contour', 'contourcarpet',
                     'densitymapbox', 'funnel', 'funnelarea',
                     'heatmap', 'heatmapgl', 'histogram',
                     'histogram2d', 'histogram2dcontour', 'icicle',
                     'image', 'indicator', 'isosurface', 'mesh3d',
                     'ohlc', 'parcats', 'parcoords', 'pie',
                     'pointcloud', 'sankey', 'scatter',
                     'scatter3d', 'scattercarpet', 'scattergeo',
                     'scattergl', 'scattermapbox', 'scatterpolar',
                     'scatterpolargl', 'scattersmith',
                     'scatterternary', 'splom', 'streamtube',
                     'sunburst', 'surface', 'table', 'treemap',
                     'violin', 'volume', 'waterfall']

        - All remaining properties are passed to the constructor of
          the specified trace type

        (e.g. [{'type': 'scatter', ...}, {'type': 'bar, ...}])
1

There are 1 best solutions below

0
EricLavault On BEST ANSWER

In general, the simplest is to use the figure returned by plotly express as the main figure, then add trace(s) to it, then fine tune the layout :

fig = px.line_mapbox(
    df_typhoon,
    lat='latitude',
    lon='longitude',
    color='name',
    animation_frame='name'
)

fig.add_trace(
    go.Scattermapbox(
        lat = df_solar_farms['latitude'],
        lon = df_solar_farms['longitude'],
        mode = 'markers',
        marker = go.scattermapbox.Marker(
            size=df_solar_farms['capacity_mw']/10
        )
    )
)

fig.update_layout(
    mapbox_style="carto-darkmatter",
    mapbox_center_lat=36,
    mapbox_center_lon=138,
    mapbox_zoom=3
)

fig.show()

screenshot