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.
map A (left) animates two typhoon paths near Japan, and map B (right) shows 3 solar farms in Japan:
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)
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()
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, ...}])
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()