001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2013, by Object Refinery Limited and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * This library is free software; you can redistribute it and/or modify it 010 * under the terms of the GNU Lesser General Public License as published by 011 * the Free Software Foundation; either version 2.1 of the License, or 012 * (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but 015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 017 * License for more details. 018 * 019 * You should have received a copy of the GNU Lesser General Public 020 * License along with this library; if not, write to the Free Software 021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 022 * USA. 023 * 024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 025 * Other names may be trademarks of their respective owners.] 026 * 027 * ------------------ 028 * DataUtilities.java 029 * ------------------ 030 * (C) Copyright 2003-2013, by Object Refinery Limited and contributors. 031 * 032 * Original Author: David Gilbert (for Object Refinery Limited); 033 * Contributor(s): Peter Kolb (patch 2511330); 034 * 035 * Changes 036 * ------- 037 * 05-Mar-2003 : Version 1 (DG); 038 * 03-Mar-2005 : Moved createNumberArray() and createNumberArray2D() methods 039 * from the DatasetUtilities class (DG); 040 * 17-May-2005 : Added calculateColumnTotal() and calculateRowTotal() 041 * methods (DG); 042 * 28-Jan-2009 : Added equal(double[][], double[][]) method (DG); 043 * 28-Jan-2009 : Added clone(double[][]) method (DG); 044 * 04-Feb-2009 : Added calculateColumnTotal/RowTotal variants (PK); 045 * 03-Jul-2013 : Use ParamChecks (DG); 046 * 047 */ 048 049package org.jfree.data; 050 051import java.util.Arrays; 052import org.jfree.chart.util.ParamChecks; 053import org.jfree.data.general.DatasetUtilities; 054 055/** 056 * Utility methods for use with some of the data classes (but not the datasets, 057 * see {@link DatasetUtilities}). 058 */ 059public abstract class DataUtilities { 060 061 /** 062 * Tests two arrays for equality. To be considered equal, the arrays must 063 * have exactly the same dimensions, and the values in each array must also 064 * match (two values that qre both NaN or both INF are considered equal 065 * in this test). 066 * 067 * @param a the first array (<code>null</code> permitted). 068 * @param b the second array (<code>null</code> permitted). 069 * 070 * @return A boolean. 071 * 072 * @since 1.0.13 073 */ 074 public static boolean equal(double[][] a, double[][] b) { 075 if (a == null) { 076 return (b == null); 077 } 078 if (b == null) { 079 return false; // already know 'a' isn't null 080 } 081 if (a.length != b.length) { 082 return false; 083 } 084 for (int i = 0; i < a.length; i++) { 085 if (!Arrays.equals(a[i], b[i])) { 086 return false; 087 } 088 } 089 return true; 090 } 091 092 /** 093 * Returns a clone of the specified array. 094 * 095 * @param source the source array (<code>null</code> not permitted). 096 * 097 * @return A clone of the array. 098 * 099 * @since 1.0.13 100 */ 101 public static double[][] clone(double[][] source) { 102 ParamChecks.nullNotPermitted(source, "source"); 103 double[][] clone = new double[source.length][]; 104 for (int i = 0; i < source.length; i++) { 105 if (source[i] != null) { 106 double[] row = new double[source[i].length]; 107 System.arraycopy(source[i], 0, row, 0, source[i].length); 108 clone[i] = row; 109 } 110 } 111 return clone; 112 } 113 114 /** 115 * Returns the total of the values in one column of the supplied data 116 * table. 117 * 118 * @param data the table of values (<code>null</code> not permitted). 119 * @param column the column index (zero-based). 120 * 121 * @return The total of the values in the specified column. 122 */ 123 public static double calculateColumnTotal(Values2D data, int column) { 124 ParamChecks.nullNotPermitted(data, "data"); 125 double total = 0.0; 126 int rowCount = data.getRowCount(); 127 for (int r = 0; r < rowCount; r++) { 128 Number n = data.getValue(r, column); 129 if (n != null) { 130 total += n.doubleValue(); 131 } 132 } 133 return total; 134 } 135 136 /** 137 * Returns the total of the values in one column of the supplied data 138 * table by taking only the row numbers in the array into account. 139 * 140 * @param data the table of values (<code>null</code> not permitted). 141 * @param column the column index (zero-based). 142 * @param validRows the array with valid rows (zero-based). 143 * 144 * @return The total of the valid values in the specified column. 145 * 146 * @since 1.0.13 147 */ 148 public static double calculateColumnTotal(Values2D data, int column, 149 int[] validRows) { 150 ParamChecks.nullNotPermitted(data, "data"); 151 double total = 0.0; 152 int rowCount = data.getRowCount(); 153 for (int v = 0; v < validRows.length; v++) { 154 int row = validRows[v]; 155 if (row < rowCount) { 156 Number n = data.getValue(row, column); 157 if (n != null) { 158 total += n.doubleValue(); 159 } 160 } 161 } 162 return total; 163 } 164 165 /** 166 * Returns the total of the values in one row of the supplied data 167 * table. 168 * 169 * @param data the table of values (<code>null</code> not permitted). 170 * @param row the row index (zero-based). 171 * 172 * @return The total of the values in the specified row. 173 */ 174 public static double calculateRowTotal(Values2D data, int row) { 175 ParamChecks.nullNotPermitted(data, "data"); 176 double total = 0.0; 177 int columnCount = data.getColumnCount(); 178 for (int c = 0; c < columnCount; c++) { 179 Number n = data.getValue(row, c); 180 if (n != null) { 181 total += n.doubleValue(); 182 } 183 } 184 return total; 185 } 186 187 /** 188 * Returns the total of the values in one row of the supplied data 189 * table by taking only the column numbers in the array into account. 190 * 191 * @param data the table of values (<code>null</code> not permitted). 192 * @param row the row index (zero-based). 193 * @param validCols the array with valid cols (zero-based). 194 * 195 * @return The total of the valid values in the specified row. 196 * 197 * @since 1.0.13 198 */ 199 public static double calculateRowTotal(Values2D data, int row, 200 int[] validCols) { 201 ParamChecks.nullNotPermitted(data, "data"); 202 double total = 0.0; 203 int colCount = data.getColumnCount(); 204 for (int v = 0; v < validCols.length; v++) { 205 int col = validCols[v]; 206 if (col < colCount) { 207 Number n = data.getValue(row, col); 208 if (n != null) { 209 total += n.doubleValue(); 210 } 211 } 212 } 213 return total; 214 } 215 216 /** 217 * Constructs an array of <code>Number</code> objects from an array of 218 * <code>double</code> primitives. 219 * 220 * @param data the data (<code>null</code> not permitted). 221 * 222 * @return An array of <code>Double</code>. 223 */ 224 public static Number[] createNumberArray(double[] data) { 225 ParamChecks.nullNotPermitted(data, "data"); 226 Number[] result = new Number[data.length]; 227 for (int i = 0; i < data.length; i++) { 228 result[i] = new Double(data[i]); 229 } 230 return result; 231 } 232 233 /** 234 * Constructs an array of arrays of <code>Number</code> objects from a 235 * corresponding structure containing <code>double</code> primitives. 236 * 237 * @param data the data (<code>null</code> not permitted). 238 * 239 * @return An array of <code>Double</code>. 240 */ 241 public static Number[][] createNumberArray2D(double[][] data) { 242 ParamChecks.nullNotPermitted(data, "data"); 243 int l1 = data.length; 244 Number[][] result = new Number[l1][]; 245 for (int i = 0; i < l1; i++) { 246 result[i] = createNumberArray(data[i]); 247 } 248 return result; 249 } 250 251 /** 252 * Returns a {@link KeyedValues} instance that contains the cumulative 253 * percentage values for the data in another {@link KeyedValues} instance. 254 * <p> 255 * The percentages are values between 0.0 and 1.0 (where 1.0 = 100%). 256 * 257 * @param data the data (<code>null</code> not permitted). 258 * 259 * @return The cumulative percentages. 260 */ 261 public static KeyedValues getCumulativePercentages(KeyedValues data) { 262 ParamChecks.nullNotPermitted(data, "data"); 263 DefaultKeyedValues result = new DefaultKeyedValues(); 264 double total = 0.0; 265 for (int i = 0; i < data.getItemCount(); i++) { 266 Number v = data.getValue(i); 267 if (v != null) { 268 total = total + v.doubleValue(); 269 } 270 } 271 double runningTotal = 0.0; 272 for (int i = 0; i < data.getItemCount(); i++) { 273 Number v = data.getValue(i); 274 if (v != null) { 275 runningTotal = runningTotal + v.doubleValue(); 276 } 277 result.addValue(data.getKey(i), new Double(runningTotal / total)); 278 } 279 return result; 280 } 281 282}