Java tutorial
/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package geogebra.kernel.statistics; import geogebra.kernel.AlgoElement; import geogebra.kernel.Construction; import geogebra.kernel.GeoBoolean; import geogebra.kernel.GeoElement; import geogebra.kernel.GeoList; import geogebra.kernel.GeoNumeric; import geogebra.kernel.arithmetic.NumberValue; import org.apache.commons.math.MathException; import org.apache.commons.math.distribution.TDistributionImpl; import org.apache.commons.math.stat.descriptive.SummaryStatistics; /** * Calculates a t-confidence interval estimate of the difference of means. * * * @author G. Sturr */ public class AlgoTMean2Estimate extends AlgoElement { private static final long serialVersionUID = 1L; private GeoList geoList1, geoList2; //input private GeoNumeric geoLevel, geoMean1, geoSD1, geoN1, geoMean2, geoSD2, geoN2; //input private GeoBoolean geoPooled; //input private GeoList result; // output private double[] val1, val2; private int size1, size2; private double level, mean1, var1, n1, mean2, var2, n2, me; boolean pooled; private SummaryStatistics stats; private TDistributionImpl tDist; private double difference; public AlgoTMean2Estimate(Construction cons, String label, GeoList geoList1, GeoList geoList2, GeoNumeric geoLevel, GeoBoolean geoPooled) { super(cons); this.geoList1 = geoList1; this.geoList2 = geoList2; this.geoLevel = geoLevel; this.geoPooled = geoPooled; this.geoMean1 = null; this.geoSD1 = null; this.geoN1 = null; this.geoMean2 = null; this.geoSD2 = null; this.geoN2 = null; result = new GeoList(cons); setInputOutput(); // for AlgoElement compute(); result.setLabel(label); } public AlgoTMean2Estimate(Construction cons, String label, GeoNumeric geoMean1, GeoNumeric geoSD1, GeoNumeric geoN1, GeoNumeric geoMean2, GeoNumeric geoSD2, GeoNumeric geoN2, GeoNumeric geoLevel, GeoBoolean geoPooled) { super(cons); this.geoList1 = null; this.geoList2 = null; this.geoLevel = geoLevel; this.geoPooled = geoPooled; this.geoMean1 = geoMean1; this.geoSD1 = geoSD1; this.geoN1 = geoN1; this.geoMean2 = geoMean2; this.geoSD2 = geoSD2; this.geoN2 = geoN2; result = new GeoList(cons); setInputOutput(); // for AlgoElement compute(); result.setLabel(label); } public String getClassName() { return "AlgoTMean2Estimate"; } protected void setInputOutput() { if (geoList1 != null) { input = new GeoElement[4]; input[0] = geoList1; input[1] = geoList2; input[2] = geoLevel; input[3] = geoPooled; } else { input = new GeoElement[8]; input[0] = geoMean1; input[1] = geoSD1; input[2] = geoN1; input[3] = geoMean2; input[4] = geoSD2; input[5] = geoN2; input[6] = geoLevel; input[7] = geoPooled; } output = new GeoElement[1]; output[0] = result; setDependencies(); // done by AlgoElement } public GeoList getResult() { return result; } /** * Computes approximate degrees of freedom for 2-sample t-estimate. * (code from Apache commons, TTestImpl class) * * @param v1 first sample variance * @param v2 second sample variance * @param n1 first sample n * @param n2 second sample n * @return approximate degrees of freedom */ private double getDegreeOfFreedom(double v1, double v2, double n1, double n2, boolean pooled) { if (pooled) return n1 + n2 - 2; else return (((v1 / n1) + (v2 / n2)) * ((v1 / n1) + (v2 / n2))) / ((v1 * v1) / (n1 * n1 * (n1 - 1d)) + (v2 * v2) / (n2 * n2 * (n2 - 1d))); } /** * Computes margin of error for 2-sample t-estimate; * this is the half-width of the confidence interval * * @param v1 first sample variance * @param v2 second sample variance * @param n1 first sample n * @param n2 second sample n * @param confLevel confidence level * @return margin of error for 2 mean interval estimate * @throws MathException */ private double getMarginOfError(double v1, double n1, double v2, double n2, double confLevel, boolean pooled) throws MathException { if (pooled) { double pooledVariance = ((n1 - 1) * v1 + (n2 - 1) * v2) / (n1 + n2 - 2); double se = Math.sqrt(pooledVariance * (1d / n1 + 1d / n2)); tDist = new TDistributionImpl(getDegreeOfFreedom(v1, v2, n1, n2, pooled)); double a = tDist.inverseCumulativeProbability((confLevel + 1d) / 2); return a * se; } else { double se = Math.sqrt((v1 / n1) + (v2 / n2)); tDist = new TDistributionImpl(getDegreeOfFreedom(v1, v2, n1, n2, pooled)); double a = tDist.inverseCumulativeProbability((confLevel + 1d) / 2); return a * se; } } protected final void compute() { try { // get statistics from sample data input if (input.length == 4) { size1 = geoList1.size(); if (!geoList1.isDefined() || size1 < 2) { result.setUndefined(); return; } size2 = geoList2.size(); if (!geoList2.isDefined() || size2 < 2) { result.setUndefined(); return; } val1 = new double[size1]; for (int i = 0; i < size1; i++) { GeoElement geo = geoList1.get(i); if (geo.isNumberValue()) { NumberValue num = (NumberValue) geo; val1[i] = num.getDouble(); } else { result.setUndefined(); return; } } val2 = new double[size2]; for (int i = 0; i < size2; i++) { GeoElement geo = geoList2.get(i); if (geo.isNumberValue()) { NumberValue num = (NumberValue) geo; val2[i] = num.getDouble(); } else { result.setUndefined(); return; } } stats = new SummaryStatistics(); for (int i = 0; i < val1.length; i++) { stats.addValue(val1[i]); } n1 = stats.getN(); var1 = stats.getVariance(); mean1 = stats.getMean(); stats.clear(); for (int i = 0; i < val2.length; i++) { stats.addValue(val2[i]); } n2 = stats.getN(); var2 = stats.getVariance(); mean2 = stats.getMean(); } else { mean1 = geoMean1.getDouble(); var1 = geoSD1.getDouble() * geoSD1.getDouble(); n1 = geoN1.getDouble(); mean2 = geoMean2.getDouble(); var2 = geoSD2.getDouble() * geoSD2.getDouble(); n2 = geoN2.getDouble(); } level = geoLevel.getDouble(); pooled = geoPooled.getBoolean(); // validate statistics if (level < 0 || level > 1 || var1 < 0 || n1 < 1 || var2 < 0 || n2 < 1) { result.setUndefined(); return; } // get interval estimate me = getMarginOfError(var1, n1, var2, n2, level, pooled); // return list = {low limit, high limit, difference, margin of error, df } difference = mean1 - mean2; result.clear(); boolean oldSuppress = cons.isSuppressLabelsActive(); cons.setSuppressLabelCreation(true); result.add(new GeoNumeric(cons, difference - me)); result.add(new GeoNumeric(cons, difference + me)); //result.add(new GeoNumeric(cons, difference)); //result.add(new GeoNumeric(cons, me)); //result.add(new GeoNumeric(cons, getDegreeOfFreedom(var1, var2, n1, n2, pooled))); cons.setSuppressLabelCreation(oldSuppress); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (MathException e) { e.printStackTrace(); } } }