/* * @(#)Sampler.java 0.0.0 99/07/05 * * Copyright (c) 1999 by Willie Wheeler. All rights reserved. */ package stats; import java.util.*; import javax.swing.*; import javax.swing.event.*; /** * Draws ordered random samples from a given population. Samples can be * drawn with or without replacement. Sample elements having the same * variable values are indistinguishable. * * @version 0.0.0 07/05/99 * @author Willie Wheeler */ public class Sampler extends JComponent implements TableModelListener { static boolean debug = false; protected DataTableModel pop, sample; protected int sampleSize; protected boolean replace; /** * Permutation of population indices used to optimize sampling without * replacement. A sample is obtained by shuffling the permutation and * keeping an initial segment. */ protected List popPerm; /** * Bag (i.e., unordered, multiplicity > 1 OK) sample representation. This * can be useful for rendering samples. */ protected Map sampleBag; public Sampler() { debug("", "Entered."); this.pop = null; this.sampleSize = 0; this.replace = false; } public Sampler(DataTableModel pop, int sampleSize, boolean replace) { debug("", "Entered."); setPopulation(pop); this.sampleSize = sampleSize; this.replace = replace; } public void setPopulation(DataTableModel pop) { debug("setPopulation()", "Entered."); this.pop = pop; // Build population index permutation. int popSize = pop.getRowCount(); popPerm = new Vector(popSize); for (int i = 0; i < popSize; i++) { popPerm.add(new Integer(i)); } // Build table representation of the sample, and add this sampler // as a listener. sample = new DataTableModel(pop.getVariables(), 0); sample.addTableModelListener(this); // Build a bag representation of the sample. sampleBag = new HashMap(); } public DataTableModel getPopulation() { debug("getPopulation()", "Entered."); return pop; } public int getPopulationSize() { debug("getPopulationSize()", "Entered."); return pop.getRowCount(); } public void setSampleSize(int sampleSize) { debug("setSampleSize()", "Entered."); this.sampleSize = sampleSize; } public int getSampleSize() { debug("getSampleSize()", "Entered."); return sampleSize; } public void setReplace(boolean replace) { debug("setReplace()", "Entered, replace=" + replace + "."); this.replace = replace; } public boolean getReplace() { debug("getReplace()", "Entered."); return replace; } public DataTableModel getDataOut() { debug("getDataOut()", "Entered."); return sample; } /** * Returns the sample multiplicity of the given population element. * * @param popID population element ID * @return multiplicity of the given population element */ public int getMultiplicity(int popID) { Integer mult = (Integer)sampleBag.get(new Integer(popID)); return (mult == null ? 0 : mult.intValue()); } public void drawSample() { debug("drawSample()", "Entered."); // Get a reference to the sample table's internal data vector. Vector dataVector = sample.getDataVector(); // Initialize. int popSize = pop.getRowCount(); int numVars = pop.getColumnCount(); dataVector.clear(); sampleBag.clear(); if (!replace) { Collections.shuffle(popPerm); } // Draw a sample. for (int i = 0; i < sampleSize; i++) { // Pick a population element. int popID = replace ? (int)(popSize * Math.random()) : ((Integer)popPerm.get(i)).intValue(); // Add it to the sample table. Vector rowData = new Vector(numVars); for (int j = 0; j < numVars; j++) { rowData.add(pop.getValueAt(popID, j)); } dataVector.add(rowData); // Add it to the sample bag. sampleBag.put(new Integer(popID), new Integer(getMultiplicity(popID) + 1)); } // Manually fire a table model event. sample.fireTableDataChanged(); } public void tableChanged(TableModelEvent e) { debug("tableChanged()", "Entered."); repaint(); } static void debug(String method, String msg) { if (debug) { System.err.println("Sampler." + method + ": " + msg); } } }