Skip to content

Commit 549f078

Browse files
mkfreemanmbostockFil
authored
Warn users when facet data doesn't match mark data (#1014)
* Add warning when facet data doesn't match mark data * Adjust for tests, add warning svg * Run prettier * Renamed files, improved conditions for warning * Fix typo * Use arrayify to check the length Co-authored-by: Mike Bostock <[email protected]> * Update warning language used. Co-authored-by: Mike Bostock <[email protected]> * Remove facet_warning.svg file * facet warning logic & wording (#1015) * logic & wording * remove fcet_warning.svg * An arguably better test/example plot. * fix my mistake (ref #1015 (review)) Not sure how to remove the warning from the yarn test log—but this doesn't seem to be blocking * arrayify(mark.data)?.length * facetData.length * revert wording Co-authored-by: Mike Bostock <[email protected]> Co-authored-by: Philippe Rivière <[email protected]>
1 parent 2e84bbf commit 549f078

File tree

4 files changed

+239
-2
lines changed

4 files changed

+239
-2
lines changed

src/plot.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {position, registry as scaleRegistry} from "./scales/index.js";
2222
import {applyInlineStyles, maybeClassName, maybeClip, styles} from "./style.js";
2323
import {basic, initializer} from "./transforms/basic.js";
2424
import {maybeInterval} from "./transforms/interval.js";
25-
import {consumeWarnings} from "./warnings.js";
25+
import {consumeWarnings, warn} from "./warnings.js";
2626

2727
export function plot(options = {}) {
2828
const {facet, style, caption, ariaLabel, ariaDescription} = options;
@@ -59,10 +59,11 @@ export function plot(options = {}) {
5959
let facetChannels; // e.g. {fx: {value}, fy: {value}}
6060
let facetsIndex; // nested array of facet indexes [[0, 1, 3, …], [2, 5, …], …]
6161
let facetsExclude; // lazily-constructed opposite of facetsIndex
62+
let facetData;
6263
if (facet !== undefined) {
6364
const {x, y} = facet;
6465
if (x != null || y != null) {
65-
const facetData = arrayify(facet.data);
66+
facetData = arrayify(facet.data);
6667
if (facetData == null) throw new Error("missing facet data");
6768
facetChannels = {};
6869
if (x != null) {
@@ -99,6 +100,18 @@ export function plot(options = {}) {
99100
const {data, facets, channels} = mark.initialize(markFacets, facetChannels);
100101
applyScaleTransforms(channels, options);
101102
stateByMark.set(mark, {data, facets, channels});
103+
104+
// Warn for the common pitfall of wanting to facet mapped data.
105+
if (
106+
facetIndex?.length > 1 && // non-trivial faceting
107+
mark.facet === "auto" && // no explicit mark facet option
108+
mark.data !== facet.data && // mark not implicitly faceted (different data)
109+
arrayify(mark.data)?.length === facetData.length // mark data seems parallel to facet data
110+
) {
111+
warn(
112+
`Warning: the ${mark.ariaLabel} mark appears to use faceted data, but isn’t faceted. The mark data has the same length as the facet data and the mark facet option is "auto", but the mark data and facet data are distinct. If this mark should be faceted, set the mark facet option to true; otherwise, suppress this warning by setting the mark facet option to false.`
113+
);
114+
}
102115
}
103116

104117
// Initalize the scales and axes.

test/output/facetWarning.svg

Lines changed: 200 additions & 0 deletions
Loading

test/plots/facet-warning.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as Plot from "@observablehq/plot";
2+
import * as d3 from "d3";
3+
4+
export default async function () {
5+
const anscombe = await d3.csv("data/anscombe.csv", d3.autoType);
6+
return Plot.plot({
7+
grid: true,
8+
inset: 10,
9+
width: 960,
10+
height: 240,
11+
facet: {
12+
data: anscombe.filter((_, i) => i % 2),
13+
x: "series"
14+
},
15+
marks: [
16+
Plot.frame(),
17+
Plot.dot(
18+
anscombe.filter((_, i) => i % 2),
19+
{x: "x", y: "y" /* , facet: true */}
20+
)
21+
]
22+
});
23+
}

test/plots/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export {default as empty} from "./empty.js";
6262
export {default as emptyLegend} from "./empty-legend.js";
6363
export {default as emptyX} from "./empty-x.js";
6464
export {default as energyProduction} from "./energy-production.js";
65+
export {default as facetWarning} from "./facet-warning.js";
6566
export {default as faithfulDensity} from "./faithful-density.js";
6667
export {default as faithfulDensity1d} from "./faithful-density-1d.js";
6768
export {default as figcaption} from "./figcaption.js";

0 commit comments

Comments
 (0)