source: src/main/java/weka/experiment/PairedStats.java @ 11

Last change on this file since 11 was 4, checked in by gnappo, 14 years ago

Import di weka.

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