Annotate an Altair chart
Altair 允许你用文本、图像和表情符号来注释你的图表。你可以通过叠加两个图表来创建一个分层图表。
Applied concepts
- 在Altair中使用分层图表来创建注释。
Prerequisites
-
本教程需要以下Python库:
streamlit altair>=4.0.0 vega_datasets -
本教程假设您有一个名为
your-repository的干净工作目录。 -
您应该对Vega-Altair图表库有一个基本的了解。
Summary
在这个例子中,您将创建一个时间序列图表来跟踪股票价格的演变。该图表将有两个层:数据层和注释层。每一层都是一个altair.Chart对象。您将使用+操作符将两个图表组合起来,创建一个分层图表。
在数据层中,您将添加一个多行工具提示以显示有关数据点的信息。要了解更多关于多行工具提示的信息,请参阅Vega-Altair文档中的这个示例。您还将在注释层中添加另一个工具提示。
以下是您将要构建的内容:
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)
Build the example
Initialize your app
-
在
your_repository中,创建一个名为app.py的文件。 -
在终端中,将目录更改为
your_repository并启动您的应用程序。streamlit run app.py您的应用程序将是空白的,因为您仍然需要添加代码。
-
在
app.py中,编写以下内容:import streamlit as st import altair as alt import pandas as pd from vega_datasets import data你将按以下方式使用这些库:
- 你将使用
vega_datasets下载一个数据集。 - 你将使用
pandas处理数据。 - 你将使用
altair定义一个图表。
- 你将使用
-
保存您的
app.py文件并查看您正在运行的应用程序。 -
点击“始终重新运行”或在运行的应用中按下“A”键。
当您保存对
app.py的更改时,您的运行预览将自动更新。您的预览仍然会是空白的。返回您的代码。
Build the data layer
你将构建一个带有多种提示线的股票价格交互式时间序列图表。x轴代表日期,y轴代表股票价格。
-
从
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。 -
在Altair中定义一个鼠标悬停选择事件。
hover = alt.selection_single( fields=["date"], nearest=True, on="mouseover", empty="none", )这定义了一个点的鼠标悬停选择。
fields=["date"]允许Altair识别具有相同日期的其他点。您将使用此功能在用户悬停在点上时创建垂直线高亮。 -
定义一个基本的折线图来绘制数据集中的五个系列。
lines = ( alt.Chart(stock_data, title="股票价格的演变") .mark_line() .encode( x="date", y="price", color="symbol", ) ) -
在线上绘制点,并根据鼠标悬停选择高亮显示它们。
points = lines.transform_filter(hover).mark_circle(size=65)由于鼠标悬停选择包括
fields=["date"],Altair 将在同一日期为每个系列绘制圆圈。 -
在鼠标悬停选择的位置绘制一条垂直规则。
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都会为您的多行工具提示添加一行。 -
将线条、点和工具提示组合成一个图表。
data_layer = lines + points + tooltips -
可选:通过渲染您的数据层来测试您的代码。
st.altair_chart(data_layer, use_container_width=True)保存您的文件并在您的应用程序中检查图表。使用鼠标悬停在点上。当您悬停在一个点上时,观察圆形标记、垂直线和工具提示。删除该行或将其保留在应用程序的末尾,以便在您继续时更新。
Build the annotation layer
现在你已经有了显示数据的第一个图表,你可以用文本和表情符号来注释它。在本节中,你将添加一些表情符号和工具提示来标记特定的兴趣点。
-
创建一个注释列表。
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")将填充相关的工具提示。
-
创建一个散点图,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的文档。
Combine the chart layers
-
定义组合图表。
combined_chart = data_layer + annotation_layer -
在Streamlit中显示图表。
st.altair_chart(combined_chart, use_container_width=True)
Next steps
尝试使用你的新应用程序。
-
如果你想使用自定义图片而不是文字或表情符号来注释你的图表,你可以将包含
.mark_text()的行替换为.mark_image()。对于存储在变量IMAGE_URL中的一些URL字符串,你可以这样做:.mark_image( width=12, height=12, url=IMAGE_URL, ) -
如果你想为你的图表启用平移和缩放功能,在定义组合图表时添加
.interactive():combined_chart = (data_layer + annotation_layer).interactive()
还有问题吗?
我们的 论坛 充满了有用的信息和Streamlit专家。