C#实现封装六西格玛数据统计工具类SixSigmaHelper

背景

在不同项目开的发过程中,可能会用到许多相同或类似的功能开发或业务处理,从抽象设计的角度考虑,通常会把这些功能或业务操作进行封装,方便在不同项目中调用,这也是重用思想的重要体现。本次分享的是在C#中实现六西格玛数据统计的功能封装。在大数据、人工智能、数据科学家炙手可热的当下,本类可以说是C#工程师在处理数据分析业务上的必备类。

相关概念请学习SPC相关课程和歇息MiniTab工具的使用

代码实现

SixSigmaHelper

常量定义

public const double d2 = 1.128;
public const double d3 = 1.693;
public const double d4 = 2.059;
public const double d5 = 2.326;

数组求和

/// <summary>
/// 数组求和
/// </summary>
/// <param name="originalData">原始数据数组</param>
/// <returns>返回数组的和</returns>
public static double GetSumValue(double[] originalData)
{
    double sum = 0.0;
    for (int i = 0; i < originalData.Length; i++)
    {
        sum = sum + originalData[i];
    }
    return DoubleFormat(sum);
}

数组求平均数

/// <summary>
/// 数组求平均数
/// </summary>
/// <param name="originalData">原始数据数组</param>
/// <returns>返回数组的平均值</returns>
public static double GetAverageValue(double[] originalData)
{
    double sum = 0.0;
    double ave = 0.0;
    for (int i = 0; i < originalData.Length; i++)
    {
        sum = sum + originalData[i];
    }
    ave = sum / originalData.Length;
    return DoubleFormat(ave);
}

按指定小数精度计算数组平均值

/// <summary>
/// 按指定小数精度计算数组平均值
/// </summary>
/// <param name="digits">精度,即保留的小数位数</param>
/// <param name="originalData"原始数据>原始数据数组</param>
/// <returns>返回指定小数精度的平均值</returns>
public static double GetAverageValue(int digits, double[] originalData)
{
    double sum = 0.0;
    double ave = 0.0;
    for (int i = 0; i < originalData.Length; i++)
    {
        sum = sum + originalData[i];
    }
    ave = sum / originalData.Length;
    return DoubleFormat(digits, ave);
}

获取整体平均值:先分组,计算组内平均值,然后计算整体平均值

/// <summary>
/// 获取整体平均值:先分组,计算组内平均值,然后计算整体平均值
/// </summary>
/// <param name="digits">精度,小数位数</param>
/// <param name="groupSize">组大小</param>
/// <param name="originalData"> 原始数据</param>
/// <returns>返回整体平均值</returns>
public static double GetTotalAveByGroup(int digits, int groupSize, double[] originalData)
{
    double[] groupAve = GetGroupAve(digits, groupSize, originalData);
    return SixSigmaHelper.GetAverageValue(digits, groupAve);
}

获取子组平均数,以数组形式返回

/// <summary>
/// 获取子组平均数,以数组形式返回
/// </summary>
/// <param name="digits">精度,小数位数</param>
/// <param name="groupSize">组大小</param>
/// <param name="originalData">原始数据</param>
/// <returns>返回子组平均值</returns>
public static double[] GetGroupAve(int digits, int groupSize, double[] originalData)
{
    double groupNum = Math.Ceiling(Convert.ToDouble(originalData.Length / groupSize));
    double[] groupAve = new double[Convert.ToInt32(groupNum)];
    for (int i = 0; i < Convert.ToInt32(groupNum); i++)
    {
        int index = i * groupSize;
        double[] temp = new double[groupSize];
        for (int j = 0; j < groupSize; j++)
        {
            temp[j] = originalData[index + j];
        }
        groupAve[i] = SixSigmaHelper.GetAverageValue(digits, temp);
    }
    return groupAve;
}

求整体标准差

/// <summary>
/// 求整体标准差
/// </summary>
/// <param name="originalData">原始数据</param>
/// <returns>返回标准差</returns>
public static double GetTotalStdDev(double[] originalData)
{
    double ave = 0.0;
    double stdDev = 0.0;
    if (originalData.Length == 1 && originalData[0] == 0.0)
    {
        return stdDev = 0.0;
    }
    ave = GetAverageValue(originalData);
    for (int i = 0; i < originalData.Length; i++)
    {
        stdDev = (double)(stdDev + Math.Pow((originalData[i] - ave), 2));
    }
    stdDev = (double)Math.Sqrt(stdDev / (originalData.Length - 1));
    return DoubleFormat(stdDev);
}

