001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2022, 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-2022, 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.internal.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 row : validRows) { 136 if (row < rowCount) { 137 Number n = data.getValue(row, column); 138 if (n != null) { 139 total += n.doubleValue(); 140 } 141 } 142 } 143 return total; 144 } 145 146 /** 147 * Returns the total of the values in one row of the supplied data 148 * table. 149 * 150 * @param data the table of values ({@code null} not permitted). 151 * @param row the row index (zero-based). 152 * 153 * @return The total of the values in the specified row. 154 */ 155 public static double calculateRowTotal(Values2D data, int row) { 156 Args.nullNotPermitted(data, "data"); 157 double total = 0.0; 158 int columnCount = data.getColumnCount(); 159 for (int c = 0; c < columnCount; c++) { 160 Number n = data.getValue(row, c); 161 if (n != null) { 162 total += n.doubleValue(); 163 } 164 } 165 return total; 166 } 167 168 /** 169 * Returns the total of the values in one row of the supplied data 170 * table by taking only the column numbers in the array into account. 171 * 172 * @param data the table of values ({@code null} not permitted). 173 * @param row the row index (zero-based). 174 * @param validCols the array with valid cols (zero-based). 175 * 176 * @return The total of the valid values in the specified row. 177 */ 178 public static double calculateRowTotal(Values2D data, int row, 179 int[] validCols) { 180 Args.nullNotPermitted(data, "data"); 181 double total = 0.0; 182 int colCount = data.getColumnCount(); 183 for (int col : validCols) { 184 if (col < colCount) { 185 Number n = data.getValue(row, col); 186 if (n != null) { 187 total += n.doubleValue(); 188 } 189 } 190 } 191 return total; 192 } 193 194 /** 195 * Constructs an array of {@code Number} objects from an array of 196 * {@code double} primitives. 197 * 198 * @param data the data ({@code null} not permitted). 199 * 200 * @return An array of {@code double}. 201 */ 202 public static Number[] createNumberArray(double[] data) { 203 Args.nullNotPermitted(data, "data"); 204 Number[] result = new Number[data.length]; 205 for (int i = 0; i < data.length; i++) { 206 result[i] = data[i]; 207 } 208 return result; 209 } 210 211 /** 212 * Constructs an array of arrays of {@code Number} objects from a 213 * corresponding structure containing {@code double} primitives. 214 * 215 * @param data the data ({@code null} not permitted). 216 * 217 * @return An array of {@code double}. 218 */ 219 public static Number[][] createNumberArray2D(double[][] data) { 220 Args.nullNotPermitted(data, "data"); 221 int l1 = data.length; 222 Number[][] result = new Number[l1][]; 223 for (int i = 0; i < l1; i++) { 224 result[i] = createNumberArray(data[i]); 225 } 226 return result; 227 } 228 229 /** 230 * Returns a {@link KeyedValues} instance that contains the cumulative 231 * percentage values for the data in another {@link KeyedValues} instance. 232 * <p> 233 * The percentages are values between 0.0 and 1.0 (where 1.0 = 100%). 234 * 235 * @param data the data ({@code null} not permitted). 236 * 237 * @return The cumulative percentages. 238 */ 239 public static <K extends Comparable<K>> KeyedValues<K> getCumulativePercentages(KeyedValues<K> data) { 240 Args.nullNotPermitted(data, "data"); 241 DefaultKeyedValues<K> result = new DefaultKeyedValues<>(); 242 double total = 0.0; 243 for (int i = 0; i < data.getItemCount(); i++) { 244 Number v = data.getValue(i); 245 if (v != null) { 246 total = total + v.doubleValue(); 247 } 248 } 249 double runningTotal = 0.0; 250 for (int i = 0; i < data.getItemCount(); i++) { 251 Number v = data.getValue(i); 252 if (v != null) { 253 runningTotal = runningTotal + v.doubleValue(); 254 } 255 result.addValue(data.getKey(i), runningTotal / total); 256 } 257 return result; 258 } 259 260}