Reputation: 23
This example code show 6 facets, ordered by their means. How could I display only e.g. 2 top or bottom facets, which are ordered this way? I tried playing around with the transform_window rank option with no luck, it limits the bar contents of all the facets instead.
import altair as alt
from vega_datasets import data
source = data.barley()
alt.Chart(source).mark_bar().encode(
x='yield:Q',
y='year:O',
color='year:N',
facet=alt.Facet('site',
sort={
'field': 'yield',
'op': 'mean',
'order': 'descending'
},
columns=1
)
)
Upvotes: 1
Views: 170
Reputation: 48919
You could use a joinaggregate transform to calculate the site means, then rank them using a window transform, and finally filter the ranks using the filter transform (similar to this example in the docs):
import altair as alt
from vega_datasets import data
source = data.barley()
n_top_sites = 3
alt.Chart(source).mark_bar().encode(
x='mean_yield_per_site:Q',
y='year:O',
color='year:N',
).facet(
alt.Facet('site', sort=['mean_yield_per_site'], title=''),
columns=1,
).transform_joinaggregate(
mean_yield_per_site='mean(yield)',
groupby=['site']
).transform_window(
rank='dense_rank()', # Don't skip any rank numbers, https://vega.github.io/vega-lite/docs/window.html#ops
sort=[alt.SortField('mean_yield_per_site', order='descending')]
).transform_filter(
f'datum.rank <= {n_top_sites}'
)
The same result could be achieved by doing the computation of the top site index labels with pandas and then filter for membership in that list via altair's filter transform:
n_top_sites = 2
top_sites = source.groupby('site').mean()['yield'].nlargest(n_top_sites).index.tolist()
alt.Chart(source).mark_bar().encode(
x='yield:Q',
y='year:O',
color='year:N',
facet=alt.Facet('site',
sort={
'field': 'yield',
'op': 'mean',
'order': 'descending'
},
columns=1
)
).transform_filter(
f'indexof({top_sites}, datum.site) != -1'
)
Upvotes: 1