~ubuntu-branches/ubuntu/precise/weka/precise

« back to all changes in this revision

Viewing changes to weka/experiment/PairedStats.java

  • Committer: Bazaar Package Importer
  • Author(s): Soeren Sonnenburg
  • Date: 2008-02-24 09:18:45 UTC
  • Revision ID: james.westby@ubuntu.com-20080224091845-1l8zy6fm6xipbzsr
Tags: upstream-3.5.7+tut1
ImportĀ upstreamĀ versionĀ 3.5.7+tut1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *    This program is free software; you can redistribute it and/or modify
 
3
 *    it under the terms of the GNU General Public License as published by
 
4
 *    the Free Software Foundation; either version 2 of the License, or
 
5
 *    (at your option) any later version.
 
6
 *
 
7
 *    This program is distributed in the hope that it will be useful,
 
8
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 *    GNU General Public License for more details.
 
11
 *
 
12
 *    You should have received a copy of the GNU General Public License
 
13
 *    along with this program; if not, write to the Free Software
 
14
 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
15
 */
 
16
 
 
17
/*
 
18
 *    PairedStats.java
 
19
 *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
 
20
 *
 
21
 */
 
22
 
 
23
 
 
24
package weka.experiment;
 
25
 
 
26
import weka.core.Utils;
 
27
import weka.core.Statistics;
 
28
 
 
29
/**
 
30
 * A class for storing stats on a paired comparison (t-test and correlation)
 
31
 *
 
32
 * @author Len Trigg (trigg@cs.waikato.ac.nz)
 
33
 * @version $Revision: 1.9 $
 
34
 */
 