按指定小数精度获取标准差

/// <summary>
/// 按指定小数精度获取标准差
/// </summary>
/// <param name="digits">精度,即小数位数</param>
/// <param name="originalData">原始数据</param>
/// <returns>返回标准差</returns>
public static double GetStdDev(int digits, double[] originalData)
{
    double ave = 0.0;
    double stdDev = 0.0;
    ave = GetAverageValue(originalData);
    for (int i = 0; i < originalData.Length; i++)
    {
        stdDev = (double)(stdDev + Math.Pow((originalData[i] - ave), 2));
    }
    stdDev = (double)Math.Sqrt(stdDev / (originalData.Length - 1));
    return DoubleFormat(digits, stdDev);
}

求移动极差均值

/// <summary>
/// 求移动极差均值
/// </summary>
/// <param name="size">子组容量</param>
/// <param name="originalData">原始数据</param>
/// <returns>返回移动极差均值</returns>
public static double GetMoveRangeMean(int size, double[] originalData)
{
    double moveSum = 0.0;
    double moveAve = 0.0;
    double[] range = new double[originalData.Length - (size - 1)];
    for (int i = (size - 1); i < originalData.Length; i++)
    {
        double[] temp = new double[size];
        int count = size;
        int idx = 0;
        do
        {
            temp[idx] = originalData[i - (count - 1)];
            idx++;
            count--;
        } while ((count > 0));
        range[i - (size - 1)] = (double)Math.Abs(GetArrMax(temp) - GetArrMin(temp));
    }
    for (int i = 0; i < range.Length; i++)
    {
        moveSum = moveSum + range[i];
    }
    moveAve = moveSum / range.Length;
    return DoubleFormat(moveAve);
}

求组内标准差

/// <summary>
/// 求组内标准差
/// </summary>
/// <param name="size">子组容量</param>
/// <param name="originalData">原始数据</param>
/// <returns>返回组内标准差</returns>
public static double GetInGroupStdDev(int size, double[] originalData)
{
    double gourpStdDev = 0.0;
    double moveAve = GetMoveRangeMean(size, originalData);
    switch (size)
    {
        case 2:
            gourpStdDev = (double)(moveAve / d2);
            break;
        case 3:
            gourpStdDev = (double)(moveAve / d3);
            break;
        case 4:
            gourpStdDev = (double)(moveAve / d4);
            break;
        case 5:
            gourpStdDev = (double)(moveAve / d5);
            break;
        default:
            gourpStdDev = (double)(moveAve / d2);
            break;
    }
    return DoubleFormat(gourpStdDev);
}

获取整体正态分布曲线数组值

/// <summary>
/// 获取整体正态分布曲线数组值
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回整体正态分布曲线数组值</returns>
public static Dictionary<string, object> GetNormalDistribution(double target, double[] original)
{
    Dictionary<string, object> json = new Dictionary<string, object>();
    double sigma = GetTotalStdDev(original);
    double lcl = DoubleFormat(target - 3 * sigma);
    double ucl = DoubleFormat(target + 3 * sigma);
    int idx = 10;
    double plus = 0.0;
    plus = ((double)((int)(ucl - lcl + 1))) / 10;
    double[] categories = new double[idx];
    double[] values = new double[idx];
    categories[0] = lcl;
    for (int i = 1; i < idx; i++)
    {
        categories[i] = DoubleFormat(categories[i - 1] + plus);
    }
    for (int i = 0; i < idx; i++)
    {
        values[i] = 0.0;
    }
    for (int i = 1; i < categories.Length; i++)
    {
        values[i] = DoubleFormat(1
                / ((Math.Sqrt(2 * Math.PI) * GetTotalStdDev(original)))
                * Math.Pow(
                        Math.E,
                        -Math.Pow((categories[i] - GetAverageValue(original)), 2)
                                / (2 * Math
                                        .Pow(GetTotalStdDev(original), 2))));
    }
    json.Add("categories", categories);
    json.Add("values", values);
    return json;
}

获取组内正态分布曲线数组值

