Altair: chart label/stack order

Created on 2 Oct 2017  Â·  8Comments  Â·  Source: altair-viz/altair

How can I control the order of labels in a legend, beyond alphabetical ordering?
Also interested in determining the order of stacked charts. (Is that alphabetical, too?)

I've been playing around with scale domain and range, but haven't figured out ordering rules, beyond alphabetical.

Margie

Most helpful comment

I was also struggling with this, but solved it by combining the Vega-lite instructions for ordering with the Altair instructions for using the calculate transform
Calculate-transform is used to create a new “order” field, in this case putting “University Farm” and “Grand Rapids” as the first (0) and second values in the stack order.

# how to order using the calculate transform
# https://vega.github.io/vega-lite/docs/stack.html#order
# https://altair-viz.github.io/user_guide/transform.html?highlight=transform#calculate-transform

import altair as alt
from vega_datasets import data

barley = data.barley()

mychart = alt.Chart(barley).mark_bar().encode(
    x='sum(yield)',
    y='variety',
    color='site',
    order='order:N'
).transform_calculate(
    order="if(datum.site === 'University Farm', 0, if(datum.site === 'Grand Rapids', 1, 2))")

All 8 comments

Update. To help troubleshoot, I used human-readable color names.

It looks like domain array order for
.encode(... color=Color( ... scale =Scale(domain=["2","1","3"]))
controls the order in the legend. But I still haven't figured out how to control the order of the stacks in the chart. Maybe getting warmer...

.encode(
    color=Color('category:N',
        legend=Legend(
            title='Result Category',
        ),
        scale=Scale(
            domain=[ '2. negative', '1. Below screen','3. Above screen)'], 
            range= ['grey', 'orange', 'blue' ]

        )
    ),

BTW, I noticed both domain and range are missing descriptions, here:
https://altair-viz.github.io/API.html#altair.Scale

Related issues:
https://github.com/vega/vega-lite/issues/1734
https://github.com/vega/vega-lite/issues/2915

Well, I feel overwhelmed by the various documentation resources. For now, I'm going to put numbers in my fields/labels so that they sort they way I want them to, but it's not ideal. Hopefully some of that documentation tells a story that I just haven't figured out yet for controlling the order of sections of a stacked bar chart

The last comment in vega/vega-lite#1734 shows an example how to do it in vl2
-- an earlier comment in the same thread also shows a VL1 example
On Tue, Oct 3, 2017 at 4:01 AM Marjorie Roswell notifications@github.com
wrote:

Related issues:
vega/vega-lite#1734 https://github.com/vega/vega-lite/issues/1734
vega/vega-lite#2915 https://github.com/vega/vega-lite/issues/2915

Well, I feel overwhelmed by the various documentation resources. For now,
I'm going to put numbers in my fields/labels so that they sort they way I
want them to, but it's not ideal. Hopefully some of that documentation
tells a story that I just haven't figured out yet for controlling the order
of sections of a stacked bar chart

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/altair-viz/altair/issues/397#issuecomment-333663969,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAGypTLB6m2cQQPrLyiar4gQYzXW2b94ks5soU8ygaJpZM4PrAaz
.

@kanitw could you be a little more specific on how one would translate this to altair? For me personally, I use these sort of tools to avoid having to learn the lower level libraries directly. I see a lot of references to 'type': 'nominal', and even that maybe this is already pulled, yet it's not working for me.

Example:

test = pd.DataFrame({'color': ['top', 'top', 'bottom', 'bottom', 'bottom'],
                     'xval': ['a', 'b', 'a', 'a', 'b']})

scale=alt.Scale(domain=['top', 'bottom'],
                range=['#444444', '#bbbbbb'], type='ordinal')

alt.Chart(test).mark_bar().encode(
    x=alt.X('xval', type='ordinal'),
    y='count(*)'
    color=alt.Color('color', type='ordinal', scale=scale))

From what I can tell, the "bigger" value alphabetically will always end up on the bottom ("top" in this case). I have three places where I think type='ordinal' could go... what am I getting wrong?

Hmmm. I now think that by "last comment" you might mean this one. In that case, I'm stumped on applying the license_index idea to altair.

Digging into altair more, it provides access to order in vega-lite. It's probably "better" to specify it via that transform method, but for now I just made a small DataFrame with my unique values, manually added a sort order column to that, merged it back, and I can simply sort by that new column. For an idea (minus the merge stuff):

test = pd.DataFrame({'x': ['A', 'A', 'A', 'A'],
                     'y': [28, 55, 43, 13],
                     'color': ['x-small', 'small', 'x-large', 'large'],
                     'order': [1, 2, 3, 4]})

scale=alt.Scale(domain=['x-small', 'small', 'x-large', 'large'],
                range=["#333333","#666666","#999999","#eeeeee"], type='ordinal')

### try this without the oder='order' option and you'll see it defaults to alphabetical
alt.Chart(test).mark_bar().encode(
    x=alt.X('x', type='nominal'),
    y='sum(y)',
    color=alt.Color('color', type='nominal', scale=scale),
    order='order')

I was also struggling with this, but solved it by combining the Vega-lite instructions for ordering with the Altair instructions for using the calculate transform
Calculate-transform is used to create a new “order” field, in this case putting “University Farm” and “Grand Rapids” as the first (0) and second values in the stack order.

# how to order using the calculate transform
# https://vega.github.io/vega-lite/docs/stack.html#order
# https://altair-viz.github.io/user_guide/transform.html?highlight=transform#calculate-transform

import altair as alt
from vega_datasets import data

barley = data.barley()

mychart = alt.Chart(barley).mark_bar().encode(
    x='sum(yield)',
    y='variety',
    color='site',
    order='order:N'
).transform_calculate(
    order="if(datum.site === 'University Farm', 0, if(datum.site === 'Grand Rapids', 1, 2))")

Altair 3 unifies this, and orders on various scales (including axes, legends, etc.) can now be supplied via the sort parameter.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nielsmde picture nielsmde  Â·  4Comments

breadbaron picture breadbaron  Â·  4Comments

HalukaMB picture HalukaMB  Â·  3Comments

bmcfee picture bmcfee  Â·  3Comments

mroswell picture mroswell  Â·  4Comments