UNPKG

23.5 kBJavaScriptView Raw
1var _ = require("lodash");
2var J = require("jStat").jStat;
3var M = require("numeric");
4R = _;
5R.M = M;
6R.J = J;
7
8function _def(pair) {
9 _.mixin(pair, {chain:false});
10}
11
12function _mix(pair) {
13 _.mixin(pair, {chain:true});
14}
15
16var calls=function() {
17 var args = Array.prototype.slice.call(arguments);
18 var n = args[0];
19 var f = args[1];
20 var params = args.slice(2, args.length);
21 var a=[];
22 for (var i=0; i<n; i++)
23 a.push(f.apply(null, params));
24 return _.map(a);
25}
26
27_mix({calls:calls});
28
29var fx = function() {
30 var args = Array.prototype.slice.call(arguments);
31 var f = args[0];
32 var fargs = args.slice(1, arguments.length);
33 return function(x) {
34 return f.apply(null, [x].concat(fargs));
35 };
36}
37
38_mix({fx:fx});
39
40var samples=function(space, size, arg) {
41 var arg = _.defaults(arg, {replace:true});
42 if (arg.replace)
43 return R.calls(size, function() { return _.sample(space); });
44 else
45 return _.sampleSize(space, size);
46}
47
48_mix({samples:samples});
49
50var steps=function(start, end, step) {
51 step = step || 1;
52 return _.range(start, end+0.00001*step, step);
53}
54
55_mix({steps:steps});
56
57// ============== format ==================
58R.setPrecision=function(n) {
59 R.precision = n;
60 R.M.precision = n;
61}
62
63R.setPrecision(2);
64
65// R.largeArray = 50;
66
67R.num2str=function(x) {
68 if (isNaN(x))
69 return "NaN";
70 else if (Math.floor(x) === x) // 整數
71 return x.toString();
72 else if (isFinite(x)) { // 有小數點
73// return x.toFixed(R.precision);
74 return _.round(x, R.precision).toString();
75 } else if (x < 0)
76 return "-Infinity";
77 else
78 return "Infinity";
79}
80
81R.ctrim=function(s, set, side) {
82 side = side||"both";
83 for (var b=0; b<s.length; b++)
84 if (set.indexOf(s[b])<0) break;
85 for (var e=s.length-1; e>=0; e--)
86 if (set.indexOf(s[e])<0) break;
87 if (side === "right") b=0;
88 if (side === "left") e=s.length-1;
89 return s.substring(b, e+1);
90}
91
92R.array2str=function(x) {
93 var s = "";
94 for (var i in x)
95 s+= R.str(x[i])+", ";
96 return "["+R.ctrim(s, ", ")+"]";
97}
98
99R.obj2str=function(x, sp) {
100 var s = "";
101 for (var k in x)
102 s+= k+":"+R.str(x[k])+sp;
103 return "{"+R.ctrim(s,sp)+"}";
104}
105
106var str = function(x) {
107 if (typeof x === 'undefined') return 'undefined';
108 else if (x === null) return 'null';
109 else if (typeof x === "number") return R.num2str(x);
110 else if(typeof x === "string") return '\"'+x.toString()+'\"';
111 else if (x instanceof Array) return R.array2str(x);
112// else if (typeof x === "object") return R.obj2str(x, ",");
113 else if (typeof x === "object") return x.toString();
114 else if (typeof x === "function") return "";
115 else return x.toString();
116}
117
118// Number.prototype.str = function() { return R.num2str(this); }
119Array.prototype.str = function() { return R.array2str(this); }
120// Array.prototype.str = function() { return M.str(this); }
121
122var _str = function(x) { return str(x); }
123
124_def({str:_str});
125
126// ============== /format ==================
127
128// 標準差
129_def({sd:function(a, flag) { return J.stdev(a, flag || 1); }});
130// 協方差
131_def({cov:function(x, y) { return J.stdev(x, y); }});
132// 相關係數
133_def({cor:function(x, y) { return J.corrcoeff(x, y); }});
134// 階層 n!
135_def({factorial : function(n) { return J.factorial(n); }});
136// log(n!)
137_def({lfactorial : function(n) { return J.factorialln(n); }});
138// 組合 C(n,m)
139_def({choose : function(n,m) { return J.combination(n, m); }});
140// log C(n,m)
141_def({lchoose : function(n,m) { return J.combinationln(n, m); }});
142// 組合 C(n,m)
143_def({permutation : function(n,m) { return J.permutation(n, m); }});
144// log C(n,m)
145_def({lchoose : function(n,m) { return J.combinationln(n, m); }});
146
147// 均等分布
148_mix({runif:function(n, a, b) { return R.calls(n, J.uniform.sample, a, b); }});
149_def({dunif:function(x, a, b) { return J.uniform.pdf(x, a, b); }});
150_def({punif:function(q, a, b) { return J.uniform.cdf(q, a, b); }});
151_def({qunif:function(p, a, b) { return J.uniform.inv(p, a, b); }});
152// 常態分布
153_mix({rnorm:function(n, mean, sd) { return R.calls(n, J.normal.sample, mean, sd); }});
154_def({dnorm:function(x, mean, sd) { return J.normal.pdf(x, mean, sd); }});
155_def({pnorm:function(q, mean, sd) { return J.normal.cdf(q, mean, sd); }});
156_def({qnorm:function(p, mean, sd) { return J.normal.inv(p, mean, sd); }});
157// 布瓦松分布
158_mix({rpois:function(n, l) { return R.calls(n, J.poisson.sample, l); }});
159_def({dpois:function(x, l) { return J.poisson.pdf(x, l); }});
160_def({ppois:function(q, l) { return J.poisson.cdf(q, l); }});
161_def({qpois:function(p, l) { return J.poisson.inv(p, l); }});
162// F 分布
163_mix({rf:function(n, df1, df2) { return R.calls(n, J.centralF.sample, df1, df2); }});
164_def({df:function(x, df1, df2) { return J.centralF.pdf(x, df1, df2); }});
165_def({pf:function(q, df1, df2) { return J.centralF.cdf(q, df1, df2); }});
166_def({qf:function(p, df1, df2) { return J.centralF.inv(p, df1, df2); }});
167// T 分布
168_mix({rt:function(n, dof) { return R.calls(n, J.studentt.sample, dof); }});
169_def({dt:function(x, dof) { return J.studentt.pdf(x, dof); }});
170_def({pt:function(q, dof) { return J.studentt.cdf(q, dof); }});
171_def({qt:function(p, dof) { return J.studentt.inv(p, dof); }});
172// Beta 分布
173_mix({rbeta:function(n, alpha, beta) { return R.calls(n, J.beta.sample, alpha, beta); }});
174_def({dbeta:function(x, alpha, beta) { return J.beta.pdf(x, alpha, beta); }});
175_def({pbeta:function(q, alpha, beta) { return J.beta.cdf(q, alpha, beta); }});
176_def({qbeta:function(p, alpha, beta) { return J.beta.inv(p, alpha, beta); }});
177// 柯西分布
178_mix({rcauchy:function(n, local, scale) { return R.calls(n, J.cauchy.sample, local, scale); }});
179_def({dcauchy:function(x, local, scale) { return J.cauchy.pdf(x, local, scale); }});
180_def({pcauchy:function(q, local, scale) { return J.cauchy.cdf(q, local, scale); }});
181_def({qcauchy:function(p, local, scale) { return J.cauchy.inv(p, local, scale); }});
182// chisquare 分布
183_mix({rchisq:function(n, dof) { return R.calls(n, J.chisquare.sample, dof); }});
184_def({dchisq:function(x, dof) { return J.chisquare.pdf(x, dof); }});
185_def({pchisq:function(q, dof) { return J.chisquare.cdf(q, dof); }});
186_def({qchisq:function(p, dof) { return J.chisquare.inv(p, dof); }});
187// 指數分布
188_mix({rexp:function(n, rate) { return R.calls(n, J.exponential.sample, rate); }});
189_def({dexp:function(x, rate) { return J.exponential.pdf(x, rate); }});
190_def({pexp:function(q, rate) { return J.exponential.cdf(q, rate); }});
191_def({qexp:function(p, rate) { return J.exponential.inv(p, rate); }});
192// Gamma 分布
193_mix({rgamma:function(n, shape, scale) { return R.calls(n, J.gamma.sample, shape, scale); }});
194_def({dgamma:function(x, shape, scale) { return J.gamma.pdf(x, shape, scale); }});
195_def({pgamma:function(q, shape, scale) { return J.gamma.cdf(q, shape, scale); }});
196_def({qgamma:function(p, shape, scale) { return J.gamma.inv(p, shape, scale); }});
197// 反 Gamma 分布
198_mix({rinvgamma:function(n, shape, scale) { return R.calls(n, J.invgamma.sample, shape, scale); }});
199_def({dinvgamma:function(x, shape, scale) { return J.invgamma.pdf(x, shape, scale); }});
200_def({pinvgamma:function(q, shape, scale) { return J.invgamma.cdf(q, shape, scale); }});
201_def({qinvgamma:function(p, shape, scale) { return J.invgamma.inv(p, shape, scale); }});
202// 對數常態分布
203_mix({rlognormal:function(n, mu, sigma) { return R.calls(n, J.lognormal.sample, mu, sigma); }});
204_def({dlognormal:function(x, mu, sigma) { return J.lognormal.pdf(x, mu, sigma); }});
205_def({plognormal:function(q, mu, sigma) { return J.lognormal.cdf(q, mu, sigma); }});
206_def({qlognormal:function(p, mu, sigma) { return J.lognormal.inv(p, mu, sigma); }});
207// Pareto 分布
208_mix({rpareto:function(n, scale, shape) { return R.calls(n, J.pareto.sample, scale, shape); }});
209_def({dpareto:function(x, scale, shape) { return J.pareto.pdf(x, scale, shape); }});
210_def({ppareto:function(q, scale, shape) { return J.pareto.cdf(q, scale, shape); }});
211_def({qpareto:function(p, scale, shape) { return J.pareto.inv(p, scale, shape); }});
212// Weibull 分布
213_mix({rweibull:function(n, scale, shape) { return R.calls(n, J.weibull.sample, scale, shape); }});
214_def({dweibull:function(x, scale, shape) { return J.weibull.pdf(x, scale, shape); }});
215_def({pweibull:function(q, scale, shape) { return J.weibull.cdf(q, scale, shape); }});
216_def({qweibull:function(p, scale, shape) { return J.weibull.inv(p, scale, shape); }});
217// 三角分布
218_mix({rtriangular:function(n, a, b, c) { return R.calls(n, J.triangular.sample, a, b, c); }});
219_def({dtriangular:function(x, a, b, c) { return J.triangular.pdf(x, a, b, c); }});
220_def({ptriangular:function(q, a, b, c) { return J.triangular.cdf(q, a, b, c); }});
221_def({qtriangular:function(p, a, b, c) { return J.triangular.inv(p, a, b, c); }});
222// 類似 Beta 分布,但計算更簡單
223_mix({rkumaraswamy:function(n, alpha, beta) { return R.calls(n, J.kumaraswamy.sample, alpha, beta); }});
224_def({dkumaraswamy:function(x, alpha, beta) { return J.kumaraswamy.pdf(x, alpha, beta); }});
225_def({pkumaraswamy:function(q, alpha, beta) { return J.kumaraswamy.cdf(q, alpha, beta); }});
226_def({qkumaraswamy:function(p, alpha, beta) { return J.kumaraswamy.inv(p, alpha, beta); }});
227
228// ============= 離散分佈 ============
229var qf=function(cdf, q, N, p) {
230 for (var i=0; i<=N; i++) {
231 if (cdf(i, N, p) > q) return i;
232 }
233 return N;
234}
235var rf=function(cdf, n, N, p) {
236 var a = [];
237 for (var i=0; i<n; i++) {
238 var q = Math.random();
239 a.push(cdf(q, N, p));
240 }
241 return a;
242}
243// 二項分布
244_def({dbinom:function(x, N, p) { return J.binomial.pdf(x, N, p); }});
245_def({pbinom:function(k, N, p) { return J.binomial.cdf(k, N, p); }});
246_def({qbinom:function(q, N, p) { return qf(R.pbinom, q, N, p); }});
247_mix({rbinom:function(n, N, p) { return rf(R.qbinom, n, N, p); }});
248// 負二項分布
249_def({dnbinom:function(x, N, p) { return jStat.negbin.pdf(x, N, p); }});
250_def({pnbinom:function(k, N, p) { return jStat.negbin.cdf(k, N, p); }});
251_def({qnbinom:function(q, N, p) { return qf(R.pnbinom, q, N, p); } });
252_mix({rnbinom:function(n, N, p) { return rf(R.qnbinom, n, N, p); }});
253// 超幾何分布
254_def({dhyper:function(x, N, m, n) { return jStat.hypgeom.pdf(x, N, m, n); }});
255_def({phyper:function(k, N, m, n) { return jStat.hypgeom.cdf(k, N, m, n); }});
256_def({qhyper:function(q, N, m, n) { return qf(R.phyper, q, N, p); } });
257_mix({rhyper:function(n, N, m, k) { return rf(R.qhyper, n, N, p); }});
258
259// =============== 檢定 ==============================
260
261// ---------------- 統計與檢定 ----------------------
262function opAlt(op) {
263 if (op === "=") return "!=";
264 if (op === "<") return ">=";
265 if (op === ">") return "<=";
266 return null;
267}
268
269R.test = function(o) { // name, D, x, mu, sd, y, alpha, op
270 o = R.defaults(o, {alpha:0.05, op:"="});
271 var alpha = o.alpha;
272 var pvalue, interval;
273 var D = o.D;
274 var q1 = D.o2q(o); // 單尾檢定的 pvalue
275
276 if (o.op === "=") {
277 if (q1>0.5) q1 = 1-q1; // (q1>0.5) 取右尾,否則取左尾。
278 pvalue= 2*q1; // 對稱情況:雙尾檢定的 p 值是單尾的兩倍。
279 interval = [D.q2p(alpha/2, o, "L"), D.q2p(1-alpha/2, o, "R")];
280 } else {
281 if (o.op === "<") { // 右尾檢定 H0: q < 1-alpha,
282 interval = [ D.q2p(alpha, o, "L"), Infinity ];
283 pvalue = 1-q1;
284 }
285 if (o.op === ">") { // 左尾檢定 H0: q > alpha
286 interval=[-Infinity, D.q2p(1-alpha, o, "R")];
287 pvalue = q1;
288 }
289 }
290 return {
291 name: o.name,
292 h: D.h(o),
293 alpha: alpha,
294 op: o.op,
295 pvalue: pvalue,
296 ci : interval,
297 df : D.df(o),
298 report: function() { R.report(this) }
299 };
300}
301
302var t1 = { // 單樣本 T 檢定 t = (X-mu)/(S/sqrt(n))
303 h:function(o) { return "H0:mu"+o.op+o.mu; },
304 o2q:function(o) {
305 var x = o.x, n = x.length;
306 var t = (R.mean(x)-o.mu)/(R.sd(x)/Math.sqrt(n));
307 return R.pt(t, n-1);
308 },
309 // P(X-mu/(S/sqrt(n))<t) = q ; 信賴區間 P(T<q)
310 // P(mu > X-t*S/sqrt(n)) = q ; 這反而成了右尾檢定,所以左尾與右尾確實會反過來
311 q2p:function(q, o) {
312 var x = o.x, n = x.length;
313 return R.mean(x) + R.qt(q, n-1) * R.sd(x) / Math.sqrt(n);
314 },
315 df:function(o) { return o.x.length-1; }
316}
317
318var t2vareq = { // σ1=σ2, 合併 T 檢定 (雙樣本)
319 h:function(o) { return "H0:mu1"+o.op+"mu2" },
320 // S^2 = (n1-1)*S1^2+(n2-1)*S2^2)/(n1-1+n2-1)
321 sd:function(o) {
322 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
323 var S1= R.sd(x), S2 = R.sd(y);
324 var S = Math.sqrt(((n1-1)*S1*S1+(n2-1)*S2*S2)/(n1-1+n2-1));
325 return S;
326 },
327 // T = ((X-Y)-(mu1-mu2))/(sqrt(1/n1+1/n2)*S)
328 o2q:function(o) {
329 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
330 var S = this.sd(o);
331 var t = (R.mean(x)-R.mean(y)-o.mu)/(Math.sqrt(1/n1+1/n2)*S);
332 return R.pt(t, n1+n2-2);
333 },
334 // t=((X-Y)-mu)/(sqrt(1/n1+1/n2)*S), (X-Y)-t*sqrt(1/n1+1/n2)*S = mu
335 q2p:function(q, o) {
336 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
337 var S = this.sd(o);
338 return R.mean(x)-R.mean(y)+ R.qt(q, n1+n2-2)*Math.sqrt(1/n1+1/n2)*S;
339 },
340 df:function(o) {
341 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
342 return n1+n2-2;
343 }
344}
345
346var t2paired = { // 成對 T 檢定 T = (X-Y-mu)/(S/sqrt(n)) (雙樣本)
347 h:function(o) { return "H0:mu1"+o.op+"mu2" },
348 sd:function(o) { // S = sd(x-y)
349 var x = o.x, n = x.length, y=o.y;
350 var S= R.sd(R.sub(x,y));
351 return S;
352 },
353 o2q:function(o) {
354 var x = o.x, n = x.length, y=o.y;
355 var S = this.sd(o);
356 var t = (R.mean(R.sub(x,y))-o.mu)/(S/Math.sqrt(n));
357 return R.pt(t, n-1);
358 },
359 // mean(x-y)+t*S/sqrt(n)
360 q2p:function(q, o) {
361 var x = o.x, n = x.length, y=o.y;
362 var S = this.sd(o);
363 return R.mean(R.sub(x,y))+ R.qt(q, n-1)*S/Math.sqrt(n);
364 },
365 df:function(o) {
366 return o.x.length-1;
367 }
368}
369
370var t2varneq = { // σ1≠σ2, Welch's t test (雙樣本) (又稱 Smith-Satterwaite 程序)
371// 參考:http://en.wikipedia.org/wiki/Welch's_t_test
372 h:function(o) { return "H0:mu1"+o.op+"mu2" },
373 // T = ((X-Y)-(mu1-mu2))/sqrt(S1^2/n1+S2^2/n2)
374 o2q:function(o) {
375 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
376 var S1 = R.sd(x), S2=R.sd(y);
377 var t = (R.mean(x)-R.mean(y)-o.mu)/Math.sqrt(S1*S1/n1+S2*S2/n2);
378 return R.pt(t, this.df(o));
379 },
380 // t=((X-Y)-mu)/sqrt(S1^2/n1+S2^2/n2), (X-Y)-t*sqrt(S1^2/n1+S2^2/n2) = mu
381 q2p:function(q, o) {
382 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
383 var S1 = R.sd(x), S2=R.sd(y);
384 return R.mean(x)-R.mean(y)+ R.qt(q, this.df(o))*Math.sqrt(S1*S1/n1+S2*S2/n2);
385 },
386 df:function(o) {
387 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
388 var S1 = R.sd(x), S2=R.sd(y);
389 var Sn1 = S1*S1/n1, Sn2 = S2*S2/n2, Sn12 = Sn1+Sn2;
390 var df = (Sn12*Sn12)/((Sn1*Sn1)/(n1-1)+(Sn2*Sn2)/(n2-1));
391 return df;
392 }
393}
394
395R.ttest = function(o) {
396 var t;
397 if (typeof o.y === "undefined") {
398 o.name = "ttest(X)";
399 o.D = t1;
400 t = R.test(o);
401 t.mean = R.mean(o.x);
402 t.sd = R.sd(o.x);
403 } else {
404 var varequal = R.opt(o, "varequal", false);
405 var paired = R.opt(o, "paired", false);
406 if (varequal) {
407 o.name = "ttest(X,Y,mu="+o.mu+",varequal=true) (pooled)";
408 o.D = t2vareq;
409 t = R.test(o);
410 } else if (paired) {
411 o.name = "ttest(x,y,mu="+o.mu+",paired=true)";
412 o.D = t2paired;
413 t = R.test(o);
414 t.mean = "mean(x-y)="+R.str(R.mean(R.sub(o.x, o.y)));
415 t.sd = "sd(x-y)="+R.str(R.sd(R.sub(o.x, o.y)));
416 } else {
417 o.name = "ttest(x,y,mu="+o.mu+",varequal=false), Welch t-test";
418 o.D = t2varneq;
419 t = R.test(o);
420 }
421 if (typeof t.mean === "undefined") {
422 t.mean = "mean(x)="+R.str(R.mean(o.x))+" mean(y)="+R.str(R.mean(o.y));
423 t.sd = "sd(x)="+R.str(R.sd(o.x))+" sd(y)="+R.str(R.sd(o.y));
424 }
425 }
426 return t;
427}
428
429var f2 = { // 檢定 σ1/σ2 = 1?
430 h:function(o) { return "H0:σ1/σ2"+o.op+"1"; },
431 // F = S1^2/S2^2
432 o2q:function(o) {
433 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
434 var S1 = R.sd(x), S2=R.sd(y);
435 var f = (S1*S1)/(S2*S2);
436 var pf = R.pf(f, n1-1, n2-1);
437 return pf;
438 },
439 // 信賴區間公式: S1^2/(S2^2*F(1-α/2), S1^2/(S2^2*F(α/2))
440 // 也就是要用 S1^2/(S2^2*f(1-q)) ,參考 R 軟體、應用統計方法 (陳景祥) 389 頁。
441 q2p:function(q, o) {
442 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
443 var S1 = R.sd(x), S2=R.sd(y);
444 var qf = R.qf(1-q, n1-1, n2-1);
445 return (S1*S1)/(S2*S2*qf);
446 },
447 df:function(o) {
448 var x = o.x, n1 = x.length, y=o.y, n2=y.length;
449 return [n1-1, n2-1];
450 }
451}
452
453R.ftest = function(o) {
454 o.name = "ftest(X, Y)";
455 o.D = f2;
456 var t = R.test(o);
457 var rsd = R.sd(o.x)/R.sd(o.y);
458 t.ratio = (rsd*rsd);
459 return t;
460}
461
462// R 軟體沒有此函數,測試請看湯銀才 143 頁
463var chisq1 = { // 檢定 σ1 = σ ?
464 h:function(o) { return "H0:σ1"+o.op+"σ"; },
465 // χ(n-1) = (n-1)S^2/σ^2
466 o2q:function(o) {
467 var x = o.x, n = x.length, S=R.sd(x);
468 var v = (n-1)*S*S/(o.sd*o.sd);
469 return R.pchisq(v, n-1);
470 },
471 // 信賴區間公式: (n-1)S^2/χ^2(1-q),參考 R 語言與統計分析 (湯銀才) 142 頁。
472 q2p:function(q, o) {
473 var x = o.x, n = x.length, S=R.sd(x);
474 return (n-1)*S*S/R.qchisq(1-q, n-1);
475 },
476 df:function(o) {
477 var x = o.x, n = x.length;
478 return n-1;
479 }
480}
481
482R.chisqtest = function(o) {
483 o.name = "chisqtest(X)";
484 o.D = chisq1;
485 return R.test(o);
486}
487
488R.vartest = function(o) {
489 if (typeof o.y === "undefined")
490 return R.chisqtest(o);
491 else
492 return R.ftest(o);
493}
494
495var z1 = { // 單樣本 Z 檢定
496 h:function(o) { return "H0:mu"+o.op+o.mu+" when sd="+o.sd; },
497 o2q:function(o) {
498 var x = o.x, n = x.length;
499 var z = (R.mean(x)-o.mu)/(o.sd/Math.sqrt(n)); // z=(X-mu)/(sd/sqrt(n))
500 return R.pnorm(z, 0, 1);
501 },
502 q2p:function(q, o) {
503 var x = o.x, n = x.length;
504 return R.mean(x) + R.qnorm(q, 0, 1) * R.sd(x) / Math.sqrt(n);
505 },
506 df:function(o) { return o.x.length; }
507}
508
509R.ztest = function(o) {
510 o.name = "ztest(X)";
511 o.D = z1;
512 return R.test(o);
513}
514
515var zprop1 = { // 比例的檢定, n 較大時的近似解 o={ x, n, p } // x 為數值,n 個中出現 x 個 1
516 h:function(o) { return "H0:p"+o.op+o.p; },
517 // Z = (p1-p)/sqrt(p(1-p)/n)
518 o2q:function(o) {
519 var x=o.x, n=o.n, p1=x/n, p=R.def(o.p, p1);
520 var z = (p1-p)/Math.sqrt(p*(1-p)/n);
521 return R.pnorm(z, 0, 1);
522 },
523 // 信賴區間公式: p1+z*sqrt(p1*(1-p1)/n),參考 R 語言與統計分析 (湯銀才) 149 頁。
524 q2p:function(q, o) {
525 var x=o.x, n=o.n, p1=x/n, p=p1;
526 var z = R.qnorm(q, 0, 1);
527 var z22n = z*z/(2*n);
528 return (p1+z22n+z*Math.sqrt( p*(1-p)/n + z22n/(2*n) ))/(1+2*z22n); // R 的版本,比較複雜的估計公式
529// return p1+z*Math.sqrt(p*(1-p)/n); // 語言與統計分析 (湯銀才) 149 頁的版本。
530 },
531 df:function(o) { return 1; }
532}
533
534var zprop2 = { // 比例的檢定, n 較大時的近似解 o={ x, y, n1, n2 }
535 h:function(o) { return "H0:p1-p2"+o.op+o.p; },
536 // Z = (p1-p2)/sqrt(p*(1-p)*(1/n1+1/n2)), p = (n1p1+n2p2)/(n1+n2),參考 R 語言與統計分析 (湯銀才) 175 頁。
537 o2q:function(o) {
538 var x=o.x, y=o.y, n1=o.n1, n2=o.n2, p1=x/n1, p2=y/n2, p=(n1*p1+n2*p2)/(n1+n2);
539 var z = (p1-p2)/Math.sqrt(p*(1-p)*(1/n1+1/n2));
540 return R.pnorm(z, 0, 1);
541 },
542 // 信賴區間公式: p1-p2+z*sqrt(p*(1-p)*(1/n1+1/n2));
543 q2p:function(q, o) {
544 var x=o.x, y=o.y, n1=o.n1, n2=o.n2, p1=x/n1, p2=y/n2, p=(n1*p1+n2*p2)/(n1+n2);
545 var z = R.qnorm(q, 0, 1);
546 return p1-p2+z*Math.sqrt(p*(1-p)*(1/n1+1/n2));
547 },
548 df:function(o) { return 1; }
549}
550
551/* 在 prop.test.R 當中,雙邊檢定的 pvalue 是用 pchisq, 單邊才是用 z ,為何呢? ( 但是信賴區間則是全部用 z)
552 if (alternative == "two.sided")
553 PVAL <- pchisq(STATISTIC, PARAMETER, lower.tail = FALSE)
554 else {
555 if (k == 1)
556 z <- sign(ESTIMATE - p) * sqrt(STATISTIC)
557 else
558 z <- sign(DELTA) * sqrt(STATISTIC)
559 PVAL <- pnorm(z, lower.tail = (alternative == "less"))
560 }
561*/
562
563R.proptest = function(o) {
564 o.p = R.opt(o, "p", 0.5);
565 o.name = "proptest("+R.str(o)+")";
566 o.correct = R.opt(o.correct, false);
567 if (o.correct) {
568 o.name += ", binomtest";
569 o.D += binom1;
570 } else {
571 if (typeof o.y === "undefined") {
572 o.name += ", zprop1";
573 o.D = zprop1;
574 } else {
575 o.p = 0; // p1-p2 = 0
576 o.name += ", zprop2";
577 o.D = zprop2;
578 }
579 }
580 var t=R.test(o);
581 if (typeof o.y === "undefined")
582 t.p = o.x/o.n;
583 else
584 t.p = [o.x/o.n1, o.y/o.n2];
585 return t;
586}
587
588// 參考: https://github.com/SurajGupta/r-source/blob/master/src/library/stats/R/binom.test.R
589var binom1 = { // 比例的檢定, n 較大時的近似解 o={ x, n, p } // x 為數值,n 個中出現 x 個 1
590 h:function(o) { return "H0:p"+o.op+o.p; },
591
592 // Z = C(n, k)*p1^k*(1-p1)^(n-k), CDF(z: from 1 to x)
593 o2q:function(o) {
594 var x=o.x, n=o.n, p = o.p, q;
595 var dx = R.dbinom(x, n, p);
596 if (o.op === "=") { // 雙尾檢定,去雙尾後 / 2
597 var q = 0;
598 for (var i=0; i<=n; i++) {
599 var di = R.dbinom(i, n, p);
600 if (di > dx+1e-5) q += di; // 為何 x 本身不算,如果算應該用 di > dx-1e-5 才對。
601 }
602 q=1-((1-q)/2); // 因為 test 會 * 2 所進行的減半調整
603 } else { // 單尾檢定
604 if (Math.abs(x - n*p)<1e-5) // 正確預測, q=1
605 q = 1;
606 else {
607 if (o.op === ">")
608 q = R.pbinom(x, n, p); // 去右尾
609 else // op=== "<"
610 q = R.pbinom(x-1, n, p); // 去右尾
611 }
612 }
613 return q;
614 },
615/* 注意上述 R 原始碼另一尾的計算方式,是用 < pbinom(最接近 x 者) 的算法,而不是直接 * 2。 問題是我們在 test 中是直接用*2 的方式。
616 d <- dbinom(x, n, p)
617 ...
618 else if (x < m) {
619 i <- seq.int(from = ceiling(m), to = n)
620 y <- sum(dbinom(i, n, p) <= d * relErr)
621 pbinom(x, n, p) 左尾 + pbinom(n - y, n, p, lower.tail = FALSE) 右尾
622 } else {
623 i <- seq.int(from = 0, to = floor(m))
624 y <- sum(dbinom(i, n, p) <= d * relErr)
625 pbinom(y - 1, n, p) 左尾 + pbinom(x - 1, n, p, lower.tail = FALSE) 右尾
626 }
627*/
628 // 信賴區間公式: P(T>c) = Σ (n, i) C(n, i) p1^i (1-p1)^(n-i) for i>c < q
629
630 q2p:function(q, o, side) {
631 var x=o.x, n=o.n, p=o.p, op=o.op;
632 if (side === "L")
633 return qbeta(q, x, n - x + 1); // 這裏採用 qbeta 是 R 的作法; 直覺上應該採用 R.qbinom(q, n, p);
634 else
635 return qbeta(q, x + 1, n - x);
636 },
637 df:function(o) { return 1; }
638}
639
640R.binomtest = function(o) {
641 o.p = R.opt(o, "p", 0.5);
642 o.name = "binomtest("+R.str(o)+")";
643 o.D = binom1;
644 var t=R.test(o);
645 t.p = o.x/o.n;
646 t.ci[0]=(o.op === ">")?0:t.ci[0];
647 t.ci[1]=(o.op === "<")?1:t.ci[1];
648 return t;
649}
650
651R.report = function(o) {
652 console.log("=========== report ==========");
653 for (var k in o) {
654 if (typeof o[k] !== "function")
655 console.log(k+"\t: "+str(o[k]));
656 }
657}
658
659// anova f-test : array1, array2, array3, ...
660R.anovaftest = function() {
661 return {
662 h0 : "σ1=σ2=...=σ"+arguments.length,
663 pvalue: J.anovaftest(),
664 score: J.anovafscore(),
665 };
666}
667
668// ========================= MATRIX ===================
669M.str = M.prettyPrint;
670
671module.exports = R;
672
673
674/*
675R.fx = function() {
676 var args = Array.prototype.slice.call(arguments);
677 var f = args[0];
678 var fargs = args.slice(1, arguments.length);
679 return function(x) {
680 return f.apply(null, [x].concat(fargs));
681 };
682}
683
684*/
685/*
686// list(from, from+step, ..., to)
687R.steps=function(from, to, step) {
688 step = step || 1;
689 var a=[];
690 for (var i=0; from+i*step<=to; i++)
691 a.push(from+i*step);
692 return a;
693}
694*/
695
696/*
697var calls=function(n,f) {
698 return _.range(n).map(f);
699}
700*/
\No newline at end of file