Merged Tooltips¶
When several data points are hit at the same cursor location, Lets-Plot shows a general tooltip for each target. Two theme() parameters control how these are displayed:
tooltipMerge— iftrue, the per-target tooltips are combined into a single merged tooltip.tooltipMaxCount— a guard against clutter: if the number of targets at a location exceeds it (default10), only the closest target is shown. Set to0to disable the limit.
These effects are interactive: hover the cursor over the lines near a shared
xto see the tooltips.
%useLatestDescriptors
%use lets-plot
LetsPlot.getInfo()
import java.util.Random
val nSeries = 12
val months = (1..12).toList()
val rnd = Random(42)
val monthCol = mutableListOf<Int>()
val valueCol = mutableListOf<Double>()
val seriesCol = mutableListOf<String>()
for (s in 0 until nSeries) {
val base = 10 + rnd.nextDouble() * 30 // uniform(10, 40)
val trend = -1.5 + rnd.nextDouble() * 3.0 // uniform(-1.5, 1.5)
for (m in months) {
val value = base + trend * m + rnd.nextGaussian() * 1.5
monthCol.add(m)
valueCol.add(Math.round(value * 10.0) / 10.0)
seriesCol.add("series " + (s + 1).toString().padStart(2, '0'))
}
}
val df = mapOf("month" to monthCol, "value" to valueCol, "series" to seriesCol)
val basePlot = letsPlot(df) { x = "month"; y = "value"; color = "series" } +
geomLine(size = 1, tooltips = layerTooltips().line("@series: @value")) +
ggsize(700, 400)
Default Behavior¶
There are 12 series, so hovering near an x hits more targets than the default tooltipMaxCount (10). When the limit is exceeded, Lets-Plot keeps the clutter down by showing only the closest target.
basePlot
Merging: tooltipMerge = true¶
tooltipMerge = true combines the per-target tooltips into a single box — one row per series, each with its color marker — a much cleaner way to show them all at once.
All 12 series appear even though that exceeds the default tooltipMaxCount of 10: merging takes priority over the limit, so tooltipMaxCount is ignored and every target is collected into the merged tooltip.
basePlot + theme(tooltipMerge = true)
Stacked Bars¶
Merging is just as useful for stacked bars: hovering over a bar hits every segment in the stack, so a merged tooltip summarizes the whole stack in a single box.
val rndBars = Random(1)
val quarters = listOf("Q1", "Q2", "Q3", "Q4")
val products = (1..5).map { "product $it" }
val qCol = mutableListOf<String>()
val pCol = mutableListOf<String>()
val salesCol = mutableListOf<Int>()
for (q in quarters) {
for (p in products) {
qCol.add(q)
pCol.add(p)
salesCol.add(5 + rndBars.nextInt(25)) // randint(5, 30)
}
}
val barsDf = mapOf("quarter" to qCol, "product" to pCol, "sales" to salesCol)
letsPlot(barsDf) { x = "quarter"; y = "sales"; fill = "product" } +
geomBar(stat = Stat.identity, tooltips = layerTooltips().line("@product: @sales")) +
ggsize(700, 400) +
theme(tooltipMerge = true)
Side Tooltips: geomErrorBar with disableSplitting()¶
By default, geoms like geomErrorBar split their tooltip: the general tooltip is broken into a general
tooltip plus a set of side tooltips (here, the interval bounds) placed next to the data.
layerTooltips().disableSplitting() turns splitting off, rebuilding a single general tooltip —
which merging can then combine across the group at a category into one box.
val rndErr = Random(2)
val cats = listOf("A", "B", "C", "D")
val groups = listOf("group 1", "group 2", "group 3")
val cCol = mutableListOf<String>()
val gCol = mutableListOf<String>()
val meanCol = mutableListOf<Double>()
val yminCol = mutableListOf<Double>()
val ymaxCol = mutableListOf<Double>()
for (c in cats) {
for (g in groups) {
val m = 8 + rndErr.nextDouble() * 10 // uniform(8, 18)
val e = 1.5 + rndErr.nextDouble() * 2.0 // uniform(1.5, 3.5)
cCol.add(c)
gCol.add(g)
meanCol.add(Math.round(m * 10.0) / 10.0)
yminCol.add(Math.round((m - e) * 10.0) / 10.0)
ymaxCol.add(Math.round((m + e) * 10.0) / 10.0)
}
}
val errDf = mapOf("category" to cCol, "group" to gCol, "mean" to meanCol, "ymin" to yminCol, "ymax" to ymaxCol)
letsPlot(errDf) { x = "category"; y = "mean"; color = "group" } +
geomErrorBar(size = 1, tooltips = layerTooltips().title("@group").disableSplitting()) { ymin = "ymin"; ymax = "ymax" } +
ggsize(700, 400) +
theme(tooltipMerge = true)