Search code examples
pythonvega-litealtair

Bars not extending the full size in Vega/Altair plot


I'm trying to plot a histogram from pre-binned data using Vega-lite (Actually, Altair in Python, but I got the issue when using Vega directly as well). My dataset contains the following fields:

  • bin: The bin ID
  • center_point: The center of the bin
  • left_bound: The beginning of the bin
  • right_bound: The end of the bin.
  • n: The count for the histogram.

I used the following Python code to plot the chart:

chart = alt.Chart(data).mark_bar().encode(
    x = "left_bound",
    x2 = "right_bound",
    y = "n"
)

And got the following result:

enter image description here

I don't understand why the bars are not going all the way down. This only happens when I specify x2. If I get rid of it the bars start to go all the way down.

chart = alt.Chart(data).mark_bar().encode(
    x = "left_bound",
    y = "n"
)

enter image description here

However, doing this is not an option because bins might be of unequal width. What might be wrong?

Below is the full Vega-lite spec in JSON, as well as a link to the VegaEditor that contains this spec.

Open the Chart in the Vega Editor

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.17.0.json",
  "config": {"view": {"continuousHeight": 300, "continuousWidth": 500}},
  "data": {"name": "data-303fbb5af18e896de75409a7bbd56ac0"},
  "datasets": {
    "data-303fbb5af18e896de75409a7bbd56ac0": [
      {
        "bin": 0,
        "center_point": -1.95,
        "left_bound": -2,
        "n": 3401,
        "right_bound": -1.9
      },
      {
        "bin": 1,
        "center_point": -1.85,
        "left_bound": -1.9,
        "n": 3945,
        "right_bound": -1.8
      },
      {
        "bin": 2,
        "center_point": -1.75,
        "left_bound": -1.8,
        "n": 4142,
        "right_bound": -1.7
      },
      {
        "bin": 3,
        "center_point": -1.65,
        "left_bound": -1.7,
        "n": 4843,
        "right_bound": -1.6
      },
      {
        "bin": 4,
        "center_point": -1.55,
        "left_bound": -1.6,
        "n": 5440,
        "right_bound": -1.5
      },
      {
        "bin": 5,
        "center_point": -1.45,
        "left_bound": -1.5,
        "n": 5847,
        "right_bound": -1.4
      },
      {
        "bin": 6,
        "center_point": -1.35,
        "left_bound": -1.4,
        "n": 6826,
        "right_bound": -1.3
      },
      {
        "bin": 7,
        "center_point": -1.25,
        "left_bound": -1.3,
        "n": 7764,
        "right_bound": -1.2
      },
      {
        "bin": 8,
        "center_point": -1.15,
        "left_bound": -1.2,
        "n": 9205,
        "right_bound": -1.1
      },
      {
        "bin": 9,
        "center_point": -1.05,
        "left_bound": -1.1,
        "n": 11149,
        "right_bound": -1
      },
      {
        "bin": 10,
        "center_point": -0.95,
        "left_bound": -1,
        "n": 13726,
        "right_bound": -0.9
      },
      {
        "bin": 11,
        "center_point": -0.85,
        "left_bound": -0.9,
        "n": 17569,
        "right_bound": -0.8
      },
      {
        "bin": 12,
        "center_point": -0.75,
        "left_bound": -0.8,
        "n": 22626,
        "right_bound": -0.7
      },
      {
        "bin": 13,
        "center_point": -0.65,
        "left_bound": -0.7,
        "n": 30866,
        "right_bound": -0.6
      },
      {
        "bin": 14,
        "center_point": -0.55,
        "left_bound": -0.6,
        "n": 45078,
        "right_bound": -0.5
      },
      {
        "bin": 15,
        "center_point": -0.45,
        "left_bound": -0.5,
        "n": 72752,
        "right_bound": -0.4
      },
      {
        "bin": 16,
        "center_point": -0.35,
        "left_bound": -0.4,
        "n": 124899,
        "right_bound": -0.3
      },
      {
        "bin": 17,
        "center_point": -0.25,
        "left_bound": -0.3,
        "n": 223861,
        "right_bound": -0.2
      },
      {
        "bin": 18,
        "center_point": -0.15,
        "left_bound": -0.2,
        "n": 416260,
        "right_bound": -0.1
      },
      {
        "bin": 19,
        "center_point": -0.05,
        "left_bound": -0.1,
        "n": 1125814,
        "right_bound": 0
      },
      {
        "bin": 20,
        "center_point": 0.05,
        "left_bound": 0,
        "n": 445494,
        "right_bound": 0.1
      },
      {
        "bin": 21,
        "center_point": 0.15,
        "left_bound": 0.1,
        "n": 386848,
        "right_bound": 0.2
      },
      {
        "bin": 22,
        "center_point": 0.25,
        "left_bound": 0.2,
        "n": 398402,
        "right_bound": 0.3
      },
      {
        "bin": 23,
        "center_point": 0.35,
        "left_bound": 0.3,
        "n": 440893,
        "right_bound": 0.4
      },
      {
        "bin": 24,
        "center_point": 0.45,
        "left_bound": 0.4,
        "n": 537249,
        "right_bound": 0.5
      },
      {
        "bin": 25,
        "center_point": 0.55,
        "left_bound": 0.5,
        "n": 611479,
        "right_bound": 0.6
      },
      {
        "bin": 26,
        "center_point": 0.65,
        "left_bound": 0.6,
        "n": 678911,
        "right_bound": 0.7
      },
      {
        "bin": 27,
        "center_point": 0.75,
        "left_bound": 0.7,
        "n": 764600,
        "right_bound": 0.8
      },
      {
        "bin": 28,
        "center_point": 0.85,
        "left_bound": 0.8,
        "n": 927396,
        "right_bound": 0.9
      },
      {
        "bin": 29,
        "center_point": 0.95,
        "left_bound": 0.9,
        "n": 4172231,
        "right_bound": 1
      }
    ]
  },
  "encoding": {
    "x": {"field": "left_bound", "type": "quantitative"},
    "x2": {"field": "right_bound"},
    "y": {"field": "n", "type": "quantitative"}
  },
  "mark": {"type": "bar"}
}

Solution

  • It seems like the bars also need a y2 encoding specified when there is an x2 encoding. Unsure why it is like that but this works:

      "encoding": {
        "x": {"field": "left_bound", "type": "quantitative"},
        "x2": {"field": "right_bound"},
        "y": {"field": "n", "type": "quantitative"},
        "y2": {"datum": 0}
      },
      "mark": {"type": "bar"}
    

    You could also use mark_rect instead, it does not need the y2 encoding it seems:

      "encoding": {
        "x": {"field": "left_bound", "type": "quantitative"},
        "x2": {"field": "right_bound"},
        "y": {"field": "n", "type": "quantitative"}
      },
      "mark": {"type": "rect"}