如何调整工具提示以仅显示散景中滑块选择的列

How to adjust tooltip to display only column selected by slider in Bokeh

我正在尝试使用 Geopandas 和 Bokeh 创建可视化。 数据具有列区域、几何形状和 >100 列(第 1 周、第 2 周、第 3 周等),这些列具有个案数值。

此任务是当鼠标悬停在某个区域上时,工具提示仅显示滑块当前选择的列中的值。

我尝试过的事情:

此选项显示工具提示中的所有列。信息太多

data.plot_bokeh(
slider=[week1,week2,week3],
slider_name="Week:",
figsize=(1600,600))

不确定将什么作为变量放在“案例”旁边,或者如何根据滑块使其动态化。

data.plot_bokeh(
slider=[week1,week2,week3],
slider_name="Week:",
hovertool_string="""<h1>@region_name</h1>
                    <h3>Cases: ?? </h3>""",
figsize=(1600,600))

Bokeh 必须根据滑块将当前值存储在某处,因为它会根据值正确地为区域着色

  • 如果您检查 geoplot.py/geoplot() 中的 plotly_bokeh 代码,您将在滑块回调 JavaScript 中找到一个内部列 Colormap 设置为与滑块中的值对应的列(代码如下)
  • 您没有提供 MWE,因此使用了 OWID COVID 数据和自然地球低分辨率多边形。 (见资料准备)
  • 有了这个就可以很简单地定义 hovertool_string 参数来按你想要的方式工作

解决方案


import warnings

# bokeh generates a lot of shapely deprecation warnings
with warnings.catch_warnings():
    warnings.simplefilter("ignore")

    gdf.plot_bokeh(
        slider=[c for c in gdf.columns if c[0:4] == "week"],
        slider_name="week ",
        colorbar_tick_format="0.0a",
        colormap="Inferno",
        colormap_range=[
            gdf.loc[:, [c for c in gdf.columns if c[0:4] == "week"]].quantile(p).quantile(p)
            for p in [0.10, 0.90]
        ],
        hovertool_string="<h3>@name</h3><pre>@Colormap{0.0a}</pre>"
    )

输出

plotly_bokeh回调

        # Define Callback for Slider widget:
        callback = CustomJS(
            args=dict(
                slider_widget=slider_widget,
                geo_source=geo_source,
                value2name=value2name,
            ),
            code="""

                //Change selection of field for Colormapper for choropleth plot:
                var slider_value = slider_widget.value;
                var i;
                for(i=0; i<value2name.data["Names"].length; i++)
                    {
                    if (value2name.data["Values"][i] == slider_value)
                        {
                         var name = value2name.data["Names"][i];
                         }

                    }
                geo_source.data["Colormap"] = geo_source.data[name];
                geo_source.change.emit();

                            """,
        )
        slider_widget.js_on_change("value", callback)


资料准备

import pandas as pd
import geopandas as gpd
import pandas_bokeh
pandas_bokeh.output_notebook()

df = pd.read_csv(
    "https://raw.githubusercontent.com/owid/covid-19-data/master/public/data/owid-covid-data.csv"
).loc[
    lambda df: ~df["iso_code"].str.contains("_"),
    ["iso_code", "date", "total_cases_per_million"],
]
df["date"] = pd.to_datetime(df["date"])

# cases for each week as columns
df2 = (
    df.merge(
        pd.DataFrame(
            {"date": pd.date_range(df["date"].quantile(.1), df["date"].max(), freq="W-MON")}
        ).assign(week=lambda d: "week" + d.index.astype(str).str.zfill(3)),
        on="date",
        how="inner",
    )
    .drop(columns=["date"])
    .set_index(["iso_code", "week"])
    .unstack("week")
    .droplevel(0, 1)
    .reset_index()
)

# geometry and cases as columns
gdf = (
    gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
    .loc[:, ["iso_a3", "name", "geometry"]]
    .merge(df2, left_on="iso_a3", right_on="iso_code")
)