loess = ({ x, y, ...options }) => {
const z = options.z ?? options.fill ?? options.stroke;
const [X, setX] = Plot.column(x);
const [Y, setY] = Plot.column(y);
const [Y1, setY1] = Plot.column(y);
const [Y2, setY2] = Plot.column(y);
return {
...Plot.transform(options, function (data, facets) {
const X = setX(Plot.valueof(data, x));
const Y = setY(Plot.valueof(data, y));
const Z = Plot.valueof(data, z);
const Y1 = setY1(new Float64Array(X.length));
const Y2 = setY2(new Float64Array(X.length));
for (const facet of facets) {
for (const I of Z ? d3.group(facet, (i) => Z[i]).values() : [facet]) {
const model = new Loess.default(
{ x: I.map((i) => X[i]), y: I.map((i) => Y[i]) },
{ span, band, degree }
).predict();
for (const [j, i] of I.entries()) {
Y[i] = model.fitted[j];
Y1[i] = model.fitted[j] - model.halfwidth[j];
Y2[i] = model.fitted[j] + model.halfwidth[j];
}
}
}
return { data, facets };
}),
x: X,
y: Y,
y1: Y1,
y2: Y2
};
}