Altair Multi-Line Tooltip

Viewed 1300

with the following dataframe:

 #   Column                 Non-Null Count  Dtype  
---  ------                 --------------  -----  
 0   Unnamed: 0             428 non-null    int64  
 1   MatchID                428 non-null    int64  
 2   For Team               428 non-null    object 
 3   Against Team           428 non-null    object 
 4   Date                   428 non-null    object 
 5   GameWeek               428 non-null    int64  
 6   Home                   428 non-null    object 
 7   Possession             428 non-null    float64
 8   Touches                428 non-null    int64  
 9   Passes                 428 non-null    int64  
 10  Tackles                428 non-null    int64  
 11  Clearances             428 non-null    int64  
 12  Corners                428 non-null    int64  
 13  Offsides               428 non-null    int64  
 14  Fouls Committed        428 non-null    int64  
 15  Yellow Cards           428 non-null    int64  
 16  Goals                  428 non-null    int64  
 17  XG                     428 non-null    float64
 18  Shots On Target        428 non-null    int64  
 19  Total Shots            428 non-null    int64  
 ...
 35  Color                  428 non-null    object 

I am trying to follow this example from Altair examples gallery:

Multiline Tootip

enter image description here


This is MY code:

# Create a selection that chooses the nearest point & selects based on x-value
nearest = alt.selection(type='single', nearest=True, on='mouseover',
                        fields=['GameWeek'], empty='none')

# The basic line
line = alt.Chart(df_teams_full_stats).mark_line(interpolate='basis').encode(
    x='GameWeek:Q',
    y='Goals:Q',
    color=alt.Color('Color', scale=None)
)

# Transparent selectors across the chart. This is what tells us
# the x-value of the cursor
selectors = alt.Chart(df_teams_full_stats).mark_point().encode(
    x='GameWeek:Q',
    opacity=alt.value(0),
).add_selection(
    nearest
)

# Draw points on the line, and highlight based on selection
points = line.mark_point().encode(
    opacity=alt.condition(nearest, alt.value(1), alt.value(0))
)

# Draw text labels near the points, and highlight based on selection
text = line.mark_text(align='left', dx=5, dy=-5).encode(
    text=alt.condition(nearest, 'Goals:Q', alt.value(' '))
)

# Draw a rule at the location of the selection
rules = alt.Chart(df_teams_full_stats).mark_rule(color='gray').encode(
    x='GameWeek:Q',
).transform_filter(
    nearest
)

# Put the five layers into a chart and bind the data
chart = alt.layer(
    line, selectors, points, rules, text
).properties(
    width=1000, height=300
)

return chart

which plots:

enter image description here

There is an offset between points and the line they should be on top of. And I can't figure out why


QUESTION:

I would like to have the list of teams at the side as legend and, on mouseover, hover over one team (either at the side or over the line itself) and have its corresponding line enhanced, like so:

enter image description here

Is this possible? How so?

1 Answers

If you are ok with clicking the legend instead of hovering, you can set bind='legend' in your selection, like in this example from the gallery:

import altair as alt
from vega_datasets import data

source = data.unemployment_across_industries.url

selection = alt.selection_multi(fields=['series'], bind='legend')

alt.Chart(source).mark_area().encode(
    alt.X('yearmonth(date):T', axis=alt.Axis(domain=False, format='%Y', tickSize=0)),
    alt.Y('sum(count):Q', stack='center', axis=None),
    alt.Color('series:N', scale=alt.Scale(scheme='category20b')),
    opacity=alt.condition(selection, alt.value(1), alt.value(0.2))
).add_selection(
    selection
)

The 'mouseover' option does not yet work with legends it seems, so if you want mouseover you need to create a separate chart to act as a legend:

import altair as alt
from vega_datasets import data

source = data.unemployment_across_industries()
s2 = pd.DataFrame(source.series.unique(), columns=['series'])
selection = alt.selection_multi(on='mouseover', fields=['series'], nearest=True)

chart = alt.Chart(source).mark_area().encode(
    alt.X('yearmonth(date):T', axis=alt.Axis(domain=False, format='%Y', tickSize=0)),
    alt.Y('sum(count):Q', stack='center', axis=None),
    alt.Color('series:N', scale=alt.Scale(scheme='category20b')),
    opacity=alt.condition(selection, alt.value(1), alt.value(0.2)))

hover_legend = alt.Chart(s2).mark_circle(size=100).encode(
    alt.Y('series:N', axis=alt.Axis(orient='right', domain=False, ticks=False), title=None),
    alt.Color('series:N', scale=alt.Scale(scheme='category20b'), legend=None),
    opacity=alt.condition(selection, alt.value(1), alt.value(0.2))
).add_selection(selection)

(chart | hover_legend).configure_view(strokeWidth=0)

enter image description here

Related