Skip to content

Commit c00cfa6

Browse files
mbostockchaichontat
authored andcommitted
refine auto bar mark determination (observablehq#1801)
* refine auto bar mark determination * add another test
1 parent 00e323f commit c00cfa6

File tree

4 files changed

+193
-28
lines changed

4 files changed

+193
-28
lines changed

src/marks/auto.js

+27-28
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {ascending, InternSet} from "d3";
22
import {marks} from "../mark.js";
3-
import {isColor, isObject, isOptions, isOrdinal, labelof, valueof} from "../options.js";
3+
import {isColor, isNumeric, isObject, isOptions, isOrdinal, labelof, valueof} from "../options.js";
44
import {bin, binX, binY} from "../transforms/bin.js";
55
import {group, groupX, groupY} from "../transforms/group.js";
66
import {areaX, areaY} from "./area.js";
@@ -113,27 +113,32 @@ export function autoSpec(data, options) {
113113
colorMode = "stroke";
114114
break;
115115
case "bar":
116-
markImpl = yZero
117-
? isOrdinalReduced(xReduce, X)
118-
? barY
119-
: rectY
120-
: xZero
121-
? isOrdinalReduced(yReduce, Y)
122-
? barX
123-
: rectX
124-
: isOrdinalReduced(xReduce, X) && isOrdinalReduced(yReduce, Y)
125-
? cell
126-
: isOrdinalReduced(xReduce, X)
127-
? barY
128-
: isOrdinalReduced(yReduce, Y)
129-
? barX
130-
: xReduce != null
131-
? rectX
132-
: yReduce != null
133-
? rectY
134-
: colorReduce != null
135-
? rect
136-
: cell;
116+
markImpl =
117+
xReduce != null // bin or group on y
118+
? isOrdinal(Y)
119+
? isSelectReducer(xReduce) && X && isOrdinal(X)
120+
? cell
121+
: barX
122+
: rectX
123+
: yReduce != null // bin or group on x
124+
? isOrdinal(X)
125+
? isSelectReducer(yReduce) && Y && isOrdinal(Y)
126+
? cell
127+
: barY
128+
: rectY
129+
: colorReduce != null || sizeReduce != null // bin or group on both x and y
130+
? X && isOrdinal(X) && Y && isOrdinal(Y)
131+
? cell
132+
: X && isOrdinal(X)
133+
? barY
134+
: Y && isOrdinal(Y)
135+
? barX
136+
: rect
137+
: X && isNumeric(X) && !(Y && isNumeric(Y))
138+
? barX // if y is temporal, treat as ordinal
139+
: Y && isNumeric(Y) && !(X && isNumeric(X))
140+
? barY // if x is temporal, treat as ordinal
141+
: cell;
137142
colorMode = "fill";
138143
break;
139144
default:
@@ -300,12 +305,6 @@ function isSelectReducer(reduce) {
300305
return /^(?:first|last|mode)$/i.test(reduce);
301306
}
302307

303-
// We can’t infer the type of a custom reducer without invoking it, so
304-
// assume most reducers produce quantitative values.
305-
function isOrdinalReduced(reduce, value) {
306-
return (reduce != null && !isSelectReducer(reduce)) || !value ? false : isOrdinal(value);
307-
}
308-
309308
// https://github.com/observablehq/plot/blob/818562649280e155136f730fc496e0b3d15ae464/src/transforms/group.js#L236
310309
function isReducer(reduce) {
311310
if (reduce == null) return false;

test/output/autoBarTimeSeries.svg

+77
Loading
+71
Loading

test/plots/autoplot.ts

+18
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,24 @@ export async function autoBar() {
103103
return Plot.auto(alphabet, {x: "frequency", y: "letter", mark: "bar"}).plot();
104104
}
105105

106+
const timeSeries = [
107+
{date: new Date("2023-04-01"), type: "triangle", value: 5},
108+
{date: new Date("2023-04-05"), type: "circle", value: 7},
109+
{date: new Date("2023-04-10"), type: "circle", value: 8},
110+
{date: new Date("2023-04-15"), type: "circle", value: 3},
111+
{date: new Date("2023-04-15"), type: "triangle", value: 7},
112+
{date: new Date("2023-04-20"), type: "triangle", value: 4},
113+
{date: new Date("2023-04-25"), type: "square", value: 5}
114+
];
115+
116+
export async function autoBarTimeSeries() {
117+
return Plot.auto(timeSeries, {x: "date", y: "value", color: "type", mark: "bar"}).plot({x: {type: "band"}}); // TODO suppress warning?
118+
}
119+
120+
export async function autoBarTimeSeriesReduce() {
121+
return Plot.auto(timeSeries, {x: "date", y: {value: "value", reduce: "sum"}, color: "type", mark: "bar"}).plot();
122+
}
123+
106124
export async function autoConnectedScatterplot() {
107125
const driving = await d3.csv<any>("data/driving.csv", d3.autoType);
108126
return Plot.auto(driving, {x: "miles", y: "gas", mark: "line"}).plot();

0 commit comments

Comments
 (0)