Skip to content

Commit 6ab5958

Browse files
committed
Initial commit
0 parents commit 6ab5958

File tree

8 files changed

+368
-0
lines changed

8 files changed

+368
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

LICENSE

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
The MIT License (MIT)
3+
4+
Copyright (c) 2014 Erik Rigtorp <erik@rigtorp.se>
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in
14+
all copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
THE SOFTWARE.

README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
statkit
2+
=======
3+
4+
A statistics toolkit for javascript.
5+
6+
Usage
7+
=====
8+
9+
Install using [npm](https://npmjs.org):
10+
```
11+
npm install statkit
12+
```
13+
14+
Calculate a confidence interval for a correlation using the bootstrap method:
15+
16+
```javascript
17+
var sk = require("statkit");
18+
19+
var lsat = [576, 635, 558, 578, 666, 580, 555,
20+
661, 651, 605, 653, 575, 545, 572, 594];
21+
var gpa = [3.39, 3.30, 2.81, 3.03, 3.44, 3.07, 3.00,
22+
3.43, 3.36, 3.13, 3.12, 2.74, 2.76, 2.88, 2.96];
23+
24+
var corr = sk.corr(gpa, lsat);
25+
var ci = sk.bootci(100000, sk.corr, gpa, lsat);
26+
27+
console.log("corr = ", corr, "ci = ", ci);
28+
```
29+
30+
Functions
31+
=========
32+
33+
* min(a) - Minimum
34+
* max(a) - Maximum
35+
* mean(a) - Mean
36+
* gmean(a) - Geometric mean
37+
* hmean(a) - Harmonic mean
38+
* var(a) - Variance
39+
* std(a) - Standard deviation
40+
* skew(a) - Skewness
41+
* kurt(a) - Kurtosis
42+
* corr(x, y) - Correlation between x and y
43+
* sample(a) - Sample with replacement
44+
* boot(nboot, bootfun, data...) - Bootstrap the bootfun statistic
45+
* bootci(nboot, bootfun, data...) - Calculate bootstrap confidence intervals using the normal model
46+
47+
Credits
48+
=======
49+
(c) 2014 Erik Rigtorp <erik@rigtorp.se>. MIT License

package.json

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "statkit",
3+
"version": "0.1.0",
4+
"description": "Statistics toolkit",
5+
"main": "statkit.js",
6+
"directories": {
7+
"test": "test"
8+
},
9+
"devDependencies": {
10+
"tape": "~2.13.3"
11+
},
12+
"scripts": {
13+
"test": "tape test/*.js"
14+
},
15+
"repository": {
16+
"type": "git",
17+
"url": "git://github.com/rigtorp/statkit.git"
18+
},
19+
"homepage": "https://github.com/rigtorp/statkit",
20+
"keywords": [
21+
"statistics",
22+
"resampling",
23+
"bootstrap",
24+
"analytics"
25+
],
26+
"author": {
27+
"name": "Erik Rigtorp",
28+
"email": "erik@rigtorp.se",
29+
"url": "http://rigtorp.se"
30+
},
31+
"license": "MIT",
32+
"readmeFilename": "README.md"
33+
}

