Annotate an Altair chart

Altair 允许你用文本、图像和表情符号来注释你的图表。你可以通过叠加两个图表来创建一个分层图表

  • 在Altair中使用分层图表来创建注释。
  • 本教程需要以下Python库:

    streamlit altair>=4.0.0 vega_datasets
  • 本教程假设您有一个名为 your-repository 的干净工作目录。

  • 您应该对Vega-Altair图表库有一个基本的了解。

在这个例子中,您将创建一个时间序列图表来跟踪股票价格的演变。该图表将有两个层:数据层和注释层。每一层都是一个altair.Chart对象。您将使用+操作符将两个图表组合起来,创建一个分层图表。

在数据层中,您将添加一个多行工具提示以显示有关数据点的信息。要了解更多关于多行工具提示的信息,请参阅Vega-Altair文档中的这个示例。您还将在注释层中添加另一个工具提示。

以下是您将要构建的内容:

Complete codeexpand_more
import streamlit as st import altair as alt import pandas as pd from vega_datasets import data @st.cache_data def get_data(): source = data.stocks() source = source[source.date.gt("2004-01-01")] return source stock_data = get_data() hover = alt.selection_single( fields=["date"], nearest=True, on="mouseover", empty="none", ) lines = ( alt.Chart(stock_data, title="Evolution of stock prices") .mark_line() .encode( x="date", y="price", color="symbol", ) ) points = lines.transform_filter(hover).mark_circle(size=65) tooltips = ( alt.Chart(stock_data) .mark_rule() .encode( x="yearmonthdate(date)", y="price", opacity=alt.condition(hover, alt.value(0.3), alt.value(0)), tooltip=[ alt.Tooltip("date", title="Date"), alt.Tooltip("price", title="Price (USD)"), ], ) .add_selection(hover) ) data_layer = lines + points + tooltips ANNOTATIONS = [ ("Sep 01, 2007", 450, "🙂", "Something's going well for GOOG & AAPL."), ("Nov 01, 2008", 220, "🙂", "The market is recovering."), ("Dec 01, 2007", 750, "😱", "Something's going wrong for GOOG & AAPL."), ("Dec 01, 2009", 680, "😱", "A hiccup for GOOG."), ] annotations_df = pd.DataFrame( ANNOTATIONS, columns=["date", "price", "marker", "description"] ) annotations_df.date = pd.to_datetime(annotations_df.date) annotation_layer = ( alt.Chart(annotations_df) .mark_text(size=20, dx=-10, dy=0, align="left") .encode(x="date:T", y=alt.Y("price:Q"), text="marker", tooltip="description") ) combined_chart = data_layer + annotation_layer st.altair_chart(combined_chart, use_container_width=True)
  1. your_repository 中,创建一个名为 app.py 的文件。

  2. 在终端中,将目录更改为 your_repository 并启动您的应用程序。

    streamlit run app.py

    您的应用程序将是空白的,因为您仍然需要添加代码。

  3. app.py 中,编写以下内容:

    import streamlit as st import altair as alt import pandas as pd from vega_datasets import data

    你将按以下方式使用这些库:

    • 你将使用 vega_datasets 下载一个数据集。
    • 你将使用 pandas 处理数据。
    • 你将使用 altair 定义一个图表。
  4. 保存您的app.py文件并查看您正在运行的应用程序。

  5. 点击“始终重新运行”或在运行的应用中按下“A”键。

    当您保存对app.py的更改时,您的运行预览将自动更新。您的预览仍然会是空白的。返回您的代码。

