Search code examples
pythondata-visualizationvegavega-litealtair

altair faceted histogram - independent scales


Let's assume I have a dataset where the variables can be scaled quite differently from each other. I want to create histograms for each of the numeric variables. I am trying to make the x and y scales independent from each other so that the scales will not affect the visual quality. But even when I use resolve_scale() it only makes the y-scale independent, while x is still common among all the variables. This can be seen from the figure below which can be obtained by applying the code. Is this the desired behavior or am I missing something?

My question is:
1. How can I make the x scale independent?
2. How can I make the title get closer to the plot?

Thanks for your help.

version: python altair 4.0

alt.__version__
'4.0.1'
import altair as alt

data = alt.datasets.load_dataset('flights-2k')
chosen_origin_airports = data.groupby('origin').size().sort_values(ascending=False).head(12).index.tolist()
data = data[data.origin.isin(chosen_origin_airports)]
data.loc[data.origin=='BWI', 'delay']  = data.loc[data.origin=='BWI', 'delay'] * (10000)

alt.Chart(data=data).mark_bar().encode(
    x = alt.X('delay:Q', 
              axis=alt.Axis(title=''), 
              scale=alt.Scale(zero=False),
              bin=alt.Bin(maxbins=20)),
    y = alt.Y('count():Q', 
              axis=alt.Axis(title='')),
    color = alt.Color('origin:N')
).properties(
    width=130,
    height=130
).facet(
    alt.Column('origin:N', sort = alt.EncodingSortField(order=None)),
    align= 'all',
    padding=0,
    columns=4,
    spacing=0
).properties(
    title=''
).configure_title(
    fontSize=20,
    font='Courier',
    anchor='middle',
    color='gray',
    align='left'
).configure_header(
    title=None,
    titleColor='green',
    titleFontSize=14,
    labelColor='forestgreen',
    labelFontSize=14
).resolve_axis(
    x='independent',
    y='independent'
).resolve_scale(
    x='independent', 
    y='independent'
)

facetted histogram


Solution

  • Your scales are independent, but your binnings are not. Unfortunately, the Vega-Lite grammar provides no easy way to define a bin transform that applies different bin parameters to different subsets of data, so you'll have to have to manually use a distinct bin transform for each panel of the chart.

    I would probably do something like this:

    chart = alt.Chart(data).mark_bar().encode(
        x = alt.X('delay:Q', 
                  axis=alt.Axis(title=''), 
                  scale=alt.Scale(zero=False),
                  bin=alt.Bin(maxbins=20)),
        y = alt.Y('count():Q', 
                  axis=alt.Axis(title='')),
        color = alt.Color('origin:N')
    ).properties(
        width=130,
        height=130
    )
    
    alt.ConcatChart(
        concat=[
          chart.transform_filter(alt.datum.origin == value).properties(title=value)
          for value in sorted(data.origin.unique())
        ],
        columns=4
    ).configure_title(
        fontSize=20,
        font='Courier',
        anchor='middle',
        color='gray',
        align='left'
    ).resolve_axis(
        x='independent',
        y='independent'
    ).resolve_scale(
        x='independent', 
        y='independent'
    )
    

    enter image description here