Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I compute aggregates of aggregates for labels/tooltips?

If I have time series data that is aggregated. Is it possible to perform additional aggregation and display it in the tooltip?

Here's a more explicit example of my question. For the code sample below, we show the sum of weights aggregated by month across three different types of fruit. Is it possible to also show the total weight each month (and/or perhaps the normalized percentage of weight by fruit each month) as a label or in the tooltip?

I've played around with transform_aggregate but couldn't seem to get it to work (it ends up mangling the group by for fruit). :(

dates = np.array([
     np.datetime64('200%s-%.02d-%.02d' % (i,j,k)) 
                   for i in range(5) 
                   for j in range(1,13) 
                   for k in range(1, 29)])
data = pd.DataFrame({
    'timestamp': dates,
    'weight': np.random.randint(0, 20, 1680),
    'fruit': np.random.randint(0,3, 1680)
})
date_month = alt.X('yearmonth(timestamp):O', title='Month')
total = alt.Y('weight:Q', aggregate='sum', title='Metric')

(alt.Chart(data).mark_bar().encode(
    x=date_month,
    y=total,
    color='fruit',
    tooltip=[date_month, total, 'fruit']
))
like image 831
henrymei Avatar asked Jan 29 '26 23:01

henrymei


1 Answers

The way to do this is with aggregate transforms, though it's a little bit tricky because you need to make sure to group the data properly before computing the aggregate. Here is how you can reproduce your chart using aggregate transforms rather than aggregates within the encoding:

alt.Chart(data).transform_timeunit(
    Month='yearmonth(timestamp)'
).transform_aggregate(
    Metric='sum(weight)',
    groupby=['fruit', 'Month']
).mark_bar().encode(
    x='yearmonth(Month):O',  # use yearmonth to control axis format
    y='Metric:Q',
    color='fruit:Q',
    tooltip=['yearmonth(Month):O', 'Metric:Q', 'fruit:Q']
)

enter image description here

Once you've done that, you can use a similar strategy (keeping close track of the groupby) to display the total above each bar:

base = alt.Chart(data).transform_timeunit(
    Month='yearmonth(timestamp)'
).encode(
    x='yearmonth(Month):O'
)

labels = base.transform_aggregate(
    Total='sum(weight)',
    groupby=['Month']
).mark_text().encode(
    y='Total:Q',
    text='Total:Q'
)

bars = base.transform_aggregate(
    Metric='sum(weight)',
    groupby=['fruit', 'Month']
).mark_bar().encode(
    y='Metric:Q',
    color='fruit:Q',
    tooltip=['Month:O', 'Metric:Q', 'fruit:Q']
)

alt.layer(bars, labels, width=1400)

enter image description here

like image 99
jakevdp Avatar answered Feb 01 '26 11:02

jakevdp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!