Published unlisted
Edited
Apr 14, 2022
1 fork
Importers
1 star
Insert cell
Insert cell
penguins = FileAttachment("penguins.csv").csv({typed: true})
Insert cell
Plot.plot({
grid: true,
marks: [
Plot.dot(penguins, {x: "culmen_length_mm", y: "culmen_depth_mm", stroke: "species"}),
linearRegression(penguins, {x: "culmen_length_mm", y: "culmen_depth_mm", stroke: "species"})
]
})
Insert cell
Plot.plot({
grid: true,
facet: {
data: penguins,
x: "species"
},
marks: [
Plot.dot(penguins, {x: "culmen_length_mm", y: "culmen_depth_mm", stroke: "species"}),
linearRegression(penguins, {x: "culmen_length_mm", y: "culmen_depth_mm"})
]
})
Insert cell
function linearRegression(data, options = {}) {
let {stroke, x, y, z} = options;
let [vstroke, cstroke] = maybeColor(stroke, "currentColor");
if (z === undefined && vstroke != null) z = vstroke;
const X1 = [];
const Y1 = [];
const X2 = [];
const Y2 = [];
const S = vstroke ? [] : undefined;
return Plot.link(data, {
...Plot.transform(options, (data, facets) => {
const X = Plot.valueof(data, x);
const Y = Plot.valueof(data, y);
const Z = z !== undefined ? Plot.valueof(data, z) : undefined;
const [x1, x2] = d3.extent(X);
const regressionFacets = [];
for (const facet of facets) {
let F = facet.filter(i => defined(X[i]) && defined(Y[i]));
const regressionFacet = [];
for (const I of Z ? d3.group(F, i => Z[i]).values() : [F]) {
const f = linearRegressionLine(I, X, Y);
const i = I[0];
X1[i] = x1;
X2[i] = x2;
Y1[i] = f(x1);
Y2[i] = f(x2);
regressionFacet.push(i);
}
regressionFacets.push(regressionFacet);
}
return {data, facets: regressionFacets};
}),
x1: X1,
y1: Y1,
x2: X2,
y2: Y2
});
}
Insert cell
function linearRegressionLine(I, X, Y) {
const n = I.length;
if (n === 1) return () => Y[I[0]];
let sx = 0, sy = 0, sxx = 0, sxy = 0;
for (const i of I) {
const x = X[i];
const y = Y[i];
sx += x;
sy += y;
sxx += x * x;
sxy += x * y;
}
const m = (n * sxy - sx * sy) / (n * sxx - sx * sx);
const b = (sy - m * sx) / n;
return x => b + m * x;
}
Insert cell
function maybeColor(value, defaultValue) {
if (value === undefined) value = defaultValue;
return value === null ? [undefined, "none"]
: isColor(value) ? [undefined, value]
: [value, undefined];
}
Insert cell
function isColor(value) {
if (typeof value !== "string") return false;
value = value.toLowerCase().trim();
return value === "none"
|| value === "currentcolor"
|| (value.startsWith("url(") && value.endsWith(")")) // <funciri>, e.g. pattern or gradient
|| (value.startsWith("var(") && value.endsWith(")")) // CSS variable
|| d3.color(value) !== null;
}
Insert cell
function defined(x) {
return x != null && !Number.isNaN(x);
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more