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