Side-by-Side Dodged displays

Don’t know if this is a question or a feature request. I want to have side-by-side dodged displays like this, which I’ve produced using facets:

I can drop the frame and change padding, etc. to get them closer, but it is then awkward to add other graphics such as a line connecting the means of the two groups. If it were like other Plot functions, it seems like the x: channel should work for groups. However, the following produced a single display but separate labels for the two groups.
Plot.plot({
height: 300,
marks: [
Plot.dot(
data,
Plot.dodgeX({
y: “y”,
x: “grp”,
fill: “grp”,
anchor: “middle”,
padding: 0.5
})
)
]
})

working notebook with code at dodge example problem / Seeing Statistics | Observable

I’m afraid the dodgeX transform is not adapted to your requirements. It creates the x dimension, but it doesn’t know how to start from given x positions. And, as you mention, it’s not possible either to have a mark that spans facets and still has access to the y dimension.

A (quite poor) solution for now is to use the identity scale for x, then move things around with dx:

Plot.plot({
  height: 300,
  x: { type: "identity", axis: null },
  marks: [
    Plot.dot(
      data,
      Plot.dodgeX({
        dx: 100,
        filter: (d) => d.grp === "control",
        y: "y",
        fill: "grp",
        anchor: "middle",
        padding: 0.5
      })
    ),
    Plot.dot(
      data,
      Plot.dodgeX({
        dx: -100,
        y: "y",
        filter: (d) => d.grp === "treatment",
        fill: "grp",
        anchor: "middle",
        padding: 0.5
      })
    ),
    Plot.link([1], {
      x1: 240,
      x2: 440,
      y1: d3.mean(
        data.filter((d) => d.grp === "treatment"),
        (d) => d.y
      ),
      y2: d3.mean(
        data.filter((d) => d.grp === "control"),
        (d) => d.y
      )
    })
  ]
})
1 Like

Wow! This works great for my present purposes. The only thing “poor” about this solution is that it uses absolute x pixel values so depends on width. But I can deal with that.

It seems like dodgeX should be able to use specified x starting locations. Should this be a feature request?

thanks for your excellent and clear solution.

Seems to me there are two feature requests in your question:

  1. expand from a given position (I’m not sure it’s possible at all with the “dodge” transform per se, but it might be worth considering with a different technique, for example Experimental Plot Beeswarm / Fil | Observable)
  2. have a mark that spans facets and still has access to the y dimension, to connect points between facets (again, not sure it’s technically feasible in a generic way)