/// <summary>
/// 获取组内正态分布曲线数组值
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回组内正态分布曲线数组值</returns>
public static Dictionary<string, object> GetInGroupNormalDistribution(double target, double[] original)
{
    Dictionary<string, object> json = new Dictionary<string, object>();
    double sigma = GetTotalStdDev(original);
    double lcl = DoubleFormat(target - 3 * sigma);
    double ucl = DoubleFormat(target + 3 * sigma);
    int idx = 10;
    double plus = 0.0;
    plus = ((double)((int)(ucl - lcl + 1))) / 10;
    double[] categories = new double[idx];
    double[] values = new double[idx];
    double inGroupStdDev = GetInGroupStdDev(2, original);
    double ave = GetAverageValue(original);
    categories[0] = lcl;
    for (int i = 1; i < idx; i++)
    {
        categories[i] = DoubleFormat(categories[i - 1] + plus);
    }
    for (int i = 0; i < idx; i++)
    {
        values[i] = 0.000000;
    }
    for (int i = 1; i < categories.Length; i++)
    {
        values[i] = DoubleFormat(1
               / ((Math.Sqrt(2 * Math.PI) * inGroupStdDev))
               * Math.Pow(
                       Math.E,
                       -Math.Pow((categories[i] - ave), 2)
                               / (2 * Math.Pow(inGroupStdDev, 2))));
    }
    json.Add("categories", categories);
    json.Add("values", values);
    return json;
}

获取数据分布情况

/// <summary>
/// 获取数据分布情况
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回数据分布情况</returns>
public static Dictionary<string, object> GetDataDistribution(double target, double[] original)
{
    Dictionary<string, object> json = new Dictionary<string, object>();
    double sigma = GetTotalStdDev(original);
    double lcl = DoubleFormat(target - 3 * sigma);
    double ucl = DoubleFormat(target + 3 * sigma);
    int idx = 10;
    double plus = 0.0;
    plus = ((double)((int)(ucl - lcl + 1))) / 10;
    double[] categories = new double[idx];
    double[] values = new double[idx];
    String[] test = new String[idx];
    categories[0] = lcl;
    for (int i = 1; i < idx; i++)
    {
        categories[i] = DoubleFormat(categories[i - 1] + plus);
    }
    for (int i = 0; i < idx; i++)
    {
        values[i] = 0.0;
        test[i] = "";
    }
    for (int i = 0; i < original.Length; i++)
    {
        for (int j = 0; j < categories.Length; j++)
        {
            if (categories[j] - 0.5 < original[i] && original[i] <= categories[j] + 0.5)
            {
                values[j] += 1;
                test[j] += original[i] + ",";
            }
        }
    }
    for (int i = 0; i < idx; i++)
    {
        values[i] = values[i] / 100;
    }
    json.Add("categories", categories);
    json.Add("values", values);
    return json;
}

无偏移过程能力指数

/// <summary>
/// 无偏移过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移过程能力指数</returns>
public static double GetPP(double upperT, double lowerT, double[] original)
{
    double pp = new double();
    double sigma = GetTotalStdDev(original);
    pp = (upperT - lowerT) / (6 * sigma);
    return DoubleFormat(pp);
}

无偏移下单限过程能力指数

/// <summary>
/// 无偏移下单限过程能力指数
/// </summary>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移下单限过程能力指数</returns>
public static double GetPPL(double lowerT, double[] original)
{
    double ppl = new double();
    double sigma = GetTotalStdDev(original);
    double ave = GetAverageValue(original);
    ppl = (ave - lowerT) / (3 * sigma);
    return DoubleFormat(ppl);
}

无偏移上单限过程能力指数

/// <summary>
/// 无偏移上单限过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移上单限过程能力指数</returns>
public static double GetPPU(double upperT, double[] original)
{
    double ppl = new double();
    double sigma = GetTotalStdDev(original);
    double ave = GetAverageValue(original);
    ppl = (upperT - ave) / (3 * sigma);
    return DoubleFormat(ppl);
}

有偏移过程能力指数

/// <summary>
/// 有偏移过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回有偏移过程能力指数</returns>
public static double getPPK(double upperT, double lowerT, double[] original)
{
    double ppl = GetPPL(lowerT, original);
    double ppu = GetPPU(upperT, original);
    return DoubleFormat(ppl > ppu ? ppu : ppl);
}

无偏移短期过程能力指数

/// <summary>
/// 无偏移短期过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移短期过程能力指数</returns>
public static double GetInGroupCP(double upperT, double lowerT, double[] original)
{
    double cp = new double();
    double sigma = GetInGroupStdDev(2, original);
    if (sigma == 0)
    {
        cp = 0;
    }
    else 
    {
        cp = (upperT - lowerT) / (6 * sigma);
    }
    
    return DoubleFormat(cp);
}

