source: branches/MetisMQI/src/main/java/weka/filters/unsupervised/attribute/SwapValues.java

Last change on this file was 29, checked in by gnappo, 15 years ago

Taggata versione per la demo e aggiunto branch.

File size: 11.6 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 *    SwapValues.java
19 *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23
24package weka.filters.unsupervised.attribute;
25
26import weka.core.Attribute;
27import weka.core.Capabilities;
28import weka.core.FastVector;
29import weka.core.Instance; 
30import weka.core.DenseInstance;
31import weka.core.Instances;
32import weka.core.Option;
33import weka.core.OptionHandler;
34import weka.core.RevisionUtils;
35import weka.core.SingleIndex;
36import weka.core.UnsupportedAttributeTypeException;
37import weka.core.Utils;
38import weka.core.Capabilities.Capability;
39import weka.filters.Filter;
40import weka.filters.StreamableFilter;
41import weka.filters.UnsupervisedFilter;
42
43import java.util.Enumeration;
44import java.util.Vector;
45
46
47/**
48 <!-- globalinfo-start -->
49 * Swaps two values of a nominal attribute.
50 * <p/>
51 <!-- globalinfo-end -->
52 *
53 <!-- options-start -->
54 * Valid options are: <p/>
55 *
56 * <pre> -C &lt;col&gt;
57 *  Sets the attribute index (default last).</pre>
58 *
59 * <pre> -F &lt;value index&gt;
60 *  Sets the first value's index (default first).</pre>
61 *
62 * <pre> -S &lt;value index&gt;
63 *  Sets the second value's index (default last).</pre>
64 *
65 <!-- options-end -->
66 *
67 * @author Eibe Frank (eibe@cs.waikato.ac.nz)
68 * @version $Revision: 5987 $
69 */
70public class SwapValues 
71  extends Filter
72  implements UnsupervisedFilter, StreamableFilter, OptionHandler {
73 
74  /** for serialization */
75  static final long serialVersionUID = 6155834679414275855L;
76
77  /** The attribute's index setting. */
78  private SingleIndex m_AttIndex = new SingleIndex("last"); 
79
80  /** The first value's index setting. */
81  private SingleIndex m_FirstIndex = new SingleIndex("first");
82
83  /** The second value's index setting. */
84  private SingleIndex m_SecondIndex = new SingleIndex("last");
85
86  /**
87   * Returns a string describing this filter
88   *
89   * @return a description of the filter suitable for
90   * displaying in the explorer/experimenter gui
91   */
92  public String globalInfo() {
93
94    return  "Swaps two values of a nominal attribute.";
95  }
96
97  /**
98   * Returns the Capabilities of this filter.
99   *
100   * @return            the capabilities of this object
101   * @see               Capabilities
102   */
103  public Capabilities getCapabilities() {
104    Capabilities result = super.getCapabilities();
105    result.disableAll();
106
107    // attributes
108    result.enableAllAttributes();
109    result.enable(Capability.MISSING_VALUES);
110   
111    // class
112    result.enableAllClasses();
113    result.enable(Capability.MISSING_CLASS_VALUES);
114    result.enable(Capability.NO_CLASS);
115   
116    return result;
117  }
118
119  /**
120   * Sets the format of the input instances.
121   *
122   * @param instanceInfo an Instances object containing the input
123   * instance structure (any instances contained in the object are
124   * ignored - only the structure is required).
125   * @return true if the outputFormat may be collected immediately
126   * @throws UnsupportedAttributeTypeException if the selected attribute
127   * is not nominal or if it only has one value.
128   * @throws Exception if the input format can't be set
129   * successfully
130   */
131  public boolean setInputFormat(Instances instanceInfo) 
132       throws Exception {
133
134    super.setInputFormat(instanceInfo);
135    m_AttIndex.setUpper(instanceInfo.numAttributes() - 1);
136    m_FirstIndex.setUpper(instanceInfo.
137                          attribute(m_AttIndex.getIndex()).numValues() - 1);
138    m_SecondIndex.setUpper(instanceInfo.
139                           attribute(m_AttIndex.getIndex()).numValues() - 1);
140    if (!instanceInfo.attribute(m_AttIndex.getIndex()).isNominal()) {
141      throw new UnsupportedAttributeTypeException("Chosen attribute not nominal.");
142    }
143    if (instanceInfo.attribute(m_AttIndex.getIndex()).numValues() < 2) {
144      throw new UnsupportedAttributeTypeException("Chosen attribute has less than " 
145                                                  + "two values.");
146    }
147    setOutputFormat();
148    return true;
149  }
150
151  /**
152   * Input an instance for filtering. The instance is processed
153   * and made available for output immediately.
154   *
155   * @param instance the input instance
156   * @return true if the filtered instance may now be
157   * collected with output().
158   * @throws IllegalStateException if no input structure has been defined.
159   */
160  public boolean input(Instance instance) {
161
162    if (getInputFormat() == null) {
163      throw new IllegalStateException("No input instance format defined");
164    }
165    if (m_NewBatch) {
166      resetQueue();
167      m_NewBatch = false;
168    }
169    Instance newInstance = (Instance)instance.copy();
170    if (!newInstance.isMissing(m_AttIndex.getIndex())) {
171      if ((int)newInstance.value(m_AttIndex.getIndex()) == m_SecondIndex.getIndex()) {
172        newInstance.setValue(m_AttIndex.getIndex(), (double)m_FirstIndex.getIndex());
173      } else if ((int)newInstance.value(m_AttIndex.getIndex()) == 
174                 m_FirstIndex.getIndex()) {
175        newInstance.setValue(m_AttIndex.getIndex(), (double)m_SecondIndex.getIndex());
176      }
177    }
178    push(newInstance);
179    return true;
180  }
181
182  /**
183   * Returns an enumeration describing the available options.
184   *
185   * @return an enumeration of all the available options.
186   */
187  public Enumeration listOptions() {
188
189    Vector newVector = new Vector(3);
190
191    newVector.addElement(new Option(
192              "\tSets the attribute index (default last).",
193              "C", 1, "-C <col>"));
194
195    newVector.addElement(new Option(
196              "\tSets the first value's index (default first).",
197              "F", 1, "-F <value index>"));
198
199    newVector.addElement(new Option(
200              "\tSets the second value's index (default last).",
201              "S", 1, "-S <value index>"));
202
203    return newVector.elements();
204  }
205
206
207  /**
208   * Parses a given list of options. <p/>
209   *
210   <!-- options-start -->
211   * Valid options are: <p/>
212   *
213   * <pre> -C &lt;col&gt;
214   *  Sets the attribute index (default last).</pre>
215   *
216   * <pre> -F &lt;value index&gt;
217   *  Sets the first value's index (default first).</pre>
218   *
219   * <pre> -S &lt;value index&gt;
220   *  Sets the second value's index (default last).</pre>
221   *
222   <!-- options-end -->
223   *
224   * @param options the list of options as an array of strings
225   * @throws Exception if an option is not supported
226   */
227  public void setOptions(String[] options) throws Exception {
228   
229    String attIndex = Utils.getOption('C', options);
230    if (attIndex.length() != 0) {
231      setAttributeIndex(attIndex);
232    } else {
233      setAttributeIndex("last");
234    }
235
236    String firstValIndex = Utils.getOption('F', options);
237    if (firstValIndex.length() != 0) {
238      setFirstValueIndex(firstValIndex);
239    } else {
240      setFirstValueIndex("first");
241    }
242
243    String secondValIndex = Utils.getOption('S', options);
244    if (secondValIndex.length() != 0) {
245      setSecondValueIndex(secondValIndex);
246    } else {
247      setSecondValueIndex("last");
248    }
249   
250    if (getInputFormat() != null) {
251      setInputFormat(getInputFormat());
252    }
253  }
254
255  /**
256   * Gets the current settings of the filter.
257   *
258   * @return an array of strings suitable for passing to setOptions
259   */
260  public String [] getOptions() {
261
262    String [] options = new String [6];
263    int current = 0;
264
265    options[current++] = "-C";
266    options[current++] = "" + (getAttributeIndex());
267    options[current++] = "-F"; 
268    options[current++] = "" + (getFirstValueIndex());
269    options[current++] = "-S"; 
270    options[current++] = "" + (getSecondValueIndex());
271    while (current < options.length) {
272      options[current++] = "";
273    }
274    return options;
275  }
276
277  /**
278   * @return tip text for this property suitable for
279   * displaying in the explorer/experimenter gui
280   */
281  public String attributeIndexTipText() {
282
283    return "Sets which attribute to process. This "
284      + "attribute must be nominal (\"first\" and \"last\" are valid values)";
285  }
286
287  /**
288   * Get the index of the attribute used.
289   *
290   * @return the index of the attribute
291   */
292  public String getAttributeIndex() {
293
294    return m_AttIndex.getSingleIndex();
295  }
296
297  /**
298   * Sets index of the attribute used.
299   *
300   * @param attIndex the index of the attribute
301   */
302  public void setAttributeIndex(String attIndex) {
303   
304    m_AttIndex.setSingleIndex(attIndex);
305  }
306
307  /**
308   * @return tip text for this property suitable for
309   * displaying in the explorer/experimenter gui
310   */
311  public String firstValueIndexTipText() {
312
313    return "The index of the first value."
314      + "(\"first\" and \"last\" are valid values)";
315  }
316
317  /**
318   * Get the index of the first value used.
319   *
320   * @return the index of the first value
321   */
322  public String getFirstValueIndex() {
323
324    return m_FirstIndex.getSingleIndex();
325  }
326
327  /**
328   * Sets index of the first value used.
329   *
330   * @param firstIndex the index of the first value
331   */
332  public void setFirstValueIndex(String firstIndex) {
333   
334    m_FirstIndex.setSingleIndex(firstIndex);
335  }
336
337  /**
338   * @return tip text for this property suitable for
339   * displaying in the explorer/experimenter gui
340   */
341  public String secondValueIndexTipText() {
342
343    return "The index of the second value."
344      + "(\"first\" and \"last\" are valid values)";
345  }
346
347  /**
348   * Get the index of the second value used.
349   *
350   * @return the index of the second value
351   */
352  public String getSecondValueIndex() {
353
354    return m_SecondIndex.getSingleIndex();
355  }
356
357  /**
358   * Sets index of the second value used.
359   *
360   * @param secondIndex the index of the second value
361   */
362  public void setSecondValueIndex(String secondIndex) {
363   
364    m_SecondIndex.setSingleIndex(secondIndex);
365  }
366
367  /**
368   * Set the output format. Swapss the desired nominal attribute values in
369   * the header and calls setOutputFormat(Instances) appropriately.
370   */
371  private void setOutputFormat() {
372   
373    Instances newData;
374    FastVector newAtts, newVals;
375     
376    // Compute new attributes
377     
378    newAtts = new FastVector(getInputFormat().numAttributes());
379    for (int j = 0; j < getInputFormat().numAttributes(); j++) {
380      Attribute att = getInputFormat().attribute(j);
381      if (j != m_AttIndex.getIndex()) {
382        newAtts.addElement(att.copy()); 
383      } else {
384         
385        // Compute list of attribute values
386         
387        newVals = new FastVector(att.numValues());
388        for (int i = 0; i < att.numValues(); i++) {
389          if (i == m_FirstIndex.getIndex()) {
390            newVals.addElement(att.value(m_SecondIndex.getIndex()));
391          } else if (i == m_SecondIndex.getIndex()) {
392            newVals.addElement(att.value(m_FirstIndex.getIndex()));
393          } else {
394            newVals.addElement(att.value(i)); 
395          }
396        }
397        newAtts.addElement(new Attribute(att.name(), newVals));
398      }
399    }
400     
401    // Construct new header
402     
403    newData = new Instances(getInputFormat().relationName(), newAtts, 0);
404    newData.setClassIndex(getInputFormat().classIndex());
405    setOutputFormat(newData);
406  }
407 
408  /**
409   * Returns the revision string.
410   *
411   * @return            the revision
412   */
413  public String getRevision() {
414    return RevisionUtils.extract("$Revision: 5987 $");
415  }
416 
417  /**
418   * Main method for testing this class.
419   *
420   * @param argv should contain arguments to the filter:
421   * use -h for help
422   */
423  public static void main(String [] argv) {
424    runFilter(new SwapValues(), argv);
425  }
426}
Note: See TracBrowser for help on using the repository browser.