8-Bit Borges
8-Bit Borges

Reputation: 10033

Altair - highlight single element in bar chart

I have this dagtaframe, talismen_players:

                        Team  TotalShots  TotalCreated  Goals  ...  WeightBetweenness  %ShotInv                     Player    Color
0                Aston Villa        55.0          68.0    7.0  ...               0.45      0.36              Jack Grealish  #770038
1            Manchester City        76.0          96.0    8.0  ...               0.44      0.32            Kevin De Bruyne  #97C1E7
2                    Watford        62.0          43.0    4.0  ...               0.37      0.34            Gerard Deulofeu  #FBEE23
3             Leicester City        60.0          67.0    6.0  ...               0.32      0.34             James Maddison  #0053A0
4               Norwich City        29.0          69.0    0.0  ...               0.31      0.32           Emiliano Buendia  #00A14E
5                    Chelsea        63.0          40.0    5.0  ...               0.28      0.23                Mason Mount  #034694
6          Tottenham Hotspur        64.0          30.0    9.0  ...               0.28      0.29              Son Heung-Min  #132257
7                    Everton        66.0          30.0   10.0  ...               0.22      0.26                Richarlison  #274488
8                    Arsenal        64.0          18.0   17.0  ...               0.21      0.27  Pierre-Emerick Aubameyang  #EF0107
9                Bournemouth        25.0          40.0    1.0  ...               0.21      0.23                Ryan Fraser  #D3151B
10            Crystal Palace        42.0          20.0    6.0  ...               0.20      0.24                Jordan Ayew  #C4122E
11                   Burnley        33.0          40.0    2.0  ...               0.20      0.27              Dwight McNeil  #630F33
12          Newcastle United        41.0          24.0    1.0  ...               0.20      0.24                  Joelinton  #231F20
13                 Liverpool        89.0          41.0   14.0  ...               0.18      0.31              Mohamed Salah  #CE1317
14  Brighton and Hove Albion        27.0          52.0    2.0  ...               0.16      0.23                Pascal Groß  #005DAA
15   Wolverhampton Wanderers        86.0          38.0   11.0  ...               0.16      0.38               Raul Jimenez  #FDB913
16          Sheffield United        31.0          35.0    5.0  ...               0.15      0.24                 John Fleck  #E52126
17           West Ham United        48.0          18.0    6.0  ...               0.15      0.25           Sebastien Haller  #7C2C3B
18               Southampton        64.0          21.0   15.0  ...               0.11      0.24                 Danny Ings  #ED1A3B
19         Manchester United        37.0          31.0    1.0  ...               0.10      0.17            Andreas Pereira  #E80909

And I have singled out one element in a series being plotted by altair, like so:

    target_team = 'Liverpool'
    # the following prints 'Mohamed Salah'
    target_player = talismen_players.loc[talismen_players['Team']==target_team, 'Player'].item()
    # all elements                
    talisman_chart = alt.Chart(talismen_players).mark_bar().encode(
            alt.Y('Player:N', title="", sort='-x'),
            alt.X('WeightBetweenness:Q', title="Interconectividade do craque com o resto do time"),
            alt.Color('Color', legend=None, scale=None),
            tooltip = [alt.Tooltip('Player:N'),
                       alt.Tooltip('Team:N'),
                       alt.Tooltip('TotalShots:Q'),
                       alt.Tooltip('%ShotInv:Q')],
        ).properties(
        width=800
        ).configure_axis(
        grid=False
        ).configure_view(
        strokeWidth=0
        )
_________

This plots all elements, but I want to highlight one of them:

enter image description here

This is the code for achieving the result using lines: Multiline highlight


I've tried with this code:

highlight = alt.selection(type='single', on='mouseover',
                      fields=['Player'], nearest=True)

base = alt.Chart(talismen_players).encode(
    alt.X('WeightBetweenness:Q'),
    alt.Y('Player:N', title=''),
    alt.Color('Color', legend=None, scale=None),
    tooltip = [alt.Tooltip('Player:N'),
                   alt.Tooltip('Team:N'),
                   alt.Tooltip('TotalShots:Q'),
                   alt.Tooltip('%ShotInv:Q')],
)

points = base.mark_circle().encode(
    opacity=alt.value(0)
).add_selection(
    highlight
).properties(
    width=700
)

lines = base.mark_bar().encode(
    size=alt.condition(~highlight, alt.value(18), alt.value(20))
)

But the result is not ideal:

enter image description here

Highlight is not working.


QUESTION:

Ideally, I'd like to have target_player bar highlighted on default. and THEN be able to highlight the other bars, with mouseover.

But having target_player bar statically highlighted suffices.

Highlight should not change bar colors, but rather have a focus quality, while other bars are out of focus.

Upvotes: 1

Views: 646

Answers (1)

jakevdp
jakevdp

Reputation: 86320

You can do this using an initialized selection, along with an opacity for highlighting. For example:

import altair as alt
import pandas as pd

df = pd.DataFrame({
    'x': [1, 2, 3, 4],
    'y': ['A', 'B', 'C', 'D'],
    'color': ['W', 'X', 'Y', 'Z'],
})

hover = alt.selection_single(fields=['y'], on='mouseover', nearest=True, init={'y': 'C'})

alt.Chart(df).mark_bar().encode(
    x='x',
    y='y',
    color='color',
    opacity=alt.condition(hover, alt.value(1.0), alt.value(0.3))
).add_selection(hover)

enter image description here

Upvotes: 2

Related Questions