Skip to content

Commit a561591

Browse files
committed
feat: add @stdlib/stats/incr/nanmpcorrdist
- Add incrementor for computing moving sample Pearson product-moment correlation distance with NaN handling - Wraps @stdlib/stats/incr/mpcorrdist and ignores NaN values in x and y - Include comprehensive tests (2069 passing), examples, benchmarks, and TypeScript definitions - Follow stdlib conventions for package structure and code style PR: #2986 --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: passed - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: passed - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: passed - task: lint_license_headers status: passed ---
1 parent 29fc92b commit a561591

9 files changed

Lines changed: 1398 additions & 0 deletions

File tree

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2018 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# incrnanmpcorrdist
22+
23+
> Compute a moving [sample Pearson product-moment correlation distance][pearson-correlation] incrementally, ignoring `NaN` values.
24+
25+
<section class="intro">
26+
27+
The [sample Pearson product-moment correlation distance][pearson-correlation] is defined as
28+
29+
<!-- <equation class="equation" label="eq:pearson_distance" align="center" raw="d_{x,y} = 1 - r_{x,y} = 1 - \frac{\operatorname{cov_n(x,y)}}{\sigma_x \sigma_y}" alt="Equation for the Pearson product-moment correlation distance."> -->
30+
31+
```math
32+
d_{x,y} = 1 - r_{x,y} = 1 - \frac{\mathop{\mathrm{cov_n(x,y)}}}{\sigma_x \sigma_y}
33+
```
34+
35+
<!-- <div class="equation" align="center" data-raw-text="d_{x,y} = 1 - r_{x,y} = 1 - \frac{\operatorname{cov_n(x,y)}}{\sigma_x \sigma_y}" data-equation="eq:pearson_distance">
36+
<img src="https://cdn.jsdelivr.net/gh/stdlib-js/stdlib@49d8cabda84033d55d7b8069f19ee3dd8b8d1496/lib/node_modules/@stdlib/stats/incr/nanmpcorrdist/docs/img/equation_pearson_distance.svg" alt="Equation for the Pearson product-moment correlation distance.">
37+
<br>
38+
</div> -->
39+
40+
<!-- </equation> -->
41+
42+
where `r` is the [sample Pearson product-moment correlation coefficient][pearson-correlation], `cov(x,y)` is the sample covariance, and `σ` corresponds to the sample standard deviation. As `r` resides on the interval `[-1,1]`, `d` resides on the interval `[0,2]`.
43+
44+
</section>
45+
46+
<!-- /.intro -->
47+
48+
<section class="usage">
49+
50+
## Usage
51+
52+
```javascript
53+
var incrnanmpcorrdist = require( '@stdlib/stats/incr/nanmpcorrdist' );
54+
```
55+
56+
#### incrnanmpcorrdist( window\[, mx, my] )
57+
58+
Returns an accumulator `function` which incrementally computes a moving [sample Pearson product-moment correlation distance][pearson-correlation], ignoring `NaN` values. The `window` parameter defines the number of values over which to compute the moving [sample Pearson product-moment correlation distance][pearson-correlation].
59+
60+
```javascript
61+
var accumulator = incrnanmpcorrdist( 3 );
62+
```
63+
64+
If means are already known, provide `mx` and `my` arguments.
65+
66+
```javascript
67+
var accumulator = incrnanmpcorrdist( 3, 5.0, -3.14 );
68+
```
69+
70+
#### accumulator( \[x, y] )
71+
72+
If provided input values `x` and `y`, the accumulator function returns an updated [sample Pearson product-moment correlation distance][pearson-correlation]. If not provided input values `x` and `y`, the accumulator function returns the current [sample Pearson product-moment correlation distance][pearson-correlation].
73+
74+
```javascript
75+
var accumulator = incrnanmpcorrdist( 3 );
76+
77+
var r = accumulator();
78+
// returns null
79+
80+
// Fill the window...
81+
r = accumulator( 2.0, 1.0 ); // [(2.0, 1.0)]
82+
// returns 1.0
83+
84+
r = accumulator( NaN, 3.14 ); // [(2.0, 1.0)]
85+
// returns 1.0
86+
87+
r = accumulator( -5.0, 3.14 ); // [(2.0, 1.0), (-5.0, 3.14)]
88+
// returns ~2.0
89+
90+
r = accumulator( 3.0, NaN ); // [(2.0, 1.0), (-5.0, 3.14)]
91+
// returns ~2.0
92+
93+
r = accumulator( 3.0, -1.0 ); // [(2.0, 1.0), (-5.0, 3.14), (3.0, -1.0)]
94+
// returns ~1.925
95+
96+
// Window begins sliding...
97+
r = accumulator( 5.0, -9.5 ); // [(-5.0, 3.14), (3.0, -1.0), (5.0, -9.5)]
98+
// returns ~1.863
99+
100+
r = accumulator( NaN, 1.5 ); // [(-5.0, 3.14), (3.0, -1.0), (5.0, -9.5)]
101+
// returns ~1.863
102+
103+
r = accumulator( -5.0, NaN ); // [(-5.0, 3.14), (3.0, -1.0), (5.0, -9.5)]
104+
// returns ~1.863
105+
106+
r = accumulator();
107+
// returns ~1.863
108+
```
109+
110+
</section>
111+
112+
<!-- /.usage -->
113+
114+
<section class="notes">
115+
116+
## Notes
117+
118+
- Input values are **not** type checked. If non-numeric inputs are possible, you are advised to type check and handle accordingly **before** passing the value to the accumulator function.
119+
- As `W` (x,y) pairs are needed to fill the window buffer, the first `W-1` returned values are calculated from smaller sample sizes. Until the window is full, each returned value is calculated from all provided **non-NaN** values.
120+
- Due to limitations inherent in representing numeric values using floating-point format (i.e., the inability to represent numeric values with infinite precision), the [sample correlation distance][pearson-correlation] between perfectly correlated random variables may **not** be `0` or `2`. In fact, the [sample correlation distance][pearson-correlation] is **not** guaranteed to be strictly on the interval `[0,2]`. Any computed distance should, however, be within floating-point roundoff error.
121+
122+
</section>
123+
124+
<!-- /.notes -->
125+
126+
<section class="examples">
127+
128+
## Examples
129+
130+
<!-- eslint no-undef: "error" -->
131+
132+
```javascript
133+
var randu = require( '@stdlib/random/base/randu' );
134+
var incrnanmpcorrdist = require( '@stdlib/stats/incr/nanmpcorrdist' );
135+
136+
var accumulator;
137+
var x;
138+
var y;
139+
var i;
140+
141+
// Initialize an accumulator:
142+
accumulator = incrnanmpcorrdist( 5 );
143+
144+
// For each simulated datum, update the moving sample correlation distance...
145+
for ( i = 0; i < 100; i++ ) {
146+
x = ( randu() < 0.2 ) ? NaN : randu() * 100.0;
147+
y = ( randu() < 0.2 ) ? NaN : randu() * 100.0;
148+
accumulator( x, y );
149+
}
150+
console.log( accumulator() );
151+
```
152+
153+
</section>
154+
155+
<!-- /.examples -->
156+
157+
<!-- Section for related `stdlib` packages. Do not manually edit this section, as it is automatically populated. -->
158+
159+
<section class="related">
160+
161+
* * *
162+
163+
## See Also
164+
165+
- <span class="package-name">[`@stdlib/stats/incr/mpcorrdist`][@stdlib/stats/incr/mpcorrdist]</span><span class="delimiter">: </span><span class="description">compute a moving sample Pearson product-moment correlation distance incrementally.</span>
166+
- <span class="package-name">[`@stdlib/stats/incr/nanmpcorr`][@stdlib/stats/incr/nanmpcorr]</span><span class="delimiter">: </span><span class="description">compute a moving sample Pearson product-moment correlation coefficient incrementally, ignoring NaN values.</span>
167+
- <span class="package-name">[`@stdlib/stats/incr/pcorrdist`][@stdlib/stats/incr/pcorrdist]</span><span class="delimiter">: </span><span class="description">compute a sample Pearson product-moment correlation distance.</span>
168+
169+
</section>
170+
171+
<!-- /.related -->
172+
173+
<!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. -->
174+
175+
<section class="links">
176+
177+
[pearson-correlation]: https://en.wikipedia.org/wiki/Pearson_correlation_coefficient
178+
179+
<!-- <related-links> -->
180+
181+
[@stdlib/stats/incr/mpcorrdist]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/stats/incr/mpcorrdist
182+
183+
[@stdlib/stats/incr/nanmpcorr]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/stats/incr/nanmpcorr
184+
185+
[@stdlib/stats/incr/pcorrdist]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/stats/incr/pcorrdist
186+
187+
<!-- </related-links> -->
188+
189+
</section>
190+
191+
<!-- /.links -->
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2018 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var randu = require( '@stdlib/random/base/randu' );
25+
var format = require( '@stdlib/string/format' );
26+
var pkg = require( './../package.json' ).name;
27+
var incrnanmpcorrdist = require( './../lib' );
28+
29+
30+
// MAIN //
31+
32+
bench( pkg, function benchmark( b ) {
33+
var f;
34+
var i;
35+
b.tic();
36+
for ( i = 0; i < b.iterations; i++ ) {
37+
f = incrnanmpcorrdist( (i%5)+1 );
38+
if ( typeof f !== 'function' ) {
39+
b.fail( 'should return a function' );
40+
}
41+
}
42+
b.toc();
43+
if ( typeof f !== 'function' ) {
44+
b.fail( 'should return a function' );
45+
}
46+
b.pass( 'benchmark finished' );
47+
b.end();
48+
});
49+
50+
bench( format( '%s::accumulator', pkg ), function benchmark( b ) {
51+
var acc;
52+
var v;
53+
var i;
54+
55+
acc = incrnanmpcorrdist( 5 );
56+
57+
b.tic();
58+
for ( i = 0; i < b.iterations; i++ ) {
59+
v = acc( randu(), randu() );
60+
if ( v !== v ) {
61+
b.fail( 'should not return NaN' );
62+
}
63+
}
64+
b.toc();
65+
if ( v !== v ) {
66+
b.fail( 'should not return NaN' );
67+
}
68+
b.pass( 'benchmark finished' );
69+
b.end();
70+
});
71+
72+
bench( format( '%s::accumulator,known_means', pkg ), function benchmark( b ) {
73+
var acc;
74+
var v;
75+
var i;
76+
77+
acc = incrnanmpcorrdist( 5, 3.0, -1.0 );
78+
79+
b.tic();
80+
for ( i = 0; i < b.iterations; i++ ) {
81+
v = acc( randu(), randu() );
82+
if ( v !== v ) {
83+
b.fail( 'should not return NaN' );
84+
}
85+
}
86+
b.toc();
87+
if ( v !== v ) {
88+
b.fail( 'should not return NaN' );
89+
}
90+
b.pass( 'benchmark finished' );
91+
b.end();
92+
});
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2019 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
// TypeScript Version: 4.1
20+
21+
/// <reference types="@stdlib/types"/>
22+
23+
/**
24+
* If provided input values, the accumulator function returns an updated moving sample correlation distance. If not provided input values, the accumulator function returns the current moving sample correlation distance.
25+
*
26+
* ## Notes
27+
*
28+
* - The correlation distance is defined as one minus the Pearson product-moment correlation coefficient and, thus, resides on the interval [0,2].
29+
* - `NaN` values are ignored.
30+
*
31+
* @param x - value
32+
* @param y - value
33+
* @returns updated moving sample correlation distance
34+
*/
35+
type accumulator = ( x?: number, y?: number ) => number | null;
36+
37+
/**
38+
* Returns an accumulator function which incrementally computes a moving sample Pearson product-moment correlation distance, ignoring `NaN` values.
39+
*
40+
* ## Notes
41+
*
42+
* - The `W` parameter defines the number of values over which to compute the moving sample correlation distance.
43+
* - As `W` (x,y) pairs are needed to fill the window buffer, the first `W-1` returned values are calculated from smaller sample sizes. Until the window is full, each returned value is calculated from all provided non-NaN values.
44+
*
45+
* @param W - window size
46+
* @param meanx - mean value
47+
* @param meany - mean value
48+
* @throws first argument must be a positive integer
49+
* @returns accumulator function
50+
*
51+
* @example
52+
* var accumulator = incrnanmpcorrdist( 3, -2.0, 10.0 );
53+
*/
54+
declare function incrnanmpcorrdist( W: number, meanx: number, meany: number ): accumulator;
55+
56+
/**
57+
* Returns an accumulator function which incrementally computes a moving sample Pearson product-moment correlation distance, ignoring `NaN` values.
58+
*
59+
* ## Notes
60+
*
61+
* - The `W` parameter defines the number of values over which to compute the moving sample correlation distance.
62+
* - As `W` (x,y) pairs are needed to fill the window buffer, the first `W-1` returned values are calculated from smaller sample sizes. Until the window is full, each returned value is calculated from all provided non-NaN values.
63+
*
64+
* @param W - window size
65+
* @throws first argument must be a positive integer
66+
* @returns accumulator function
67+
*
68+
* @example
69+
* var accumulator = incrnanmpcorrdist( 3 );
70+
*
71+
* var d = accumulator();
72+
* // returns null
73+
*
74+
* d = accumulator( 2.0, 1.0 );
75+
* // returns 1.0
76+
*
77+
* d = accumulator( NaN, 3.14 );
78+
* // returns 1.0
79+
*
80+
* d = accumulator( -5.0, 3.14 );
81+
* // returns ~2.0
82+
*
83+
* d = accumulator( 3.0, NaN );
84+
* // returns ~2.0
85+
*
86+
* d = accumulator( 3.0, -1.0 );
87+
* // returns ~1.925
88+
*
89+
* d = accumulator( 5.0, -9.5 );
90+
* // returns ~1.863
91+
*
92+
* d = accumulator();
93+
* // returns ~1.863
94+
*/
95+
declare function incrnanmpcorrdist( W: number ): accumulator;
96+
97+
98+
// EXPORTS //
99+
100+
export = incrnanmpcorrdist;

0 commit comments

Comments
 (0)