需要安装包 MathNet.Numerics
公式地址
https://support.minitab.com/zh-cn/minitab/18/help-and-how-to/quality-and-process-improvement/control-charts/how-to/box-cox-transformation/methods-and-formulas/methods-and-formulas/
最优Lambda求解代码
using MathNet.Numerics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Spc.Core
{
/// <summary>
/// 最优Lambda求解
/// </summary>
public class OptimalSolutionLambda
{
private readonly double MAXLAMBDA = 5D;
private readonly double MINLAMBDA = -5D;
/// <summary>
/// 最优Lambda求解 移动极差平均法
/// </summary>
/// <param name="sample"></param>
/// <param name="step"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public double GetLambda(double[] sample, double step = 0.5D)
{
step = Math.Abs(step);
if (step == 0)
{
throw new Exception("步长不能为0!");
}
double product = 1D;
double geometricAverage;
for (int i = 0; i < sample.Length; i++)
{
product = product.Mul(sample[i]);
}
IEstimateSigma sigma = new MovingRangeAverageEstimateSigma();
geometricAverage = Math.Pow(product, 1 / sample.Length);
Dictionary<double, double> list = new Dictionary<double, double>();
for (double lambda = MINLAMBDA; lambda <= MAXLAMBDA; lambda = lambda.Add(step))
{
double[] zValue = new double[sample.Length];
if (lambda == 0D)
{
for (int i = 0; i < sample.Length; i++)
{
zValue[i] = geometricAverage.Mul(SpecialFunctions.Gamma(sample[i]));
}
}
else
{
for (int i = 0; i < sample.Length; i++)
{
zValue[i] = (Math.Pow(sample[i], lambda).Sub(1)).Div(lambda.Mul(Math.Pow(geometricAverage, lambda.Sub(1))));
}
}
list.Add(lambda, sigma.GetSigma(zValue, true));
}
return list.First(m => m.Value == list.Min(m => m.Value)).Key;
}
/// <summary>
/// 最优Lambda求解 合并标准差法
/// </summary>
/// <param name="sample"></param>
/// <param name="step"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public double GetLambda(double[][] sample, double step = 0.5D)
{
step = Math.Abs(step);
if (step == 0)
{
throw new Exception("步长不能为0!");
}
double product = 1;
double geometricAverage;
int count = 0;
for (int i = 0; i < sample.Length; i++)
{
for (int j = 0; j < sample[i].Length; j++)
{
product = product.Mul(sample[i][j]);
count++;
}
}
IEstimateSigma sigma = new OverallEstimateSigma();
geometricAverage = Math.Pow(product, 1 / count);
Dictionary<double, double> list = new Dictionary<double, double>();
for (double lambda = MINLAMBDA; lambda <= MAXLAMBDA; lambda = lambda.Add(step))
{
double[][] zValue = new double[sample.Length][];
if (lambda == 0D)
{
for (int i = 0; i < sample.Length; i++)
{
zValue[i] = new double[sample[i].Length];
for (int j = 0; j < sample[i].Length; j++)
{
zValue[i][j] = geometricAverage.Mul(SpecialFunctions.Gamma(sample[i][j]));
}
}
}
else
{
for (int i = 0; i < sample.Length; i++)
{
zValue[i] = new double[sample[i].Length];
for (int j = 0; j < sample[i].Length; j++)
{
zValue[i][j] = (Math.Pow(sample[i][j], lambda).Sub(1)).Div(lambda.Mul(Math.Pow(geometricAverage, lambda.Sub(1))));
}
}
}
list.Add(lambda, sigma.GetSigma(zValue, true));
}
return list.First(m => m.Value == list.Min(m => m.Value)).Key;
}
}
}
Box-Cox 变换代码
using MathNet.Numerics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Spc.Core
{
/// <summary>
/// Box-Cox
/// </summary>
public class BoxCoxFunc
{
/// <summary>
/// Box-Cox转换
/// </summary>
/// <param name="sample"></param>
/// <param name="lambda"></param>
/// <returns></returns>
public double[] Transform(double[] sample, double lambda)
{
double[] result = new double[sample.Length];
if (lambda == 0D)
{
for (int i = 0; i < sample.Length; i++)
{
result[i] = Math.Pow(sample[i], lambda);
}
}
else
{
for (int i = 0; i < sample.Length; i++)
{
result[i] = Math.Log(sample[i]);
}
}
return result;
}
/// <summary>
/// Box-Cox转换
/// </summary>
/// <param name="sample"></param>
/// <param name="lambda"></param>
/// <returns></returns>
public double[][] Transform(double[][] sample, double lambda)
{
double[][] result = new double[sample.Length][];
if (lambda == 0D)
{
for (int i = 0; i < sample.Length; i++)
{
result[i] = new double[sample[i].Length];
for (int j = 0; j < sample[i].Length; j++)
{
result[i][j] = Math.Pow(sample[i][j], lambda);
}
}
}
else
{
for (int i = 0; i < sample.Length; i++)
{
result[i] = new double[sample[i].Length];
for (int j = 0; j < sample[i].Length; j++)
{
result[i][j] = Math.Log(sample[i][j]);
}
}
}
return result;
}
}
}
---------------------------------END--------------------------------