Center-Aligning text mark with rectY and date intervals

I am showing time-series data (one bar per month) by using a rectY() mark along with the interval: "month" transform.

I am also using a text() mark to show the value of the bar above it, and an axisX() to show an axis below it with ticks for each month label.

Without the interval transform, the text mark and the axis both center their values on the bars, which is what I want. But then empty months don’t show up (i.e. I lose the benefit of the interval transform - which I do want).

With the interval transform set, the text mark left-aligns to the bar, which is not what I want (and using dx is not helpful because the width is dynamic) and the axisX also left-aligns, which I would like the ticks to stay centered under the rectY bars.

Note that I understand why it’s doing it, not looking for that to be explained to me, but rather I am looking to figure out how, if possible, to retain the center-alignment of the text and axis under the bars in the rectY with the interval transform.

Here’s my code:

        marks: [
          Plot.rectY(eventsByMonth, {
            interval: "month",
            fill: "#613889",
            x: "month",
            y: "total",
          }),
          Plot.text(eventsByMonth, {
            x: "month",
            y: "total",
            dy: -10,
            text: "total",
          }),
          Plot.axisX({
            ticks: eventsByMonth.length,
            label: null,
            tickFormat: (d) => moment(d).format("MMM YY"),
          }),
          Plot.ruleY([0])
        ]

Here’s what it looks like without the interval transform (and what I would like the text and axisX marks to look like):

And here’s what it looks like when I add the interval transform:

I’ve tried a bunch of options for the marks and can’t figure it out…

Figured this out. My data is monthly but the date value was set to the first of the month.

By setting the date for each month to the 15th of the month, I was able to center the text mark, and by changing the ticks property of the axisX mark from eventsByMonth.length to eventsByMonth.map(e => e.month) It centered the ticks on the axis.

Also worth noting that I added a domain to the parent Plot.plot() object that contains the marks (not shown in the code above), to ensure that every chart in the series has the same start and end month (in the event that one of the sets doesn’t have data for every month):

x: {
  domain: [
          new Date(startMonth),
          new Date(endMonth)
  ] 
}

Here startMonth and endMonth are computed from the data ahead of time, and are set to the first and last days of the months (respectively).

:+1: In the future please open a GitHub discussion instead, as we’re trying to move the conversations about Plot to a central place.

1 Like