Skip to content

Commit b5b9471

Browse files
mbostockFil
andauthored
Unify group, bin, and reduce. (#272)
* checkpoint new group * group boxplot! * check for value-less reduce * update example * require reduce * don’t compute z twice * reorder * missing imports * bin groups * fix reducer test * half-fix plots that need default {x: count} or {fill: count} still missing: - normalize - automatic scale label (Frequency ↑) * fix plots (reduce => group) * firstof {z, fill, stroke} * reduce proportion * maybeGroup * reduce percent * fix value-less reducers * remove unused import * update tests * more tests * smarter facet axis position * percent-z, percent-facet * generalize normalize * add test output * normalize * proportional reducers * allow external scoped reducers * bad vscode * require group channels * bin outputs * fix inset * cumulative bins * reorder export * no insets for binMid * restore labels * reverse cumulative * fix secondary group dimension * proportion-group * fix tests * apply maybeReduce to data channel * remove noop * shorten * binned replaces input * don’t subgroup if output * restore test * scale percent * rm proportion-group * update snapshot Co-authored-by: Philippe Rivière <fil@rezo.net>
1 parent a217e1d commit b5b9471

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+14432
-1685
lines changed

src/axes.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ export function Axes(
88
let {axis: yAxis = true} = y;
99
let {axis: fxAxis = true} = fx;
1010
let {axis: fyAxis = true} = fy;
11-
if (xAxis === true) xAxis = "bottom";
12-
if (yAxis === true) yAxis = "left";
13-
if (fxAxis === true) fxAxis = xAxis === "bottom" ? "top" : "bottom";
14-
if (fyAxis === true) fyAxis = yAxis === "left" ? "right" : "left";
11+
if (!xScale) xAxis = null; else if (xAxis === true) xAxis = "bottom";
12+
if (!yScale) yAxis = null; else if (yAxis === true) yAxis = "left";
13+
if (!fxScale) fxAxis = null; else if (fxAxis === true) fxAxis = xAxis === "bottom" ? "top" : "bottom";
14+
if (!fyScale) fyAxis = null; else if (fyAxis === true) fyAxis = yAxis === "left" ? "right" : "left";
1515
return {
16-
...xScale && xAxis && {x: new AxisX({grid, ...x, axis: xAxis})},
17-
...yScale && yAxis && {y: new AxisY({grid, ...y, axis: yAxis})},
18-
...fxScale && fxAxis && {fx: new AxisX({name: "fx", grid: facetGrid, ...fx, axis: fxAxis})},
19-
...fyScale && fyAxis && {fy: new AxisY({name: "fy", grid: facetGrid, ...fy, axis: fyAxis})}
16+
...xAxis && {x: new AxisX({grid, ...x, axis: xAxis})},
17+
...yAxis && {y: new AxisY({grid, ...y, axis: yAxis})},
18+
...fxAxis && {fx: new AxisX({name: "fx", grid: facetGrid, ...fx, axis: fxAxis})},
19+
...fyAxis && {fy: new AxisY({name: "fy", grid: facetGrid, ...fy, axis: fyAxis})}
2020
};
2121
}
2222

@@ -102,10 +102,11 @@ function inferLabel(channels = [], scale, axis, key) {
102102
else if (candidate !== label) return;
103103
}
104104
if (candidate !== undefined) {
105-
const {invert} = scale;
105+
const {percent, invert} = scale;
106106
// Ignore the implicit label for temporal scales if it’s simply “date”.
107107
if (scale.type === "temporal" && /^(date|time|year)$/i.test(candidate)) return;
108108
if (scale.type !== "ordinal" && (key === "x" || key === "y")) {
109+
if (percent) candidate = `${candidate} (%)`;
109110
if (axis.labelAnchor === "center") {
110111
candidate = `${candidate} →`;
111112
} else if (key === "x") {

src/facet.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class Facet extends Mark {
6060
}
6161
const named = Object.create(null);
6262
for (const [name, channel] of channels) {
63-
if (name !== undefined) named[name] = channel.value;
63+
if (name !== undefined) Object.defineProperty(named, name, {get: () => channel.value}); // scale transform
6464
subchannels.push([undefined, channel]);
6565
}
6666
marksChannels.push(named);

src/index.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ export {Rect, rect, rectX, rectY} from "./marks/rect.js";
1111
export {RuleX, RuleY, ruleX, ruleY} from "./marks/rule.js";
1212
export {Text, text, textX, textY} from "./marks/text.js";
1313
export {TickX, TickY, tickX, tickY} from "./marks/tick.js";
14-
export {bin, binX, binY, binXMid, binYMid, binR} from "./transforms/bin.js";
15-
export {group, groupX, groupY, groupR, groupZ, groupZX, groupZY, groupZR} from "./transforms/group.js";
14+
export {bin, binMid, binX, binY, binXMid, binYMid} from "./transforms/bin.js";
15+
export {group, groupX, groupY, groupZ} from "./transforms/group.js";
1616
export {normalizeX, normalizeY} from "./transforms/normalize.js";
1717
export {map, mapX, mapY} from "./transforms/map.js";
18-
export {reduce, reduceX, reduceY} from "./transforms/reduce.js";
1918
export {windowX, windowY} from "./transforms/window.js";
2019
export {selectFirst, selectLast, selectMaxX, selectMaxY, selectMinX, selectMinY} from "./transforms/select.js";
2120
export {stackX, stackX1, stackX2, stackXMid, stackY, stackY1, stackY2, stackYMid} from "./transforms/stack.js";

src/plot.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,8 @@ export function plot(options = {}) {
3333
const {scale} = channel;
3434
if (scale !== undefined) {
3535
const scaled = scaleChannels.get(scale);
36-
const {transform} = options[scale] || {};
37-
if (transform !== undefined) {
38-
channel.value = Array.from(channel.value, transform);
39-
}
36+
const {percent, transform = percent ? x => x * 100 : undefined} = options[scale] || {};
37+
if (transform !== undefined) channel.value = Array.from(channel.value, transform);
4038
if (scaled) scaled.push(channel);
4139
else scaleChannels.set(scale, [channel]);
4240
}

src/scales/quantitative.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ export function ScaleQ(key, scale, channels, {
137137
clamp,
138138
zero,
139139
domain = (registry.get(key) === radius ? inferRadialDomain : inferDomain)(channels),
140+
percent,
140141
round,
141142
range = registry.get(key) === radius ? inferRadialRange(channels, domain) : undefined,
142143
scheme,
@@ -167,7 +168,7 @@ export function ScaleQ(key, scale, channels, {
167168

168169
if (range !== undefined) scale.range(range);
169170
if (clamp) scale.clamp(clamp);
170-
return {type: "quantitative", invert, domain, range, scale, inset};
171+
return {type: "quantitative", invert, domain, range, scale, inset, percent};
171172
}
172173

173174
export function ScaleLinear(key, channels, options) {

0 commit comments

Comments
 (0)