/* * ------------------------------------------------------------------------- * $Id: CVPanel.java,v 1.3 2004/10/14 16:20:03 estewart Exp $ * ------------------------------------------------------------------------- * Copyright (c) 2004 Visual Numerics Inc. All Rights Reserved. * * This software is confidential information which is proprietary to * and a trade secret of Visual Numerics, Inc. Use, duplication or * disclosure is subject to the terms of an appropriate license * agreement. * * VISUAL NUMERICS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. VISUAL * NUMERICS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR * ITS DERIVATIVES. *-------------------------------------------------------------------------- */ /* * CorrelationPicture * Copyright (c), 2003, Gary H. McClelland * Shows relationship between degree of scatter in a scattergram * and the correlation coefficient. A slider allows user to change * the degree of scatter and observe the resulting changes in the * correlation coefficient. */ /** * @author Gary H. McClelland * @created 2 October 2003 */ package com.imsl.demo.stats; import com.imsl.chart.*; import com.imsl.stat.Random; import com.imsl.stat.*; import java.awt.*; import java.awt.event.*; import java.text.DecimalFormat; import javax.swing.*; import javax.swing.event.*; public class CVPanel extends JPanel { private JFrame parentFrame; private JPanelChart jPanelChart; private JPanel jPanel; private JLabel jLabel; private JSlider wtSlider; private JButton jButton; private Random rand; Chart chart; AxisXY axis; Data scat; double x[], y[]; final int numberOfPoints = 30; public CVPanel(javax.swing.JFrame parent) { this.parentFrame = parent; initComponents(); setPreferredSize(new java.awt.Dimension( parent.getSize().width, (int)(0.85*parent.getSize().height))); jPanelChart.setPreferredSize(new java.awt.Dimension( parent.getSize().width, (int)(0.66*parent.getSize().height))); //basic chart setup, layout of slider jPanelChart.setChart(new Chart()); chart = jPanelChart.getChart(); axis = new AxisXY(chart); //want fixed, unchanging range for both axes //allowing rescaling would make changes jumpy final double[] range = {0,100}; final DecimalFormat df = new java.text.DecimalFormat("###"); axis.getAxisX().setWindow(range); axis.getAxisY().setWindow(range); axis.getAxisX().setAutoscaleInput(Axis.AUTOSCALE_OFF); axis.getAxisY().setAutoscaleInput(Axis.AUTOSCALE_OFF); axis.getAxisX().getAxisTitle().setTitle("X Values"); axis.getAxisY().getAxisTitle().setTitle("Y Values"); axis.getAxisX().setTextFormat(df); axis.getAxisY().setTextFormat(df); //generate two random variables x = newSample(numberOfPoints,123321); y = newSample(numberOfPoints,321123); //correlation of the two random variables will be near zero //but we want it to be exactly zero x = adjustToZero(x,y); drawGraph(0.0); } private void initComponents() { jPanel = new JPanel(); jPanelChart = new com.imsl.chart.JPanelChart(); setLayout(new BorderLayout()); jPanel.setLayout(new FlowLayout()); jLabel = new JLabel("<html><center>Move the slider to adjust the "+ "<br>correlation between -1 and +1.</center></html>"); jPanel.add(jLabel); wtSlider = new JSlider(JSlider.HORIZONTAL,-500,500,0); wtSlider.setMajorTickSpacing(100); wtSlider.setMinorTickSpacing(25); wtSlider.setPaintTicks(true); wtSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent evt) { sliderChanged(evt); } }); jPanel.add(wtSlider); add(jPanel, BorderLayout.NORTH); jPanelChart.setPreferredSize(new java.awt.Dimension(500, 500)); add(jPanelChart, BorderLayout.CENTER); } // generates random normal variable of length k // rescaled to min = 0 and max = 100 private double[] newSample(int k, int seed) { rand = new Random(seed); double v[] = new double[k]; double min = 1000; double max = -1000; for(int i=0; i<=k-1; i++) { v[i] = rand.nextNormalAR(); //nextNormalAR(); if(v[i] < min) min = v[i]; if(v[i] > max) max = v[i]; } for(int i=0; i<k; i++) v[i] = 100 * (v[i] - min)/(max - min); return v; } private double getCorrelation(double[] x, double[] y) { double mat[][] = new double[y.length][2]; for(int i=0; i<= y.length-1; i++) { mat[i][0] = x[i]; mat[i][1] = y[i]; } Covariances cov = new Covariances(mat); double[][] cor = new double[2][2]; try { cor = cov.compute(Covariances.STDEV_CORRELATION_MATRIX); } catch (Exception e) {} return cor[0][1]; } //computes weighted average of two variables //weight ranges from -1 to +1 private double[] applyWeight(double wt, double u[], double v[]) { double w[] = new double[v.length]; for(int i=0; i<=v.length-1; i++) if(wt >= 0) w[i] = (1-wt)*v[i] + wt*u[i]; else w[i] = (1+wt)*v[i] - wt*(100-u[i]); return w; } //finds weighted average of the two variables that produces a //zero correlation between that weighted average and one of the //variables. private double[] adjustToZero(double u[], double v[]) { double r = getCorrelation(v,u); double minwt = -1; double maxwt = 1; double wt = 0; double tol = .0001; int maxIter = 100; int iter = 0; while(Math.abs(r) > tol && iter < maxIter) { if(r > 0) { //look down maxwt = wt; wt = (minwt + wt)/2; } else { //look up minwt = wt; wt = (maxwt + wt)/2; } r = getCorrelation(v,applyWeight(wt,v,u)); iter = iter + 1; } return applyWeight(wt,v,u); } //slider determines weight and hence correlation private void sliderChanged(ChangeEvent e) { JSlider source = (JSlider)e.getSource(); //get new weight from slider double wt = (double)source.getValue()/500.; drawGraph(wt); repaint(); } //draws scattergram with variable y and the x variable being //a weighted average of x and y. private void drawGraph(double wt) { double r = getCorrelation(applyWeight(wt,y,x),y); final DecimalFormat df = new DecimalFormat("0.000"); try{ chart.getChartTitle().setTitle("r = " + df.format(r)); chart.getChartTitle().setFontSize(16); if(r < 0) chart.getChartTitle().setTextColor(Color.red); else chart.getChartTitle().setTextColor(Color.blue); //get rid of old data if it exists or it persists on graph if(scat != null) scat.remove(); scat = new Data(axis, applyWeight(wt,y,x), y); scat.setDataType(Data.DATA_TYPE_MARKER); scat.setMarkerType(Data.MARKER_TYPE_FILLED_CIRCLE); scat.setMarkerColor(Color.black); } catch (Exception e) {} } }