简体   繁体   English

使用 Altair 直接标记线图

[英]Direct labeling a line plot with Altair

I'm plotting a line graph in Altair (4.1.0) and would like to use direct labeling (annotations) instead of a regular legend.我正在 Altair (4.1.0) 中绘制折线图,​​并希望使用直接标记(注释)而不是常规图例。
As such, the text mark for each line (say, time series) should appear only once and at the right-most point of the x-axis (as opposed to this scatter plot example labeling every data point ).因此,每条线(比如时间序列)的文本标记应该只出现一次,并且出现在 x 轴的最右侧(与 这个标记每个数据点的散点图示例相反)。
While I'm able to use pandas to manipulate the data to get the desired results, I think it would be more elegant to have a pure-Altair implementation, but I can't seem to get it right.虽然我能够使用 Pandas 来操作数据以获得所需的结果,但我认为拥有纯 Altair 实现会更优雅,但我似乎无法正确实现。

For example, given the following data:例如,给定以下数据:

import numpy as np
import pandas as pd
import altair as alt

np.random.seed(10)
time = pd.date_range(start="10/21/2020", end="10/22/2020", periods=n)
data = pd.concat([
    pd.DataFrame({
        "time": time,
        "group": "One",
        "value": np.random.normal(10, 2, n)}),
    pd.DataFrame({
        "time": time,
        "group": "Two",
        "value": np.random.normal(5, 2, n)}).iloc[:-1]
], ignore_index=True)

I can generate a satisfactory result using pandas to create a subset that includes the last time-point for each group:我可以使用 Pandas 创建一个包含每个组的最后一个时间点的子集,从而产生令人满意的结果:

lines = alt.Chart(data).mark_line(
    point=True
).encode(
    x="time:T",
    y="value:Q",
    color=alt.Color("group:N", legend=None),  # Remove legend
)

text_data = data.loc[data.groupby('group')['time'].idxmax()]  # Subset the data for text positions
labels = alt.Chart(text_data).mark_text(
    # some adjustments
).encode(
    x="time:T",
    y="value:Q",
    color="group:N",
    text="group:N"
)

chart = lines + labels

在此处输入图片说明

However, if I try to use the main data and add Altair aggregations, for example using x=max(time) or explicit transform_aggregate() , I either get text annotations on all points or none at all (respectively).但是,如果我尝试使用主数据并添加 Altair 聚合,例如使用x=max(time)或显式transform_aggregate() ,我要么在所有点上获得文本注释,要么根本没有(分别)。

Is there a better way to obtain the above result?有没有更好的方法来获得上述结果?

You can do this using an argmax aggregate in the y encoding.您可以在 y 编码中使用argmax聚合来执行此操作。 For example, your labels layer might look like this:例如,您的标签图层可能如下所示:

labels = alt.Chart(data).mark_text(
    align='left', dx=5
).encode(
    x='max(time):T',
    y=alt.Y('value:Q', aggregate={'argmax': 'time'}),
    text='group:N',
    color='group:N',
)

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM