Skip to content

Commit 0f30405

Browse files
authored
allow sort to reduce data (#517)
* allow sort to reduce data; update tests * declare data as input
1 parent 6af2740 commit 0f30405

8 files changed

+31
-25
lines changed

src/mark.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class Mark {
4949
const {name} = channel;
5050
return [name == null ? undefined : name + "", Channel(data, channel)];
5151
});
52-
if (this.sort != null) channelSort(channels, facetChannels, this.sort);
52+
if (this.sort != null) channelSort(channels, facetChannels, data, this.sort);
5353
return {index, channels};
5454
}
5555
plot({marks = [], ...options} = {}) {
@@ -67,7 +67,7 @@ function Channel(data, {scale, type, value}) {
6767
};
6868
}
6969

70-
function channelSort(channels, facetChannels, options) {
70+
function channelSort(channels, facetChannels, data, options) {
7171
const {reverse: defaultReverse, reduce: defaultReduce = true, limit: defaultLimit} = options;
7272
for (const x in options) {
7373
if (!registry.has(x)) continue; // ignore unknown scale keys
@@ -85,9 +85,14 @@ function channelSort(channels, facetChannels, options) {
8585
return domain;
8686
};
8787
} else {
88-
const Y = channels.find(([name]) => name === y);
89-
if (!Y) throw new Error(`missing channel: ${y}`);
90-
const YV = Y[1].value;
88+
let YV;
89+
if (y === "data") {
90+
YV = data;
91+
} else {
92+
const Y = channels.find(([name]) => name === y);
93+
if (!Y) throw new Error(`missing channel: ${y}`);
94+
YV = Y[1].value;
95+
}
9196
const reducer = maybeReduce(reduce === true ? "max" : reduce, YV);
9297
X[1].domain = () => {
9398
let domain = rollup(range(XV), I => reducer.reduce(I, YV), i => XV[i]);

test/plots/athletes-nationality.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,15 @@ import * as d3 from "d3";
33

44
export default async function() {
55
const athletes = await d3.csv("data/athletes.csv", d3.autoType);
6-
const top = new Set(d3.groupSort(athletes, g => -g.length, d => d.nationality).slice(0, 20));
76
return Plot.plot({
87
x: {
98
grid: true
109
},
1110
y: {
12-
domain: top,
1311
label: null
1412
},
1513
marks: [
16-
Plot.barX(athletes, Plot.groupY({x: "count"}, {y: "nationality"}))
14+
Plot.barX(athletes, Plot.groupY({x: "count"}, {y: "nationality", sort: {y: "x", reverse: true, limit: 20}}))
1715
]
1816
});
1917
}

test/plots/athletes-sport-sex.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import * as d3 from "d3";
33

44
export default async function() {
55
const athletes = await d3.csv("data/athletes.csv", d3.autoType);
6-
const female = data => d3.mean(data, d => d.sex === "female");
76
return Plot.plot({
87
marginLeft: 100,
98
x: {
@@ -14,11 +13,10 @@ export default async function() {
1413
grid: true
1514
},
1615
y: {
17-
label: null,
18-
domain: d3.groupSort(athletes, female, d => d.sport)
16+
label: null
1917
},
2018
marks: [
21-
Plot.barX(athletes, Plot.groupY({x: female}, {y: "sport"}))
19+
Plot.barX(athletes, Plot.groupY({x: "mean"}, {x: d => d.sex === "female", y: "sport", sort: {y: "x"}}))
2220
]
2321
});
2422
}

test/plots/ballot-status-race.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ export default async function() {
6262
axis: null
6363
},
6464
fy: {
65-
domain: d3.groupSort(rollup, group => -group.find(d => d.status === "ACCEPTED").percent, d => d.race),
6665
label: null
6766
},
6867
color: {
@@ -75,7 +74,17 @@ export default async function() {
7574
marginLeft: 210
7675
},
7776
marks: [
78-
Plot.barX(rollup, {x: "percent", y: "status", fill: "status", title: d => `${d.percent.toFixed(1)}%`}),
77+
Plot.barX(rollup, {
78+
x: "percent",
79+
y: "status",
80+
fill: "status",
81+
title: d => `${d.percent.toFixed(1)}%`,
82+
sort: {
83+
fy: "data",
84+
reduce: data => data.find(d => d.status === "ACCEPTED").percent,
85+
reverse: true
86+
}
87+
}),
7988
Plot.ruleX([0])
8089
]
8190
});

test/plots/d3-survey-2015.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ function bars(groups, title) {
3434
y: {
3535
padding: 0,
3636
label: title,
37-
labelAnchor: "top",
38-
domain: d3.groupSort(groups, ([[, value]]) => -value, ([key]) => key)
37+
labelAnchor: "top"
3938
},
4039
marks: [
4140
Plot.barX(groups, {
4241
x: ([, value]) => value,
4342
y: ([key]) => key,
4443
fill: "steelblue",
45-
insetTop: 1
44+
insetTop: 1,
45+
sort: {y: "x", reverse: true}
4646
}),
4747
Plot.ruleX([0])
4848
]

test/plots/metro-unemployment-ridgeline.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export default async function() {
1111
axis: null
1212
},
1313
fy: {
14-
domain: d3.groupSort(data, g => -d3.max(g, d => d.unemployment), d => d.division),
1514
label: null
1615
},
1716
facet: {
@@ -21,7 +20,7 @@ export default async function() {
2120
},
2221
marks: [
2322
Plot.areaY(data, {x: "date", y: "unemployment", fill: "#eee"}),
24-
Plot.line(data, {x: "date", y: "unemployment"}),
23+
Plot.line(data, {x: "date", y: "unemployment", sort: {fy: "y", reverse: true}}),
2524
Plot.ruleY([0])
2625
]
2726
});

test/plots/movies-profit-by-genre.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ export default async function() {
1313
label: "Profit ($M) →",
1414
domain: [d3.min(movies, Profit), 1e3]
1515
},
16-
y: {
17-
domain: d3.groupSort(movies, movies => -d3.median(movies, Profit), Genre)
18-
},
1916
marks: [
2017
Plot.ruleX([0]),
2118
Plot.barX(movies, Plot.groupY({x1: quartile1, x2: quartile3}, {
@@ -32,7 +29,8 @@ export default async function() {
3229
y: Genre,
3330
x: Profit,
3431
stroke: "red",
35-
strokeWidth: 2
32+
strokeWidth: 2,
33+
sort: {y: "x", reverse: true}
3634
}))
3735
]
3836
});

test/plots/us-population-state-age-dots.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export default async function() {
1515
transform: d => d * 100
1616
},
1717
y: {
18-
domain: d3.groupSort(stateage, g => -g.find(d => d.age === "≥80").population / d3.sum(g, d => d.population), d => d.state),
1918
axis: null
2019
},
2120
color: {
@@ -26,7 +25,7 @@ export default async function() {
2625
Plot.ruleX([0]),
2726
Plot.ruleY(stateage, Plot.groupY({x1: "min", x2: "max"}, position)),
2827
Plot.dot(stateage, {...position, fill: "age"}),
29-
Plot.text(stateage, Plot.selectMinX({...position, textAnchor: "end", dx: -6, text: "state"}))
28+
Plot.text(stateage, Plot.selectMinX({...position, textAnchor: "end", dx: -6, text: "state", sort: {y: "x", reduce: "min", reverse: true}}))
3029
]
3130
});
3231
}

0 commit comments

Comments
 (0)