statkit.js

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
"use strict"
2+
3+
exports.min = function(a) {
4+
var n = a.length;
5+
var s = a[0];
6+
for (var i = 1; i < n; ++i) {
7+
if (a[i] < s) {
8+
s = a[i];
9+
}
10+
}
11+
return s;
12+
};
13+
14+
exports.max = function(a) {
15+
var n = a.length;
16+
var s = a[0];
17+
for (var i = 1; i < n; ++i) {
18+
if (a[i] > s) {
19+
s = a[i];
20+
}
21+
}
22+
return s;
23+
};
24+
25+
exports.mean = function(a) {
26+
var n = a.length;
27+
var s = 0.0;
28+
for (var i = 0; i < n; ++i) {
29+
s += a[i];
30+
}
31+
return s / n;
32+
};
33+
34+
exports.gmean = function(a) {
35+
var n = a.length;
36+
var s = 0.0;
37+
for (var i = 0; i < n; ++i) {
38+
s += Math.log(a[i]);
39+
}
40+
return Math.exp(s / n);
41+
};
42+
43+
exports.hmean = function(a) {
44+
var n = a.length;
45+
var s = 0.0;
46+
for (var i = 0; i < n; ++i) {
47+
s += 1.0 / a[i];
48+
}
49+
return n / s;
50+
};
51+
52+
exports.var = function(a, m) {
53+
var n = a.length;
54+
var s = 0.0;
55+
if (m === void 0) {
56+
m = exports.mean(a);
57+
}
58+
for (var i = 0; i < n; ++i) {
59+
var z = a[i] - m;
60+
s += z * z;
61+
}
62+
return s / n;
63+
};
64+
65+
exports.std = function(a, m) {
66+
return Math.sqrt(exports.var(a, m));
67+
};
68+
69+
exports.skew = function(a, m) {
70+
var n = a.length;
71+
var cm2 = 0.0;
72+
var cm3 = 0.0;
73+
if (m === void 0) {
74+
m = exports.mean(a);
75+
}
76+
for (var i = 0; i < n; ++i) {
77+
var z = a[i] - m;
78+
var z2 = z * z;
79+
cm2 += z2;
80+
cm3 += z2 * z;
81+
}
82+
cm2 /= n;
83+
cm3 /= n;
84+
return cm3 / Math.sqrt(cm2 * cm2 * cm2);
85+
};
86+
87+
exports.kurt = function(a, m) {
88+
var n = a.length;
89+
var cm2 = 0.0;
90+
var cm4 = 0.0;
91+
if (m === void 0) {
92+
m = exports.mean(a);
93+
}
94+
for (var i = 0; i < n; ++i) {
95+
var z = a[i] - m;
96+
var z2 = z * z;
97+
cm2 += z2;
98+
cm4 += z2 * z2;
99+
}
100+
cm2 /= n;
101+
cm4 /= n;
102+
return (cm4 / (cm2 * cm2)) - 3;
103+
};
104+
105+
exports.corr = function(x, y) {
106+
var n = x.length;
107+
var xm = exports.mean(x);
108+
var ym = exports.mean(y);
109+
var sxy = 0.0;
110+
var sx2 = 0.0;
111+
var sy2 = 0.0;
112+
for (var i = 0; i < n; ++i) {
113+
var xz = x[i] - xm;
114+
var yz = y[i] - ym;
115+
sxy += xz * yz;
116+
sx2 += xz * xz;
117+
sy2 += yz * yz;
118+
}
119+
return sxy / Math.sqrt(sx2 * sy2);
120+
};
121+
122+
exports.sample = function(a) {
123+
var n = a.length;
124+
var s = a.slice(0);
125+
for (var i = 0; i < n; ++i) {
126+
s[i] = a[Math.floor(n * Math.random())];
127+
}
128+
return s;
129+
}
130+
131+
exports.boot = function(nboot, bootfun) {
132+
var data = [];
133+
for (var i = 2; i < arguments.length; ++i) {
134+
data[i - 2] = arguments[i];
135+
}
136+
var sample = [];
137+
for (var i = 0; i < data.length; ++i) {
138+
sample[i] = data[i].slice(0);
139+
}
140+
var n = data[0].length;
141+
var res = Array(nboot);
142+
for (var i = 0; i < nboot; ++i) {
143+
for (var j = 0; j < n; ++j) {
144+
var idx = Math.floor(n * Math.random());
145+
for (var k = 0; k < sample.length; ++k) {
146+
sample[k][j] = data[k][idx];
147+
}
148+
}
149+
res[i] = bootfun.apply(null, sample);
150+
}
151+
return res;
152+
};
153+
154+
exports.bootci = function(nboot, bootfun) {
155+
var data = [];
156+
for (var i = 2; i < arguments.length; ++i) {
157+
data[i - 2] = arguments[i];
158+
}
159+
var v = bootfun.apply(null, data);
160+
var bootstat = exports.boot.apply(null, [nboot, bootfun].concat(data));
161+
var s = exports.std(bootstat);
162+
return [v - 2*s, v + 2*s];
163+
};
164+
165+
// http://picomath.org/javascript/erf.js.html
166+
exports.erf = function(x) {
167+
// constants
168+
var a1 = 0.254829592;
169+
var a2 = -0.284496736;
170+
var a3 = 1.421413741;
171+
var a4 = -1.453152027;
172+
var a5 = 1.061405429;
173+
var p = 0.3275911;
174+
175+
// Save the sign of x
176+
var sign = 1;
177+
if (x < 0) {
178+
sign = -1;
179+
}
180+
x = Math.abs(x);
181+
182+
// A&S formula 7.1.26
183+
var t = 1.0/(1.0 + p*x);
184+
var y = 1.0 - (((((a5*t + a4)*t) + a3)*t + a2)*t + a1)*t*Math.exp(-x*x);
185+
186+
return sign*y;
187+
};
188+
189+
190+
exports.normcdf = function(x) {
191+
return 0.5 * (1.0 + exports.erf(x / Math.sqrt(2)));
192+
}

