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