C# 使用MathNET的置信区间

C# 使用MathNET的置信区间,c#,confidence-interval,math.net,mathnet-numerics,C#,Confidence Interval,Math.net,Mathnet Numerics,我有一个IEnumerable数据样本。我想计算信号/数据的90%置信区间。我可以随意使用,但我对如何正确使用图书馆感到困惑。根据我的数据,我们的想法是返回另外两个包含原始信号置信区间的数据数组 using MathNet.Numerics.Statistics; using MathNet.Numerics.Distributions; public static List<double[]> ConfidenceIntervals(IEnumerable<double&g

我有一个
IEnumerable
数据样本。我想计算信号/数据的90%置信区间。我可以随意使用,但我对如何正确使用图书馆感到困惑。根据我的数据,我们的想法是返回另外两个包含原始信号置信区间的数据数组

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.Numerics.Statistics;
使用MathNet.Numerics.Distributions;
公共静态列表置信区间(IEnumerable样本,双区间)
{
合同要求(间隔>0和间隔<1.0);
int sampleSize=sample.Count();
双α=1.0-间隔;
双平均值=sample.mean();
双标准差=样品标准偏差();
双t,mu;
double[]upper=新的double[sampleSize];
double[]lower=新的double[sampleSize];
StudentT StudentT=新学生T(平均值,α,样本大小-1);
int指数=0;
foreach(样品中的双d)
{
t=学生t.累积分布(d);
双tmp=t*(sd/Math.Sqrt(sampleSize));
mu=平均值-tmp;
上[指数]=d+mu;
较低的[指数]=d-mu;
}
返回新列表(){upper,lower};
}

就数学而言,这并不复杂,我只是对如何正确使用我在应用程序中可用的函数/方法感到困惑

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

所以我想这就是你得到错误结果的原因

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

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 };
}
使用MathNet.Numerics.Statistics;
使用MathNet.Numerics.Distributions;
公共静态列表置信区间(IEnumerable样本,双区间)
{
合同要求(间隔>0和间隔<1.0);
int sampleSize=sample.Count();
双α=1.0-间隔;
双平均值=sample.mean();
双标准差=样品标准偏差();
双t,mu;
double[]upper=新的double[sampleSize];
double[]lower=新的double[sampleSize];
StudentT StudentT=新学生T(平均值,α,样本大小-1);
int指数=0;
foreach(样品中的双d)
{
t=学生t.累积分布(d);
双tmp=t*(sd/Math.Sqrt(sampleSize));
mu=平均值-tmp;
上[指数]=d+mu;
较低的[指数]=d-mu;
索引++;
}
返回新列表(){upper,lower};
}

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

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);
}
例如,对于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);
}
公共静态元组B(双[]个样本,双间隔)
{
双θ=(间隔+1.0)/2;
double T=FindRoots.offfunction(x=>StudentT.CDF(0,1,samples.Length-1,x)-theta,-800800);
双平均值=样本数。平均值();
双sd=样本。标准偏差();
双t=t*(sd/Math.Sqrt(samples.Length));
返回Tuple.Create(mean-t,mean+t);
}
这还不是完整的答案,因为我知道您希望以某种方式将置信区间应用于每个样本,但希望它有助于实现这一目标


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

+1,您的索引增量是正确的。然而,这是我在打印问题时的疏忽,所以我道歉。上面的实现给出了错误的置信水平。他们太离谱了。你使用MathNET吗?在上述实现中,您是否还发现了其他错误?谢谢你的时间。不,我从未使用过它,但我已经安装了这个库。也许我可以帮你更多:)我会在我的电脑上测试,我想知道哪些是样本值和区间值?Crisroph,非常感谢你的回复。我现在完成了一天的工作,所以明天将实施并反馈。明天我可能会问另一个关于MathNET的问题,这是关于执行矩阵运算时强制转换的要求
矩阵M=(DenseMatrix)(SomeMatrixA*SomeMatrixB)
。这是一个单独的问题,所以我明天会问另一个问题。另外,非常感谢您维护这么一个伟大的图书馆!祝你一切顺利…很抱歉耽误了你的时间。我刚刚尝试使用您上面提供的代码,但是没有
StudentT.CDF
方法可供我使用;然而,正态分布是有规律的。我需要更新我的库吗?注意,我说有
Normal
分布。有一个名为
CDF
publicstatic
方法,但我似乎无法使用最新的NuGet包访问它;如果我下载源代码并自己编译,就可以了?
StudentT.CDF
是在v3.0.0-alpha7(汇编版本3.0.0.40)中添加的。您使用的是什么版本?源代码未按设计在本地版本上设置版本号。如果您从GitHub获得了源代码,那么它们可能是最新的。对于NuGet,您需要明确允许预发布:
PM>安装软件包MathNet.Numerics-pre
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);
}