4

我有一个IEnumerable<double>数据样本。我想计算信号/数据的 90% 置信区间。我可以使用MathNET 库,但我对如何正确使用该库感到困惑。给定我的数据,想法是返回两个额外的数据数组,其中包含原始信号的置信区间

using MathNet.Numerics.Statistics;
using MathNet.Numerics.Distributions;

public static List<double[]> ConfidenceIntervals(IEnumerable<double> sample, double interval)
{
    Contract.Requires(interval > 0 && interval < 1.0);
    int sampleSize = sample.Count();
    double alpha = 1.0 - interval;
    double mean = sample.Mean();
    double sd = sample.StandardDeviation();

    double t, mu;
    double[] upper = new double[sampleSize];
    double[] lower = new double[sampleSize];
    StudentT studentT = new StudentT(mean, alpha, sampleSize - 1);
    int index = 0;
    foreach (double d in sample)
    {
        t = studentT.CumulativeDistribution(d);
        double tmp = t * (sd / Math.Sqrt(sampleSize));
        mu = mean - tmp;
        upper[index] = d + mu;
        lower[index] = d - mu;
    }
    return new List<double[]>() { upper, lower };
}

这在数学方面确实并不复杂,我只是对如何正确使用MathNET 库中可用的函数/方法感到困惑。

4

2 回答 2

7

我不完全确定我理解信号的置信区间应该如何应用于信号的每个样本,但我们可以计算样本集的置信区间,如下所示:

public static Tuple<double, double> A(double[] samples, double interval)
{
    double theta = (interval + 1.0)/2;
    double mean = samples.Mean();
    double sd = samples.StandardDeviation();
    double T = StudentT.InvCDF(0,1,samples.Length-1,theta);
    double t = T * (sd / Math.Sqrt(samples.Length));
    return Tuple.Create(mean-t, mean+t);
}

除了我们计算 T 的行没有编译,因为不幸的是StudentT.InvCDF在当前的 Math.NET Numerics 中还没有。但与此同时,我们仍然可以对其进行数值评估作为一种解决方法:

var student = new StudentT(0,1,samples.Length-1);
double T = FindRoots.OfFunction(x => student.CumulativeDistribution(x)-theta,-800,800);

例如,对于 16 个样本和 alpha 0.05,我们得到了预期的 2.131。如果有超过 ~60-100 个样本,这也可以用正态分布来近似:

double T = Nomal.InvCDF(0,1,theta);

总而言之:

public static Tuple<double, double> B(double[] samples, double interval)
{
    double theta = (interval + 1.0)/2;
    double T = FindRoots.OfFunction(x => StudentT.CDF(0,1,samples.Length-1,x)-theta,-800,800);

    double mean = samples.Mean();
    double sd = samples.StandardDeviation();
    double t = T * (sd / Math.Sqrt(samples.Length));
    return Tuple.Create(mean-t, mean+t);
}

这还不是完整的答案,因为我知道您想以某种方式将置信区间应用于每个样本,但希望它有助于实现目标。

PS:使用 Math.NET Numerics v3.0.0-alpha7

于 2013-12-30T17:48:46.957 回答
1

我注意到您没有在foreach循环中增加索引值。这将使索引 0 处的值被下一次计算替换(当您尝试设置upper[index]lower[index]值时)。

所以我想这是你得到不正确结果的原因。

如果是这样,您的代码应该是

using MathNet.Numerics.Statistics;
using MathNet.Numerics.Distributions;

public static List<double[]> ConfidenceIntervals(IEnumerable<double> sample, double interval)
{
    Contract.Requires(interval > 0 && interval < 1.0);
    int sampleSize = sample.Count();
    double alpha = 1.0 - interval;
    double mean = sample.Mean();
    double sd = sample.StandardDeviation();

    double t, mu;
    double[] upper = new double[sampleSize];
    double[] lower = new double[sampleSize];
    StudentT studentT = new StudentT(mean, alpha, sampleSize - 1);
    int index = 0;
    foreach (double d in sample)
    {
        t = studentT.CumulativeDistribution(d);
        double tmp = t * (sd / Math.Sqrt(sampleSize));
        mu = mean - tmp;
        upper[index] = d + mu;
        lower[index] = d - mu;
        index++;
    }
    return new List<double[]>() { upper, lower };
}
于 2013-12-30T14:26:10.887 回答