public static double Calculate(IEnumerable <double> x, IEnumerable <double> y, bool?exact = null, bool correct = true) { double pVal; //TODO: remove infinite/Nan x,y double nx = x.Count(); double ny = y.Count(); if (nx < 1) { throw new ArgumentException("Not enough finite x oberservations"); } if (nx < 1) { throw new ArgumentException("Not enough finite y oberservations"); } List <double> ranks = Helpers.Rank(x.Concat(y)).Ranks; //Console.WriteLine("Ranks: {0}", string.Join(",", ranks)); if (!exact.HasValue) { exact = (nx < 50) && (ny < 50); } //sum the ranks of the x samples and subtract stuff.. double statistic = ranks.Take((int)nx).Sum() - nx * (nx + 1) / 2; bool ties = ranks.Count() != ranks.Distinct().Count(); //TODO: better check for ties? if (exact.Value && !ties) { double p = 0; if (statistic > (nx * ny / 2)) { p = pwilcox(statistic - 1, nx, ny, 0, 0); } else { p = pwilcox(statistic, nx, ny, 1, 0); } pVal = Math.Min(2 * p, 1); } else { Dictionary <double, int> nties = Helpers.NumTies(ranks); double z = statistic - nx * ny / 2; double sigma = Math.Sqrt((nx * ny / 12) * ((nx + ny + 1) - nties.Sum(a => Math.Pow(a.Value, 3) - a.Value) / ((nx + ny) * (nx + ny - 1)))); double correction = 0; if (correct) { correction = Math.Sign(z) * 0.5; } z = (z - correction) / sigma; bool lower = z < 0; pVal = 2 * NormalDistribution.pnorm(z, 0, 1, lower, false); //pVal = 2 * Math.Min(NormalDistribution.pnorm(z, 0, 1, true, false), NormalDistribution.pnorm(z, 0, 1, false, false)); } return(pVal); }
public static double Calculate(List <double> x, List <double> y, bool?exact = null, bool correct = true) { double pVal; //TODO: remove infinite/NaN x,y double nx = x.Count; double ny = y.Count; if (nx < 1) { throw new ArgumentException("Not enough finite x oberservations"); } if (nx < 1) { throw new ArgumentException("Not enough finite y oberservations"); } List <double> ranks = Helpers.Rank(x.Concat(y)).Ranks; if (!exact.HasValue) { exact = nx < 50 && ny < 50; } //sum the ranks of the x samples double sum = 0; for (int i = 0; i < (int)nx; i++) { sum += ranks[i]; } double statistic = sum - nx * (nx + 1) / 2; bool ties = ranks.Count != ranks.Distinct().Count(); //TODO: better check for ties? if (exact.Value && !ties) { double p = statistic > (nx * ny / 2) ? pwilcox(statistic - 1, nx, ny, 0, 0) : pwilcox(statistic, nx, ny, 1, 0); pVal = Math.Min(2 * p, 1); } else { Dictionary <double, int> nties = Helpers.NumTies(ranks); double z = statistic - nx * ny / 2; double ntiesSum = 0; foreach (var kvp in nties) { ntiesSum += Math.Pow(kvp.Value, 3) - kvp.Value; } double sigma = Math.Sqrt((nx * ny / 12) * ((nx + ny + 1) - ntiesSum / ((nx + ny) * (nx + ny - 1)))); double correction = 0; if (correct) { correction = Math.Sign(z) * 0.5; } z = (z - correction) / sigma; bool lower = z < 0; pVal = 2 * NormalDistribution.Pnorm(z, 0, 1, lower, false); } return(pVal); }