'Altair mark_text position based on condition
I have this chart with mark_text to denote the value of each bar. There is a slider to go back/forth in time.
I would like to change the positioning of the text (the numbers in the bars) depending on the Y value: if it is larger than a certain value, it will go just below the top of the bar (baseline='line-top), otherwise just above (baseline='line-bottom').
This way, as I slide through time the text will appear below/above the top of the bar depending on Y.
I think I have to use some condition or expression, but I cannot figure out how.
import numpy as np
import pandas as pd
import altair as alt
np.random.seed(0)
################################################################################
model_keys = ['M1', 'M2']
scene_keys = ['S1', 'S2']
layer_keys = ['L1', 'L2']
time_keys = [1, 2, 3]
ys = []
models = []
dataset = []
layers = []
scenes = []
times = []
for sc in scene_keys:
for m in model_keys:
for l in layer_keys:
for s in range(10):
y = np.random.rand(10) / 10
if m == 'M1':
y *= 10
if l == 'L1':
y *= 5
for t in time_keys:
y += 1
ys += list(y)
scenes += [sc] * len(y)
models += [m] * len(y)
layers += [l] * len(y)
times += [t] * len(y)
# ------------------------------------------------------------------------------
df = pd.DataFrame({'Y': ys,
'Model': models,
'Layer': layers,
'Scenes': scenes,
'Time': times})
bars = alt.Chart(df, width=100, height=90).mark_bar().encode(
x=alt.X('Scenes:N',
title=None,
axis=alt.Axis(
grid=False,
title=None,
labels=False,
),
),
y=alt.Y('Y:Q',
aggregate='mean',
axis=alt.Axis(
grid=True,
title='Y',
titleFontWeight='normal',
),
),
)
text = alt.Chart(df).mark_text(align='center',
baseline='line-top',
color='black',
dy=5,
fontSize=13,
).encode(
x=alt.X('Scenes:N'),
y=alt.Y('mean(Y):Q'),
text=alt.Text('mean(Y):Q',
format='.1f'
),
)
bars = bars + text
bars = bars.facet(
row=alt.Row('Model:N',
title=None,
),
column=alt.Column('Layer:N',
title=None,
),
spacing={"row": 10, "column": 10},
)
slider = alt.binding_range(
min=1,
max=3,
step=1,
name='Time',
)
selector = alt.selection_single(
name='Selector',
fields=['Time'],
bind=slider,
init={'Time': 3},
)
bars = bars.add_selection(
selector
).transform_filter(
selector
)
bars.save('test.html')
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|

