Skip to content

Commit

Permalink
refine auto bar mark determination (#1801)
Browse files Browse the repository at this point in the history
* refine auto bar mark determination

* add another test
  • Loading branch information
mbostock authored and Fil committed Aug 21, 2023
1 parent 5c670e7 commit d8c2d4c
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 28 deletions.
55 changes: 27 additions & 28 deletions src/marks/auto.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ascending, InternSet} from "d3";
import {marks} from "../mark.js";
import {isColor, isObject, isOptions, isOrdinal, labelof, valueof} from "../options.js";
import {isColor, isNumeric, isObject, isOptions, isOrdinal, labelof, valueof} from "../options.js";
import {bin, binX, binY} from "../transforms/bin.js";
import {group, groupX, groupY} from "../transforms/group.js";
import {areaX, areaY} from "./area.js";
Expand Down Expand Up @@ -113,27 +113,32 @@ export function autoSpec(data, options) {
colorMode = "stroke";
break;
case "bar":
markImpl = yZero
? isOrdinalReduced(xReduce, X)
? barY
: rectY
: xZero
? isOrdinalReduced(yReduce, Y)
? barX
: rectX
: isOrdinalReduced(xReduce, X) && isOrdinalReduced(yReduce, Y)
? cell
: isOrdinalReduced(xReduce, X)
? barY
: isOrdinalReduced(yReduce, Y)
? barX
: xReduce != null
? rectX
: yReduce != null
? rectY
: colorReduce != null
? rect
: cell;
markImpl =
xReduce != null // bin or group on y
? isOrdinal(Y)
? isSelectReducer(xReduce) && X && isOrdinal(X)
? cell
: barX
: rectX
: yReduce != null // bin or group on x
? isOrdinal(X)
? isSelectReducer(yReduce) && Y && isOrdinal(Y)
? cell
: barY
: rectY
: colorReduce != null || sizeReduce != null // bin or group on both x and y
? X && isOrdinal(X) && Y && isOrdinal(Y)
? cell
: X && isOrdinal(X)
? barY
: Y && isOrdinal(Y)
? barX
: rect
: X && isNumeric(X) && !(Y && isNumeric(Y))
? barX // if y is temporal, treat as ordinal
: Y && isNumeric(Y) && !(X && isNumeric(X))
? barY // if x is temporal, treat as ordinal
: cell;
colorMode = "fill";
break;
default:
Expand Down Expand Up @@ -300,12 +305,6 @@ function isSelectReducer(reduce) {
return /^(?:first|last|mode)$/i.test(reduce);
}

// We can’t infer the type of a custom reducer without invoking it, so
// assume most reducers produce quantitative values.
function isOrdinalReduced(reduce, value) {
return (reduce != null && !isSelectReducer(reduce)) || !value ? false : isOrdinal(value);
}

// https://github.com/observablehq/plot/blob/818562649280e155136f730fc496e0b3d15ae464/src/transforms/group.js#L236
function isReducer(reduce) {
if (reduce == null) return false;
Expand Down
77 changes: 77 additions & 0 deletions test/output/autoBarTimeSeries.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 71 additions & 0 deletions test/output/autoBarTimeSeriesReduce.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions test/plots/autoplot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,24 @@ export async function autoBar() {
return Plot.auto(alphabet, {x: "frequency", y: "letter", mark: "bar"}).plot();
}

const timeSeries = [
{date: new Date("2023-04-01"), type: "triangle", value: 5},
{date: new Date("2023-04-05"), type: "circle", value: 7},
{date: new Date("2023-04-10"), type: "circle", value: 8},
{date: new Date("2023-04-15"), type: "circle", value: 3},
{date: new Date("2023-04-15"), type: "triangle", value: 7},
{date: new Date("2023-04-20"), type: "triangle", value: 4},
{date: new Date("2023-04-25"), type: "square", value: 5}
];

export async function autoBarTimeSeries() {
return Plot.auto(timeSeries, {x: "date", y: "value", color: "type", mark: "bar"}).plot({x: {type: "band"}}); // TODO suppress warning?
}

export async function autoBarTimeSeriesReduce() {
return Plot.auto(timeSeries, {x: "date", y: {value: "value", reduce: "sum"}, color: "type", mark: "bar"}).plot();
}

export async function autoConnectedScatterplot() {
const driving = await d3.csv<any>("data/driving.csv", d3.autoType);
return Plot.auto(driving, {x: "miles", y: "gas", mark: "line"}).plot();
Expand Down

0 comments on commit d8c2d4c

Please sign in to comment.