source: src/main/java/weka/gui/AttributeSummaryPanel.java @ 24

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

Import di weka.

File size: 13.4 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 *    AttributeSummaryPanel.java
19 *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23
24package weka.gui;
25
26import weka.core.Attribute;
27import weka.core.AttributeStats;
28import weka.core.Instances;
29import weka.core.Utils;
30
31import java.awt.BorderLayout;
32import java.awt.GridBagConstraints;
33import java.awt.GridBagLayout;
34
35import javax.swing.BorderFactory;
36import javax.swing.JLabel;
37import javax.swing.JPanel;
38import javax.swing.JScrollPane;
39import javax.swing.JTable;
40import javax.swing.ListSelectionModel;
41import javax.swing.SwingConstants;
42import javax.swing.SwingUtilities;
43import javax.swing.table.DefaultTableCellRenderer;
44import javax.swing.table.DefaultTableModel;
45
46/**
47 * This panel displays summary statistics about an attribute: name, type
48 * number/% of missing/unique values, number of distinct values. For
49 * numeric attributes gives some other stats (mean/std dev), for nominal
50 * attributes gives counts for each attribute value.
51 *
52 * @author Len Trigg (trigg@cs.waikato.ac.nz)
53 * @version $Revision: 5297 $
54 */
55public class AttributeSummaryPanel 
56  extends JPanel {
57 
58  /** for serialization */
59  static final long serialVersionUID = -5434987925737735880L;
60
61  /** Message shown when no instances have been loaded and no attribute set */
62  protected static final String NO_SOURCE = "None";
63
64  /** Displays the name of the relation */
65  protected JLabel m_AttributeNameLab = new JLabel(NO_SOURCE);
66 
67  /** Displays the type of attribute */
68  protected JLabel m_AttributeTypeLab = new JLabel(NO_SOURCE);
69 
70  /** Displays the number of missing values */
71  protected JLabel m_MissingLab = new JLabel(NO_SOURCE);
72   
73  /** Displays the number of unique values */
74  protected JLabel m_UniqueLab = new JLabel(NO_SOURCE);
75   
76  /** Displays the number of distinct values */
77  protected JLabel m_DistinctLab = new JLabel(NO_SOURCE);
78
79  /** Displays other stats in a table */
80  protected JTable m_StatsTable = new JTable() {
81    /** for serialization */
82    private static final long serialVersionUID = 7165142874670048578L;
83
84    /**
85     * returns always false, since it's just information for the user
86     *
87     * @param row       the row
88     * @param column    the column
89     * @return          always false, i.e., the whole table is not editable
90     */
91    public boolean isCellEditable(int row, int column) {
92      return false;
93    }
94  };
95 
96  /** The instances we're playing with */
97  protected Instances m_Instances;
98
99  /** Cached stats on the attributes we've summarized so far */
100  protected AttributeStats [] m_AttributeStats;
101 
102  /** Do all instances have the same weight */
103  protected boolean m_allEqualWeights = true;
104 
105  /**
106   * Creates the instances panel with no initial instances.
107   */
108  public AttributeSummaryPanel() {
109
110    JPanel simple = new JPanel();
111    GridBagLayout gbL = new GridBagLayout();
112    simple.setLayout(gbL);
113    JLabel lab = new JLabel("Name:", SwingConstants.RIGHT);
114    lab.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
115    GridBagConstraints gbC = new GridBagConstraints();
116    gbC.anchor = GridBagConstraints.EAST;
117    gbC.fill = GridBagConstraints.HORIZONTAL;
118    gbC.gridy = 0;     gbC.gridx = 0;
119    gbL.setConstraints(lab, gbC);
120    simple.add(lab);
121    gbC = new GridBagConstraints();
122    gbC.anchor = GridBagConstraints.WEST;
123    gbC.fill = GridBagConstraints.HORIZONTAL;
124    gbC.gridy = 0;     gbC.gridx = 1;
125    gbC.weightx = 100; gbC.gridwidth = 3;
126    gbL.setConstraints(m_AttributeNameLab, gbC);
127    simple.add(m_AttributeNameLab);
128    m_AttributeNameLab.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 10));
129   
130    lab = new JLabel("Type:", SwingConstants.RIGHT);
131    lab.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
132    gbC = new GridBagConstraints();
133    gbC.anchor = GridBagConstraints.EAST;
134    gbC.fill = GridBagConstraints.HORIZONTAL;
135    gbC.gridy = 0;     gbC.gridx = 4;
136    gbL.setConstraints(lab, gbC);
137    simple.add(lab);
138    gbC = new GridBagConstraints();
139    gbC.anchor = GridBagConstraints.WEST;
140    gbC.fill = GridBagConstraints.HORIZONTAL;
141    gbC.gridy = 0;     gbC.gridx = 5;
142    gbC.weightx = 100;
143    gbL.setConstraints(m_AttributeTypeLab, gbC);
144    simple.add(m_AttributeTypeLab);
145    m_AttributeTypeLab.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 10));
146
147    // Put into a separate panel?
148    lab = new JLabel("Missing:", SwingConstants.RIGHT);
149    lab.setBorder(BorderFactory.createEmptyBorder(0, 10, 5, 0));
150    gbC = new GridBagConstraints();
151    gbC.anchor = GridBagConstraints.EAST;
152    gbC.fill = GridBagConstraints.HORIZONTAL;
153    gbC.gridy = 1;     gbC.gridx = 0;
154    gbL.setConstraints(lab, gbC);
155    simple.add(lab);
156    gbC = new GridBagConstraints();
157    gbC.anchor = GridBagConstraints.WEST;
158    gbC.fill = GridBagConstraints.HORIZONTAL;
159    gbC.gridy = 1;     gbC.gridx = 1;
160    gbC.weightx = 100;
161    gbL.setConstraints(m_MissingLab, gbC);
162    simple.add(m_MissingLab);
163    m_MissingLab.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 10));
164
165    lab = new JLabel("Distinct:", SwingConstants.RIGHT);
166    lab.setBorder(BorderFactory.createEmptyBorder(0, 10, 5, 0));
167    gbC = new GridBagConstraints();
168    gbC.anchor = GridBagConstraints.EAST;
169    gbC.fill = GridBagConstraints.HORIZONTAL;
170    gbC.gridy = 1;     gbC.gridx = 2;
171    gbL.setConstraints(lab, gbC);
172    simple.add(lab);
173    gbC = new GridBagConstraints();
174    gbC.anchor = GridBagConstraints.WEST;
175    gbC.fill = GridBagConstraints.HORIZONTAL;
176    gbC.gridy = 1;     gbC.gridx = 3;
177    gbC.weightx = 100;
178    gbL.setConstraints(m_DistinctLab, gbC);
179    simple.add(m_DistinctLab);
180    m_DistinctLab.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 10));
181
182    lab = new JLabel("Unique:", SwingConstants.RIGHT);
183    lab.setBorder(BorderFactory.createEmptyBorder(0, 10, 5, 0));
184    gbC = new GridBagConstraints();
185    gbC.anchor = GridBagConstraints.EAST;
186    gbC.fill = GridBagConstraints.HORIZONTAL;
187    gbC.gridy = 1;     gbC.gridx = 4;
188    gbL.setConstraints(lab, gbC);
189    simple.add(lab);
190    gbC = new GridBagConstraints();
191    gbC.anchor = GridBagConstraints.WEST;
192    gbC.fill = GridBagConstraints.HORIZONTAL;
193    gbC.gridy = 1;     gbC.gridx = 5;
194    gbC.weightx = 100;
195    gbL.setConstraints(m_UniqueLab, gbC);
196    simple.add(m_UniqueLab);
197    m_UniqueLab.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 10));
198   
199    setLayout(new BorderLayout());
200    add(simple, BorderLayout.NORTH);
201    add(new JScrollPane(m_StatsTable), BorderLayout.CENTER);
202    m_StatsTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
203  }
204
205  /**
206   * Tells the panel to use a new set of instances.
207   *
208   * @param inst a set of Instances
209   */
210  public void setInstances(Instances inst) {
211   
212    m_Instances = inst;
213    m_AttributeStats = new AttributeStats [inst.numAttributes()];
214    m_AttributeNameLab.setText(NO_SOURCE);
215    m_AttributeTypeLab.setText(NO_SOURCE);
216    m_MissingLab.setText(NO_SOURCE);
217    m_UniqueLab.setText(NO_SOURCE);
218    m_DistinctLab.setText(NO_SOURCE);
219    m_StatsTable.setModel(new DefaultTableModel());
220   
221    m_allEqualWeights = true;
222    double w = m_Instances.instance(0).weight();
223    for (int i = 1; i < m_Instances.numInstances(); i++) {
224      if (m_Instances.instance(i).weight() != w) {
225        m_allEqualWeights = false;
226        break;
227      }
228    }
229  }
230
231  /**
232   * Sets the attribute that statistics will be displayed for.
233   *
234   * @param index the index of the attribute to display
235   */
236  public void setAttribute(final int index) {
237
238    setHeader(index);
239    if (m_AttributeStats[index] == null) {
240      Thread t = new Thread() {
241        public void run() {
242          m_AttributeStats[index] = m_Instances
243          .attributeStats(index);
244          SwingUtilities.invokeLater(new Runnable() {
245            public void run() {
246              setDerived(index);
247              m_StatsTable.sizeColumnsToFit(-1);
248              m_StatsTable.revalidate();
249              m_StatsTable.repaint();
250            }
251          });
252        }
253      };
254      t.setPriority(Thread.MIN_PRIORITY);
255      t.start();
256    } else {
257      setDerived(index);
258    }
259  }
260 
261  /**
262   * Sets the gui elements for fields that are stored in the AttributeStats
263   * structure.
264   *
265   * @param index       the index of the attribute
266   */
267  protected void setDerived(int index) {
268   
269    AttributeStats as = m_AttributeStats[index];
270    long percent = Math.round(100.0 * as.missingCount / as.totalCount);
271    m_MissingLab.setText("" + as.missingCount + " (" + percent + "%)");
272    percent = Math.round(100.0 * as.uniqueCount / as.totalCount);
273    m_UniqueLab.setText("" + as.uniqueCount + " (" + percent + "%)");
274    m_DistinctLab.setText("" + as.distinctCount);
275    setTable(as, index);
276  }
277
278  /**
279   * Creates a tablemodel for the attribute being displayed
280   *
281   * @param as          the attribute statistics
282   * @param index       the index of the attribute
283   */
284  protected void setTable(AttributeStats as, int index) {
285
286    if (as.nominalCounts != null) {
287      Attribute att = m_Instances.attribute(index);
288      Object [] colNames = {"No.", "Label", "Count", "Weight"};
289      Object [][] data = new Object [as.nominalCounts.length][4];
290      for (int i = 0; i < as.nominalCounts.length; i++) {
291        data[i][0] = new Integer(i + 1);
292        data[i][1] = att.value(i);
293        data[i][2] = new Integer(as.nominalCounts[i]);
294        data[i][3] = new Double(Utils.doubleToString(as.nominalWeights[i], 3));
295      }
296      m_StatsTable.setModel(new DefaultTableModel(data, colNames));
297      m_StatsTable.getColumnModel().getColumn(0).setMaxWidth(60);
298      DefaultTableCellRenderer tempR = new DefaultTableCellRenderer();
299      tempR.setHorizontalAlignment(JLabel.RIGHT);
300      m_StatsTable.getColumnModel().getColumn(0).setCellRenderer(tempR);
301    } else if (as.numericStats != null) {
302      Object [] colNames = {"Statistic", "Value"};
303      Object [][] data = new Object [4][2];
304      data[0][0] = "Minimum"; data[0][1] = Utils.doubleToString(as.numericStats.min, 3);
305      data[1][0] = "Maximum"; data[1][1] = Utils.doubleToString(as.numericStats.max, 3);
306      data[2][0] = "Mean" + ((!m_allEqualWeights) ? " (weighted)" : "");   
307      data[2][1] = Utils.doubleToString(as.numericStats.mean, 3);
308      data[3][0] = "StdDev" + ((!m_allEqualWeights) ? " (weighted)" : ""); 
309      data[3][1] = Utils.doubleToString(as.numericStats.stdDev, 3);
310      m_StatsTable.setModel(new DefaultTableModel(data, colNames));
311    } else {
312      m_StatsTable.setModel(new DefaultTableModel());
313    }
314    m_StatsTable.getColumnModel().setColumnMargin(4);
315  }
316 
317  /**
318   * Sets the labels for fields we can determine just from the instance
319   * header.
320   *
321   * @param index       the index of the attribute
322   */
323  protected void setHeader(int index) {
324   
325    Attribute att = m_Instances.attribute(index);
326    m_AttributeNameLab.setText(att.name());
327    switch (att.type()) {
328    case Attribute.NOMINAL:
329      m_AttributeTypeLab.setText("Nominal");
330      break;
331    case Attribute.NUMERIC:
332      m_AttributeTypeLab.setText("Numeric");
333      break;
334    case Attribute.STRING:
335      m_AttributeTypeLab.setText("String");
336      break;
337    case Attribute.DATE:
338      m_AttributeTypeLab.setText("Date");
339      break;
340    case Attribute.RELATIONAL:
341      m_AttributeTypeLab.setText("Relational");
342      break;
343    default:
344      m_AttributeTypeLab.setText("Unknown");
345      break;
346    }
347    m_MissingLab.setText("...");
348    m_UniqueLab.setText("...");
349    m_DistinctLab.setText("...");
350  }
351
352  /**
353   * Tests out the attribute summary panel from the command line.
354   *
355   * @param args optional name of dataset to load
356   */
357  public static void main(String [] args) {
358
359    try {
360      final javax.swing.JFrame jf = new javax.swing.JFrame("Attribute Panel");
361      jf.getContentPane().setLayout(new BorderLayout());
362      final AttributeSummaryPanel p = new AttributeSummaryPanel();
363      p.setBorder(BorderFactory.createTitledBorder("Attribute"));
364      jf.getContentPane().add(p, BorderLayout.CENTER);
365      final javax.swing.JComboBox j = new javax.swing.JComboBox();
366      j.setEnabled(false);
367      j.addActionListener(new java.awt.event.ActionListener() {
368        public void actionPerformed(java.awt.event.ActionEvent e) {
369          p.setAttribute(j.getSelectedIndex());
370        }
371      });
372      jf.getContentPane().add(j, BorderLayout.NORTH);
373      jf.addWindowListener(new java.awt.event.WindowAdapter() {
374        public void windowClosing(java.awt.event.WindowEvent e) {
375          jf.dispose();
376          System.exit(0);
377        }
378      });
379      jf.pack();
380      jf.setVisible(true);
381      if (args.length == 1) {
382        java.io.Reader r = new java.io.BufferedReader(
383                           new java.io.FileReader(args[0]));
384        Instances inst = new Instances(r);
385        p.setInstances(inst);
386        p.setAttribute(0);
387        String [] names = new String [inst.numAttributes()];
388        for (int i = 0; i < names.length; i++) {
389          names[i] = inst.attribute(i).name();
390        }
391        j.setModel(new javax.swing.DefaultComboBoxModel(names));
392        j.setEnabled(true);
393      }
394    } catch (Exception ex) {
395      ex.printStackTrace();
396      System.err.println(ex.getMessage());
397    }
398  }
399}
Note: See TracBrowser for help on using the repository browser.