I hacked together this code to plot lat and lon coordinates on a map, and the code works pretty darn well, but I can't seem to get the legend displayed, so it's hard to tell what I'm actually looking at.
import pandas as pd
import pandas_bokeh
import matplotlib.pyplot as plt
import pgeocode
import geopandas as gpd
from shapely.geometry import Point
from geopandas import GeoDataFrame
pandas_bokeh.output_notebook()
import plotly.graph_objects as go
nomi = pgeocode.Nominatim('us')
df_melted['Latitude'] = (nomi.query_postal_code(df_melted['my_zip'].tolist()).latitude)
df_melted['Longitude'] = (nomi.query_postal_code(df_melted['my_zip'].tolist()).longitude)
df_melted['colors'] = df_melted['value'].groupby(df_melted['value']).transform('count')
print(df_melted.shape)
print(df_melted.head())
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
fig = go.Figure(data=go.Scattergeo(
lon = df_melted['Longitude'],
lat = df_melted['Latitude'],
text = df_melted['value'],
marker_color = df_melted['colors']
))
fig.update_layout(
autosize=False,
width=1000,
height=1000,
title = 'Footprints Compared Based on Lat & Lon Coordinates)',
geo_scope='usa',
showlegend=True
)
fig.update_layout(legend=dict(
orientation="h",
yanchor="bottom",
y=1.02,
xanchor="right",
x=1
))
fig.show()
When I run the code, I see a nice map of the US, but there is not legend, even though I'm using this small script directly below, which came straight from the Plotly documentation.
legend=True & showlegend=True
Both gave me errors. Any idea how to get the legend to show up here?
have used earthquake data to be able to simulate df_melted with compatible columns
there really is only one missing parameter: marker_coloraxis="coloraxis"
also changed showlegend=False
full working example using OP plotting code
import pandas as pd
import matplotlib.pyplot as plt
import geopandas as gpd
from shapely.geometry import Point
from geopandas import GeoDataFrame
import plotly.graph_objects as go
import requests
res = requests.get(
"https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_week.geojson"
)
us = (
gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
.loc[lambda d: d["iso_a3"].eq("USA"), "geometry"]
.values[0]
)
gdf = gpd.GeoDataFrame.from_features(res.json(), crs="epsg:4386").loc[
lambda d: d.intersects(us)
]
df_melted = pd.DataFrame(
{
"Latitude": gdf["geometry"].y,
"Longitude": gdf["geometry"].x,
"colors": gdf["mag"],
"value": gdf["place"],
}
)
fig = go.Figure(
data=go.Scattergeo(
lon=df_melted["Longitude"],
lat=df_melted["Latitude"],
text=df_melted["value"],
marker_color=df_melted["colors"],
marker_coloraxis="coloraxis",
)
)
fig.update_layout(
autosize=False,
width=400,
height=400,
title="Footprints Compared Based on Lat & Lon Coordinates)",
geo_scope="usa",
showlegend=False,
)
fig.update_layout(
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1)
)
fig.show()
Related
I try to display a map using json but this is the first time and I am probably using it wrong because when using px.choropleth alone my map is showing.
But I would like to use px.choropleth mapbox for a more elaborate map.
Here is the code below
Thanks for your help
import pandas as pd
import matplotlib
import folium
import matplotlib.pyplot as plt
import plotly.graph_objects as go
import plotly.express as px
from plotly.offline import plot
import json
import plotly.io as pio
Final = pd.read_excel('/Users/Desktop/Data_Extract_From_Indicateurs_du_développement_dans_le_monde (3).xlsx')
DataSet.head()
worldmap = json.load(open("/Users/Desktop/countries.geojson",'r'))
worldmap['features'][1]['properties']
world_id_map = {}
for feature in worldmap['features']:
feature['id'] = feature['properties']['ADMIN']
world_id_map[feature['properties']['ISO_A3']] = feature['id']
world_id_map = json.loads(worldmap)
figmap = px.choropleth(Final,
locations='Country Code',
color='CO2 emissions',
color_continuous_scale="Algae",
animation_frame='Date',
range_color=[20,10],
title='Worldwilde CO2 Emissions per habitant',
)
plot(figmap)
fig = go.Figure(go.Choroplethmapbox(geojson=world_id_map,
locations=Final['Country Code'],
z=Final['CO2 emissions'],
colorscale='algae', zmin=0, zmax=35,
colorbar_title = "CO2 emissions",
marker_opacity=0.5, marker_line_width=0.2))
fig.update_geos(fitbounds="locations", visible=True)
fig.update_layout(mapbox_style="carto-positron")
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
plot(fig)
have simulated your data frame and dynamically sourced heojson from GitHub
there is not need to manipulate the geojson all you need to do is pass the featureidkey parameter to link to locations
have left code in place for producing choropleth and choropleth_mapbox
import pandas as pd
import plotly.express as px
from plotly.offline import plot
import plotly.io as pio
import requests
import numpy as np
# Final = pd.read_excel('/Users/Desktop/Data_Extract_From_Indicateurs_du_développement_dans_le_monde (3).xlsx')
# DataSet.head()
# worldmap = json.load(open("/Users/Desktop/countries.geojson",'r'))
# get countries from internet...
worldmap = requests.get(
"https://raw.githubusercontent.com/nvkelso/natural-earth-vector/master/geojson/ne_110m_admin_0_countries.geojson"
).json()
# simulate dataframe, don't to local file
Final = pd.DataFrame(
{
"Country Code": [f["properties"]["ADM0_A3"] for f in worldmap["features"]],
"Date": np.tile(
pd.date_range("1-jan-2015", freq="Y", periods=7).strftime("%Y-%m-%d"), 100
)[0 : len(worldmap["features"])],
"CO2 emissions": np.random.uniform(10, 20, len(worldmap["features"])),
}
)
figmap = px.choropleth(
Final,
locations="Country Code",
color="CO2 emissions",
color_continuous_scale="Algae",
animation_frame="Date",
range_color=[20, 10],
title="Worldwilde CO2 Emissions per habitant",
)
figmap = px.choropleth_mapbox(
Final,
locations="Country Code",
geojson=worldmap,
featureidkey="properties.ADM0_A3",
color="CO2 emissions",
color_continuous_scale="Algae",
animation_frame="Date",
range_color=[20, 10],
title="Worldwilde CO2 Emissions per habitant",
mapbox_style="carto-positron",
).update_layout(mapbox={"zoom":2})
plot(figmap)
The code is running well; however, in my dataset, there is a column SD in my custom dataset. I would like the size of these markers should be based on SD and I did it in the seaborn library, it is running well. However, I get errors here.
%Error is
Did you mean "line"?
Bad property path:
size
^^^^
Code is
df=pd.read_csv("Lifecycle.csv")
df1=df[df["Specie"]=="pot_marigold"]
df1
df2=df[df["Specie"]=="Sunflowers"]
df2
trace=go.Scatter(x=df1["Days"], y=df1["Lifecycle"],text=df1["Specie"],marker={"color":"green"}, size=df1[SD],
mode="lines+markers")
trace1=go.Scatter(x=df2["Days"], y=df2["Lifecycle"],text=df2["Specie"],marker={"color":"red"},
mode="lines+markers")
data=[trace,trace1]
layout=go.Layout(
title="Lifecycle",
xaxis={"title":"Days"},
yaxis={"title":"Lifecycle"})
fig=go.Figure(data=data,layout=layout)
pyo.plot(fig)
you have not provided sample data, so I have simulated based on what I can imply from your code
simply you can set marker_size within framework you have used
this type of plot is far simpler with Plotly Express have also shown code for this
import pandas as pd
import numpy as np
import plotly.graph_objects as go
# df=pd.read_csv("Lifecycle.csv")
df = pd.DataFrame(
{
"Specie": np.repeat(["pot_marigold", "Sunflowers"], 10),
"Days": np.tile(np.arange(1, 11, 1), 2),
"Lifecycle": np.concatenate(
[np.sort(np.random.uniform(1, 5, 10)).astype(int) for _ in range(2)]
),
"SD": np.random.randint(1, 8, 20),
}
)
df1 = df[df["Specie"] == "pot_marigold"]
df2 = df[df["Specie"] == "Sunflowers"]
trace = go.Scatter(
x=df1["Days"],
y=df1["Lifecycle"],
text=df1["Specie"],
marker={"color": "green"},
marker_size=df1["SD"],
mode="lines+markers",
)
trace1 = go.Scatter(
x=df2["Days"],
y=df2["Lifecycle"],
text=df2["Specie"],
marker={"color": "red"},
mode="lines+markers",
)
data = [trace, trace1]
layout = go.Layout(
title="Lifecycle", xaxis={"title": "Days"}, yaxis={"title": "Lifecycle"}
)
fig = go.Figure(data=data, layout=layout)
fig
Plotly Express
import plotly.express as px
px.scatter(
df,
x="Days",
y="Lifecycle",
color="Specie",
size="SD",
color_discrete_map={"pot_marigold": "green", "Sunflowers": "red"},
).update_traces(mode="lines+markers")
You can use plotly.express instead:
import plotly.express as px
trace=px.scatter(df, x="Days", y="Lifecycle", text="Specie", marker="SD")
Trying to add data to hover of boxplot express in plotly and following the instructions here in plotly 5.4.1. It is mentioned in the tutorial that additional information to be shown in the hover can be added by hover_data and hover_name argument. However, The additional hover data, in this case information from continent column, is not presented in the hover. I am not sure what is going wrong here? (Here is the code I test in Google colab)
import plotly.express as px
import pandas as pd
import numpy as np
np.random.seed(1234)
df = pd.DataFrame(np.random.randn(20, 1),columns=['Col1'])
df['country']=['canada','france']*10
df['continent']=['america','europe']*10
fig = px.box(df, x="country", y="Col1", hover_data=['continent'])
fig.show()
Here is what i get in google colab:
Error I get with suggested solution (this was solved with pip install plotly --upgrade):
The solution offered by #Rob works but to make it a generic function, here is what I wrote out of it:
def box_with_hover(df,x,y,hover_data):
fig = px.box(df, x=x, y=y, hover_data=[hover_data])
fig.add_traces(
px.bar(
df.groupby([x, hover_data], as_index=False).agg(
base=(y, "min"), y=(y, lambda s: s.max() - s.min())
),
x=x,
base="base",
y="y",
hover_data={hover_data:True, x:True, "base":False, "y":False},
)
.update_traces(opacity=0.1)
.data ).update_layout(bargap=0.8)
fig.show()
this is similar to Change Plotly Boxplot Hover Data
boxplot hover info is within javascript layer of plotly. Hence have overlayed a bar plot where hover can be controlled in way you require. When you hover over boxplot you get standard boxplot hover. bar different hover info
import plotly.express as px
import pandas as pd
import numpy as np
np.random.seed(1234)
df = pd.DataFrame(np.random.randn(20, 1), columns=["Col1"])
df["country"] = ["canada", "france"] * 10
df["continent"] = ["america", "europe"] * 10
fig = px.box(df, x="country", y="Col1", hover_data=["continent"])
fig.add_traces(
px.bar(
df.groupby(["country", "continent"], as_index=False).agg(
base=("Col1", "min"), y=("Col1", lambda s: s.max() - s.min())
),
x="country",
base="base",
y="y",
hover_data={"continent":True, "country":True, "base":False, "y":False},
)
.update_traces(opacity=0.1)
.data
).update_layout(bargap=0.8)
fig
generic function
import plotly.express as px
import pandas as pd
import numpy as np
np.random.seed(1234)
df = pd.DataFrame(np.random.randn(20, 1), columns=["Col1"])
df["country"] = ["canada", "france"] * 10
df["continent"] = ["america", "europe"] * 10
df["letter"] = list("AB") * 10
def box_with_hover(*args, **kwargs):
if isinstance(args[0], pd.DataFrame):
kwargs["data_frame"] = args[0]
fig = px.box(**kwargs)
fig.add_traces(
px.bar(
kwargs["data_frame"]
.groupby([kwargs["x"]], as_index=False)
.agg(
**{
**{
"base": (kwargs["y"], "min"),
"y": (kwargs["y"], lambda s: s.max() - s.min()),
},
**{c: (c, "first") for c in kwargs["hover_data"]},
}
),
x=kwargs["x"],
base="base",
y="y",
hover_data={
**{c: True for c in kwargs["hover_data"]},
**{kwargs["x"]: True, "base": False, "y": False},
},
)
.update_traces(opacity=0.1)
.data
).update_layout(bargap=0.8)
return fig
box_with_hover(
df.reset_index(), x="country", y="Col1", hover_data=["continent", "letter", "index"]
)
I wish to plot a choropleth of count (frequency) and regions (using regional ISO codes) in US. I'm using plotly currently but I can't seem to figure why the colors which should show frequency isn't been displayed.
I haven't got fibs column, all I've got is ISO.
Thanks..
from urllib.request import urlopen
import pandas as pd
import plotly.express as px
import json
from pyspark.sql.types import IntegerType
# with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as # response:
# counties = json.load(response)
df = location_test.toPandas()
fig = px.choropleth_mapbox(df, locations=df['location_region_iso_code'], color=df['count'],
color_continuous_scale="Viridis",
range_color=(0, 15),
mapbox_style="carto-positron",
zoom=3, center = {"lat": 37.0902, "lon": -95.7129},
opacity=0.5,
labels={'count':'Count'}
)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
This is the output I get:
My goal is to create an animation with my 3D data in plotly.
I have 3 variables x,y,z for simplicity and I plot the 4th value depending on these x,y,z.
I create a 3D scatter plot where the 4th dim sort to speak is the color like this:
from numpy import genfromtxt
import numpy as np
import plotly.io as pio
import plotly.express as px
pio.renderers.default = 'notebook'
import plotly.graph_objects as go
import math
import pandas as pd
data = pd.read_csv("paramtp_1e-05_big.txt")
data.head()
data = data.iloc[::10, :]
color_data = data['gopt'].astype(float).round(decimals=2)
color_data[color_data>= 10] = 10
color_data_nopt = data['nopt'].astype(float).round(decimals=3)
color_data_mc = data['mc'].astype(float).round(decimals=3)
color_data_P= data['P']
color_data_P[color_data_P >= 1] = 1
data= data.replace(np.nan, '', regex=True)
data.tail()
fig = px.scatter_3d(data, x='NpN0', y='s', z='mu',log_x=True, log_z=True,
opacity = 0.5,
color=color_data,color_continuous_scale=px.colors.sequential.Viridis)
fig.add_trace(
go.Scatter(
mode='markers',
marker=dict(
size=1,
opacity=0.5,
),
)
)
fig.show()
Similarly to this wonderful animation: https://plotly.com/python/visualizing-mri-volume-slices/
I would like to slice up my data to isosurfaces with respect to any x,y,z coordinates.
As in the example they use images, I could not wrap my head around to create the same with my raw data.
Thank you in advance.