pythonaltair

Bars in bar charts aligned differently based on axis direction


I am trying to place two horizontal bar charts side by side, each proceeding in the opposite direction, as in this example. However, as can be seen in the example, and in the test case below, horizontal bars seem to be offset by 1 pixel to the left of the grid, regardless of which direction they proceed in. This makes for unsatisfyingly asymmetrical visualizations, in which bars proceeding to the left do not the right-oriented y-axis they sit on, while bars proceeding to the right overlap the left-oriented axis they sit on.

import pandas as pd
import altair as alt

data = pd.DataFrame(data={
    'A': ['Item 1','Item 2','Item 3'],
    'B': [1,2,3],
})

left = alt.Chart(data).mark_bar().encode(
    alt.Y('A:N').axis(orient='right'),
    alt.X('B:Q').scale(reverse=True),
).properties(title='Bars do not overlap right-oriented y-axis')

right = alt.Chart(data).mark_bar().encode(
    alt.Y('A:N').axis(offset=1),
    alt.X('B:Q').axis(tickOffset=-1, gridDashOffset=10),
).properties(title='Bars do overlap left-oriented y-axis')

left | right

enter image description here

I would expect the left and right charts to be symmetrical. If there is a good reason for this difference in bar alignment, I would like to offset the bars in the right example by one pixel to the right with respect to the grid, so that they do not overlap the y-axis.

I have tried to achieve this effect by tweaking the offset of the y-axis in the right chart, as below. However, this results in a 1-pixel gap between the zero point on the x-axis, the bounding box, and the grid. Trying to fix these multiplies the offset issues. I simply want to offset the bars one pixel to the right, leaving the rest of the axes unchanged.

alt.Chart(data).mark_bar().encode(
    alt.Y('A:N').axis(offset=1),
    alt.X('B:Q'),
)

Solution

  • You could use the offset parameter:

    right = alt.Chart(data).mark_bar(xOffset=1).encode(
        alt.Y('A:N'),
        alt.X('B:Q'),
    )
    right
    

    However, this really looks like a bug in Vega-Lite, and the default behavior should be the same for both charts (the correct behavior is the non-overlapping, which is also the case for vertical bars from bottom to top, but the same issue is seen when the bars go from top to bottom). Could you file an issue at https://github.com/vega/vega-lite/issues with your example? (if you are interested in exploring more what goes wrong, you could open the chart in the vega editor and inspect the compiled vega spec)