如何为具有缺失值的土地着色并在 plotly choropleth 中获得它们的名字?在火柴盒中添加额外的值?按年份动画情节?

How to colorize lands which have missing values and get their name in plotly choropleth? Add extra values ​in the matchbox? Animate the plot by year?

我使用来自 plotly 的 choropleth 制作了一张包含特定数据的世界地图。 对于某些国家/地区,我缺少值,这给了我未着色的区域,尤其是无法识别它们。

编辑: 我找到了如何通过在“update_layout”的“geo=dict()”中添加这个来为具有缺失值的国家着色:

landcolor = 'lightgray',
showland = True,
showcountries = True,
countrycolor = 'gray',
countrywidth = 0.5,

这给出了这个代码:

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()

而这张图片结果:

Choropleth result update

Choropleth result before

如何通过将光标悬停在这些灰色国家(具有缺失值)上来获取它们的名称?

借助 GeoPandas,我设法使用以下代码为缺失的区域着色:

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()

GeoPandas result

如何用 plotly 做同样的事情?

是否可以在匹配框中添加数据框其他列的值,或者我只能显示一列的值?如果可能,如何从一种颜色切换到另一种颜色?

是否也可以根据我们的数据逐年演变制作动画世界地图?

有多个问题

  1. 如何给缺失的国家上色?
  2. 如何在缺少的国家/地区显示悬停文本?
  3. 如何动画年?
  4. 悬停时如何显示其他栏目?
  • 从使用plotly express开始,使用界面更简单

  • 使用animation_frame制作动画的简单案例。答案 3.

  • 使用hover_data回答4.

  • https://plotly.com/python/map-configuration/#physical-base-maps 表示国家来自自然地球。一个简单的方法是使用 geopandas

    • 为每个动画帧检查缺少哪些国家并添加额外的跟踪。答案 1.
    • 此跟踪包含答案 2.
    • 的信息
  • 我遇到的一件奇怪的事情是需要使用 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)