MakeIndicatorFilter.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 12k
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.  *    MakeIndicatorFilter.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.  * Creates a new dataset with a boolean attribute replacing a nominal
  27.  * attribute.  In the new dataset, a value of 1 is assigned to an
  28.  * instance that exhibits a particular range of attribute values, a 0 to an
  29.  * instance that doesn't. The boolean attribute is coded as numeric by
  30.  * default.<p>
  31.  * 
  32.  * Valid filter-specific options are: <p>
  33.  *
  34.  * -C col <br>
  35.  * Index of the attribute to be changed. (default "last")<p>
  36.  *
  37.  * -V index1,index2-index4,...<br>
  38.  * Specify list of values to indicate. First and last are valid indices.
  39.  * (default "last")<p>
  40.  *
  41.  * -N <br>
  42.  * Set if new boolean attribute nominal.<p>
  43.  *
  44.  * @author Eibe Frank (eibe@cs.waikato.ac.nz) 
  45.  * @version $Revision: 1.14 $
  46.  *
  47.  */
  48. public class MakeIndicatorFilter extends Filter implements OptionHandler {
  49.   /** The attribute's index option setting. */
  50.   private int m_AttIndexSet = -1;
  51.   /** The attribute's index */
  52.   private int m_AttIndex;
  53.   /** The value's index */
  54.   private Range m_ValIndex;
  55.   
  56.   /** Make boolean attribute numeric. */
  57.   private boolean m_Numeric = true;
  58.   public MakeIndicatorFilter() {
  59.       m_ValIndex = new Range("last");
  60.   }
  61.   /**
  62.    * Sets the format of the input instances.
  63.    *
  64.    * @param instanceInfo an Instances object containing the input 
  65.    * instance structure (any instances contained in the object are 
  66.    * ignored - only the structure is required).
  67.    * @return true if the outputFormat may be collected immediately
  68.    * @exception UnsupportedAttributeTypeException the selecte attribute is not nominal
  69.    * @exception UnsupportedAttributeTypeException the selecte attribute has fewer than two values.
  70.    */
  71.   public boolean setInputFormat(Instances instanceInfo) 
  72.        throws Exception {
  73.     super.setInputFormat(instanceInfo);
  74.     m_AttIndex = m_AttIndexSet;
  75.     if (m_AttIndex < 0) {
  76.       m_AttIndex = instanceInfo.numAttributes() - 1;
  77.     }
  78.     
  79.     m_ValIndex.setUpper(instanceInfo.attribute(m_AttIndex).numValues() - 1);
  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.     setOutputFormat();
  87.     return true;
  88.   }
  89.   /**
  90.    * Input an instance for filtering. The instance is processed
  91.    * and made available for output immediately.
  92.    *
  93.    * @param instance the input instance
  94.    * @return true if the filtered instance may now be
  95.    * collected with output().
  96.    * @exception IllegalStateException if no input format has been set.
  97.    */
  98.   public boolean input(Instance instance) {
  99.     if (getInputFormat() == null) {
  100.       throw new IllegalStateException("No input instance format defined");
  101.     }
  102.     if (m_NewBatch) {
  103.       resetQueue();
  104.       m_NewBatch = false;
  105.     }
  106.     Instance newInstance = (Instance)instance.copy();
  107.     if (!newInstance.isMissing(m_AttIndex)) {
  108.       if (m_ValIndex.isInRange((int)newInstance.value(m_AttIndex))) {
  109. newInstance.setValue(m_AttIndex, 1);
  110.       } else {
  111. newInstance.setValue(m_AttIndex, 0);
  112.       }
  113.     }
  114.     push(newInstance);
  115.     return true;
  116.   }
  117.   /**
  118.    * Returns an enumeration describing the available options
  119.    *
  120.    * @return an enumeration of all the available options
  121.    */
  122.   public Enumeration listOptions() {
  123.     Vector newVector = new Vector(3);
  124.     newVector.addElement(new Option(
  125.               "tSets the attribute index.",
  126.               "C", 1, "-C <col>"));
  127.     newVector.addElement(new Option(
  128.               "tSpecify the list of values to indicate. First and last aren"+
  129.               "tvalid indexes (default last)",
  130.               "V", 1, "-V <index1,index2-index4,...>"));
  131.     newVector.addElement(new Option(
  132.               "tSet if new boolean attribute nominal.",
  133.               "N", 0, "-N <index>"));
  134.     return newVector.elements();
  135.   }
  136.   /**
  137.    * Parses the options for this object. Valid options are: <p>
  138.    *
  139.    * -C col <br>
  140.    * Index of the attribute to be changed.<p>
  141.    *
  142.    * -V index1,index2-index4,...<br>
  143.    * Specify list of values to indicate. First and last are valid indices.
  144.    * (default "last")<p>
  145.    *
  146.    * -N <br>
  147.    * Set if new boolean attribute nominal.<p>
  148.    *
  149.    * @param options the list of options as an array of strings
  150.    * @exception Exception if an option is not supported
  151.    */
  152.   public void setOptions(String[] options) throws Exception {
  153.     
  154.     String attIndex = Utils.getOption('C', options);
  155.     if (attIndex.length() != 0) {
  156.       if (attIndex.toLowerCase().equals("last")) {
  157. setAttributeIndex(-1);
  158.       } else if (attIndex.toLowerCase().equals("first")) {
  159. setAttributeIndex(0);
  160.       } else {
  161. setAttributeIndex(Integer.parseInt(attIndex) - 1);
  162.       }
  163.     } else {
  164.       setAttributeIndex(-1);
  165.     }
  166.     
  167.     String valIndex = Utils.getOption('V', options);
  168.     if (valIndex.length() != 0) {
  169.       setValueIndices(valIndex);
  170.     } else {
  171.       setValueIndices("last");
  172.     }
  173.     setNumeric(!Utils.getFlag('N', options));
  174.     if (getInputFormat() != null) {
  175.       setInputFormat(getInputFormat());
  176.     }
  177.   }
  178.   /**
  179.    * Gets the current settings of the filter.
  180.    *
  181.    * @return an array of strings suitable for passing to setOptions
  182.    */
  183.   public String [] getOptions() {
  184.     String [] options = new String [5];
  185.     int current = 0;
  186.     options[current++] = "-C";
  187.     options[current++] = "" + (getAttributeIndex() + 1);
  188.     options[current++] = "-V"; 
  189.     options[current++] = getValueIndices();
  190.     if (!getNumeric()) {
  191.       options[current++] = "-N"; 
  192.     }
  193.     while (current < options.length) {
  194.       options[current++] = "";
  195.     }
  196.     return options;
  197.   }
  198.   /**
  199.    * @return a description of the filter suitable for
  200.    * displaying in the explorer/experimenter gui
  201.    */
  202.   public String globalInfo() {
  203.     return "A filter that creates a new dataset with a boolean attribute "
  204.       + "replacing a nominal attribute.  In the new dataset, a value of 1 is "
  205.       + "assigned to an instance that exhibits a particular range of attribute "
  206.       + "values, a 0 to an instance that doesn't. The boolean attribute is "
  207.       + "coded as numeric by default.";
  208.   }
  209.   /**
  210.    * @return tip text for this property suitable for
  211.    * displaying in the explorer/experimenter gui
  212.    */
  213.   public String attributeIndexTipText() {
  214.     return "Sets which attribute should be replaced by the indicator. This "
  215.       + "attribute must be nominal. Give the attribute index (numbered from "
  216.       + "0). Use -1 to indicate the last attribute.";
  217.   }
  218.   /**
  219.    * Get the index of the attribute used.
  220.    *
  221.    * @return the index of the attribute
  222.    */
  223.   public int getAttributeIndex() {
  224.     return m_AttIndexSet;
  225.   }
  226.   /**
  227.    * Sets index of of the attribute used.
  228.    *
  229.    * @param index the index of the attribute
  230.    */
  231.   public void setAttributeIndex(int attIndex) {
  232.     
  233.     m_AttIndexSet = attIndex;
  234.   }
  235.   /**
  236.    * Get the range containing the indicator values.
  237.    *
  238.    * @return the range containing the indicator values
  239.    */
  240.   public Range getValueRange() {
  241.     return m_ValIndex;
  242.   }
  243.   /**
  244.    * @return tip text for this property suitable for
  245.    * displaying in the explorer/experimenter gui
  246.    */
  247.   public String valueIndicesTipText() {
  248.     return "Specify range of nominal values to act on."
  249.       + " This is a comma separated list of attribute indices (numbered from"
  250.       + " 1), with "first" and "last" valid values. Specify an inclusive"
  251.       + " range with "-". E.g: "first-3,5,6-10,last".";
  252.   }
  253.   /**
  254.    * Get the indices of the indicator values.
  255.    *
  256.    * @return the indices of the indicator values
  257.    */
  258.   public String getValueIndices() {
  259.     return m_ValIndex.getRanges();
  260.   }
  261.   /**
  262.    * Sets indices of the indicator values.
  263.    *
  264.    * @param range the string representation of the indicator value indices
  265.    * @see Range
  266.    */
  267.   public void setValueIndices(String range) {
  268.     
  269.     m_ValIndex.setRanges(range);
  270.   }
  271.   /**
  272.    * Sets index of the indicator value.
  273.    *
  274.    * @param index the index of the indicator value
  275.    */
  276.   public void setValueIndex(int index) {
  277.     setValueIndices("" +  (index + 1));
  278.   }
  279.   /**
  280.    * Set which attributes are to be deleted (or kept if invert is true)
  281.    *
  282.    * @param attributes an array containing indexes of attributes to select.
  283.    * Since the array will typically come from a program, attributes are indexed
  284.    * from 0.
  285.    * @exception InvalidArgumentException if an invalid set of ranges is supplied
  286.    */
  287.   public void setValueIndicesArray(int [] indices) {
  288.     
  289.     setValueIndices(Range.indicesToRangeList(indices));
  290.   }
  291.   /**
  292.    * @return tip text for this property suitable for
  293.    * displaying in the explorer/experimenter gui
  294.    */
  295.   public String numericTipText() {
  296.     return "Determines whether the output indicator attribute is numeric. If "
  297.       + "this is set to false, the output attribute will be nominal.";
  298.   }
  299.   /**
  300.    * Sets if the new Attribute is to be numeric.
  301.    *
  302.    * @param bool true if new Attribute is to be numeric
  303.    */
  304.   public void setNumeric(boolean bool) {
  305.     m_Numeric = bool;
  306.   }
  307.   /**
  308.    * Check if new attribute is to be numeric.
  309.    *
  310.    * @return true if new attribute is to be numeric
  311.    */
  312.   public boolean getNumeric() {
  313.     return m_Numeric;
  314.   }
  315.   /**
  316.    * Set the output format.
  317.    */
  318.   private void setOutputFormat() {
  319.     
  320.     Instances newData;
  321.     FastVector newAtts, newVals;
  322.       
  323.     // Compute new attributes
  324.     
  325.     newAtts = new FastVector(getInputFormat().numAttributes());
  326.     for (int j = 0; j < getInputFormat().numAttributes(); j++) {
  327.       Attribute att = getInputFormat().attribute(j);
  328.       if (j != m_AttIndex) {
  329. newAtts.addElement(att.copy());
  330.       } else {
  331. if (m_Numeric) {
  332.   newAtts.addElement(new Attribute(att.name()));
  333. } else {
  334.           String vals;
  335.           int [] sel = m_ValIndex.getSelection();
  336.           if (sel.length == 1) {
  337.             vals = att.value(sel[0]);
  338.           } else {
  339.             vals = m_ValIndex.getRanges().replace(',','_');
  340.           }
  341.   newVals = new FastVector(2);
  342.   newVals.addElement("neg_" + vals);
  343.   newVals.addElement("pos_" + vals);
  344.   newAtts.addElement(new Attribute(att.name(), newVals));
  345. }
  346.       }
  347.     }
  348.     // Construct new header
  349.     newData = new Instances(getInputFormat().relationName(), newAtts, 0);
  350.     newData.setClassIndex(getInputFormat().classIndex());
  351.     setOutputFormat(newData);
  352.   }
  353.  
  354.   /**
  355.    * Main method for testing this class.
  356.    *
  357.    * @param argv should contain arguments to the filter: 
  358.    * use -h for help
  359.    */
  360.   public static void main(String [] argv) {
  361.     try {
  362.       if (Utils.getFlag('b', argv)) {
  363.   Filter.batchFilterFile(new MakeIndicatorFilter(), argv);
  364.       } else {
  365. Filter.filterFile(new MakeIndicatorFilter(), argv);
  366.       }
  367.     } catch (Exception ex) {
  368.       System.out.println(ex.getMessage());
  369.     }
  370.   }
  371. }