我需要将z分数转换为百分位数。我找到了我可以使用的function in the jStat library的引用(jstat.ztest),但是jStat文档似乎领先于可用库,因为currently available version of the library中没有这样的函数。
我认为有more recent version of the library on GitHub,可能包含ztest函数,但我是linux新手,无法弄清楚如何从指令构建库。我花了大约一天时间学习git bash和cygwin试图构建库;我终于决定在这里问好了。
那么,有没有人能指出我能做我需要的javascript函数? 或者,是否有人可以指向包含ztest功能的jStat库的内置版本?
答案 0 :(得分:16)
我在网上找到了一个论坛,它就像一个魅力。
function GetZPercent(z)
{
//z == number of standard deviations from the mean
//if z is greater than 6.5 standard deviations from the mean
//the number of significant digits will be outside of a reasonable
//range
if ( z < -6.5)
return 0.0;
if( z > 6.5)
return 1.0;
var factK = 1;
var sum = 0;
var term = 1;
var k = 0;
var loopStop = Math.exp(-23);
while(Math.abs(term) > loopStop)
{
term = .3989422804 * Math.pow(-1,k) * Math.pow(z,k) / (2 * k + 1) / Math.pow(2,k) * Math.pow(z,k+1) / factK;
sum += term;
k++;
factK *= k;
}
sum += 0.5;
return sum;
}
我不需要为一个函数包含一个大型库。
答案 1 :(得分:2)
只需编辑保罗答案中的代码进行双边t检验
function GetZPercent(z)
{
//z == number of standard deviations from the mean
//if z is greater than 6.5 standard deviations from the mean
//the number of significant digits will be outside of a reasonable
//range
if ( z < -6.5)
return 0.0;
if( z > 6.5)
return 1.0;
if (z > 0) { z = -z;}
var factK = 1;
var sum = 0;
var term = 1;
var k = 0;
var loopStop = Math.exp(-23);
while(Math.abs(term) > loopStop)
{
term = .3989422804 * Math.pow(-1,k) * Math.pow(z,k) / (2 * k + 1) / Math.pow(2,k) * Math.pow(z,k+1) / factK;
sum += term;
k++;
factK *= k;
}
sum += 0.5;
return (2*sum);
}
答案 2 :(得分:0)
这似乎是一个简单的问题,但是我很难跟踪执行此操作的库而不是复制一些随机代码段。最好的告诉我,这将使用简单统计信息库根据百分比计算z得分。
我阅读了他们关于“累积标准常态概率”的文档,并支持以下算法。感觉应该有一种更简单的方法,但谁知道呢。
https://simplestatistics.org/docs/#cumulativestdnormalprobability
const z_score = inverseErrorFunction((percentile_value - 0.5) / 0.5) * Math.sqrt(2);
答案 3 :(得分:0)
正如 Shane 已经正确说明的那样,该方程是普通 cdf 的泰勒展开式的实现。 sum
值在“真实”值的上方和下方以越来越高的精度迭代。如果该值接近 1 或 0,那么 sum
将 >1 或 <0 的可能性非常低,但存在的可能性很小,因为(相对)较早地被 loopstop
突破。
通过将 1/Math.sqrt(2*Math.Pi)
舍入为 0.3989422804
以及 javascript 浮点数的精度问题,进一步加强了偏差。此外,提供的解决方案不适用于 z-scores >7 或 <-7
我使用 decimal.js npm 库更新了代码以使其更准确并直接返回 p 值:
function GetpValueFromZ(_z, type = "twosided")
{
if(_z < -14)
{
_z = -14
}
else if(_z > 14)
{
_z = 14
}
Decimal.set({precision: 100});
let z = new Decimal(_z);
var sum = new Decimal(0);
var term = new Decimal(1);
var k = new Decimal(0);
var loopstop = new Decimal("10E-50");
var minusone = new Decimal(-1);
var two = new Decimal(2);
let pi = new Decimal("3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647")
while(term.abs().greaterThan(loopstop))
{
term = new Decimal(1)
for (let i = 1; i <= k; i++) {
term = term.times(z).times(z.dividedBy(two.times(i)))
}
term = term.times(minusone.toPower(k)).dividedBy(k.times(2).plus(1))
sum = sum.plus(term);
k = k.plus(1);
}
sum = sum.times(z).dividedBy(two.times(pi).sqrt()).plus(0.5);
if(sum.lessThan(0))
sum = sum.abs();
else if(sum.greaterThan(1))
sum = two.minus(sum);
switch (type) {
case "left":
return parseFloat(sum.toExponential(40));
case "right":
return parseFloat((new Decimal(1).minus(sum)).toExponential(40));
case "twosided":
return sum.lessThan(0.5)? parseFloat(sum.times(two).toExponential(40)) : parseFloat((new Decimal(1).minus(sum).times(two)).toExponential(40))
}
}
通过增加 Decimal.js precision
值并减少 loopstop
值,您可以获得准确的 p 值,用于计算时间成本的非常小(或非常高)的 z 分数。< /p>