MergeTwoValuesFilter.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 11k
Category:

Windows Develop

Development Platform:

Java

  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.  *    MergeTwoValuesFilter.java
  18.  *    Copyright (C) 1999 Eibe Frank
  19.  *
  20.  */
  21. package weka.filters;
  22. import java.io.*;
  23. import java.util.*;
  24. import weka.core.*;
  25. /** 
  26.  * Merges two values of a nominal attribute.<p>
  27.  * 
  28.  * Valid filter-specific options are: <p>
  29.  *
  30.  * -C col <br>
  31.  * The column containing the values to be merged. (default last)<p>
  32.  *
  33.  * -F index <br>
  34.  * Index of the first value (default first).<p>
  35.  *
  36.  * -S index <br>
  37.  * Index of the second value (default last).<p>
  38.  *
  39.  * @author Eibe Frank (eibe@cs.waikato.ac.nz) 
  40.  * @version $Revision: 1.9 $
  41.  */
  42. public class MergeTwoValuesFilter extends Filter implements OptionHandler {
  43.   /** The attribute's index setting. */
  44.   private int m_AttIndexSet = -1; 
  45.   /** The first value's index setting. */
  46.   private int m_FirstIndexSet = 0;
  47.   /** The second value's index setting. */
  48.   private int m_SecondIndexSet = -1;
  49.   /** The attribute's index. */
  50.   private int m_AttIndex; 
  51.   /** The first value's index. */
  52.   private int m_FirstIndex;
  53.   /** The second value's index. */
  54.   private int m_SecondIndex;
  55.   /**
  56.    * Sets the format of the input instances.
  57.    *
  58.    * @param instanceInfo an Instances object containing the input 
  59.    * instance structure (any instances contained in the object are 
  60.    * ignored - only the structure is required).
  61.    * @return true if the outputFormat may be collected immediately
  62.    * @exception Exception if the input format can't be set 
  63.    * successfully
  64.    */
  65.   public boolean setInputFormat(Instances instanceInfo) 
  66.        throws Exception {
  67.     super.setInputFormat(instanceInfo);
  68.     m_AttIndex = m_AttIndexSet;
  69.     if (m_AttIndex < 0) {
  70.       m_AttIndex = instanceInfo.numAttributes() - 1;
  71.     }
  72.     m_FirstIndex = m_FirstIndexSet;
  73.     if (m_FirstIndex < 0) {
  74.       m_FirstIndex = instanceInfo.attribute(m_AttIndex).numValues() - 1;
  75.     }
  76.     m_SecondIndex = m_SecondIndexSet;
  77.     if (m_SecondIndex < 0) {
  78.       m_SecondIndex = instanceInfo.attribute(m_AttIndex).numValues() - 1;
  79.     }
  80.     if (!instanceInfo.attribute(m_AttIndex).isNominal()) {
  81.       throw new UnsupportedAttributeTypeException("Chosen attribute not nominal.");
  82.     }
  83.     if (instanceInfo.attribute(m_AttIndex).numValues() < 2) {
  84.       throw new UnsupportedAttributeTypeException("Chosen attribute has less than two values.");
  85.     }
  86.     if (m_SecondIndex <= m_FirstIndex) {
  87.       // XXX Maybe we should just swap the values??
  88.       throw new Exception("The second index has to be greater "+
  89.   "than the first.");
  90.     }
  91.     setOutputFormat();
  92.     return true;
  93.   }
  94.   /**
  95.    * Input an instance for filtering. The instance is processed
  96.    * and made available for output immediately.
  97.    *
  98.    * @param instance the input instance
  99.    * @return true if the filtered instance may now be
  100.    * collected with output().
  101.    * @exception IllegalStateException if no input format has been set.
  102.    */
  103.   public boolean input(Instance instance) {
  104.     if (getInputFormat() == null) {
  105.       throw new IllegalStateException("No input instance format defined");
  106.     }
  107.     if (m_NewBatch) {
  108.       resetQueue();
  109.       m_NewBatch = false;
  110.     }
  111.     Instance newInstance = (Instance)instance.copy();
  112.     if ((int)newInstance.value(m_AttIndex) == m_SecondIndex) {
  113.       newInstance.setValue(m_AttIndex, (double)m_FirstIndex);
  114.     }
  115.     else if ((int)newInstance.value(m_AttIndex) > m_SecondIndex) {
  116.       newInstance.setValue(m_AttIndex,
  117.    newInstance.value(m_AttIndex) - 1);
  118.     }
  119.     push(newInstance);
  120.     return true;
  121.   }
  122.   /**
  123.    * Returns an enumeration describing the available options
  124.    *
  125.    * @return an enumeration of all the available options
  126.    */
  127.   public Enumeration listOptions() {
  128.     Vector newVector = new Vector(3);
  129.     newVector.addElement(new Option(
  130.               "tSets the attribute index (default last).",
  131.               "C", 1, "-C <col>"));
  132.     newVector.addElement(new Option(
  133.               "tSets the first value's index (default first).",
  134.               "F", 1, "-F <value index>"));
  135.     newVector.addElement(new Option(
  136.               "tSets the second value's index (default last).",
  137.               "S", 1, "-S <value index>"));
  138.     return newVector.elements();
  139.   }
  140.   /**
  141.    * Parses the options for this object. Valid options are: <p>
  142.    *
  143.    * -C col <br>
  144.    * The column containing the values to be merged. (default last)<p>
  145.    *
  146.    * -F index <br>
  147.    * Index of the first value (default first).<p>
  148.    *
  149.    * -S index <br>
  150.    * Index of the second value (default last).<p>
  151.    *
  152.    * @param options the list of options as an array of strings
  153.    * @exception Exception if an option is not supported
  154.    */
  155.   public void setOptions(String[] options) throws Exception {
  156.     
  157.     String attIndex = Utils.getOption('C', options);
  158.     if (attIndex.length() != 0) {
  159.       if (attIndex.toLowerCase().equals("last")) {
  160. setAttributeIndex(-1);
  161.       } else if (attIndex.toLowerCase().equals("first")) {
  162. setAttributeIndex(0);
  163.       } else {
  164. setAttributeIndex(Integer.parseInt(attIndex) - 1);
  165.       }
  166.     } else {
  167.       setAttributeIndex(-1);
  168.     }
  169.     
  170.     String firstIndex = Utils.getOption('F', options);
  171.     if (firstIndex.length() != 0) {
  172.       if (firstIndex.toLowerCase().equals("last")) {
  173. setFirstValueIndex(-1);
  174.       } else if (firstIndex.toLowerCase().equals("first")) {
  175. setFirstValueIndex(0);
  176.       } else {
  177. setFirstValueIndex(Integer.parseInt(firstIndex) - 1);
  178.       }
  179.     } else {
  180.       setFirstValueIndex(0);
  181.     }
  182.      
  183.     String secondIndex = Utils.getOption('S', options);
  184.     if (secondIndex.length() != 0) {
  185.       if (secondIndex.toLowerCase().equals("last")) {
  186. setSecondValueIndex(-1);
  187.       } else if (secondIndex.toLowerCase().equals("first")) {
  188. setSecondValueIndex(0);
  189.       } else {
  190. setSecondValueIndex(Integer.parseInt(secondIndex) - 1);
  191.       }
  192.     } else {
  193.       setSecondValueIndex(-1);
  194.     }
  195.    
  196.     if (getInputFormat() != null) {
  197.       setInputFormat(getInputFormat());
  198.     }
  199.   }
  200.   /**
  201.    * Gets the current settings of the filter.
  202.    *
  203.    * @return an array of strings suitable for passing to setOptions
  204.    */
  205.   public String [] getOptions() {
  206.     String [] options = new String [6];
  207.     int current = 0;
  208.     options[current++] = "-C";
  209.     options[current++] = "" + (getAttributeIndex() + 1);
  210.     options[current++] = "-F"; 
  211.     options[current++] = "" + (getFirstValueIndex() + 1);
  212.     options[current++] = "-S"; 
  213.     options[current++] = "" + (getSecondValueIndex() + 1);
  214.     while (current < options.length) {
  215.       options[current++] = "";
  216.     }
  217.     return options;
  218.   }
  219.   /**
  220.    * Get the index of the attribute used.
  221.    *
  222.    * @return the index of the attribute
  223.    */
  224.   public int getAttributeIndex() {
  225.     return m_AttIndexSet;
  226.   }
  227.   /**
  228.    * Sets index of the attribute used.
  229.    *
  230.    * @param index the index of the attribute
  231.    */
  232.   public void setAttributeIndex(int attIndex) {
  233.     
  234.     m_AttIndexSet = attIndex;
  235.   }
  236.   /**
  237.    * Get the index of the first value used.
  238.    *
  239.    * @return the index of the first value
  240.    */
  241.   public int getFirstValueIndex() {
  242.     return m_FirstIndexSet;
  243.   }
  244.   /**
  245.    * Sets index of the first value used.
  246.    *
  247.    * @param index the index of the first value
  248.    */
  249.   public void setFirstValueIndex(int firstIndex) {
  250.     
  251.     m_FirstIndexSet = firstIndex;
  252.   }
  253.   /**
  254.    * Get the index of the second value used.
  255.    *
  256.    * @return the index of the second value
  257.    */
  258.   public int getSecondValueIndex() {
  259.     return m_SecondIndexSet;
  260.   }
  261.   /**
  262.    * Sets index of the second value used.
  263.    *
  264.    * @param index the index of the second value
  265.    */
  266.   public void setSecondValueIndex(int secondIndex) {
  267.     
  268.     m_SecondIndexSet = secondIndex;
  269.   }
  270.   /**
  271.    * Set the output format. Takes the current average class values
  272.    * and m_InputFormat and calls setOutputFormat(Instances) 
  273.    * appropriately.
  274.    */
  275.   private void setOutputFormat() {
  276.     
  277.     Instances newData;
  278.     FastVector newAtts, newVals;
  279.     boolean firstEndsWithPrime = false, 
  280.       secondEndsWithPrime = false;
  281.     StringBuffer text = new StringBuffer();
  282.       
  283.     // Compute new attributes
  284.       
  285.     newAtts = new FastVector(getInputFormat().numAttributes());
  286.     for (int j = 0; j < getInputFormat().numAttributes(); j++) {
  287.       Attribute att = getInputFormat().attribute(j);
  288.       if (j != m_AttIndex) {
  289. newAtts.addElement(att.copy());
  290.       } else {
  291.   
  292. // Compute new value
  293.   
  294. if (att.value(m_FirstIndex).endsWith("'")) {
  295.   firstEndsWithPrime = true;
  296. }
  297. if (att.value(m_SecondIndex).endsWith("'")) {
  298.   secondEndsWithPrime = true;
  299. }
  300. if (firstEndsWithPrime || secondEndsWithPrime) {
  301.   text.append("'");
  302. }
  303. if (firstEndsWithPrime) {
  304.   text.append(((String)att.value(m_FirstIndex)).
  305.       substring(1, ((String)att.value(m_FirstIndex)).
  306. length() - 1));
  307. } else {
  308.   text.append((String)att.value(m_FirstIndex));
  309. }
  310. text.append('_');
  311. if (secondEndsWithPrime) {
  312.   text.append(((String)att.value(m_SecondIndex)).
  313.       substring(1, ((String)att.value(m_SecondIndex)).
  314. length() - 1));
  315. } else {
  316.   text.append((String)att.value(m_SecondIndex));
  317. }
  318. if (firstEndsWithPrime || secondEndsWithPrime) {
  319.   text.append("'");
  320. }
  321.   
  322. // Compute list of attribute values
  323.   
  324. newVals = new FastVector(att.numValues() - 1);
  325. for (int i = 0; i < att.numValues(); i++) {
  326.   if (i == m_FirstIndex) {
  327.     newVals.addElement(text.toString());
  328.   } else if (i != m_SecondIndex) {
  329.     newVals.addElement(att.value(i));
  330.   }
  331. }
  332. newAtts.addElement(new Attribute(att.name(), newVals));
  333.       }
  334.     }
  335.       
  336.     // Construct new header
  337.       
  338.     newData = new Instances(getInputFormat().relationName(), newAtts,
  339.     0);
  340.     newData.setClassIndex(getInputFormat().classIndex());
  341.     setOutputFormat(newData);
  342.   }
  343.   
  344.   /**
  345.    * Main method for testing this class.
  346.    *
  347.    * @param argv should contain arguments to the filter: 
  348.    * use -h for help
  349.    */
  350.   public static void main(String [] argv) {
  351.     try {
  352.       if (Utils.getFlag('b', argv)) {
  353.   Filter.batchFilterFile(new MergeTwoValuesFilter(), argv);
  354.       } else {
  355. Filter.filterFile(new MergeTwoValuesFilter(), argv);
  356.       }
  357.     } catch (Exception ex) {
  358.       System.out.println(ex.getMessage());
  359.     }
  360.   }
  361. }