import altair as alt
from vega_datasets import data
= data.movies.url source
Adjusting jitter width in Altair charts
In a previous post I made a strip plot with jitter. I realized as I was making that plot that I did not know how to adjust the “jitter width” (i.e how far points are spread apart). Below I describe one method for modifying jitter width.
I’ll set up the chart similar to last time. But, instead of calculating jitter using a vega-lite expression string, I will just write the expression in Python and I am also going to add a jitter width parameter to the calculation whose value is bound to a slider.
1= alt.binding_range(min=0, max=1, name="Jitter width: ")
slider 2= alt.param(bind=slider, value=0.35)
jitter_width
= (
base =alt.Step(25), width=500)
alt.Chart(source, height
.transform_calculate(3=(alt.expr.random() - 0.5) * jitter_width,
jitter
)4
.add_params(
jitter_width
) )
- 1
- Here we create a slider.
- 2
- The jitter width parameter is bound to the slider value with a default value of 0.35.
- 3
-
This is where the jitter is calculated. This transform adds a
jitter
column that we can reference later. - 4
- We need to add the jitter width parameter in order to reference it. This will also make the slider show up in the chart.
The rest of the chart is almost identical to the original. The only difference is the scale
setting for the yOffset
encoding. You want to fix the scale domain so that it does not change with your jitter width effectively canceling out your jitter spread adjustment.
= "IMDB_Rating"
x_field = "Q"
type_ = alt.EncodingSortField(field=x_field, op="median", order="descending")
sort = {"titleFontSize": 14, "titlePadding": 15, "labelFontSize": 12}
axis_kwargs
= base.mark_circle(
points =20, stroke="steelblue", strokeOpacity=0.5, fill="steelblue", fillOpacity=0.15
size
).encode(=alt.Y("Major_Genre:N").sort(sort).axis(title=None, **axis_kwargs),
y=alt.X(f"{x_field}:{type_}"),
x1=alt.YOffset("jitter:Q").scale(domain=[-0.5, 0.5]),
yOffset
)
= base.mark_tick(stroke="firebrick", strokeOpacity=0.85, thickness=1.5).encode(
ticks =alt.Y("Major_Genre:N").sort(sort),
y=alt.X(f"{x_field}:{type_}", aggregate="median").axis(
x="IMDB Rating", **axis_kwargs
title
),
)
+ ticks points
- 1
- Note how the scale domain is fixed.