Search code examples
vega-lite

Emulating Violin plot with bar chart


I dislike KDEs and want to show that bar charts are often as good.

I'm wondering

(1) if there is a way to center the bars in the second chart so that it would look closer to a violin plot. However, if there is any visualization theory that suggests that we shouldn't center; happy to hear that too!

(2) if there is a way to remove the repeated x label, call_counts, and merge into a global label?

(3) what's the most vega-lite way to order the days? I can denormalize the data and add 1/2/3... to Mon/Tue/Wed and then order by that column, but seems a little tedious.

(4) is there a way to make the hours start at 7 AM instead of 0? --- again, I can create a new column that specifies the order, like 1/2/3 for 7/8/9 etc., but that again is a little tedious.

Thanks! The code for the vegalite used for the second image is at the bottom.

enter image description here

enter image description here

{"config": {"view": {"width": 400, "height": 300}, "mark": {"tooltip": null}}, "data": {"name": "data-48e44ddf7145f9f73a437aa53255a270"}, "mark": "bar", "encoding": {"column": {"type": "nominal", "field": "Day"}, "x": {"type": "quantitative", "field": "call_count"}, "y": {"type": "ordinal", "field": "hour_bin"}}, "height": 200, "width": 50, "$schema": "https://vega.github.io/schema/vega-lite/v3.4.0.json", "datasets": {"data-48e44ddf7145f9f73a437aa53255a270": [{"Day": "Friday", "hour_bin": 0, "call_count": 39}, {"Day": "Friday", "hour_bin": 1, "call_count": 17}, {"Day": "Friday", "hour_bin": 2, "call_count": 10}, {"Day": "Friday", "hour_bin": 3, "call_count": 4}, {"Day": "Friday", "hour_bin": 4, "call_count": 6}, {"Day": "Friday", "hour_bin": 5, "call_count": 8}, {"Day": "Friday", "hour_bin": 6, "call_count": 15}, {"Day": "Friday", "hour_bin": 7, "call_count": 18}, {"Day": "Friday", "hour_bin": 8, "call_count": 28}, {"Day": "Friday", "hour_bin": 9, "call_count": 30}, {"Day": "Friday", "hour_bin": 10, "call_count": 25}, {"Day": "Friday", "hour_bin": 11, "call_count": 29}, {"Day": "Friday", "hour_bin": 12, "call_count": 47}, {"Day": "Friday", "hour_bin": 13, "call_count": 44}, {"Day": "Friday", "hour_bin": 14, "call_count": 32}, {"Day": "Friday", "hour_bin": 15, "call_count": 35}, {"Day": "Friday", "hour_bin": 16, "call_count": 53}, {"Day": "Friday", "hour_bin": 17, "call_count": 51}, {"Day": "Friday", "hour_bin": 18, "call_count": 46}, {"Day": "Friday", "hour_bin": 19, "call_count": 53}, {"Day": "Friday", "hour_bin": 20, "call_count": 59}, {"Day": "Friday", "hour_bin": 21, "call_count": 49}, {"Day": "Friday", "hour_bin": 22, "call_count": 37}, {"Day": "Friday", "hour_bin": 23, "call_count": 43}, {"Day": "Monday", "hour_bin": 0, "call_count": 56}, {"Day": "Monday", "hour_bin": 1, "call_count": 20}, {"Day": "Monday", "hour_bin": 2, "call_count": 11}, {"Day": "Monday", "hour_bin": 3, "call_count": 11}, {"Day": "Monday", "hour_bin": 4, "call_count": 13}, {"Day": "Monday", "hour_bin": 5, "call_count": 8}, {"Day": "Monday", "hour_bin": 6, "call_count": 11}, {"Day": "Monday", "hour_bin": 7, "call_count": 22}, {"Day": "Monday", "hour_bin": 8, "call_count": 26}, {"Day": "Monday", "hour_bin": 9, "call_count": 33}, {"Day": "Monday", "hour_bin": 10, "call_count": 29}, {"Day": "Monday", "hour_bin": 11, "call_count": 28}, {"Day": "Monday", "hour_bin": 12, "call_count": 49}, {"Day": "Monday", "hour_bin": 13, "call_count": 43}, {"Day": "Monday", "hour_bin": 14, "call_count": 33}, {"Day": "Monday", "hour_bin": 15, "call_count": 27}, {"Day": "Monday", "hour_bin": 16, "call_count": 34}, {"Day": "Monday", "hour_bin": 17, "call_count": 53}, {"Day": "Monday", "hour_bin": 18, "call_count": 57}, {"Day": "Monday", "hour_bin": 19, "call_count": 66}, {"Day": "Monday", "hour_bin": 20, "call_count": 47}, {"Day": "Monday", "hour_bin": 21, "call_count": 45}, {"Day": "Monday", "hour_bin": 22, "call_count": 41}, {"Day": "Monday", "hour_bin": 23, "call_count": 25}, {"Day": "Saturday", "hour_bin": 0, "call_count": 58}, {"Day": "Saturday", "hour_bin": 1, "call_count": 20}, {"Day": "Saturday", "hour_bin": 2, "call_count": 22}, {"Day": "Saturday", "hour_bin": 3, "call_count": 21}, {"Day": "Saturday", "hour_bin": 4, "call_count": 16}, {"Day": "Saturday", "hour_bin": 5, "call_count": 4}, {"Day": "Saturday", "hour_bin": 6, "call_count": 8}, {"Day": "Saturday", "hour_bin": 7, "call_count": 13}, {"Day": "Saturday", "hour_bin": 8, "call_count": 21}, {"Day": "Saturday", "hour_bin": 9, "call_count": 26}, {"Day": "Saturday", "hour_bin": 10, "call_count": 34}, {"Day": "Saturday", "hour_bin": 11, "call_count": 32}, {"Day": "Saturday", "hour_bin": 12, "call_count": 32}, {"Day": "Saturday", "hour_bin": 13, "call_count": 30}, {"Day": "Saturday", "hour_bin": 14, "call_count": 38}, {"Day": "Saturday", "hour_bin": 15, "call_count": 34}, {"Day": "Saturday", "hour_bin": 16, "call_count": 37}, {"Day": "Saturday", "hour_bin": 17, "call_count": 46}, {"Day": "Saturday", "hour_bin": 18, "call_count": 40}, {"Day": "Saturday", "hour_bin": 19, "call_count": 48}, {"Day": "Saturday", "hour_bin": 20, "call_count": 34}, {"Day": "Saturday", "hour_bin": 21, "call_count": 44}, {"Day": "Saturday", "hour_bin": 22, "call_count": 48}, {"Day": "Saturday", "hour_bin": 23, "call_count": 43}, {"Day": "Sunday", "hour_bin": 0, "call_count": 44}, {"Day": "Sunday", "hour_bin": 1, "call_count": 34}, {"Day": "Sunday", "hour_bin": 2, "call_count": 19}, {"Day": "Sunday", "hour_bin": 3, "call_count": 8}, {"Day": "Sunday", "hour_bin": 4, "call_count": 13}, {"Day": "Sunday", "hour_bin": 5, "call_count": 5}, {"Day": "Sunday", "hour_bin": 6, "call_count": 9}, {"Day": "Sunday", "hour_bin": 7, "call_count": 16}, {"Day": "Sunday", "hour_bin": 8, "call_count": 26}, {"Day": "Sunday", "hour_bin": 9, "call_count": 22}, {"Day": "Sunday", "hour_bin": 10, "call_count": 23}, {"Day": "Sunday", "hour_bin": 11, "call_count": 27}, {"Day": "Sunday", "hour_bin": 12, "call_count": 29}, {"Day": "Sunday", "hour_bin": 13, "call_count": 24}, {"Day": "Sunday", "hour_bin": 14, "call_count": 29}, {"Day": "Sunday", "hour_bin": 15, "call_count": 38}, {"Day": "Sunday", "hour_bin": 16, "call_count": 31}, {"Day": "Sunday", "hour_bin": 17, "call_count": 32}, {"Day": "Sunday", "hour_bin": 18, "call_count": 41}, {"Day": "Sunday", "hour_bin": 19, "call_count": 40}, {"Day": "Sunday", "hour_bin": 20, "call_count": 45}, {"Day": "Sunday", "hour_bin": 21, "call_count": 40}, {"Day": "Sunday", "hour_bin": 22, "call_count": 38}, {"Day": "Sunday", "hour_bin": 23, "call_count": 27}, {"Day": "Thursday", "hour_bin": 0, "call_count": 45}, {"Day": "Thursday", "hour_bin": 1, "call_count": 18}, {"Day": "Thursday", "hour_bin": 2, "call_count": 15}, {"Day": "Thursday", "hour_bin": 3, "call_count": 12}, {"Day": "Thursday", "hour_bin": 4, "call_count": 8}, {"Day": "Thursday", "hour_bin": 5, "call_count": 11}, {"Day": "Thursday", "hour_bin": 6, "call_count": 8}, {"Day": "Thursday", "hour_bin": 7, "call_count": 12}, {"Day": "Thursday", "hour_bin": 8, "call_count": 30}, {"Day": "Thursday", "hour_bin": 9, "call_count": 16}, {"Day": "Thursday", "hour_bin": 10, "call_count": 23}, {"Day": "Thursday", "hour_bin": 11, "call_count": 42}, {"Day": "Thursday", "hour_bin": 12, "call_count": 39}, {"Day": "Thursday", "hour_bin": 13, "call_count": 41}, {"Day": "Thursday", "hour_bin": 14, "call_count": 42}, {"Day": "Thursday", "hour_bin": 15, "call_count": 42}, {"Day": "Thursday", "hour_bin": 16, "call_count": 40}, {"Day": "Thursday", "hour_bin": 17, "call_count": 45}, {"Day": "Thursday", "hour_bin": 18, "call_count": 56}, {"Day": "Thursday", "hour_bin": 19, "call_count": 49}, {"Day": "Thursday", "hour_bin": 20, "call_count": 52}, {"Day": "Thursday", "hour_bin": 21, "call_count": 45}, {"Day": "Thursday", "hour_bin": 22, "call_count": 41}, {"Day": "Thursday", "hour_bin": 23, "call_count": 39}, {"Day": "Tuesday", "hour_bin": 0, "call_count": 35}, {"Day": "Tuesday", "hour_bin": 1, "call_count": 13}, {"Day": "Tuesday", "hour_bin": 2, "call_count": 20}, {"Day": "Tuesday", "hour_bin": 3, "call_count": 11}, {"Day": "Tuesday", "hour_bin": 4, "call_count": 13}, {"Day": "Tuesday", "hour_bin": 5, "call_count": 10}, {"Day": "Tuesday", "hour_bin": 6, "call_count": 6}, {"Day": "Tuesday", "hour_bin": 7, "call_count": 13}, {"Day": "Tuesday", "hour_bin": 8, "call_count": 25}, {"Day": "Tuesday", "hour_bin": 9, "call_count": 24}, {"Day": "Tuesday", "hour_bin": 10, "call_count": 26}, {"Day": "Tuesday", "hour_bin": 11, "call_count": 31}, {"Day": "Tuesday", "hour_bin": 12, "call_count": 49}, {"Day": "Tuesday", "hour_bin": 13, "call_count": 37}, {"Day": "Tuesday", "hour_bin": 14, "call_count": 35}, {"Day": "Tuesday", "hour_bin": 15, "call_count": 45}, {"Day": "Tuesday", "hour_bin": 16, "call_count": 49}, {"Day": "Tuesday", "hour_bin": 17, "call_count": 46}, {"Day": "Tuesday", "hour_bin": 18, "call_count": 44}, {"Day": "Tuesday", "hour_bin": 19, "call_count": 44}, {"Day": "Tuesday", "hour_bin": 20, "call_count": 56}, {"Day": "Tuesday", "hour_bin": 21, "call_count": 33}, {"Day": "Tuesday", "hour_bin": 22, "call_count": 42}, {"Day": "Tuesday", "hour_bin": 23, "call_count": 23}, {"Day": "Wednesday", "hour_bin": 0, "call_count": 36}, {"Day": "Wednesday", "hour_bin": 1, "call_count": 11}, {"Day": "Wednesday", "hour_bin": 2, "call_count": 7}, {"Day": "Wednesday", "hour_bin": 3, "call_count": 9}, {"Day": "Wednesday", "hour_bin": 4, "call_count": 7}, {"Day": "Wednesday", "hour_bin": 5, "call_count": 15}, {"Day": "Wednesday", "hour_bin": 6, "call_count": 9}, {"Day": "Wednesday", "hour_bin": 7, "call_count": 14}, {"Day": "Wednesday", "hour_bin": 8, "call_count": 25}, {"Day": "Wednesday", "hour_bin": 9, "call_count": 28}, {"Day": "Wednesday", "hour_bin": 10, "call_count": 32}, {"Day": "Wednesday", "hour_bin": 11, "call_count": 37}, {"Day": "Wednesday", "hour_bin": 12, "call_count": 43}, {"Day": "Wednesday", "hour_bin": 13, "call_count": 42}, {"Day": "Wednesday", "hour_bin": 14, "call_count": 34}, {"Day": "Wednesday", "hour_bin": 15, "call_count": 34}, {"Day": "Wednesday", "hour_bin": 16, "call_count": 38}, {"Day": "Wednesday", "hour_bin": 17, "call_count": 60}, {"Day": "Wednesday", "hour_bin": 18, "call_count": 55}, {"Day": "Wednesday", "hour_bin": 19, "call_count": 47}, {"Day": "Wednesday", "hour_bin": 20, "call_count": 54}, {"Day": "Wednesday", "hour_bin": 21, "call_count": 39}, {"Day": "Wednesday", "hour_bin": 22, "call_count": 50}, {"Day": "Wednesday", "hour_bin": 23, "call_count": 25}]}}

Thanks!


Solution

  • (1)

    To center the bars, you can use stacking.

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v4.json",
      "data": ...,
      "mark": "bar",
      "encoding": {
        "column": {"type": "nominal", "field": "Day"},
        "x": {"type": "quantitative", "field": "call_count", "stack": "center"},
        "y": {"type": "ordinal", "field": "hour_bin"}
      }
    }
    

    (2)

    You could describe the chart in the title. We don't have a way to reasonably merge titles right now.

    (3)

    The easiest way is to define the sort order

    "column": {"type": "nominal", "field": "Day",
               "sort": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]}
    

    Alternatively, if you had the data as dates, you could use time unit to facet the data. But then you need the raw data.

    (4)

    Again, you could use sort. It's a bit admittedly tedious, though. I have to think more about a different approach here.

    "y": {"type": "ordinal", "field": "hour_bin",
          "sort": [7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,0,1,2,3,4,5,6]}
    

    screenshot of result