VegaLite.jl Grouped Bar Chart with Labels

I am having some issues trying to create a grouped bar chart with labels using VegaLite.jl. From this answer on Discoure, it looks like I should be able to just “sum” two plots.

However, the following doesn’t work:

using VegaLite, VegaDatasets

bplot = dataset("population") |>
@vlplot(
    :bar,
    transform=[
        {filter="datum.year == 2000"},
        {calculate="datum.sex == 2 ? 'Female' : 'Male'", as="gender"}
    ],
    column="age:o",
    y={"sum(people)", axis={title="population", grid=false}},
    x={"gender:n", axis={title=""}},
    color={"gender:n", scale={range=["#675193", "#ca8861"]}},
    spacing=10,
    config={
        view={stroke=:transparent},
        axis={domainWidth=1}
    }
)

tplot = dataset("population") |>
@vlplot(
    mark={
        :text,
        dx=-5,
        angle=90,
        align="right",
        baseline="middle",
        dx=-5
        },
    transform=[
        {filter="datum.year == 2000"},
        {calculate="datum.sex == 2 ? 'Female' : 'Male'", as="gender"}
    ],
    column="age:o",
    y={"sum(people)", axis={title="population", grid=false}},
    x={"gender:n", axis={title=""}},
    text="age",
    spacing=10,
    config={
        view={stroke=:transparent},
        axis={domainWidth=1}
    })

@vlplot() + bplot + tplot

It appears that @vlplot() + bplot + tplot removes the groups.

I came across this answer on stackoverflow.com, but I don’t quite know how to “translate” the VegaLite JSON to Julia. I also don’t really want to work with JSON.

Also, I’m not deadset on using VegaLite.jl. If someone could maybe explain how one might accomplish this with Plots.jl or StatsPlots.jl then I’d be happy too.

Any help, whatsoever, would be much appreciated.

This is a working translation of the stackoverflow solution:

bplot = dataset("population") |>
@vlplot(
    transform=[
        {filter="datum.year == 2000"},
        {calculate="datum.sex == 2 ? 'Female' : 'Male'", as="gender"}
    ],
    spacing=10,
    facet={field="age",type="ordinal"},
	spec={
		encoding={
			y={"sum(people)", axis={title="population", grid=false}},
			x={"gender:n", axis={title=""}},
		},
		layer=[{
			:bar,
			color={"gender:n", scale={range=["#675193", "#ca8861"]}},
		},
		{
			text="age",
			mark={
				:text,
				dx=-5,
				angle=90,
				align="right",
				baseline="middle",
				dx=-5
				},
		}]
	},
    config={
        view={stroke=:transparent},
        axis={domainWidth=1}
    }
)

For the reason why your attempt doesn’t work I can only speculate a bit:
In the single grouped bar char Bar Charts · VegaLite.jl the line column="age:o" defines that we want facets plotted as columns.
By adding your two plots this information gets lost, because the x-axis has to be equal for the two plots and is defined as only x="gender:n" which is exactly two values on x. It would translate into:

dataset("population") |>
@vlplot(
    transform=[
        {filter="datum.year == 2000"},
        {calculate="datum.sex == 2 ? 'Female' : 'Male'", as="gender"}
    ],
    x={"gender:n", axis={title=""}}
) + @vlplot(
    :bar,
    ...
) + @vlplot(
    mark={
        :text,
        ....
)

The above VegaLite.jl solution just makes the facet and the spec explicit to reproduce the original solution. I tried with column and several shortcuts, but they didn’t work. A shortcut for example I thought should work would be:

...
facet="age:o",
...

but don’t work.

1 Like

Awesome! Thank you, @oheil, that worked.

1 Like