test/bootstrap.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var st = require("../statkit.js")
2+
, tape = require("tape")
3+
4+
tape("bootstrap", function(t) {
5+
6+
var lsat = [576, 635, 558, 578, 666, 580, 555, 661, 651, 605, 653, 575, 545, 572, 594];
7+
var gpa = [3.39, 3.30, 2.81, 3.03, 3.44, 3.07, 3.00, 3.43, 3.36, 3.13, 3.12, 2.74, 2.76, 2.88, 2.96];
8+
9+
t.ok(Math.abs(st.corr(gpa, lsat) - 0.776) < 1e-3, "corr");
10+
11+
var ci = st.bootci(100000, st.corr, gpa, lsat);
12+
t.ok(Math.abs(ci[0] - 0.509) < 1e-2, "lci");
13+
t.ok(Math.abs(ci[1] - 1.043) < 1e-2, "uci");
14+
15+
t.end();
16+
})

test/test.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
var st = require("../statkit.js")
2+
, tape = require("tape")
3+
4+
tape("stats", function(t) {
5+
6+
var a = [0.7004371218578347, 0.8441866428504345, 0.6765143359376254,
7+
0.7278580572480748, 0.9514579574463393, 0.012703197034767633,
8+
0.41358769878652346, 0.04881279380000003, 0.09992856132121142,
9+
0.5080663057670065];
10+
11+
var tol = 1e-16;
12+
13+
function near(a, b, msg) {
14+
t.ok(Math.abs(a - b) < tol, msg)
15+
}
16+
17+
t.equal(st.min(a), 0.01270319703476763262, "min")
18+
t.equal(st.max(a), 0.95145795744633931967, "max")
19+
near(st.mean(a), 0.49835526720498179998, "mean")
20+
near(st.gmean(a), 0.28557127946531724039, "gmean")
21+
near(st.hmean(a), 0.08325329480982600339, "hmean")
22+
near(st.var(a), 0.10541207022165724472, "var")
23+
near(st.std(a), 0.32467225046446029912, "std")
24+
near(st.kurt(a), -1.34748749550481905501, "kurt")
25+
near(st.skew(a), -0.31810224917209384277, "skew")
26+
27+
t.end()
28+
})

test/test.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
import scipy.stats as st
3+
4+
np.set_printoptions(precision=20)
5+
6+
np.random.seed(666)
7+
a = np.random.rand(10)
8+
9+
print a.tolist()
10+
11+
print "min", np.array([np.min(a)])
12+
print "max", np.array([np.max(a)])
13+
print "mean", np.array([np.mean(a)])
14+
print "gmean", np.array([st.gmean(a)])
15+
print "hmean", np.array([st.hmean(a)])
16+
print "var", np.array([np.var(a)])
17+
print "std", np.array([np.std(a)])
18+
print "kurtosis", np.array([st.kurtosis(a)])
19+
print "skew", np.array([st.skew(a)])
20+
21+
22+
p = [0.0000001, 0.00001, 0.001, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65,
23+
0.75, 0.85, 0.95, 0.999, 0.99999, 0.9999999]
24+
25+
x = st.norm.ppf(p)
26+
27+
print x

0 commit comments

Comments
 (0)