I made a world map with specific data using choropleth from plotly. For some countries I have missing values and this gives me uncolored areas and especially without being able to identify them.
Edit: I found how to colorize the countries with missing values by adding this in the "geo=dict()" of "update_layout":
landcolor = 'lightgray',
showland = True,
showcountries = True,
countrycolor = 'gray',
countrywidth = 0.5,
Which gives this code:
import plotly.graph_objects as go
fig = go.Figure(data = go.Choropleth(
locations = world_map_df_sous_nutrition["Code zone (ISO3)"],
z = round((world_map_df_sous_nutrition["Proportion pop en sous-nutrition"]),2),
text = world_map_df_sous_nutrition["Zone"],
colorscale = "earth",
autocolorscale = False,
reversescale = True,
marker_line_color = "white",
marker_line_width = .2,
colorbar_tickprefix = "%",
colorbar_title = "Proportion de personnes en sous nutrition"
))
fig.update_layout(
title_text="L'état de la sous-nutrition dans le monde en 2017",
geo=dict(
landcolor = 'lightgray',
showland = True,
showcountries = True,
countrycolor = 'gray',
countrywidth = 0.5,
showframe=False,
showcoastlines=False,
projection_type='equirectangular'
),
annotations = [dict(
x=0.55,
y=0.1,
xref='paper',
yref='paper',
text='Source: <a href="https://www.fao.org/faostat/fr/#data">\
FAO</a>',
showarrow = False
)],
margin={"r":0,"t":0,"l":0,"b":0},
)
fig.show()
And this image result:
How to get the name of these greyed out countries (having missing values) by hovering the cursor over them?
With GeoPandas I managed to colorize my missing areas with this code:
from geopandas import GeoDataFrame
world_map_df_sous_nutrition = GeoDataFrame(world_map_df_sous_nutrition)
world_map_df_sous_nutrition.plot(column="Proportion pop en sous-nutrition",cmap='cividis', figsize=(20, 20), missing_kwds={
"color": "lightgrey",
"edgecolor": "red",
"hatch": "///",
"label": "Missing values",
}).axis('off')
plt.show()
How to do the same with plotly?
Is it possible in the matchbox to add values from other columns of my dataframe in addition or I can only display values from one column? If possible how to switch from one colorization to another?
Is it possible too to make an animated world map with the evolution of our data by years?
There are multiple questions
start by using plotly express It's a simpler to use interface
simple case of using animation_frame for animation. Answers 3.
use hover_data to answer 4.
https://plotly.com/python/map-configuration/#physical-base-maps states that countries are from natural earth. A simple way to get this is is use geopandas
one strange thing I encountered was need to recreate the figure as final step using go
import plotly.graph_objects as go
import plotly.express as px
import geopandas as gpd
import pandas as pd
import numpy as np
# need to know countries that make up natural earth...
world = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
# synthesize data by year for animation
df = pd.concat(
[
pd.DataFrame(
{
"Code zone (ISO3)": world["iso_a3"].sample(150),
"Proportion pop en sous-nutrition": np.random.uniform(0, 100, 150),
"Zone": np.random.choice(list("ABCD"), 150),
"Product": np.reshape(
np.concatenate(
[
np.random.choice(list("jklmn"), 150),
np.random.choice(list("jklmn"), 150),
]
),
[150, 2],
).tolist(),
}
).assign(year=y)
for y in range(2010, 2022)
]
)
# use px, simpler... especially animation
fig = px.choropleth(
df,
locations="Code zone (ISO3)",
color="Proportion pop en sous-nutrition",
color_continuous_scale="earth_r",
animation_frame="year",
hover_data=["Zone", "Product"],
).update_layout(
title_text="L'état de la sous-nutrition dans le monde en 2017",
geo=dict(
# landcolor="lightgray",
showland=True,
showcountries=True,
countrycolor="gray",
countrywidth=0.5,
showframe=False,
showcoastlines=False,
projection_type="equirectangular",
),
annotations=[
dict(
x=0.55,
y=0.1,
xref="paper",
yref="paper",
text='Source: <a href="https://www.fao.org/faostat/fr/#data">\
FAO</a>',
showarrow=False,
)
],
margin={"r": 0, "t": 0, "l": 0, "b": 0},
coloraxis2={"colorscale": [[0, "red"], [1, "red"]], "showscale": False},
)
# update each of the animation frames with missing countries
for fr in fig.frames:
tr_missing = (
px.choropleth(
world.loc[~world["iso_a3"].isin(fr.data[0]["locations"]), "iso_a3"]
.to_frame()
.assign(color=1),
color="color",
locations="iso_a3",
color_continuous_scale=[[0, "red"], [1, "red"]],
)
.update_traces(hovertemplate="missing: %{location}", coloraxis="coloraxis2")
.data[0]
)
fr.update(data=[fr.data[0], tr_missing])
# re-construct the figure...
go.Figure(data=fig.frames[0].data, layout=fig.layout, frames=fig.frames)