I am trying to make a density plot and mark part of the region based on the X value. The following snippet mostly works but has a weird angled cut-off between regions. How do I fix it?
np.random.seed(0)
df = pd.DataFrame({'x': np.random.normal(size=1000)})
(alt.Chart(df).
transform_density('x', as_=['val', 'density']).
transform_calculate(crit='(datum.val < -1.96) | (datum.val > 1.96)').
mark_area().encode(
x='val:Q',
y=alt.Y('density:Q', impute={'value': 0}),
color='crit:N'
)
)
This happens because the area mark tries to interpolate linearly from where the blue and orange region ends to the bottom of the x-axis for each section of the area. If you set interpolate='step'
you will see that the border is sharp (removing impute
will improve it for the area). You can try to upsample the data to have the interpolation happen over such a small distance that it appears to be a straight vertical line and the areas look connected, more details in the answer to this question How to correctly shift the baseline in an area plot to a particular y location and change the fill color correspondingly, in Altair? .
Another solution is to layer the middle portion on top of the entire density plot:
import numpy as np
import pandas as pd
import altair as alt
np.random.seed(0)
df = pd.DataFrame({'x': np.random.normal(size=1000)})
chart = (
alt.Chart(df)
.transform_density('x', as_=['x', 'density'])
.mark_area(color='coral')
.encode(x='x', y=alt.Y('density:Q')))
chart + (
chart
.mark_area(color='steelblue')
.transform_filter('(datum.x > -1.96) & (datum.x < 1.96)'))