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

Any way to sort two layers together? #820

Closed
Ram-N opened this issue May 6, 2018 · 11 comments
Closed

Any way to sort two layers together? #820

Ram-N opened this issue May 6, 2018 · 11 comments

Comments

@Ram-N
Copy link

Ram-N commented May 6, 2018

I have a sorted mark_bar() and would like to add a layer of mark_tick or top of this, while preserving the sorted order.

This sorting works:

from vega_datasets import data
df = data.movies()
df['WW_Margin'] = (df['Worldwide_Gross'] - df['Production_Budget']) / 1e6
  
lower_box = 'q1(WW_Margin):Q'
upper_box = 'q3(WW_Margin):Q'

bar_plot = alt.Chart(df).mark_bar(size=5.0).encode(
    alt.X('Major_Genre:O',
#          sort=alt.SortField(field='WW_Margin', op='median', 
#                             order='descending')
         ),
    y=lower_box,
    y2=upper_box,
)

median_tick = bar_plot.mark_tick(
    color='white',
    size=5.0
).encode(
    y='median(WW_Margin):Q',
)

bar_plot

image

But when I add a mark_tick layer, the sorting or the bars is gone, and it reverts to alphabetical sorting.

from vega_datasets import data
df = data.movies()
df['WW_Margin'] = (df['Worldwide_Gross'] - df['Production_Budget']) / 1e6
  
lower_box = 'q1(WW_Margin):Q'
upper_box = 'q3(WW_Margin):Q'

bar_plot = alt.Chart(df).mark_bar(size=5.0).encode(
    alt.X('Major_Genre:O',
          sort=alt.SortField(field='WW_Margin', op='median', 
                             order='descending')
         ),
    y=lower_box,
    y2=upper_box,
)

median_tick = bar_plot.mark_tick(
    color='white',
    size=5.0
).encode(
    y='median(WW_Margin):Q',
)

bar_plot + median_tick #note below that sorting is gone

image

This is quite possibly related to #698 which in turn refers to a Vega-lite issue(vega/vega-lite#2177). Will this get resolved when a newer version of Vega-lite is incorporated into Altair? Thanks much.

@jakevdp
Copy link
Collaborator

jakevdp commented May 6, 2018

I think this is a bug in vega-lite; I've opened an issue there: vega/vega-lite#3710

@jakevdp
Copy link
Collaborator

jakevdp commented May 6, 2018

Looks like it's still an unfixed bug in Vega. As a workaround, you can set resolve/scale/x to "independent" and then turn off the second set of axis labels:

import altair as alt
alt.themes.enable('none')

from vega_datasets import data

sort = alt.SortField(field='WW_Margin', op='median', 
                             order='descending')

bars = alt.Chart().mark_bar(size=5.0).encode(
    alt.X('Major_Genre:N', sort=sort),
    y='q1(WW_Margin):Q',
    y2='q3(WW_Margin):Q'
)

ticks = alt.Chart().mark_tick(
    color='black',
    size=5.0
).encode(
    alt.X('Major_Genre:N', sort=sort, axis=alt.Axis(labels=False, ticks=False)),
    y='median(WW_Margin):Q',
)

alt.layer(bars, ticks, data=data.movies.url).transform_calculate(
    WW_Margin = "(datum.Worldwide_Gross - datum.Production_Budget) / 1e6"
).resolve_scale(x='independent')

visualization 14

@Ram-N
Copy link
Author

Ram-N commented May 6, 2018

.resolve_scale(x='independent') is a good work-around. Thanks much.

@Alcampopiano
Copy link

Hi all,

Here is a workaround in case it helps. It turns out that if you sort your data values first (df.sort_values...), and then specify the usual sort options in Altair (op...field...order), the data will be sorted (at least in the example linked below):

vega/vega-lite#4075

@jakevdp
Copy link
Collaborator

jakevdp commented May 27, 2019

This is fixed in Altair 3:

from vega_datasets import data
df = data.movies()
df['WW_Margin'] = (df['Worldwide_Gross'] - df['Production_Budget']) / 1e6
  
lower_box = 'q1(WW_Margin):Q'
upper_box = 'q3(WW_Margin):Q'

bar_plot = alt.Chart(df).mark_bar(size=5.0).encode(
    alt.X('Major_Genre:O',
          sort=alt.EncodingSortField(field='WW_Margin', order='descending')
         ),
    y=lower_box,
    y2=upper_box,
)

median_tick = bar_plot.mark_tick(
    color='white',
    size=5.0
).encode(
    y='median(WW_Margin):Q',
)

bar_plot + median_tick

visualization - 2019-05-27T065145 431

@77QingLiu
Copy link

mixed order when two plots are combined
image

the bar plot and line plot order right in the single plot, but mixed when combined

alt.layer(
    bar,
    line
).resolve_scale(
    y='independent'
)

@jakevdp
Copy link
Collaborator

jakevdp commented Oct 9, 2019

if you want a solution to your problem please include the full code to reproduce your chart.

@77QingLiu
Copy link

@jakevdp here is full code

# %%
import pandas as pd
import numpy as np
pd.options.display.float_format = '{:,.3f}'.format

# %%
df = pd.DataFrame(
{'group': ['a', 'b', 'c'],
 'value1': [3723189706, 511785521, 448873396],
 'value2': [1471506853, 261248709, 226229611],
 'ratio': [0.3952274716265022, 0.5104652220662801, 0.5039942516577337]}
)

# %%
import altair as alt
alt.renderers.enable('nteract')

df_stack = df.melt(id_vars='group', value_vars=['value1', 'value2'])

labels = ['a', 'c', 'b']
bar = alt.Chart(df_stack).mark_bar().encode(
    alt.X('group:O', sort=labels),
    alt.Y('value:Q'),
    alt.Color('variable', legend=alt.Legend(title="类型"))
)

line =  alt.Chart(df).mark_line(color='red').encode(
    alt.X('group:O', sort=labels),
    alt.Y('ratio:Q', axis=alt.Axis(format='%'))
)

alt.layer(
    bar,
    line
).resolve_scale(
    y='independent'
).properties(
width=600
).configure_axisX(
labelAngle=-45
)

below is the output, the order is not the same as specified in sort option
image

@jakevdp
Copy link
Collaborator

jakevdp commented Oct 10, 2019

The order of the axis and the order in which the points are connected are distinct concepts. If you want to change the order in which the points are connected, you can use the order channel. Details in the docs here: https://altair-viz.github.io/user_guide/encoding.html#ordering-marks

@jakevdp
Copy link
Collaborator

jakevdp commented Oct 10, 2019

Also, ordering of axis for layered charts based on different datasets is still not supported (open the javascript console and you'll see the relevant warnings output by Vega-Lite). You'll need to source both charts from the same dataset if you want the orders to be propagated to the layered chart.

@quantoid
Copy link

quantoid commented Jan 2, 2024

The sorting issue still occurs in Altair 5.2.0 on layered charts where sort="-x" is used to sort the y-axis to get highest x-value at the top.

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

No branches or pull requests

5 participants