001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-present, by David Gilbert 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 * DataUtils.java 029 * -------------- 030 * (C) Copyright 2003-present, by David Gilbert and contributors. 031 * 032 * Original Author: David Gilbert; 033 * Contributor(s): Peter Kolb (patch 2511330); 034 * 035 */ 036 037package org.jfree.data; 038 039import java.util.Arrays; 040import org.jfree.chart.util.Args; 041import org.jfree.data.general.DatasetUtils; 042 043/** 044 * Utility methods for use with some of the data classes (but not the datasets, 045 * see {@link DatasetUtils}). 046 */ 047public abstract class DataUtils { 048 049 /** 050 * Tests two arrays for equality. To be considered equal, the arrays must 051 * have exactly the same dimensions, and the values in each array must also 052 * match (two values that qre both NaN or both INF are considered equal 053 * in this test). 054 * 055 * @param a the first array ({@code null} permitted). 056 * @param b the second array ({@code null} permitted). 057 * 058 * @return A boolean. 059 */ 060 public static boolean equal(double[][] a, double[][] b) { 061 if (a == null) { 062 return (b == null); 063 } 064 if (b == null) { 065 return false; // already know 'a' isn't null 066 } 067 if (a.length != b.length) { 068 return false; 069 } 070 for (int i = 0; i < a.length; i++) { 071 if (!Arrays.equals(a[i], b[i])) { 072 return false; 073 } 074 } 075 return true; 076 } 077 078 /** 079 * Returns a clone of the specified array. 080 * 081 * @param source the source array ({@code null} not permitted). 082 * 083 * @return A clone of the array. 084 */ 085 public static double[][] clone(double[][] source) { 086 Args.nullNotPermitted(source, "source"); 087 double[][] clone = new double[source.length][]; 088 for (int i = 0; i < source.length; i++) { 089 if (source[i] != null) { 090 double[] row = new double[source[i].length]; 091 System.arraycopy(source[i], 0, row, 0, source[i].length); 092 clone[i] = row; 093 } 094 } 095 return clone; 096 } 097 098 /** 099 * Returns the total of the values in one column of the supplied data 100 * table. 101 * 102 * @param data the table of values ({@code null} not permitted). 103 * @param column the column index (zero-based). 104 * 105 * @return The total of the values in the specified column. 106 */ 107 public static double calculateColumnTotal(Values2D data, int column) { 108 Args.nullNotPermitted(data, "data"); 109 double total = 0.0; 110 int rowCount = data.getRowCount(); 111 for (int r = 0; r < rowCount; r++) { 112 Number n = data.getValue(r, column); 113 if (n != null) { 114 total += n.doubleValue(); 115 } 116 } 117 return total; 118 } 119 120 /** 121 * Returns the total of the values in one column of the supplied data 122 * table by taking only the row numbers in the array into account. 123 * 124 * @param data the table of values ({@code null} not permitted). 125 * @param column the column index (zero-based). 126 * @param validRows the array with valid rows (zero-based). 127 * 128 * @return The total of the valid values in the specified column. 129 */ 130 public static double calculateColumnTotal(Values2D data, int column, 131 int[] validRows) { 132 Args.nullNotPermitted(data, "data"); 133 double total = 0.0; 134 int rowCount = data.getRowCount(); 135 for (int v = 0; v < validRows.length; v++) { 136 int row = validRows[v]; 137 if (row < rowCount) { 138 Number n = data.getValue(row, column); 139 if (n != null) { 140 total += n.doubleValue(); 141 } 142 } 143 } 144 return total; 145 } 146 147 /** 148 * Returns the total of the values in one row of the supplied data 149 * table. 150 * 151 * @param data the table of values ({@code null} not permitted). 152 * @param row the row index (zero-based). 153 * 154 * @return The total of the values in the specified row. 155 */ 156 public static double calculateRowTotal(Values2D data, int row) { 157 Args.nullNotPermitted(data, "data"); 158 double total = 0.0; 159 int columnCount = data.getColumnCount(); 160 for (int c = 0; c < columnCount; c++) { 161 Number n = data.getValue(row, c); 162 if (n != null) { 163 total += n.doubleValue(); 164 } 165 } 166 return total; 167 } 168 169 /** 170 * Returns the total of the values in one row of the supplied data 171 * table by taking only the column numbers in the array into account. 172 * 173 * @param data the table of values ({@code null} not permitted). 174 * @param row the row index (zero-based). 175 * @param validCols the array with valid cols (zero-based). 176 * 177 * @return The total of the valid values in the specified row. 178 */ 179 public static double calculateRowTotal(Values2D data, int row, 180 int[] validCols) { 181 Args.nullNotPermitted(data, "data"); 182 double total = 0.0; 183 int colCount = data.getColumnCount(); 184 for (int v = 0; v < validCols.length; v++) { 185 int col = validCols[v]; 186 if (col < colCount) { 187 Number n = data.getValue(row, col); 188 if (n != null) { 189 total += n.doubleValue(); 190 } 191 } 192 } 193 return total; 194 } 195 196 /** 197 * Constructs an array of {@code Number} objects from an array of 198 * {@code double} primitives. 199 * 200 * @param data the data ({@code null} not permitted). 201 * 202 * @return An array of {@code double}. 203 */ 204 public static Number[] createNumberArray(double[] data) { 205 Args.nullNotPermitted(data, "data"); 206 Number[] result = new Number[data.length]; 207 for (int i = 0; i < data.length; i++) { 208 result[i] = data[i]; 209 } 210 return result; 211 } 212 213 /** 214 * Constructs an array of arrays of {@code Number} objects from a 215 * corresponding structure containing {@code double} primitives. 216 * 217 * @param data the data ({@code null} not permitted). 218 * 219 * @return An array of {@code double}. 220 */ 221 public static Number[][] createNumberArray2D(double[][] data) { 222 Args.nullNotPermitted(data, "data"); 223 int l1 = data.length; 224 Number[][] result = new Number[l1][]; 225 for (int i = 0; i < l1; i++) { 226 result[i] = createNumberArray(data[i]); 227 } 228 return result; 229 } 230 231 /** 232 * Returns a {@link KeyedValues} instance that contains the cumulative 233 * percentage values for the data in another {@link KeyedValues} instance. 234 * <p> 235 * The percentages are values between 0.0 and 1.0 (where 1.0 = 100%). 236 * 237 * @param data the data ({@code null} not permitted). 238 * 239 * @return The cumulative percentages. 240 */ 241 public static KeyedValues getCumulativePercentages(KeyedValues data) { 242 Args.nullNotPermitted(data, "data"); 243 DefaultKeyedValues result = new DefaultKeyedValues(); 244 double total = 0.0; 245 for (int i = 0; i < data.getItemCount(); i++) { 246 Number v = data.getValue(i); 247 if (v != null) { 248 total = total + v.doubleValue(); 249 } 250 } 251 double runningTotal = 0.0; 252 for (int i = 0; i < data.getItemCount(); i++) { 253 Number v = data.getValue(i); 254 if (v != null) { 255 runningTotal = runningTotal + v.doubleValue(); 256 } 257 result.addValue(data.getKey(i), runningTotal / total); 258 } 259 return result; 260 } 261 262}