diff --git a/src/transforms/group.js b/src/transforms/group.js index db419d32d0..a6f678e3f2 100644 --- a/src/transforms/group.js +++ b/src/transforms/group.js @@ -87,8 +87,8 @@ function group2(xv, yv, {z, fill, stroke, weight, domain, normalize, ...options} if (normalize === "facet") n = W ? sum(facet, i => W[i]) : facet.length; for (const [, I] of groups(facet, G)) { if (normalize === "z") n = W ? sum(I, i => W[i]) : I.length; - for (const [y, fy] of groups(I, Y, ydefined)) { - for (const [x, f] of groups(fy, X, xdefined)) { + for (const [y, fy] of groups(I, Y, ydefined, ydomain)) { + for (const [x, f] of groups(fy, X, xdefined, xdomain)) { const l = W ? sum(f, i => W[i]) : f.length; groupFacet.push(i++); groupData.push(take(data, f)); @@ -129,8 +129,10 @@ function maybeNormalize(normalize) { throw new Error("invalid normalize"); } -export function groups(I, X, defined) { +export function groups(I, X, defined, domain) { if (!X) return [[, I]]; const G = grouper(I, i => X[i]); - return sort(defined ? Array.from(G).filter(defined) : G, first); + return domain + ? domain.map(x => [x, G.has(x) ? G.get(x) : []]) + : sort(defined ? Array.from(G).filter(defined) : G, first); } diff --git a/test/transforms/group-test.js b/test/transforms/group-test.js new file mode 100644 index 0000000000..e06397533f --- /dev/null +++ b/test/transforms/group-test.js @@ -0,0 +1,36 @@ +import * as Plot from "@observablehq/plot"; +import tape from "tape-await"; + +tape("groupX respects the domain option (#255)", test => { + const data = ["A", "A", "C"]; + const options = {x: d => d, domain: ["C", "B", "A"]}; + const mark = Plot.dot(data, Plot.groupX(options)); + const A = mark.initialize(); + test.deepEqual(A.index, [0, 1, 2]); + test.deepEqual(A.channels.find(d => d[0] === "x")[1].value, ["C", "B", "A"]); + test.deepEqual(A.channels.find(d => d[0] === "y")[1].value, [1, 0, 2]); +}); + +tape("groupY respects the domain option (#255)", test => { + const data = ["A", "A", "C"]; + const options = {x: d => d, domain: ["C", "B", "A"]}; + const mark = Plot.dot(data, Plot.groupY(options)); + const A = mark.initialize(); + test.deepEqual(A.index, [0, 1, 2]); + test.deepEqual(A.channels.find(d => d[0] === "y")[1].value, ["C", "B", "A"]); + test.deepEqual(A.channels.find(d => d[0] === "x")[1].value, [1, 0, 2]); +}); + +tape("group respects the domain option (#255)", test => { + const data = ["A", "A", "C", "A", "C"]; + const options = {x: d => d, y: d => d, domain: ["C", "B", "A"]}; + const mark = Plot.dot(data, Plot.group(options)); + const A = mark.initialize(); + test.deepEqual(A.index, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + test.deepEqual(A.channels.find(d => d[0] === "fill")[1].value, [ + //C, B, A + 2, 0, 0, // C + 0, 0, 0, // B + 0, 0, 3 // A + ]); +});