无偏移下单限短期过程能力指数

/// <summary>
/// 无偏移下单限短期过程能力指数
/// </summary>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回无偏移下单限短期过程能力指数</returns>
public static double GetInGroupCPL(double lowerT, double[] original)
{
    double cpl = new double();
    double sigma = GetInGroupStdDev(2, original);
    if (sigma == 0)
    {
        return 0;
    }
    else 
    {
        double ave = GetAverageValue(original);
        cpl = (ave - lowerT) / (3 * sigma);
        return DoubleFormat(cpl);
    }
}

无偏移上单限短期过程能力指数

/// <summary>
/// 无偏移上单限短期过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="original">原始数据</param>
/// <returns>反回无偏移上单限短期过程能力指数</returns>
public static double GetInGroupCPU(double upperT, double[] original)
{
    double cpu = new double();
    double sigma = GetInGroupStdDev(2, original);
    if (sigma == 0)
    {
        return 0;
    }
    else
    {
        double ave = GetAverageValue(original);
        cpu = (upperT - ave) / (3 * sigma);
        return DoubleFormat(cpu);
    }
}

有偏移短期过程能力指数

/// <summary>
/// 有偏移短期过程能力指数
/// </summary>
/// <param name="upperT">公差上限</param>
/// <param name="lowerT">公差下限</param>
/// <param name="original">原始数据</param>
/// <returns>返回有偏移短期过程能力指数</returns>
public static double GetInGroupCPK(double upperT, double lowerT, double[] original)
{
    double cpl = GetInGroupCPL(lowerT, original);
    double cpu = GetInGroupCPU(upperT, original);
    return DoubleFormat(cpl > cpu ? cpu : cpl);
}

自然上限

/// <summary>
/// 自然上限
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回自然上限</returns>
public static double GetUCL(double target, double[] original)
{
    double sigma = GetTotalStdDev(original);
    return DoubleFormat(target + 3 * sigma);
}

自然下限

/// <summary>
/// 自然下限
/// </summary>
/// <param name="target">望目</param>
/// <param name="original">原始数据</param>
/// <returns>返回自然下限</returns>
public static double GetLCL(double target, double[] original)
{
    double sigma = GetTotalStdDev(original);
    return DoubleFormat(target - 3 * sigma);
}

最小值

/// <summary>
/// 最小值
/// </summary>
/// <param name="array">原始数据数组</param>
/// <returns>返回最小值</returns>
public static double GetArrMin(double[] array)
{
    double min = array[0];
    for (int i = 0; i < array.Length; i++)
    {
        if (min > array[i])
            min = array[i];
    }
    return min;
}

最大值

/// <summary>
/// 最大值
/// </summary>
/// <param name="array">原始数据数组</param>
/// <returns>返回最大值</returns>
public static double GetArrMax(double[] array)
{
    double max = array[0];
    for (int i = 0; i < array.Length; i++)
    {
        if (max < array[i])
            max = array[i];
    }
    return max;
}

数据格式化,默认保留5位小数

/// <summary>
/// 数据格式化,默认保留5位小数
/// </summary>
/// <param name="d">要格式化的数据</param>
/// <returns>返回格式化后的数据</returns>
public static double DoubleFormat(double d)
{
    double result = 0.0;
    if (double.TryParse(d.ToString(), out result))
    {
        decimal b = new decimal(d);
        double formatD = Convert.ToDouble(Math.Round(b, 5));
        //b.setScale(5, BigDecimal.ROUND_HALF_UP).doubleValue();
        return formatD;
    }
    else
    {
        return 0.0;
    }
}

按指定精度进行数据格式化

/// <summary>
/// 按指定精度进行数据格式化
/// </summary>
/// <param name="digits">精度,小数位数</param>
/// <param name="d">要格式化的数据</param>
/// <returns>返回格式化后的数据</returns>
public static double DoubleFormat(int digits, double d)
{
    double result = 0.0;
    if (double.TryParse(d.ToString(), out result))
    {
        decimal b = new decimal(d);
        double formatD = Convert.ToDouble(Math.Round(b, digits));
        //Double formatD = b.setScale(digits, BigDecimal.ROUND_HALF_UP).doubleValue();
        return formatD;
    }
    else
    {
        return 0.0;
    }
}

完整代码下载

完整代码下载

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值