Showing combined data in tooltip for stacked plots

Hey there,

I am struggling with adapting tooltips to my needs in stacked charts. My charts basically show data from two channels. The tooltip by default would only show me the data for the single channel that I’m hovering. I would like to customize this, to show the data for both channels and the sum of both channels, in the tooltip. What is the best way to achieve that?

So far, I managed it a bit by duplicating my data, basically I transform my data first:

tidyUp(rawGeneratedByHour, function(row) {
  return [{
    hour: row.hour - timeZoneHourOffset,
    channel: "East",
    out: row.ch1,
    out_ch1: row.ch1,
    out_ch2: row.ch2,
    out_combined: row.ch1 + row.ch2
  }, {
    hour: row.hour - timeZoneHourOffset,
    channel: "South",
    out: row.ch2,
    out_ch1: row.ch1,
    out_ch2: row.ch2,
    out_combined: row.ch1 + row.ch2
  }];
})

Then I can hide the “y” and instead show the custom data:


    resize((width) => Plot.plot({
      title: "Hourly Energy Production; Avg: " +
        formatEnergy(d3.mean(rawGeneratedByHour, sumCh1Ch2)) +
        ", Max: " + formatEnergy(d3.max(rawGeneratedByHour, sumCh1Ch2)),
      subtitle: "Generated power in the last 24h",
      width,
      x: {grid: true, type: "band", label: "Hour"},
      y: {grid: true, label: "Generated Energy [kWh]"},
      color: {legend: true},
      marks: [
        Plot.barY(generatedByHour, {x: "hour", y: "out", tip: {
          channels: {
            combined: { value: "out_combined", label: "Combined [kWh]" },
            ch1: { value: "out_ch1", label: "East [kWh]" },
            ch2: { value: "out_ch2", label: "South [kWh]" },
          },
          format: {
            combined: true,
            ch1: true,
            ch2: true,
            y: false,
            x: true,
          }
        }, fill: "channel"})
      ]
    }))

This works, but feels pretty convoluted - is there an easier way? And sadly it still shows the “channel” that I’m hovering and I cannot manage to hide that - how could I do that?

Now, I can live with the above. But when I try to apply the same trick on a sum-aggregated plot, e.g.:

    resize((width) => Plot.plot({
      title: "Weekly Energy Production",
      subtitle: "Generated energy in the last weeks",
      width,
      x: {type: "band"},
      y: {grid: true, label: "Generated Energy [kWh]"},
      color: {legend: true},
      marks: [
        Plot.barY(
          generatedByDayLastYear,
          Plot.binX(
            {y: "sum"},
            {x: {interval: d3.utcDay.every(7), value: "date"}, y: "out", tip: {
              channels: {
                combined: { value: "out_combined", label: "Combined [kWh]" },
                ch1: { value: "out_ch1", label: "East [kWh]" },
                ch2: { value: "out_ch2", label: "South [kWh]" },
              },
              format: {
                combined: true,
                ch1: true,
                ch2: true,
                y: false,
                x: true,
              }
            }, fill: "channel"}
          )
        ),
        Plot.ruleY([0]),
        Plot.axisX(d3.scaleTime([generatedByDayLastYear.at(0).date, generatedByDayLastYear.at(-1).date], [0, 12]).ticks(), {
          type: "band",
          grid: true,
          label: "Week",
          tickFormat: function(date, i) {
            return monthNames[date.getMonth()];
          }
        }),
      ]
    }))

then the tooltip would show me the raw data for an individual point, and not the summed one:

How would I handle that? I.e. how could I also apply something like y: "sum" for the y: "out" to my other data fields like out_ch1, out_ch2, and out_combined?

Again, it feels like my approach is backwards. The way it breaks down here makes me believe I’m not doing it the right way.

Cheers