How To Plot Visualize A Linestring Over A Map With Python?
I have some coordinates from Lng and lat, that I combined to a Linestring. The Linestring is made of 2 Points. From one point starting=origin and from one point ending = destinatio
Solution 1:
Using the examples and data from the official plotly reference, I have replaced your questions and identified the issues that prevent line segments from being drawn. You need to specify a column of text that indicates the group to be set in color. So set the color to the column that is the group key in your data.
import plotly.express as px
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.sort_values('cnt', ascending=False, inplace=True)
df_flight_paths = df_flight_paths.query("airport2 in ['DFW','LAX']")
df_flight_paths.head()
start_lat   start_lon   end_lat     end_lon     airline     airport1    airport2    cnt
3333.942536   -118.40807432.895951   -97.0372    AA  LAX     DFW     9145029.533694   -98.46977832.895951   -97.0372    AA  SAT     DFW     8264441.979595   -87.90446432.895951   -97.0372    AA  ORD     DFW     8252030.194533   -97.66987232.895951   -97.0372    AA  AUS     DFW     8201933.640444   -84.42694432.895951   -97.0372    AA  ATL     DFW     580
fig = px.line_mapbox(df_flight_paths,
                     lat="start_lat", 
                     lon="start_lon", 
                     color="airport2",
                     hover_name="airport1",
                     #animation_frame="time",
                     center =dict(lon=-97.0,lat=38.0),
                     zoom=3, height=600
                    )
fig.update_layout(mapbox_style="stamen-terrain",
                  mapbox_zoom=4,
                  mapbox_center_lon=-97.0,
                  mapbox_center_lat=38.0,
                  margin={"r":0,"t":0,"l":0,"b":0}
                 )
fig.show()
Solution 2:
- setup some data that are lines between points. Have used 5 random UK hospitals
- created a LineString geometry between the origin and destination
- used https://plotly.com/python/lines-on-mapbox/#lines-on-mapbox-maps-from-geopandas example to show using LineString as geometry works as per example
import requests, io, json
import geopandas as gpd
import shapely.geometry
import pandas as pd
import numpy as np
import itertools
import plotly.express as px
# get some public addressess - hospitals.  data that has GPS lat / lon
dfhos = pd.read_csv(io.StringIO(requests.get("http://media.nhschoices.nhs.uk/data/foi/Hospital.csv").text),
    sep="¬",engine="python",).loc[:, ["OrganisationName", "Latitude", "Longitude"]]
a = np.arange(len(dfhos))
np.random.shuffle(a)
# establish N links between hospitals
N = 10
df = (
    pd.DataFrame({0:a[0:N], 1:a[25:25+N]}).merge(dfhos,left_on=0,right_index=True)
    .merge(dfhos,left_on=1, right_index=True, suffixes=("_origin", "_destination"))
)
# build a geopandas data frame that has LineString between two hospitals
gdf = gpd.GeoDataFrame(
    data=df,
    geometry=df.apply(
        lambda r: shapely.geometry.LineString(
            [(r["Longitude_origin"], r["Latitude_origin"]),
             (r["Longitude_destination"], r["Latitude_destination"]) ]), axis=1)
)
# sample code https://plotly.com/python/lines-on-mapbox/#lines-on-mapbox-maps-from-geopandas
lats = []
lons = []
names = []
for feature, name inzip(gdf.geometry, gdf["OrganisationName_origin"] + " - " + gdf["OrganisationName_destination"]):
    ifisinstance(feature, shapely.geometry.linestring.LineString):
        linestrings = [feature]
    elifisinstance(feature, shapely.geometry.multilinestring.MultiLineString):
        linestrings = feature.geoms
    else:
        continuefor linestring in linestrings:
        x, y = linestring.xy
        lats = np.append(lats, y)
        lons = np.append(lons, x)
        names = np.append(names, [name]*len(y))
        lats = np.append(lats, None)
        lons = np.append(lons, None)
        names = np.append(names, None)
fig = px.line_mapbox(lat=lats, lon=lons, hover_name=names)
fig.update_layout(mapbox_style="stamen-terrain",
                  mapbox_zoom=4,
                  mapbox_center_lon=gdf.total_bounds[[0,2]].mean(),
                  mapbox_center_lat=gdf.total_bounds[[1,3]].mean(),
                  margin={"r":0,"t":0,"l":0,"b":0}
                 )
simplified version
- using dataframe of links between hospitals as sample data
- plotly documentation and labels clearly note need to delimit lines with Nonein arrays passed topx.line_mapbox(). construct these in a far more direct way using numpy there is no need to construct LineString, use geopnadas or shapely
# plotly takes array delimited with None between lines. Use numpy padding and shaping to generate this array
# from pair of features
def line_array(df, cols):
    return np.pad(df.loc[:,cols].values, [(0, 0), (0, 1)], constant_values=None).reshape(1,(len(df)*3))[0]
    
fig = px.line_mapbox(lat=line_array(df, ["Latitude_origin", "Latitude_destination"]), 
                     lon=line_array(df, ["Longitude_origin", "Longitude_destination"]),
                     hover_name=line_array(df, ["OrganisationName_origin", "OrganisationName_destination"]),
)
fig.update_layout(mapbox_style="stamen-terrain",
                  mapbox_zoom=4,
                  mapbox_center_lon=df.loc[:,["Longitude_origin","Longitude_destination"]].mean().mean(),
                  mapbox_center_lat=df.loc[:,["Latitude_origin","Latitude_destination"]].mean().mean(),
                  margin={"r":0,"t":0,"l":0,"b":0}
                 )


Post a Comment for "How To Plot Visualize A Linestring Over A Map With Python?"