I am looking for a way to display multiple elements within one tooltip. I did not find a way to do this in Altair directly. In vega-lite, I would do something like
"tooltip": [
{"type": "quantitative", "aggregate": "sum", "field": "A"},
{"type": "quantitative", "aggregate": "sum", "field": "B"}
],
and it would show the sum of A and the sum of B like so:

If Altair does not yet support this, I think this is a useful feature to be added in the future.
Regards, Immanuel
This is supported in the master branch, and will be included in the version 2.1 release. Just pass multiple field names to the tooltip encoding; e.g.
chart.encode(
tooltip=['sum(A):Q', 'sum(B):Q']
)
It can also be done in version 2.0, but not as conveniently. You have to bypass the encode() method and modify the encoding directly without any shorthands; e.g.
chart = alt.Chart().encode(...) #... define the full chart + encodings first
# add multiple tooltips
chart.encoding.tooltip = [
{"type": "quantitative", "aggregate": "sum", "field": "A"},
{"type": "quantitative", "aggregate": "sum", "field": "B"}
]
I am looking forward to v2.1! And thanks a lot for the fast reply with the hack for v2.0
Sadly, it is not working (but almost):
With
my_chart.tooltip = [
{"type": "quantitative", "aggregate": "sum", "field": "A"},
{"type": "quantitative", "aggregate": "sum", "field": "B"}
]
Altair emits the following vega-lite specification
tooltip: [
{'type': 'quantitative', 'aggregate': 'sum', 'field': 'A'},
{'type': 'quantitative', 'aggregate': 'sum', 'field': 'B'}
]
which has a syntactic error because the single quotes ' should be double quotes ".
Fixing the quotes in the vega-lite code manually results in properly rendered graphics.
That's really strange... the JSON output that's passed to the renderer goes through the json.dumps() function, which should produce valid JSON no matter how the chart was constructed.
Can you paste code that reproduces the error you're seeing?
First I define the chart (which is a heatmap) as follows:
activity_heatmap = alt.Chart(df_dbms).mark_bar().encode(
x = alt.X('Time', bin=alt.Bin(maxbins=25), axis=alt.Axis(title='Time [seconds]')),
y = alt.Y('Address', bin=alt.Bin(step=4096*2**12), axis=alt.Axis(format='0X', title='Virtual Address Range')),
color = alt.Color('count()', title='# of Operations (x1000)'),
)
And then I set the tooltip
activity_heatmap.tooltip = [
{"type": "quantitative", "aggregate": "sum", "field": "is_read"},
{"type": "quantitative", "aggregate": "sum", "field": "is_write"}
]
When trying to render the plot, I get the following error:
SchemaValidationError Traceback (most recent call last)
/usr/lib/python3.6/site-packages/altair/vegalite/v2/api.py in to_dict(self, *args, **kwargs)
338 if dct is None:
339 kwargs['validate'] = 'deep'
--> 340 dct = super(TopLevelMixin, copy).to_dict(*args, **kwargs)
341
342 if is_top_level:
/usr/lib/python3.6/site-packages/altair/utils/schemapi.py in to_dict(self, validate, ignore, context)
243 result = _todict(self._args[0])
244 elif not self._args:
--> 245 result = _todict({k: v for k, v in self._kwds.items()
246 if k not in ignore})
247 else:
/usr/lib/python3.6/site-packages/altair/utils/schemapi.py in _todict(val)
235 return [_todict(v) for v in val]
236 elif isinstance(val, dict):
--> 237 return {k: _todict(v) for k, v in val.items()
238 if v is not Undefined}
239 else:
/usr/lib/python3.6/site-packages/altair/utils/schemapi.py in <dictcomp>(.0)
236 elif isinstance(val, dict):
237 return {k: _todict(v) for k, v in val.items()
--> 238 if v is not Undefined}
239 else:
240 return val
/usr/lib/python3.6/site-packages/altair/utils/schemapi.py in _todict(val)
233 return val.to_dict(validate=sub_validate, context=context)
234 elif isinstance(val, (list, tuple)):
--> 235 return [_todict(v) for v in val]
236 elif isinstance(val, dict):
237 return {k: _todict(v) for k, v in val.items()
/usr/lib/python3.6/site-packages/altair/utils/schemapi.py in <listcomp>(.0)
233 return val.to_dict(validate=sub_validate, context=context)
234 elif isinstance(val, (list, tuple)):
--> 235 return [_todict(v) for v in val]
236 elif isinstance(val, dict):
237 return {k: _todict(v) for k, v in val.items()
/usr/lib/python3.6/site-packages/altair/utils/schemapi.py in _todict(val)
231 def _todict(val):
232 if isinstance(val, SchemaBase):
--> 233 return val.to_dict(validate=sub_validate, context=context)
234 elif isinstance(val, (list, tuple)):
235 return [_todict(v) for v in val]
/usr/lib/python3.6/site-packages/altair/vegalite/v2/api.py in to_dict(self, *args, **kwargs)
338 if dct is None:
339 kwargs['validate'] = 'deep'
--> 340 dct = super(TopLevelMixin, copy).to_dict(*args, **kwargs)
341
342 if is_top_level:
/usr/lib/python3.6/site-packages/altair/utils/schemapi.py in to_dict(self, validate, ignore, context)
252 self.validate(result)
253 except jsonschema.ValidationError as err:
--> 254 raise SchemaValidationError(self, err)
255 return result
256
SchemaValidationError: Invalid specification
altair.vegalite.v2.api.Chart, validating 'additionalProperties'
Additional properties are not allowed ('tooltip' was unexpected)
from which I conclude that there is a problem validating the generated JSON specification for vega.
The emitted vega code contains the following tooltip definition:
tooltip: [
{'type': 'quantitative', 'aggregate': 'sum', 'field': 'is_read'},
{'type': 'quantitative', 'aggregate': 'sum', 'field': 'is_write'}
]
Now if i render the plot without the tooltop specification and open it in the vega editor and paste the erroneous tooltip specification from above, I get syntax errors. Then, replacing single quotes ' by double quotes " fixes these errors and I get the plot and tooltips as desired. The vega code then looks as follows
"encoding": {
"tooltip": [
{"type": "quantitative", "aggregate": "sum", "field": "is_read"},
{"type": "quantitative", "aggregate": "sum", "field": "is_write"}
],
...
}
Sorry, my mistake. Instead of activity_heatmap.tooltip = [...] you need to use activity_heatmap.encoding.tooltip = [...].
Thanks, that did the trick ;)
Most helpful comment
It can also be done in version 2.0, but not as conveniently. You have to bypass the
encode()method and modify the encoding directly without any shorthands; e.g.