'Is there a way to control which vertices connect in a plotly.express.line_geo map?

I'm trying to make a connection map that has the option to use an animation_frame to show different months/years. Plotly.express has this option, but the plotly.express.line_geo maps seem to just attach the vertices of the network at random. I was looking at these examples from https://plotly.com/python/lines-on-maps/.

import plotly.express as px
df = px.data.gapminder().query("year == 2007")
fig = px.line_geo(df, locations="iso_alpha",
                  color="continent", # "continent" is one of the columns of gapminder
                  projection="orthographic")
fig.show()

Plotly.graph_objects allows you to map actual connections between vertices, but doesn't seem to have an animation option.

import plotly.graph_objects as go
import pandas as pd

df_airports = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2011_february_us_airport_traffic.csv')
df_airports.head()

df_flight_paths = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/2011_february_aa_flight_paths.csv')
df_flight_paths.head()

fig = go.Figure()

flight_paths = []
for i in range(len(df_flight_paths)):
    fig.add_trace(
        go.Scattergeo(
            locationmode = 'USA-states',
            lon = [df_flight_paths['start_lon'][i], df_flight_paths['end_lon'][i]],
            lat = [df_flight_paths['start_lat'][i], df_flight_paths['end_lat'][i]],
            mode = 'lines',
            line = dict(width = 1,color = 'red'),
            opacity = float(df_flight_paths['cnt'][i]) / float(df_flight_paths['cnt'].max()),
        )
    )

fig.show()

Does anyone know of a way that i could make a map like the flight path map, but allow an animation option to look at the flight maps for different months/years?



Solution 1:[1]

  • you can animate any trace type using frames
  • taking sample flight path data used in question, have split it into groups based on first letter of start airport
  • there is no need to create a trace per flight, instead create pairs of start end locations in arrays separated by None
  • with this it is simple to create a frame with a trace for each group
  • then just create the figure from the frames, plus a default trace
  • add play button and slider
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd

df_flight_paths = pd.read_csv(
    "https://raw.githubusercontent.com/plotly/datasets/master/2011_february_aa_flight_paths.csv"
)

frames = []

# lets split data based on first letter of start airport
# create a frame for each grouping
bins = 6
for color, df in df_flight_paths.groupby(
    pd.qcut(
        df_flight_paths["airport1"].str[0].apply(ord),
        q=bins,
        labels=px.colors.qualitative.Plotly[:bins],
    )
):
    name = f'{df["airport1"].str[0].min()}-{df["airport1"].str[0].max()}'
    frames.append(
        go.Frame(
            name=name,
            data=go.Scattergeo(
                lon=df.assign(nan=None)[["start_lon", "end_lon", "nan"]].values.ravel(),
                lat=df.assign(nan=None)[["start_lat", "end_lat", "nan"]].values.ravel(),
                mode="lines",
                line=dict(width=1, color=color),
            ),
        )
    )

# now create figure and add play button and slider
go.Figure(
    data=frames[0].data,
    frames=frames,
    layout={
        "updatemenus": [
            {
                "type": "buttons",
                "buttons": [{"label": "Play", "method": "animate", "args": [None]}],
            }
        ],
        "sliders": [
            {
                "active": 0,
                "steps": [
                    {
                        "label": f.name,
                        "method": "animate",
                        "args": [[f.name]],
                    }
                    for f in frames
                ],
            }
        ],
    },
).update_geos(
    scope="north america",
)

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Rob Raymond