35
public class PairedStats {
 
36
  
 
37
  /** The stats associated with the data in column 1 */
 
38
  public Stats xStats;
 
39
  
 
40
  /** The stats associated with the data in column 2 */
 
41
  public Stats yStats;
 
42
  
 
43
  /** The stats associated with the paired differences */
 
44
  public Stats differencesStats;
 
45
 
 
46
  /** The probability of obtaining the observed differences */
 
47
  public double differencesProbability;
 
48
 
 
49
  /** The correlation coefficient */
 
50
  public double correlation;
 
51
 
 
52
  /** The sum of the products */
 
53
  public double xySum;
 
54
  
 
55
  /** The number of data points seen */
 
56
  public double count;
 
57
  
 
58
  /**
 
59
   * A significance indicator:
 
60
   * 0 if the differences are not significant
 
61
   * > 0 if x significantly greater than y
 
62
   * < 0 if x significantly less than y
 
63
   */
 
64
  public int differencesSignificance;
 
65
  
 
66
  /** The significance level for comparisons */
 
67
  public double sigLevel;
 
68
 
 
69
  /** The degrees of freedom (if set programmatically) */
 
70
  protected int m_degreesOfFreedom = 0;
 
71
    
 
72
  /**
 
73
   * Creates a new PairedStats object with the supplied significance level.
 
74
   *
 
75
   * @param sig the significance level for comparisons
 
76
   */
 
77
  public PairedStats(double sig) {
 
78
      
 
79
    xStats = new Stats();
 
80
    yStats = new Stats();
 
81
    differencesStats = new Stats();
 
82
    sigLevel = sig;
 
83
  }
 
84
 
 
85
  /**
 
86
   * Sets the degrees of freedom (if calibration is required).
 
87
   */
 
88
  public void setDegreesOfFreedom(int d) {
 
89
   
 
90
    if (d <= 0) {
 
91
      throw new IllegalArgumentException("PairedStats: degrees of freedom must be >= 1");
 
92
    }
 
93
    m_degreesOfFreedom = d;
 
94
  }
 
95
 
 
96
  /**
 
97
   * Gets the degrees of freedom.
 
98
   */
 
99
  public int getDegreesOfFreedom() {
 
100
 
 
101
    return m_degreesOfFreedom;
 
102
  }
 
103
 
 
104
  /**
 
105
   * Add an observed pair of values.
 
106
   *
 
107
   * @param value1 the value from column 1
 
108
   * @param value2 the value from column 2
 
109
   */
 
110
  public void add(double value1, double value2) {
 
111
 
 
112
    xStats.add(value1);
 
113
    yStats.add(value2);
 
114
    differencesStats.add(value1 - value2);
 
115
    xySum += value1 * value2;
 
116
    count ++;
 
117
  }
 
118
    
 
119
  /**
 
120
   * Removes an observed pair of values.
 
121
   *
 
122
   * @param value1 the value from column 1
 
123
   * @param value2 the value from column 2
 
124
   */
 
125
  public void subtract(double value1, double value2) {
 
126
 
 
127
    xStats.subtract(value1);
 
128
    yStats.subtract(value2);
 
129
    differencesStats.subtract(value1 - value2);
 
130
    xySum -= value1 * value2;
 
131
    count --;
 
132
  }
 
133
 
 
134
    
 
135
  /**
 
136
   * Adds an array of observed pair of values.
 
137
   *
 
138
   * @param value1 the array containing values from column 1
 
139
   * @param value2 the array containing values from column 2
 
140
   */
 
141
  public void add(double value1[], double value2[]) {
 
142
    if ((value1 == null) || (value2 == null)) {
 
143
      throw new NullPointerException();
 
144
    }
 
145
    if (value1.length != value2.length) {
 
146
      throw new IllegalArgumentException("Arrays must be of the same length");
 
147
    }
 
148
    for (int i = 0; i < value1.length; i++) {
 
149
      add(value1[i], value2[i]);
 
150
    }
 
151
  }
 
152
 
 
153
 
 
154
  /**
 
155
   * Removes an array of observed pair of values.
 
156
   *
 
157
   * @param value1 the array containing values from column 1
 
158
   * @param value2 the array containing values from column 2
 
159
   */
 
160
  public void subtract(double value1[], double value2[]) {
 
161
    if ((value1 == null) || (value2 == null)) {
 
162
      throw new NullPointerException();
 
163
    }
 
164
    if (value1.length != value2.length) {
 
165
      throw new IllegalArgumentException("Arrays must be of the same length");
 
166
    }
 
167
    for (int i = 0; i < value1.length; i++) {
 
168
      subtract(value1[i], value2[i]);
 
169
    }
 
170
  }  
 
171
 
 
172
 
 
173
  /**
 
174
   * Calculates the derived statistics (significance etc).
 
175
   */
 
176
  public void calculateDerived() {
 
177
 
 
178
    xStats.calculateDerived();
 
179
    yStats.calculateDerived();
 
180
    differencesStats.calculateDerived();
 
181
 
 
182
    correlation = Double.NaN;
 
183
    if (!Double.isNaN(xStats.stdDev) && !Double.isNaN(yStats.stdDev)
 
184
        && !Utils.eq(xStats.stdDev, 0)) {
 
185
      double slope = (xySum - xStats.sum * yStats.sum / count)
 
186
        / (xStats.sumSq - xStats.sum * xStats.mean);
 
187
      if (!Utils.eq(yStats.stdDev, 0)) {
 
188
        correlation = slope * xStats.stdDev / yStats.stdDev;
 
189
      } else {
 
190
        correlation = 1.0;
 
191
      }
 
192
    }
 
193
 
 
194
    if (Utils.gr(differencesStats.stdDev, 0)) {
 
195
      double tval = differencesStats.mean
 
196
        * Math.sqrt(count)
 
197
        / differencesStats.stdDev;
 
198
 
 
199
      if (m_degreesOfFreedom >= 1){
 
200
        differencesProbability = Statistics.FProbability(tval * tval, 1,
 
201
                                                         m_degreesOfFreedom);
 
202
      } else {
 
203
        if (count > 1) {
 
204
          differencesProbability = Statistics.FProbability(tval * tval, 1,
 
205
                                                           (int) count - 1);
 
206
        } else {
 
207
          differencesProbability = 1;
 
208
        }
 
209
      }
 
210
    } else {
 
211
      if (differencesStats.sumSq == 0) {
 
212
        differencesProbability = 1.0;
 
213
      } else {
 
214
        differencesProbability = 0.0;
 
215
      }
 
216
    }
 
217
    differencesSignificance = 0;
 
218
    if (differencesProbability <= sigLevel) {
 
219
      if (xStats.mean > yStats.mean) {
 
220
        differencesSignificance = 1;
 
221
      } else {
 
222
        differencesSignificance = -1;
 
223
      }
 
224
    }
 
225
  }
 
226
    
 
227
  /**
 
228
   * Returns statistics on the paired comparison.
 
229
   *
 
230
   * @return the t-test statistics as a string
 
231
   */
 
232
  public String toString() {
 
233
 
 
234
    return "Analysis for " + Utils.doubleToString(count, 0)
 
235
      + " points:\n"
 
236
      + "                "
 
237
      + "         Column 1"
 
238
      + "         Column 2"
 
239
      + "       Difference\n"
 
240
      + "Minimums        "
 
241
      + Utils.doubleToString(xStats.min, 17, 4)
 
242
      + Utils.doubleToString(yStats.min, 17, 4)
 
243
      + Utils.doubleToString(differencesStats.min, 17, 4) + '\n'
 
244
      + "Maximums        "
 
245
      + Utils.doubleToString(xStats.max, 17, 4)
 
246
      + Utils.doubleToString(yStats.max, 17, 4)
 
247
      + Utils.doubleToString(differencesStats.max, 17, 4) + '\n'
 
248
      + "Sums            "
 
249
      + Utils.doubleToString(xStats.sum, 17, 4)
 
250
      + Utils.doubleToString(yStats.sum, 17, 4)
 
251
      + Utils.doubleToString(differencesStats.sum, 17, 4) + '\n'
 
252
      + "SumSquares      "
 
253
      + Utils.doubleToString(xStats.sumSq, 17, 4)
 
254
      + Utils.doubleToString(yStats.sumSq, 17, 4)
 
255
      + Utils.doubleToString(differencesStats.sumSq, 17, 4) + '\n'
 
256
      + "Means           "
 
257
      + Utils.doubleToString(xStats.mean, 17, 4)
 
258
      + Utils.doubleToString(yStats.mean, 17, 4)
 
259
      + Utils.doubleToString(differencesStats.mean, 17, 4) + '\n'
 
260
      + "SDs             "
 
261
      + Utils.doubleToString(xStats.stdDev, 17, 4)
 
262
      + Utils.doubleToString(yStats.stdDev, 17, 4)
 
263
      + Utils.doubleToString(differencesStats.stdDev, 17, 4) + '\n'
 
264
      + "Prob(differences) "
 
265
      + Utils.doubleToString(differencesProbability, 4)
 
266
      + " (sigflag " + differencesSignificance + ")\n"
 
267
      + "Correlation       "
 
268
      + Utils.doubleToString(correlation,4) + "\n";
 
269
  }
 
270
 
 
271
  /**
 
272
   * Tests the paired stats object from the command line.
 
273
   * reads line from stdin, expecting two values per line.
 
274
   *
 
275
   * @param args ignored.
 
276
   */
 
277
  public static void main(String [] args) {
 
278
 
 
279
    try {
 
280
      PairedStats ps = new PairedStats(0.05);
 
281
      java.io.LineNumberReader r = new java.io.LineNumberReader(
 
282
                                   new java.io.InputStreamReader(System.in));
 
283
      String line;
 
284
      while ((line = r.readLine()) != null) {
 
285
        line = line.trim();
 
286
        if (line.equals("") || line.startsWith("@") || line.startsWith("%")) {
 
287
          continue;
 
288
        }
 
289
        java.util.StringTokenizer s 
 
290
          = new java.util.StringTokenizer(line, " ,\t\n\r\f");
 
291
        int count = 0;
 
292
        double v1 = 0, v2 = 0;
 
293
        while (s.hasMoreTokens()) {
 
294
          double val = (new Double(s.nextToken())).doubleValue();
 
295
          if (count == 0) {
 
296
            v1 = val;
 
297
          } else if (count == 1) {
 
298
            v2 = val;
 
299
          } else {
 
300
            System.err.println("MSG: Too many values in line \"" 
 
301
                               + line + "\", skipped.");
 
302
            break;
 
303
          }
 
304
          count++;
 
305
        }
 
306
        if (count == 2) {
 
307
          ps.add(v1, v2);
 
308
        }
 
309
      }
 
310
      ps.calculateDerived();
 
311
      System.err.println(ps);
 
312
    } catch (Exception ex) {
 
313
      ex.printStackTrace();
 
314
      System.err.println(ex.getMessage());
 
315
    }
 
316
  }
 
317
} // PairedStats
 
318
 
 
319