Skip to content

Commit 4d36de0

Browse files
authored
improve bin type coercion (#790)
1 parent 9c0d93d commit 4d36de0

File tree

7 files changed

+313
-2
lines changed

7 files changed

+313
-2
lines changed

src/transforms/bin.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {bin as binner, extent, thresholdFreedmanDiaconis, thresholdScott, thresholdSturges, utcTickInterval} from "d3";
22
import {valueof, range, identity, maybeLazyChannel, maybeTuple, maybeColorChannel, maybeValue, mid, labelof, isTemporal} from "../options.js";
3-
import {coerceDate} from "../scales.js";
3+
import {coerceDate, coerceNumber} from "../scales.js";
44
import {basic} from "./basic.js";
55
import {hasOutput, maybeEvaluator, maybeGroup, maybeOutput, maybeOutputs, maybeReduce, maybeSort, maybeSubgroup, reduceCount, reduceIdentity} from "./group.js";
66
import {maybeInsetX, maybeInsetY} from "./inset.js";
@@ -181,7 +181,7 @@ function maybeBin(options) {
181181
if (options == null) return;
182182
const {value, cumulative, domain = extent, thresholds} = options;
183183
const bin = data => {
184-
let V = valueof(data, value);
184+
let V = valueof(data, value, Array); // d3.bin prefers Array input
185185
const bin = binner().value(i => V[i]);
186186
if (isTemporal(V) || isTimeThresholds(thresholds)) {
187187
V = V.map(coerceDate);
@@ -197,6 +197,7 @@ function maybeBin(options) {
197197
}
198198
bin.thresholds(t).domain([min, max]);
199199
} else {
200+
V = V.map(coerceNumber);
200201
let d = domain;
201202
let t = thresholds;
202203
if (isInterval(t)) {

test/output/binStrings.svg

Lines changed: 105 additions & 0 deletions
Loading

test/output/binTimestamps.svg

Lines changed: 86 additions & 0 deletions
Loading

test/output/stringBins.svg

Lines changed: 105 additions & 0 deletions
Loading

test/plots/bin-strings.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import * as Plot from "@observablehq/plot";
2+
3+
export default async function() {
4+
return Plot.rectY(["9.6", "9.6", "14.8", "14.8", "7.2"], Plot.binX()).plot();
5+
}

test/plots/bin-timestamps.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as Plot from "@observablehq/plot";
2+
import * as d3 from "d3";
3+
4+
export default async function() {
5+
const timestamps = Float64Array.of(1609459200000, 1609545600000, 1609632000000, 1609718400000, 1609804800000, 1609891200000, 1609977600000);
6+
return Plot.rectY(timestamps, Plot.binX({y: "count"}, {interval: d3.utcDay})).plot();
7+
}

test/plots/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export {default as athletesWeightCumulative} from "./athletes-weight-cumulative.
2323
export {default as availability} from "./availability.js";
2424
export {default as ballotStatusRace} from "./ballot-status-race.js";
2525
export {default as beckerBarley} from "./becker-barley.js";
26+
export {default as binStrings} from "./bin-strings.js";
27+
export {default as binTimestamps} from "./bin-timestamps.js";
2628
export {default as boxplot} from "./boxplot.js";
2729
export {default as caltrain} from "./caltrain.js";
2830
export {default as caltrainDirection} from "./caltrain-direction.js";

0 commit comments

Comments
 (0)