Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chart label/stack order #397

Closed
mroswell opened this issue Oct 2, 2017 · 8 comments
Closed

chart label/stack order #397

mroswell opened this issue Oct 2, 2017 · 8 comments

Comments

@mroswell
Copy link
Contributor

mroswell commented Oct 2, 2017

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

@mroswell
Copy link
Contributor Author

mroswell commented Oct 2, 2017

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' ]

        )
    ),

@mroswell
Copy link
Contributor Author

mroswell commented Oct 2, 2017

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

@mroswell
Copy link
Contributor Author

mroswell commented Oct 2, 2017

Related issues:
vega/vega-lite#1734
vega/vega-lite#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

@kanitw
Copy link
Member

kanitw commented Oct 19, 2017 via email

@jwhendy
Copy link

jwhendy commented Nov 5, 2017

@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?

@jwhendy
Copy link

jwhendy commented Nov 5, 2017

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')

@hjhilden
Copy link

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))")

@jakevdp
Copy link
Collaborator

jakevdp commented May 26, 2019

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants