DoubleArray.java [src/java/cfa] Revision: 4daefd1ac3a5cce6d2af07d219b133db7ce0b7a4 Date: Thu Sep 26 16:17:42 MDT 2013
package cfa;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
/**
* Last Updated: 31-January-2013
* @author Tyler Wible
* @since 21-June-2012
*/
public class DoubleArray {
/**
* Append a value on to the end of list of values
* @param currentArray current list of values (double[])
* @param newValue new value to append to the list
* @return the new list containing the currentArray list of values and the appened newValue
*/
public double[] appendcolumn(double[] currentArray, double newValue){
//Initialize new array to contain the new value
double[] newArray = new double[currentArray.length + 1];
//Fill the new array
for(int i=0; i<currentArray.length; i++){
newArray[i] = currentArray[i];
}
//Append newValue
newArray[currentArray.length] = newValue;
return newArray;
}
/**
* Append a value on to the end of list of values
* @param currentArray current list of values (double[])
* @param newValue new value to append to the list
* @return the new list containing the currentArray list of values and the appened newValue
*/
public Double[] appendcolumn(double[] currentArray, double[] newValue){
//Initialize new array to contain the new value
Double[] newArray = new Double[currentArray.length + newValue.length];
//Fill the new array
for(int i=0; i<newArray.length; i++){
if(i<currentArray.length){
newArray[i] = currentArray[i];
}else{
newArray[i] = newValue[i - currentArray.length];
}
}
return newArray;
}
/**
* Appends an array onto another array to create a 2D array. double[][] newArray = {currentArray, newArray};
* @param currentArray1 current list of values (double[])
* @param currentArray2 new value to append to the list (double[])
* @return the new list containing the currentArray list of values and the appened newValue
*/
public double[][] appendcolumn_Matrix(double[] currentArray1, double[] currentArray2){
//Check that the arrays are the same size to be combined
if(currentArray1.length != currentArray2.length){
System.out.println("The arrays are not the same size so they can not be combined");
return new double[0][0];
}
//Initialize new array to contain the new value
double[][] newArray = new double[currentArray1.length][2];
//Fill the new array
for(int i=0; i<newArray.length; i++){
newArray[i][0] = currentArray1[i];
newArray[i][1] = currentArray2[i];
}
return newArray;
}
/**
* Append a value on to the end of list of values
* @param currentArray current list of values (double[][])
* @param newValue new value to append to the list (double[])
* @return the new list containing the currentArray list of values and the appened newValue
*/
public double[][] appendcolumn_Matrix(double[][] array1, double[] array2){
//Check that the arrays are the same size to be combined
if(array1.length != array2.length){
System.out.println("The arrays are not the same size so they can not be combined");
return new double[0][0];
}
//Initialize new array to contain the new value
double[][] newArray = new double[array1.length][array1[0].length + 1];
//Fill the new array
for(int i=0; i<newArray.length; i++){
for(int j=0; j<array1[i].length; j++){
newArray[i][j] = array1[i][j];
}
newArray[i][newArray[i].length - 1] = array2[i];
}
return newArray;
}
/**
* Replace the first ("numberOfRows" + 1) of "startingArray" with those of "replacingArray"
* @param startingArray the double[] array to begin duplicating
* @param replacingArray the double[] array to be used replacing the first (rows + 1) of starting Array
* @param numberOfRows the number of rows in startingArray to be replaced by those in replacingArray
* @return a duplicate of startingArray with the first rows ("numberOfRows" + 1) being from replacingArray not startingArray
*/
public double[] replaceRows(double[] startingArray, double[] replacingArray, int numberOfRows){
//Matlab code: m(Z+1:end) = mh(Z+1:end);
double[] newArray = new double[startingArray.length];
for(int i=0; i<startingArray.length; i++){
if(i<(numberOfRows+1)){
//Replace the elements of startingArray with those of replacingArray
newArray[i] = replacingArray[i];
}else{
//Otherwise keep the elements of startingArray
newArray[i] = startingArray[i];
}
}
return newArray;
}
/**
* Keeps only the rows in startingArray that are not listed in rowIndexList
* @param startingArray The array to be minimized (double[][])
* @param rowIndexList a row index of the rows not to be included in the new minimized array (ArrayList<Integer>)
* @return the minimized version of the startingArray (double[][])
*/
public double[][] replaceRows(double[][] startingArray, ArrayList<Integer> rowIndexList){
//Initialize new array
double[][] newArray = new double[startingArray.length][startingArray[0].length];
//Keep only the rows in startingArray that are not contained in the rowIndexList
int indexCtr = 0;
int currentRowIndex = rowIndexList.get(indexCtr);
for(int i=0; i<startingArray.length; i++){//Loop rows of startingArray
if(i != currentRowIndex){//Check if the current row should be kept or not
//Keep current row's infomation
newArray[i][0] = startingArray[i][0];//Populate the newArray with the content of startingArray
newArray[i][1] = startingArray[i][1];
}else{
//Don't keep current row's information
newArray[i][0] = startingArray[i][0];//Populate the newArray with the content of startingArray
newArray[i][1] = 99999;//replace the values below 0.002
indexCtr++;
if(indexCtr >= rowIndexList.size()){
//If the indexCtr == rowIndexList.size then the last row index has been used out
//of the rowIndexList so define an empty early index to keep the loop going
currentRowIndex = 0;
}else{
//Then get the next row
currentRowIndex = rowIndexList.get(indexCtr);
}
}
}
return newArray;
}
/**
* Gets the unique values of the specified column of a double[][] array
* @param dataArray the double array
* @param column the desired column of the double array
* @return a double[] array of the unique valued contained in the specified column of the dataArray
*/
public double[] getUnique(double[][] dataArray, int column){
//Matlab code: P = unique(ktable(:,2));
double[] currentColumn = new double[dataArray.length];
for(int i=0; i<dataArray.length; i++){
currentColumn[i] = dataArray[i][column];
}
Arrays.sort(currentColumn);
//Check and remove duplicate values for a list of unique values
double[] uniqueColumn = getUnique(currentColumn);
return uniqueColumn;
}
/**
* Gets the unique values of the double[] array
* @param currentColumn the double array
* @return a double[] array of the unique valued contained in the dataArray
*/
public double[] getUnique(double[] currentColumn){
Arrays.sort(currentColumn);
//Check and remove duplicate values for a list of unique values
int ctr=0;
for(int i=0; i<currentColumn.length; i++){
if(i == 0){
ctr++;
continue;
}
if(Double.compare(currentColumn[i-1],currentColumn[i]) != 0){
ctr++;
}
}
double[] uniqueColumn = new double[ctr];
ctr=0;
for(int i=0; i<currentColumn.length; i++){
if(i==0){
uniqueColumn[ctr] = currentColumn[i];
ctr++;
continue;
}
if(Double.compare(currentColumn[i-1],currentColumn[i]) != 0){
uniqueColumn[ctr] = currentColumn[i];
ctr++;
}
}
return uniqueColumn;
}
/**
* Creates an ArrayList<Integer> of the rows in dataArray that have the column number "column" equal to "currentValue"
* @param dataArray the double[][] data array
* @param column the column of interest of the data array
* @param currentValue the desired value from the data array
* @return an ArrayList<Integer> of the rows in dataArray[][column] == currentValue
*/
public ArrayList<Integer> findRowsEqual(double[][] dataArray, int column, double currentValue){
ArrayList<Integer> rowIndexList = new ArrayList<Integer>();
for(int i=0; i<dataArray.length; i++){
if(Double.compare(dataArray[i][column],currentValue) == 0){
rowIndexList.add(i);
}
}
return rowIndexList;
}
/**
* Creates an ArrayList<Integer> of the rows in dataArray that have the column number "column" less or greater than to "currentValue"
* @param dataArray the double[][] data array
* @param column the column of interest of the data array
* @param currentValue the desired value from the data array
* @param lessThan if true, then all the rows with data less than the currentValue will be returned, if false all the rows with data greater than the current value will be returned
* @return an ArrayList<Integer> of the rows in dataArray[][column] less than or greater than (depending on the value of "lessThan" provided) currentValue
*/
public ArrayList<Integer> findRowsConditional(double[][] dataArray, int column, double currentValue, boolean lessThan){
ArrayList<Integer> rowIndexList = new ArrayList<Integer>();
for(int i=0; i<dataArray.length; i++){
if(lessThan){//If lessThan == true, then find values less than the currentValue
if(Double.compare(dataArray[i][column],currentValue) < 0){
rowIndexList.add(i);
}
}else{//If lessThan == false, then find values greater than the currentValue
if(Double.compare(dataArray[i][column],currentValue) > 0){
rowIndexList.add(i);
}
}
}
return rowIndexList;
}
/**
* Creates an ArrayList<Integer> of the rows in dataArray that have the column number "column" less/equal to or greater than to "currentValue"
* @param dataArray the double[][] data array
* @param column the column of interest of the data array
* @param currentValue the desired value from the data array
* @param lessThan if true, then all the rows with data less than the currentValue will be returned, if false all the rows with data greater than the current value will be returned
* @return an ArrayList<Integer> of the rows in dataArray[][column] less than/equal to or greater than (depending on the value of "lessThan" provided) currentValue
*/
public ArrayList<Integer> findRowsConditional(double[] dataArray, double currentValue, boolean lessThan){
ArrayList<Integer> rowIndexList = new ArrayList<Integer>();
for(int i=0; i<dataArray.length; i++){
if(lessThan){//If lessThan == true, then find values less than the currentValue
if(Double.compare(dataArray[i],currentValue) <= 0){
rowIndexList.add(i);
}
}else{//If lessThan == false, then find values greater than the currentValue
if(Double.compare(dataArray[i],currentValue) >= 0){
rowIndexList.add(i);
}
}
}
return rowIndexList;
}
/**
* Creates a double[] array of the elements in dataArray[all][column]
* @param dataArray the double[][] data array
* @param column the desired column from data array
* @return a double[] array of the elements in dataArray[all][column]
*/
public double[] getColumn(double[][] dataArray, int column){
//Gets the values of dataArray[all][column] in a double[]
double[] currentElements = new double[dataArray.length];
for(int i=0; i<dataArray.length; i++){
currentElements[i] = dataArray[i][column];
}
return currentElements;
}
/**
* Creates a double[] array of the elements in dataArray[rowIndexList][column]
* @param dataArray the double[][] data array
* @param column the desired column from data array
* @param rowIndexList an ArrayList<Integer> containing the desired row indices from dataArray
* @return a double[] array of the elements in dataArray[rowIndexList][column]
*/
public double[] getColumn(double[][] dataArray, int column, ArrayList<Integer> rowIndexList){
//Gets the values of dataArray[rowIndexList][column] in a double[]
double[] currentElements = new double[rowIndexList.size()];
int indexCtr = 0;
for(int i=0; i<dataArray.length; i++){
if(i == rowIndexList.get(indexCtr)){
currentElements[indexCtr] = dataArray[i][column];
indexCtr++;
if(indexCtr == rowIndexList.size()){
//If the indexCtr == rowIndexList.size then the last row
//index has been used out of the rowIndexList so exit the loop and return the list
break;
}
}
}
return currentElements;
}
/**
* Creates a double[] array of the elements in dataArray[row][all]
* @param dataArray the double[][] data array
* @param row the desired row from data array
* @return a double[] array of the elements in dataArray[row][all]
*/
public double[] getRow(double[][] dataArray, int row){
//Gets the values of dataArray[row][all] in a double[]
double[] currentElements = new double[dataArray[row].length];
for(int i=0; i<dataArray[row].length; i++){
currentElements[i] = dataArray[row][i];
}
return currentElements;
}
/**
* Creates a double[] array of the elements in dataArray[row][columnIndexList]
* @param dataArray the double[][] data array
* @param row the desired row from data array
* @param columnIndexList an ArrayList<Integer> containing the desired row indices from dataArray
* @return a double[] array of the elements in dataArray[rowIndexList][column]
*/
public double[] getRow(double[][] dataArray, int row, ArrayList<Integer> columnIndexList){
//Gets the values of dataArray[rowIndexList][column] in a double[]
double[] currentElements = new double[columnIndexList.size()];
int indexCtr = 0;
for(int i=0; i<dataArray[row].length; i++){
if(i == columnIndexList.get(indexCtr)){
currentElements[indexCtr] = dataArray[row][i];
indexCtr++;
if(indexCtr == columnIndexList.size()){
//If the indexCtr == rowIndexList.size then the last row
//index has been used out of the rowIndexList so exit the loop and return the list
break;
}
}
}
return currentElements;
}
/**
* Creates a double[] array of the elements in dataArray[rowIndexList]
* @param dataArray the double[] data array
* @param rowIndexList an ArrayList<Integer> containing the desired row indices from dataArray
* @return a double[] array of the elements in dataArray[rowIndexList]
*/
public double[] getRows(double[] dataArray, ArrayList<Integer> rowIndexList){
//Gets the values of dataArray[rowIndexList] in a double[]
double[] newArray = new double[rowIndexList.size()];
int indexCtr = 0;
for(int i=0; i<dataArray.length; i++){
if(i == rowIndexList.get(indexCtr)){
newArray[indexCtr] = dataArray[i];
indexCtr++;
if(indexCtr == rowIndexList.size()){
//If the indexCtr == rowIndexList.size then the last row
//index has been used out of the rowIndexList so exit the loop and return the list
break;
}
}
}
return newArray;
}
/**
* Creates a double[][] array of the elements in dataArray[rowIndexList][] (aka it keeps some rows and all columns)
* @param dataArray the double[][] data array
* @param rowIndexList an ArrayList<Integer> containing the desired row indices from dataArray
* @return a double[][] array containing the desired rows from rowIndexList and all the columns
*/
public double[][] getDataArrayRows(double[][] dataArray, ArrayList<Integer> rowIndexList){
//Gets the values of dataArray[rowIndexList][all] in a double[][]
double[][] currentElements = new double[rowIndexList.size()][dataArray[0].length];
if(rowIndexList.size() == 0){
return currentElements;
}
int indexCtr = 0;
for(int i=0; i<dataArray.length; i++){//Loop rows of data array
if(i == rowIndexList.get(indexCtr)){//Check if current row is a desired row from the rowIndexList
for(int j=0; j<dataArray[i].length; j++){//Loop columns of data array
currentElements[indexCtr][j] = dataArray[i][j];
}
indexCtr++;
if(indexCtr == rowIndexList.size()){
//If the indexCtr == rowIndexList.size then the last row
//index has been used out of the rowIndexList so exit the loop and return the list
break;
}
}
}
return currentElements;
}
/**
* Compares array1 and array2 and returns an ArrayList<Integer> of the "j" rows in which array1[i] = array2[j]
* @param array1 double[] first arary to compare
* @param array2 double[] second array to compare
* @return an ArrayList<Integer> containing the rows in which array1[i] = array2[i]
*/
public ArrayList<Integer> intersect(double[] array1, double[] array2){
ArrayList<Integer> rowIndex = new ArrayList<Integer>();
//Find the "j" rows where array1[i] = array2[j]
for(int i=0; i<array1.length; i++){
for(int j=0; j<array2.length; j++){
if(Double.compare(array1[i], array2[j]) == 0){
rowIndex.add(j);
}
}
}
Collections.sort(rowIndex);
return rowIndex;
}
/**
* Creates an double[] array of random numbers of array.length = size
* @param size the number of elements desired in the array
* @return
*/
public double[] RandomArray(int size){
double[] randomArray = new double[size];
for(int i=0; i<size; i++){
randomArray[i] = Math.random();
}
return randomArray;
}
/**
* Merges the public dataset (first input) with the user dataset (second input)
* based on the merge method selected
* @param publicDataset a String[][] array with the first column containing dates (yyyy-mm-dd)
* and the second column values of flow or water quality test to be treated as the "public dataset"
* for merge method purposes
* @param userDataset a String[][] array with the first column containing dates (yyyy-mm-dd)
* and the second column values of flow or water quality test to be treated as the "user dataset"
* for merge method purposes
* @param mergeMethod the method to merge the two datasets, one of the following:
* "user" = overwrite public data with user data
* "public" = overwrite user data with public data
* "maximum" = take the maximum value for that day from both datasets
* "average" = take the average of the two values for that day from both datasets
* "minimum" = take the minimum value for that day from both datasets
* @return
*/
public String[][] mergeData(String[][] publicDataset, String[][] userDataset, String mergeMethod){
//Sort by dates for comparison purposes
Arrays.sort(publicDataset, new DateComparator());
Arrays.sort(userDataset, new DateComparator());
//Allocate an array of values to determine if userdata needs to be kept (true) or merged (false)
boolean[] useUserDataset = new boolean[userDataset.length];
for(int i=0; i<useUserDataset.length; i++){
useUserDataset[i] = true;
}
int ctr = 0;
for(int i=0; i<publicDataset.length; i++){
for(int j=0; j<userDataset.length; j++){
if(publicDataset[i][0].equalsIgnoreCase(userDataset[j][0])){
useUserDataset[j] = false;
ctr++;
continue;
}
}
}
String[][] mergeDataset = new String[publicDataset.length + userDataset.length - ctr][2];
boolean merge = false;
ctr = 0;
for(int i=0; i<publicDataset.length; i++){
for(int j=0; j<userDataset.length; j++){
//If the dates match, merge the datasets
if(publicDataset[i][0].equalsIgnoreCase(userDataset[j][0])){
if(mergeMethod.equalsIgnoreCase("user")){
mergeDataset[ctr][0] = userDataset[j][0];
mergeDataset[ctr][1] = userDataset[j][1];
ctr++;
}else if(mergeMethod.equalsIgnoreCase("public")){
mergeDataset[ctr][0] = publicDataset[i][0];
mergeDataset[ctr][1] = publicDataset[i][1];
ctr++;
}else if(mergeMethod.equalsIgnoreCase("max")){
double userValue = Double.valueOf(userDataset[j][1]);
double publicValue = Double.valueOf(publicDataset[i][1]);
if(Double.compare(userValue, publicValue) < 0){
mergeDataset[ctr][1] = String.valueOf(publicValue);
}else{
mergeDataset[ctr][1] = String.valueOf(userValue);
}
mergeDataset[ctr][0] = publicDataset[i][0];
ctr++;
}else if(mergeMethod.equalsIgnoreCase("average")){
double userValue = Double.valueOf(userDataset[j][1]);
double publicValue = Double.valueOf(publicDataset[i][1]);
mergeDataset[ctr][0] = publicDataset[i][0];
mergeDataset[ctr][1] = String.valueOf((userValue + publicValue)/2);
ctr++;
}else if(mergeMethod.equalsIgnoreCase("min")){
double userValue = Double.valueOf(userDataset[j][1]);
double publicValue = Double.valueOf(publicDataset[i][1]);
if(Double.compare(userValue, publicValue) < 0){
mergeDataset[ctr][1] = String.valueOf(userValue);
}else{
mergeDataset[ctr][1] = String.valueOf(publicValue);
}
mergeDataset[ctr][0] = publicDataset[i][0];
ctr++;
}
merge = true;
continue;
}
}
if(!merge){
mergeDataset[ctr][0] = publicDataset[i][0];
mergeDataset[ctr][1] = publicDataset[i][1];
ctr++;
}
merge = false;
}
//Include the points from the user dataset that aren't duplicate points
for(int i=0; i<useUserDataset.length; i++){
if(useUserDataset[i]){
mergeDataset[ctr][0] = userDataset[i][0];
mergeDataset[ctr][1] = userDataset[i][1];
ctr++;
}
}
Arrays.sort(mergeDataset, new DateComparator());
return mergeDataset;
}
/**
* Merges the public dataset (first input) with the user dataset (second input)
* based on the merge method selected
* @param publicDataset a double[][] array with the first column containing years (yyyy)
* and the second column values of flow or water quality test to be treated as the "public dataset"
* for merge method purposes
* @param userDataset a String[][] array with the first column containing years (yyyy)
* and the second column values of flow or water quality test to be treated as the "user dataset"
* for merge method purposes
* @param mergeMethod the method to merge the two datasets, one of the following:
* "user" = overwrite public data with user data
* "public" = overwrite user data with public data
* "max" = take the maximum value for that day from both datasets
* "average" = take the average of the two values for that day from both datasets
* "min" = take the minimum value for that day from both datasets
* @return
*/
public double[][] mergeData(double[][] publicDataset, double[][] userDataset, String mergeMethod){
//Sort by dates for comparison purposes
Arrays.sort(publicDataset, new sort1_smallToLargeDoubleMath());
Arrays.sort(userDataset, new sort1_smallToLargeDoubleMath());
//Allocate an array of values to determine if userdata needs to be kept (true) or merged (false)
boolean[] useUserDataset = new boolean[userDataset.length];
for(int i=0; i<useUserDataset.length; i++){
useUserDataset[i] = true;
}
int ctr = 0;
for(int i=0; i<publicDataset.length; i++){
for(int j=0; j<userDataset.length; j++){
if(Double.compare(publicDataset[i][0],userDataset[j][0]) == 0){
useUserDataset[j] = false;
ctr++;
continue;
}
}
}
double[][] mergeDataset = new double[publicDataset.length + userDataset.length - ctr][2];
boolean merge = false;
ctr = 0;
for(int i=0; i<publicDataset.length; i++){
for(int j=0; j<userDataset.length; j++){
//If the dates match, merge the datasets
if(Double.compare(publicDataset[i][0],userDataset[j][0]) == 0){
if(mergeMethod.equalsIgnoreCase("user")){
mergeDataset[ctr][0] = userDataset[j][0];
mergeDataset[ctr][1] = userDataset[j][1];
ctr++;
}else if(mergeMethod.equalsIgnoreCase("public")){
mergeDataset[ctr][0] = publicDataset[i][0];
mergeDataset[ctr][1] = publicDataset[i][1];
ctr++;
}else if(mergeMethod.equalsIgnoreCase("max")){
if(Double.compare(userDataset[i][1], publicDataset[i][1]) < 0){
mergeDataset[ctr][1] = publicDataset[i][1];
}else{
mergeDataset[ctr][1] = userDataset[j][1];
}
mergeDataset[ctr][0] = publicDataset[i][0];
ctr++;
}else if(mergeMethod.equalsIgnoreCase("average")){
mergeDataset[ctr][0] = publicDataset[i][0];
mergeDataset[ctr][1] = (userDataset[j][1] + publicDataset[j][1])/2;
ctr++;
}else if(mergeMethod.equalsIgnoreCase("min")){
if(Double.compare(userDataset[j][1], publicDataset[j][1]) < 0){
mergeDataset[ctr][1] = userDataset[j][1];
}else{
mergeDataset[ctr][1] = publicDataset[i][1];
}
mergeDataset[ctr][0] = publicDataset[i][0];
ctr++;
}
merge = true;
continue;
}
}
if(!merge){
mergeDataset[ctr][0] = publicDataset[i][0];
mergeDataset[ctr][1] = publicDataset[i][1];
ctr++;
}
merge = false;
}
//Include the points from the user dataset that aren't duplicate points
for(int i=0; i<useUserDataset.length; i++){
if(useUserDataset[i]){
mergeDataset[ctr][0] = userDataset[i][0];
mergeDataset[ctr][1] = userDataset[i][1];
ctr++;
}
}
Arrays.sort(mergeDataset, new sort1_smallToLargeDoubleMath());
return mergeDataset;
}
}