Skip to content

Commit 8d6cee7

Browse files
committed
linearRegressionX
1 parent f63e9c5 commit 8d6cee7

File tree

2 files changed

+54
-19
lines changed

2 files changed

+54
-19
lines changed

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export {Frame, frame} from "./marks/frame.js";
1010
export {Hexgrid, hexgrid} from "./marks/hexgrid.js";
1111
export {Image, image} from "./marks/image.js";
1212
export {Line, line, lineX, lineY} from "./marks/line.js";
13-
export {linearRegressionY} from "./marks/linearRegression.js";
13+
export {linearRegressionX, linearRegressionY} from "./marks/linearRegression.js";
1414
export {Link, link} from "./marks/link.js";
1515
export {Rect, rect, rectX, rectY} from "./marks/rect.js";
1616
export {RuleX, RuleY, ruleX, ruleY} from "./marks/rule.js";

src/marks/linearRegression.js

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {identity, indexOf, maybeZ} from "../options.js";
33
import {Mark} from "../plot.js";
44
import {qt} from "../stats.js";
55
import {applyDirectStyles, applyGroupedChannelStyles, applyIndirectStyles, applyTransform, groupZ, offset} from "../style.js";
6-
import {maybeDenseIntervalX} from "../transforms/bin.js";
6+
import {maybeDenseIntervalX, maybeDenseIntervalY} from "../transforms/bin.js";
77

88
const defaults = {
99
ariaLabel: "linear-regression",
@@ -16,7 +16,7 @@ const defaults = {
1616
strokeMiterlimit: 1
1717
};
1818

19-
class LinearRegressionY extends Mark {
19+
class LinearRegression extends Mark {
2020
constructor(data, options = {}) {
2121
const {x, y, z, p = 0.05, precision = 4} = options;
2222
super(
@@ -37,7 +37,7 @@ class LinearRegressionY extends Mark {
3737
}
3838
render(I, {x, y}, channels, dimensions) {
3939
const {x: X, y: Y, z: Z} = channels;
40-
const {dx, dy, p, precision} = this;
40+
const {dx, dy} = this;
4141
return create("svg:g")
4242
.call(applyIndirectStyles, this, dimensions)
4343
.call(applyTransform, x, y, offset + dx, offset + dy)
@@ -48,29 +48,64 @@ class LinearRegressionY extends Mark {
4848
.attr("stroke", "none")
4949
.call(applyDirectStyles, this)
5050
.call(applyGroupedChannelStyles, this, {...channels, stroke: null, strokeOpacity: null, strokeWidth: null})
51-
.attr("d", I => {
52-
const [x1, x2] = extent(I, i => X[i]);
53-
const f = linearRegressionF(I, X, Y);
54-
const g = confidenceIntervalF(I, X, Y, p, f);
55-
return shapeArea()
56-
.x(x => x)
57-
.y0(x => g(x, -1))
58-
.y1(x => g(x, +1))
59-
(range(x1, x2 - precision / 2, precision).concat(x2));
60-
}))
51+
.attr("d", I => this._renderBand(I, X, Y)))
6152
.call(enter => enter.append("path")
6253
.attr("fill", "none")
6354
.call(applyDirectStyles, this)
6455
.call(applyGroupedChannelStyles, this, {...channels, fill: null, fillOpacity: null})
65-
.attr("d", I => {
66-
const [x1, x2] = extent(I, i => X[i]);
67-
const f = linearRegressionF(I, X, Y);
68-
return `M${x1},${f(x1)}L${x2},${f(x2)}`;
69-
})))
56+
.attr("d", I => this._renderLine(I, X, Y))))
7057
.node();
7158
}
7259
}
7360

61+
class LinearRegressionX extends LinearRegression {
62+
constructor(data, options) {
63+
super(data, options);
64+
}
65+
_renderBand(I, X, Y) {
66+
const {p, precision} = this;
67+
const [y1, y2] = extent(I, i => Y[i]);
68+
const f = linearRegressionF(I, Y, X);
69+
const g = confidenceIntervalF(I, Y, X, p, f);
70+
return shapeArea()
71+
.y(y => y)
72+
.x0(y => g(y, -1))
73+
.x1(y => g(y, +1))
74+
(range(y1, y2 - precision / 2, precision).concat(y2));
75+
}
76+
_renderLine(I, X, Y) {
77+
const [y1, y2] = extent(I, i => Y[i]);
78+
const f = linearRegressionF(I, Y, X);
79+
return `M${f(y1)},${y1}L${f(y2)},${y2}`;
80+
}
81+
}
82+
83+
class LinearRegressionY extends LinearRegression {
84+
constructor(data, options) {
85+
super(data, options);
86+
}
87+
_renderBand(I, X, Y) {
88+
const {p, precision} = this;
89+
const [x1, x2] = extent(I, i => X[i]);
90+
const f = linearRegressionF(I, X, Y);
91+
const g = confidenceIntervalF(I, X, Y, p, f);
92+
return shapeArea()
93+
.x(x => x)
94+
.y0(x => g(x, -1))
95+
.y1(x => g(x, +1))
96+
(range(x1, x2 - precision / 2, precision).concat(x2));
97+
}
98+
_renderLine(I, X, Y) {
99+
const [x1, x2] = extent(I, i => X[i]);
100+
const f = linearRegressionF(I, X, Y);
101+
return `M${x1},${f(x1)}L${x2},${f(x2)}`;
102+
}
103+
}
104+
105+
export function linearRegressionX(data, {y = indexOf, x = identity, stroke, fill = stroke, ...options} = {}) {
106+
return new LinearRegressionX(data, maybeDenseIntervalY({...options, x, y, fill, stroke}));
107+
}
108+
74109
export function linearRegressionY(data, {x = indexOf, y = identity, stroke, fill = stroke, ...options} = {}) {
75110
return new LinearRegressionY(data, maybeDenseIntervalX({...options, x, y, fill, stroke}));
76111
}

0 commit comments

Comments
 (0)