source: src/main/java/weka/classifiers/evaluation/output/prediction/CSV.java @ 4

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

Import di weka.

File size: 9.3 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 * CSV.java
19 * Copyright (C) 2009 University of Waikato, Hamilton, New Zealand
20 */
21
22package weka.classifiers.evaluation.output.prediction;
23
24import weka.classifiers.Classifier;
25import weka.core.Instance;
26import weka.core.Option;
27import weka.core.Utils;
28
29import java.util.Enumeration;
30import java.util.Vector;
31
32/**
33 <!-- globalinfo-start -->
34 * Outputs the predictions as CSV.
35 * <p/>
36 <!-- globalinfo-end -->
37 *
38 <!-- options-start -->
39 * Valid options are: <p/>
40 *
41 * <pre> -p &lt;range&gt;
42 *  The range of attributes to print in addition to the classification.
43 *  (default: none)</pre>
44 *
45 * <pre> -distribution
46 *  Whether to turn on the output of the class distribution.
47 *  Only for nominal class attributes.
48 *  (default: off)</pre>
49 *
50 * <pre> -decimals &lt;num&gt;
51 *  The number of digits after the decimal point.
52 *  (default: 3)</pre>
53 *
54 * <pre> -file &lt;path&gt;
55 *  The file to store the output in, instead of outputting it on stdout.
56 *  Gets ignored if the supplied path is a directory.
57 *  (default: .)</pre>
58 *
59 * <pre> -suppress
60 *  In case the data gets stored in a file, then this flag can be used
61 *  to suppress the regular output.
62 *  (default: not suppressed)</pre>
63 *
64 * <pre> -use-tab
65 *  Whether to use TAB as separator instead of comma.
66 *  (default: comma)</pre>
67 *
68 <!-- options-end -->
69 *
70 * @author  fracpete (fracpete at waikato dot ac dot nz)
71 * @version $Revision: 5987 $
72 */
73public class CSV
74  extends AbstractOutput {
75 
76  /** for serialization. */
77  private static final long serialVersionUID = 3401604538169573720L;
78
79  /** the delimiter. */
80  protected String m_Delimiter = ",";
81 
82  /**
83   * Returns a string describing the output generator.
84   *
85   * @return            a description suitable for
86   *                    displaying in the GUI
87   */
88  public String globalInfo() {
89    return "Outputs the predictions as CSV.";
90  }
91 
92  /**
93   * Returns a short display text, to be used in comboboxes.
94   *
95   * @return            a short display text
96   */
97  public String getDisplay() {
98    return "CSV";
99  }
100
101  /**
102   * Returns an enumeration of all the available options..
103   *
104   * @return            an enumeration of all available options.
105   */
106  public Enumeration listOptions() {
107    Vector      result;
108    Enumeration enm;
109   
110    result = new Vector();
111   
112    enm = super.listOptions();
113    while (enm.hasMoreElements())
114      result.add(enm.nextElement());
115   
116    result.addElement(new Option(
117        "\tWhether to use TAB as separator instead of comma.\n"
118        + "\t(default: comma)",
119        "use-tab", 0, "-use-tab"));
120   
121    return result.elements();
122  }
123
124  /**
125   * Sets the OptionHandler's options using the given list. All options
126   * will be set (or reset) during this call (i.e. incremental setting
127   * of options is not possible).
128   *
129   * @param options     the list of options as an array of strings
130   * @throws Exception  if an option is not supported
131   */
132  public void setOptions(String[] options) throws Exception {
133    setUseTab(Utils.getFlag("use-tab", options));
134    super.setOptions(options);
135  }
136
137  /**
138   * Gets the current option settings for the OptionHandler.
139   *
140   * @return the list of current option settings as an array of strings
141   */
142  public String[] getOptions() {
143    Vector<String>      result;
144    String[]            options;
145    int                 i;
146   
147    result = new Vector<String>();
148   
149    options = super.getOptions();
150    for (i = 0; i < options.length; i++)
151      result.add(options[i]);
152   
153    if (getUseTab())
154      result.add("-use-tab");
155   
156    return result.toArray(new String[result.size()]);
157  }
158 
159  /**
160   * Sets whether to use tab instead of comma as separator.
161   *
162   * @param value       true if tab is to be used
163   */
164  public void setUseTab(boolean value) {
165    if (value)
166      m_Delimiter = "\t";
167    else
168      m_Delimiter = ",";
169  }
170 
171  /**
172   * Returns whether tab is used as separator.
173   *
174   * @return            true if tab is used instead of comma
175   */
176  public boolean getUseTab() {
177    return m_Delimiter.equals("\t");
178  }
179
180  /**
181   * Returns the tip text for this property.
182   *
183   * @return            tip text for this property suitable for
184   *                    displaying in the GUI
185   */
186  public String useTabTipText() {
187    return "Whether to use TAB instead of COMMA as column separator.";
188  }
189
190  /**
191   * Performs the actual printing of the header.
192   */
193  protected void doPrintHeader() {
194    if (m_Header.classAttribute().isNominal()) {
195      if (m_OutputDistribution) {
196        append("inst#" + m_Delimiter + "actual" + m_Delimiter + "predicted" + m_Delimiter + "error" + m_Delimiter + "distribution");
197        for (int i = 1; i < m_Header.classAttribute().numValues(); i++)
198          append(m_Delimiter);
199      }
200      else {
201        append("inst#" + m_Delimiter + "actual" + m_Delimiter + "predicted" + m_Delimiter + "error" + m_Delimiter + "prediction");
202      }
203    }
204    else {
205      append("inst#" + m_Delimiter + "actual" + m_Delimiter + "predicted" + m_Delimiter + "error");
206    }
207   
208    if (m_Attributes != null) {
209      append(m_Delimiter);
210      boolean first = true;
211      for (int i = 0; i < m_Header.numAttributes(); i++) {
212        if (i == m_Header.classIndex())
213          continue;
214
215        if (m_Attributes.isInRange(i)) {
216          if (!first)
217            append(m_Delimiter);
218          append(m_Header.attribute(i).name());
219          first = false;
220        }
221      }
222    }
223   
224    append("\n");
225  }
226
227  /**
228   * Builds a string listing the attribute values in a specified range of indices,
229   * separated by commas and enclosed in brackets.
230   *
231   * @param instance    the instance to print the values from
232   * @return            a string listing values of the attributes in the range
233   */
234  protected String attributeValuesString(Instance instance) {
235    StringBuffer text = new StringBuffer();
236    if (m_Attributes != null) {
237      m_Attributes.setUpper(instance.numAttributes() - 1);
238      boolean first = true;
239      for (int i=0; i<instance.numAttributes(); i++)
240        if (m_Attributes.isInRange(i) && i != instance.classIndex()) {
241          if (!first)
242            text.append(m_Delimiter);
243          text.append(instance.toString(i));
244          first = false;
245        }
246    }
247    return text.toString();
248  }
249
250  /**
251   * Store the prediction made by the classifier as a string.
252   *
253   * @param classifier  the classifier to use
254   * @param inst        the instance to generate text from
255   * @param index       the index in the dataset
256   * @throws Exception  if something goes wrong
257   */
258  protected void doPrintClassification(Classifier classifier, Instance inst, int index) throws Exception {
259    int prec = m_NumDecimals;
260
261    Instance withMissing = (Instance)inst.copy();
262    withMissing.setDataset(inst.dataset());
263    withMissing.setMissing(withMissing.classIndex());
264    double predValue = classifier.classifyInstance(withMissing);
265
266    // index
267    append("" + (index+1));
268
269    if (inst.dataset().classAttribute().isNumeric()) {
270      // actual
271      if (inst.classIsMissing())
272        append(m_Delimiter + "?");
273      else
274        append(m_Delimiter + Utils.doubleToString(inst.classValue(), prec));
275      // predicted
276      if (Utils.isMissingValue(predValue))
277        append(m_Delimiter + "?");
278      else
279        append(m_Delimiter + Utils.doubleToString(predValue, prec));
280      // error
281      if (Utils.isMissingValue(predValue) || inst.classIsMissing())
282        append(m_Delimiter + "?");
283      else
284        append(m_Delimiter + Utils.doubleToString(predValue - inst.classValue(), prec));
285    } else {
286      // actual
287      append(m_Delimiter + ((int) inst.classValue()+1) + ":" + inst.toString(inst.classIndex()));
288      // predicted
289      if (Utils.isMissingValue(predValue))
290        append(m_Delimiter + "?");
291      else
292        append(m_Delimiter + ((int) predValue+1) + ":" + inst.dataset().classAttribute().value((int)predValue));
293      // error?
294      if (!Utils.isMissingValue(predValue) && !inst.classIsMissing() && ((int) predValue+1 != (int) inst.classValue()+1))
295        append(m_Delimiter + "+");
296      else
297        append(m_Delimiter + "");
298      // prediction/distribution
299      if (m_OutputDistribution) {
300        if (Utils.isMissingValue(predValue)) {
301          append(m_Delimiter + "?");
302        }
303        else {
304          append(m_Delimiter);
305          double[] dist = classifier.distributionForInstance(withMissing);
306          for (int n = 0; n < dist.length; n++) {
307            if (n > 0)
308              append(m_Delimiter);
309            if (n == (int) predValue)
310              append("*");
311            append(Utils.doubleToString(dist[n], prec));
312          }
313        }
314      }
315      else {
316        if (Utils.isMissingValue(predValue))
317          append(m_Delimiter + "?");
318        else
319          append(m_Delimiter + Utils.doubleToString(classifier.distributionForInstance(withMissing) [(int)predValue], prec));
320      }
321    }
322
323    // attributes
324    if (m_Attributes != null)
325      append(m_Delimiter + attributeValuesString(withMissing));
326    append("\n");
327  }
328 
329  /**
330   * Does nothing.
331   */
332  protected void doPrintFooter() {
333  }
334}
Note: See TracBrowser for help on using the repository browser.