diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 24195df416..0c1a11b070 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -2,6 +2,7 @@ import {bin as binner, cross, group, sum} from "d3"; import {firstof} from "../defined.js"; import {valueof, first, second, range, identity, lazyChannel, maybeLazyChannel, maybeTransform, maybeColor, maybeValue, mid, take, labelof} from "../mark.js"; import {offset} from "../style.js"; +import {groups} from "./group.js"; // Group on y, z, fill, or stroke, if any, then bin on x. export function binX({x, y, out = y == null ? "y" : "fill", inset, insetLeft, insetRight, ...options} = {}) { @@ -162,7 +163,7 @@ function bin2(x, y, {weight, domain, thresholds, normalize, z, fill, stroke, ... let i = 0; for (const facet of facets) { const binFacet = []; - for (const I of G ? group(facet, i => G[i]).values() : [facet]) { + for (const [, I] of groups(facet, G)) { if (normalize === "z") n = W ? sum(I, i => W[i]) : I.length; const set = new Set(I); for (const b of B) { diff --git a/src/transforms/group.js b/src/transforms/group.js index b92431b4eb..5f89f41ff0 100644 --- a/src/transforms/group.js +++ b/src/transforms/group.js @@ -85,10 +85,10 @@ function group2(xv, yv, {z, fill, stroke, weight, domain, normalize, ...options} for (const facet of facets) { const groupFacet = []; if (normalize === "facet") n = W ? sum(facet, i => W[i]) : facet.length; - for (const I of G ? grouper(facet, i => G[i]).values() : [facet]) { + for (const [, I] of groups(facet, G, defined1)) { if (normalize === "z") n = W ? sum(I, i => W[i]) : I.length; - for (const [y, fy] of Y ? sort(grouper(I, i => Y[i]), first).filter(ydefined) : [[, I]]) { - for (const [x, f] of X ? sort(grouper(fy, i => X[i]), first).filter(xdefined) : [[, fy]]) { + for (const [y, fy] of groups(I, Y, ydefined)) { + for (const [x, f] of groups(fy, X, xdefined)) { const l = W ? sum(f, i => W[i]) : f.length; groupFacet.push(i++); groupData.push(take(data, f)); @@ -119,10 +119,6 @@ function maybeDomain(domain) { return ([key]) => domain.has(key); } -function defined1([key]) { - return defined(key); -} - function maybeNormalize(normalize) { if (!normalize) return; if (normalize === true) return 100; @@ -132,3 +128,11 @@ function maybeNormalize(normalize) { } throw new Error("invalid normalize"); } + +function defined1([key]) { + return defined(key); +} + +export function groups(I, X, defined = defined1) { + return X ? sort(grouper(I, i => X[i]), first).filter(defined) : [[, I]]; +} diff --git a/test/output/penguinSpeciesGroup.svg b/test/output/penguinSpeciesGroup.svg index a159847956..3f1492bbb6 100644 --- a/test/output/penguinSpeciesGroup.svg +++ b/test/output/penguinSpeciesGroup.svg @@ -1,48 +1,37 @@ - - 0 + 0 - - 10 + 10 - - 20 + 20 - - 30 + 30 - - 40 + 40 - - 50 + 50 - - 60 + 60 - - 70 + 70 - - 80 + 80 - - 90 + 90 - - 100 + 100 Frequency (%) → @@ -50,6 +39,7 @@ + AdelieChinstrapGentoo diff --git a/test/output/penguinSpeciesIsland.svg b/test/output/penguinSpeciesIsland.svg index dca4f34026..fcf694a89f 100644 --- a/test/output/penguinSpeciesIsland.svg +++ b/test/output/penguinSpeciesIsland.svg @@ -45,11 +45,11 @@ species - - + - + + diff --git a/test/plots/penguin-species-group.js b/test/plots/penguin-species-group.js index d6b8fdc034..f915e9b7d9 100644 --- a/test/plots/penguin-species-group.js +++ b/test/plots/penguin-species-group.js @@ -4,11 +4,9 @@ import * as d3 from "d3"; export default async function() { const penguins = await d3.csv("data/penguins.csv", d3.autoType); return Plot.plot({ - x: { - grid: true - }, marks: [ Plot.barX(penguins, Plot.stackX(Plot.groupZX({fill: "species", normalize: true}))), + Plot.text(penguins, Plot.stackXMid(Plot.groupZX({z: "species", normalize: true, text: ([d]) => d.species}))), Plot.ruleX([0, 100]) ] });