Stacked bar graphs

@davidanthoff from your previous code that worked perfectly:

df |>
  @vlplot(:bar,
    x=:Sex,
    y=:Freq,
    color=:Eye,
    column={:haircut_woman, sort=["Red", "Blond", "Brown", "Black"]}
  )

I’m trying exactly as above to sort for color as well. If I run:

df |>
  @vlplot(:bar,
    x=:Sex,
    y=:Freq,
    color={:Eye, sort=["Green", "Blue", "Hazel", "Brown"]},
    column={:haircut_woman, sort=["Red", "Blond", "Brown", "Black"]}
  )

I end up getting that the legend shows the new ordering that I specified, however the actual ordering of the stack remains the same (and colors change now for some other reason). If I try putting this in the y={:Freq, sort=["Green", "Blue", "Hazel", "Brown"] }, it doesn’t change anything either, and if I specify it only in the y without specifying it in the color, it goes back to the original sorting of “Blue, Brown, Green, Hazel” that it (alphabetically?) specified initially on its own. If I specify sort=true with the color, it ignores my specified sorting and sorts by the dataframe specification which is unhelpful since I draw from various files to organise the data frame and this isn’t the ordering I’d want.

How do I sort this with color?

Try Gadfly: Tutorial · Gadfly.jl
Also a new feature has been added: Stat.dodge, allowing the stacking and dodging of labels and errorbars (scroll down).

1 Like

It is a bit complicated :wink: I think they are aware that this should be made easier, see here. The workaround here is essentially adapted from the last example here.

df |> 
  @vlplot(:bar,
    transform=[{
      calculate="if(datum.Eye==='Green', 0, if(datum.Eye==='Blue', 1, if(datum.Eye==='Hazel',2,3)))",
      as=:siteOrder}], 
    x=:Sex,
    y=:Freq,
    color=:Eye,
    column={:Hair, sort=["Red", "Blond", "Brown", "Black"]},
    order="siteOrder:q"
)

So the strategy here is to add a new computed field called siteOrder, and then use that to order the stacked bars. You could also add the sort keyword back to the color channel to sort the elements in the legend again.

Oh, and one more thing: you could of course add this additional column outside of the @vlplot macro, using normal DataFrame operations or Query.jl or something like that.

And if you want the actual colors to be equal to hair colors you would change the color parameter:

color = {field = :Eye, type = "nominal",
            scale = {domain = ["Green", "Blue", "Hazel", "Brown"], range = ["#F1C40F", "#95A5A6", "#F1C40F",   "#F1C40F"] } }

Changing the hex values to the proper colors.

However, it seems that the order of bars in the graph and legend entries is not the same. I wonder how one can fix this? More precisely, the vertical order of bars in the graph is alphabetical where as legend entries are in the order specified in “domain”.

I notice that there is a small problem: all the legend entries mentioned in “domain” are shown even if the data is not present.