@@ -3,7 +3,7 @@ import {identity, indexOf, maybeZ} from "../options.js";
33import { Mark } from "../plot.js" ;
44import { qt } from "../stats.js" ;
55import { 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
88const 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+
74109export 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