Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/OnlineCalculators/HoeffdingsDependenceCalculator.cs @ 8113

Last change on this file since 8113 was 7969, checked in by gkronber, 12 years ago

#1292: Added HoeffdingsDependenceCalculator to calculate the non-parametric Hoeffding's dependency. Ideally it should be possible to show either Pearson's R², Spearman's rank correlation, or Hoeffding's dependency in the heat-map.

File size: 4.9 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using HeuristicLab.Common;
26
27namespace HeuristicLab.Problems.DataAnalysis {
28  public class HoeffdingsDependenceCalculator {
29
30    public static double Calculate(IEnumerable<double> originalValues, IEnumerable<double> estimatedValues, out OnlineCalculatorError errorState) {
31      double d = HoeffD(originalValues, estimatedValues, out errorState);
32      if (errorState != OnlineCalculatorError.None) return double.NaN;
33      return d;
34    }
35
36    /// <summary>
37    /// computes Hoeffding's dependence coefficient.
38    /// Source: hoeffd.r from R package hmisc http://cran.r-project.org/web/packages/Hmisc/index.html
39    /// </summary>
40    private static double HoeffD(IEnumerable<double> xs, IEnumerable<double> ys, out OnlineCalculatorError errorState) {
41      double[] rx = TiedRank(xs);
42      double[] ry = TiedRank(ys);
43      if (rx.Length != ry.Length) throw new ArgumentException("The number of elements in xs and ys does not match");
44      double[] rxy = TiedRank(xs, ys);
45
46      int n = rx.Length;
47      double q = 0, r = 0, s = 0;
48      double scaling = 1.0 / (n * (n - 1));
49      for (int i = 0; i < n; i++) {
50        q += (rx[i] - 1) * (rx[i] - 2) * (ry[i] - 1) * (ry[i] - 2) * scaling;
51        r += (rx[i] - 2) * (ry[i] - 2) * rxy[i] * scaling;
52        s += rxy[i] * (rxy[i] - 1) * scaling;
53      }
54      errorState = OnlineCalculatorError.None;
55      // return 30.0 * (q - 2 * (n - 2) * r + (n - 2) * (n - 3) * s) / n / (n - 1) / (n - 2) / (n - 3) / (n - 4);
56      double t0 = q / (n - 2) / (n - 3) / (n - 4);
57      double t1 = 2 * r / (n - 3) / (n - 4);
58      double t2 = s / (n - 4);
59      return 30.0 * (t0 - t1 + t2);
60    }
61
62    private static double[] TiedRank(IEnumerable<double> xs) {
63      var xsArr = xs.ToArray();
64      var idx = Enumerable.Range(1, xsArr.Length).ToArray();
65      Array.Sort(xsArr, idx);
66      CRank(xsArr);
67      Array.Sort(idx, xsArr);
68      return xsArr;
69    }
70
71    /// <summary>
72    /// Calculates the joint rank with midranks for ties. Source: hoeffd.r from R package hmisc http://cran.r-project.org/web/packages/Hmisc/index.html
73    /// </summary>
74    /// <param name="xs"></param>
75    /// <param name="ys"></param>
76    /// <returns></returns>
77    private static double[] TiedRank(IEnumerable<double> xs, IEnumerable<double> ys) {
78      var xsArr = xs.ToArray();
79      var ysArr = ys.ToArray();
80      var r = new double[xsArr.Length];
81      int n = r.Length;
82      for (int i = 0; i < n; i++) {
83        var xi = xsArr[i];
84        var yi = ysArr[i];
85        double ri = 0.0;
86        for (int j = 0; j < n; j++) {
87          if (i != j) {
88            double cx;
89            if (xsArr[j] < xi) cx = 1.0;
90            else if (xsArr[j] > xi) cx = 0.0;
91            else cx = 0.5;  // eq
92            double cy;
93            if (ysArr[j] < yi) cy = 1.0;
94            else if (ysArr[j] > yi) cy = 0.0;
95            else cy = 0.5; // eq
96            ri = ri + cx * cy;
97          }
98        }
99        r[i] = ri;
100      }
101      return r;
102    }
103
104    /// <summary>
105    /// Calculates midranks. Source: Numerical Recipes in C.
106    /// </summary>
107    /// <param name="w">Sorted array of elements, replaces the elements by their rank, including midranking of ties</param>
108    /// <returns></returns>
109    private static void CRank(double[] w) {
110      int i = 0;
111      int n = w.Length;
112      while (i < n - 1) {
113        if (w[i + 1] > w[i]) {    // w[i+1] must be larger or equal w[i] as w must be sorted
114          // not a tie
115          w[i] = i + 1;
116          i++;
117        } else {
118          int j;
119          for (j = i + 1; j < n && w[j] <= w[i]; j++) ; // how far does it go (<= effectively means == as w must be sorted)
120          double rank = 0.5 * (i + j - 1);
121          int k;
122          for (k = i; k < j - 1; k++) w[k] = rank; // set the rank for all tied entries
123          i = j;
124        }
125      }
126
127      if (i == n - 1) w[n - 1] = n - 1;   // if the last element was not tied, this is its rank
128    }
129  }
130}
Note: See TracBrowser for help on using the repository browser.