using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Misc
{
///
/// 扩展 Enumerable 计算
///
public static class Enumerable
{
///
/// 获取 σ
///
///
///
///
///
public static double Sigma(this IEnumerable source, Func selector)
{
if (source.Count() < 2)
return double.NaN;
double avg = source.Average(selector);
double sum_pow = source.Sum((s) => Math.Pow((selector(s) - avg), 2));
return Math.Sqrt(sum_pow / (source.Count() - 1));
}
///
/// 获取 σ
///
///
///
public static double Sigma(this IEnumerable source)
{
return source.Sigma(d => (int)d);
}
///
/// 获取 σ
///
///
///
public static double Sigma(this IEnumerable source)
{
var list = source.Where((d) =>
{
if (double.IsNaN(d))
return false;
else
return true;
});
return list.Sigma(d => d);
}
///
/// 获取CPK
///
///
///
///
///
///
///
public static double CPK(this IEnumerable source, Func selector, double usl, double lsl)
{
if (source.Count() < 2)
return -1;
//CPK = Min(CPKu,CPKl)
//USL(Upper specification limit): 规格上限。
//LSL(Low specification limit): 规格下限。
//ˉx = (x1 + x2 +...+ xn) / n : 平均值。
//T = USL - LSL : 规格公差。
//U = (USL + LSL) / 2:规格中心。
//CPKu = | USL - ˉx | / 3σ
//CPKl = | ˉx - LSL | / 3σ
double avg = source.Average(selector);
double sigma3 = source.Sigma(selector) * 3;
double CPKu = Math.Abs(usl - avg) / sigma3;
double CPKl = Math.Abs(lsl - avg) / sigma3;
double CPK = Math.Min(CPKu, CPKl);
return CPK;
}
///
/// 获取CPK
///
///
///
///
///
public static double CPK(this IEnumerable source, double usl, double lsl)
{
var list = source.Where((d) =>
{
if (double.IsNaN(d))
return false;
else
return true;
});
return list.CPK(d => d, usl, lsl);
}
///
/// 获取直方图,统计数据
///
///
///
///
///
///
public static List GetHistogram(this IEnumerable source, Func selector, double step)
{
List list = new List();
foreach (var v in source)
{
double x = ((int)(selector(v) / step)) * step;
XY xy = list.Find(_xy => _xy.X == x);
if (xy != null)
{
xy.Y++;
}
else
{
xy = new XY(x, 1);
list.Add(xy);
}
}
//没有数据也能排序的,不会错
list.Sort();
return list;
}
///
/// 获取直方图,统计数据
///
///
///
///
public static List GetHistogram(this IEnumerable source, double step)
{
var list = source.Where((d) =>
{
if (double.IsNaN(d))
return false;
else
return true;
});
return list.GetHistogram(d => d, step);
}
///
/// 当有 NaN 数据,不统计它。
///
///
///
public static double AverageNoNull(this IEnumerable source)
{
return source.AverageNoNull(d => d);
}
///
/// 当有 NaN 数据,不统计它。
///
///
///
///
///
public static double AverageNoNull(this IEnumerable source, Func selector)
{
if (source.Count() == 0)
return double.NaN;
var list = source.Select(selector);
var list2 = list.Where((d) =>
{
if (double.IsNaN(d))
return false;
else
return true;
});
if (list2.Count() == 0)
return double.NaN;
return list2.Average();
}
///
/// 扩展 System.Linq.Enumerable.SequenceEqual
/// 支持 first,second 为null 的情况
///
///
///
///
///
///
public static bool SequenceEqual(IEnumerable first, IEnumerable second, IEqualityComparer comparer)
{
if (first == second)
{
return true;
}
else if (first == null || second == null)
{
return false;
}
return System.Linq.Enumerable.SequenceEqual(first, second, comparer);
}
///
/// 对数列平滑;
/// 数列的两端,平滑量只有 radius;中间数据平滑量 = radius*2+1
///
/// 数列
/// 平滑半径
///
public static double[] Smooth(this IEnumerable frame, int radius)
{
if (radius > 0)
{
double[] frame2 = new double[frame.Count()];
for (int i = 0; i < frame.Count(); i++)
{
double sum = 0;
int cnt = 0;
int index_b = i - radius;
int index_e = i + radius;
for (int j = index_b; j <= index_e; j++)
{
if ((j >= 0) && (j < frame.Count()))
{
double v = frame.ElementAt(j);
if (!double.IsNaN(v))
{
sum += v;
cnt++;
}
}
}
if (cnt > 0)
frame2[i] = sum / cnt;
else
frame2[i] = double.NaN;
}
return frame2;
}
else
{
return frame.ToArray();
}
}
}
///
/// X Y 组合
///
public class XY : IComparable, ICloneable, ICopiable
{
public double X { get; set; }
public double Y { get; set; }
public XY()
{
}
public XY(double x, double y)
{
X = x;
Y = y;
}
public int CompareTo(object obj)
{
XY xy = obj as XY;
return X.CompareTo(xy.X);
}
public object Clone()
{
XY xy = new XY();
xy.Copy(this);
return xy;
}
public override string ToString()
{
return $"{X}.{Y}";
}
public void Copy(object src)
{
Misc.PropertiesManager.CopyTo(src, this);
}
}
}