diff --git a/src/transforms/bin.js b/src/transforms/bin.js index 00d0bc2730..2af0502fa6 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -1,6 +1,6 @@ import {bin as binner, extent, thresholdFreedmanDiaconis, thresholdScott, thresholdSturges, utcTickInterval} from "d3"; import {valueof, range, identity, maybeLazyChannel, maybeTuple, maybeColorChannel, maybeValue, mid, labelof, isTemporal} from "../options.js"; -import {coerceDate} from "../scales.js"; +import {coerceDate, coerceNumber} from "../scales.js"; import {basic} from "./basic.js"; import {hasOutput, maybeEvaluator, maybeGroup, maybeOutput, maybeOutputs, maybeReduce, maybeSort, maybeSubgroup, reduceCount, reduceIdentity} from "./group.js"; import {maybeInsetX, maybeInsetY} from "./inset.js"; @@ -181,7 +181,7 @@ function maybeBin(options) { if (options == null) return; const {value, cumulative, domain = extent, thresholds} = options; const bin = data => { - let V = valueof(data, value); + let V = valueof(data, value, Array); // d3.bin prefers Array input const bin = binner().value(i => V[i]); if (isTemporal(V) || isTimeThresholds(thresholds)) { V = V.map(coerceDate); @@ -197,6 +197,7 @@ function maybeBin(options) { } bin.thresholds(t).domain([min, max]); } else { + V = V.map(coerceNumber); let d = domain; let t = thresholds; if (isInterval(t)) { diff --git a/test/output/binStrings.svg b/test/output/binStrings.svg new file mode 100644 index 0000000000..9f753a21b6 --- /dev/null +++ b/test/output/binStrings.svg @@ -0,0 +1,105 @@ + + + + + 0.0 + + + 0.2 + + + 0.4 + + + 0.6 + + + 0.8 + + + 1.0 + + + 1.2 + + + 1.4 + + + 1.6 + + + 1.8 + + + 2.0 + + + 2.2 + + + 2.4 + + + 2.6 + + + 2.8 + + + 3.0 + ↑ Frequency + + + + 5 + + + 6 + + + 7 + + + 8 + + + 9 + + + 10 + + + 11 + + + 12 + + + 13 + + + 14 + + + 15 + + + + + + + \ No newline at end of file diff --git a/test/output/binTimestamps.svg b/test/output/binTimestamps.svg new file mode 100644 index 0000000000..02535494eb --- /dev/null +++ b/test/output/binTimestamps.svg @@ -0,0 +1,86 @@ + + + + + 0.0 + + + 0.1 + + + 0.2 + + + 0.3 + + + 0.4 + + + 0.5 + + + 0.6 + + + 0.7 + + + 0.8 + + + 0.9 + + + 1.0 + ↑ Frequency + + + + 2021 + + + Sat 02 + + + Jan 03 + + + Mon 04 + + + Tue 05 + + + Wed 06 + + + Thu 07 + + + Fri 08 + + + + + + + + + + + + \ No newline at end of file diff --git a/test/output/stringBins.svg b/test/output/stringBins.svg new file mode 100644 index 0000000000..9f753a21b6 --- /dev/null +++ b/test/output/stringBins.svg @@ -0,0 +1,105 @@ + + + + + 0.0 + + + 0.2 + + + 0.4 + + + 0.6 + + + 0.8 + + + 1.0 + + + 1.2 + + + 1.4 + + + 1.6 + + + 1.8 + + + 2.0 + + + 2.2 + + + 2.4 + + + 2.6 + + + 2.8 + + + 3.0 + ↑ Frequency + + + + 5 + + + 6 + + + 7 + + + 8 + + + 9 + + + 10 + + + 11 + + + 12 + + + 13 + + + 14 + + + 15 + + + + + + + \ No newline at end of file diff --git a/test/plots/bin-strings.js b/test/plots/bin-strings.js new file mode 100644 index 0000000000..2058fa0903 --- /dev/null +++ b/test/plots/bin-strings.js @@ -0,0 +1,5 @@ +import * as Plot from "@observablehq/plot"; + +export default async function() { + return Plot.rectY(["9.6", "9.6", "14.8", "14.8", "7.2"], Plot.binX()).plot(); +} diff --git a/test/plots/bin-timestamps.js b/test/plots/bin-timestamps.js new file mode 100644 index 0000000000..21bfed562b --- /dev/null +++ b/test/plots/bin-timestamps.js @@ -0,0 +1,7 @@ +import * as Plot from "@observablehq/plot"; +import * as d3 from "d3"; + +export default async function() { + const timestamps = Float64Array.of(1609459200000, 1609545600000, 1609632000000, 1609718400000, 1609804800000, 1609891200000, 1609977600000); + return Plot.rectY(timestamps, Plot.binX({y: "count"}, {interval: d3.utcDay})).plot(); +} diff --git a/test/plots/index.js b/test/plots/index.js index b9cf61dd18..c748254805 100644 --- a/test/plots/index.js +++ b/test/plots/index.js @@ -23,6 +23,8 @@ export {default as athletesWeightCumulative} from "./athletes-weight-cumulative. export {default as availability} from "./availability.js"; export {default as ballotStatusRace} from "./ballot-status-race.js"; export {default as beckerBarley} from "./becker-barley.js"; +export {default as binStrings} from "./bin-strings.js"; +export {default as binTimestamps} from "./bin-timestamps.js"; export {default as boxplot} from "./boxplot.js"; export {default as caltrain} from "./caltrain.js"; export {default as caltrainDirection} from "./caltrain-direction.js";