你将构建一个带有多种提示线的股票价格交互式时间序列图表。x轴代表日期,y轴代表股票价格。

  1. vega_datasets导入数据。

    @st.cache_data def get_data(): source = data.stocks() source = source[source.date.gt("2004-01-01")] return source stock_data = get_data()

    @st.cache_data装饰器将get_data()转换为缓存函数。由于数据将保存在缓存中,Streamlit只会下载一次数据。有关缓存的更多信息,请参阅Caching overview

  2. 在Altair中定义一个鼠标悬停选择事件。

    hover = alt.selection_single( fields=["date"], nearest=True, on="mouseover", empty="none", )

    这定义了一个点的鼠标悬停选择。fields=["date"]允许Altair识别具有相同日期的其他点。您将使用此功能在用户悬停在点上时创建垂直线高亮。

  3. 定义一个基本的折线图来绘制数据集中的五个系列。

    lines = ( alt.Chart(stock_data, title="股票价格的演变") .mark_line() .encode( x="date", y="price", color="symbol", ) )
  4. 在线上绘制点,并根据鼠标悬停选择高亮显示它们。

    points = lines.transform_filter(hover).mark_circle(size=65)

    由于鼠标悬停选择包括 fields=["date"],Altair 将在同一日期为每个系列绘制圆圈。

  5. 在鼠标悬停选择的位置绘制一条垂直规则。

    tooltips = ( alt.Chart(stock_data) .mark_rule() .encode( x="yearmonthdate(date)", y="price", opacity=alt.condition(hover, alt.value(0.3), alt.value(0)), tooltip=[ alt.Tooltip("date", title="日期"), alt.Tooltip("price", title="价格 (USD)"), ], ) .add_selection(hover) )

    opacity 参数确保每条垂直线仅在鼠标悬停选择时可见。每个 alt.Tooltip 都会为您的多行工具提示添加一行。

  6. 将线条、点和工具提示组合成一个图表。

    data_layer = lines + points + tooltips
  7. 可选:通过渲染您的数据层来测试您的代码。

    st.altair_chart(data_layer, use_container_width=True)

    保存您的文件并在您的应用程序中检查图表。使用鼠标悬停在点上。当您悬停在一个点上时,观察圆形标记、垂直线和工具提示。删除该行或将其保留在应用程序的末尾,以便在您继续时更新。

现在你已经有了显示数据的第一个图表,你可以用文本和表情符号来注释它。在本节中,你将添加一些表情符号和工具提示来标记特定的兴趣点。

  1. 创建一个注释列表。

    ANNOTATIONS = [ ("Sep 01, 2007", 450, "🙂", "GOOG 和 AAPL 的情况不错。"), ("Nov 01, 2008", 220, "🙂", "市场正在复苏。"), ("Dec 01, 2007", 750, "😱", "GOOG 和 AAPL 出了点问题。"), ("Dec 01, 2009", 680, "😱", "GOOG 出了点小问题。"), ] annotations_df = pd.DataFrame( ANNOTATIONS, columns=["date", "price", "marker", "description"] ) annotations_df.date = pd.to_datetime(annotations_df.date)

    前两列("date" 和 "price")决定了 Altair 将标记放置的位置。第三列("marker")决定了 Altair 将放置的图标。最后一列("description")将填充相关的工具提示。

  2. 创建一个散点图,x轴代表日期,y轴代表每个注释的高度("价格")。

    annotation_layer = ( alt.Chart(annotations_df) .mark_text(size=20, dx=-10, dy=0, align="left") .encode(x="date:T", y=alt.Y("price:Q"), text="marker", tooltip="description") )

    .mark_text()中的dx=-10, dy=0偏移图标,使它们在注释数据框中的坐标处居中。四个列通过.encode()方法传递给图表。如果你想对所有点使用相同的标记,可以从.encode()方法中移除text="marker",并将标记添加到.mark_text()中。例如,.mark_text(text="🥳")将使所有图标变为"🥳"。有关.mark_text()的更多信息,请参阅Altair的文档

  1. 定义组合图表。

    combined_chart = data_layer + annotation_layer
  2. 在Streamlit中显示图表。

    st.altair_chart(combined_chart, use_container_width=True)

尝试使用你的新应用程序。

  • 如果你想使用自定义图片而不是文字或表情符号来注释你的图表,你可以将包含.mark_text()的行替换为.mark_image()。对于存储在变量IMAGE_URL中的一些URL字符串,你可以这样做:

    .mark_image( width=12, height=12, url=IMAGE_URL, )
  • 如果你想为你的图表启用平移和缩放功能,在定义组合图表时添加 .interactive()

    combined_chart = (data_layer + annotation_layer).interactive()
forum

还有问题吗?

我们的 论坛 充满了有用的信息和Streamlit专家。