All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jessemull.microflexbigdecimal.stat.Percentile Maven / Gradle / Ivy

The newest version!
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/* -------------------------------- Package -------------------------------- */

package com.github.jessemull.microflexbigdecimal.stat;

/* ----------------------------- Dependencies ------------------------------ */

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import com.google.common.base.Preconditions;

import com.github.jessemull.microflexbigdecimal.plate.Plate;
import com.github.jessemull.microflexbigdecimal.plate.Well;
import com.github.jessemull.microflexbigdecimal.plate.WellSet;

/**
 * This class calculates percentiles for BigDecimal plate stacks, plates, 
 * wells and well sets using the following steps:
 * 
 * 

* *
    *
  1. Calculate R as P/100 x (N + 1) where N is the number of values and P is the desired percentile
  2. *
  3. Define IR as the integer portion of R
  4. *
  5. Define FR as the fractional portion of R
  6. *
  7. Find the scores with Rank IR and with Rank IR + 1
  8. *
  9. Interpolate using the formula (Score IR+1 - Score IR) * FR + Score IR and return the result
  10. *
* *
* * Statistical operations can be performed on stacks, plates, sets and wells using * standard or aggregated functions. Standard functions calculate the desired * statistic for each well in the stack, plate or set. Aggregated functions aggregate * the values from all the wells in the stack, plate or set and perform the statistical * operation on the aggregated values. Both standard and aggregated functions can * be performed on a subset of data within the stack, plate, set or well. * *

* * The methods within the MicroFlex library are meant to be flexible and the * descriptive statistic object supports operations using a single stack, plate, * set or well as well as collections and arrays of stacks, plates, sets or wells. * * * * * * * * * * * * * * * * * * *
Operation
Beginning
Index
Length of
Subset
Input/Output
* * * * *
Standard
*
* * * * *
+/-
*
* * * * *
+/-
*
* * * * * * * *
Accepts a single well, set, plate or stack as input
Calculates the statistic for each well in a well, set, plate or stack
*
* * * * *
Aggregated
*
* * * * *
+/-
*
* * * * *
+/-
*
* * * * * * * *
Accepts a single well/set/plate/stack or a collection/array of wells/sets/plates/stacks as input
Aggregates the data from all the wells in a well/set/plate/stack and calculates the statistic using the aggregated data
*
* * @author Jesse L. Mull * @update Updated Oct 18, 2016 * @address http://www.jessemull.com * @email [email protected] */ public class Percentile { /* --------------- Well percentiles for all plate wells ----------------- */ /** * Returns the percentile for each plate well. * @param Plate the plate * @param int the percentile * @return map of wells and results */ public Map plate(Plate plate, int p) { Preconditions.checkNotNull(plate, "The plate value cannot be null."); Map result = new TreeMap(); for (Well well : plate) { Well clone = new Well(well); result.put(clone, well(well, p)); } return result; } /** * Returns the percentile for each plate well using the values between the * beginning and ending indices. * @param Plate the plate * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return map of wells and results */ public Map plate(Plate plate, int begin, int length, int p) { Preconditions.checkNotNull(plate, "The plate value cannot be null."); Map result = new TreeMap(); for (Well well : plate) { Well clone = new Well(well); result.put(clone, well(well, begin, length, p)); } return result; } /* --------------------- Aggregated plate percentiles ------------------ */ /** * Returns the aggregated percentile for the plate. * @param Plate the plate * @param int the percentile * @return the aggregated result */ public BigDecimal platesAggregated(Plate plate, int p) { Preconditions.checkNotNull(plate, "The plate cannot be null."); List aggregated = new ArrayList(); for (Well well : plate) { aggregated.addAll(well.data()); } return calculate(aggregated, p); } /** * Returns the aggregated percentile for each plate. * @param Collection collection of plates * @param int the percentile * @return map of plates and aggregated results */ public Map platesAggregated(Collection collection, int p) { Preconditions.checkNotNull(collection, "The plate collection cannot be null."); Map results = new TreeMap(); for(Plate plate : collection) { List aggregated = new ArrayList(); Plate clone = new Plate(plate); for (Well well : plate) { aggregated.addAll(well.data()); } results.put(clone, calculate(aggregated, p)); } return results; } /** * Returns the aggregated percentile for each plate. * @param PlateBigDecimal[] array of plates * @param int the percentile * @return map of plates and aggregated result */ public Map platesAggregated(Plate[] array, int p) { Preconditions.checkNotNull(array, "The plate array cannot be null."); Map results = new TreeMap(); for(Plate plate : array) { List aggregated = new ArrayList(); Plate clone = new Plate(plate); for (Well well : plate) { aggregated.addAll(well.data()); } results.put(clone, calculate(aggregated, p)); } return results; } /** * Returns the aggregated percentile for each plate using the values between * the indices. * @param Plate the plate * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return the aggregated result */ public BigDecimal platesAggregated( Plate plate, int begin, int length, int p) { Preconditions.checkNotNull(plate, "The plate cannot be null."); List aggregated = new ArrayList(); for (Well well : plate) { aggregated.addAll(well.data().subList(begin, begin + length)); } return calculate(aggregated, p); } /** * Returns the aggregated percentile for each plate using the values between * the indices. * @param Collection collection of plates * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return map of plates and aggregated results */ public Map platesAggregated( Collection collection, int begin, int length, int p) { Preconditions.checkNotNull(collection, "The plate collection cannot be null."); Map results = new TreeMap(); for(Plate plate : collection) { List aggregated = new ArrayList(); Plate clone = new Plate(plate); for (Well well : plate) { aggregated.addAll(well.data().subList(begin, begin + length)); } results.put(clone, calculate(aggregated, p)); } return results; } /** * Returns the aggregated percentile for each plate using the values between * the indices. * @param PlateBigDecimal[] array of plates * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return map of plates and aggregated results */ public Map platesAggregated( Plate[] array, int begin, int length, int p) { Preconditions.checkNotNull(array, "The plate array cannot be null."); Map results = new TreeMap(); for(Plate plate : array) { List aggregated = new ArrayList(); Plate clone = new Plate(plate); for (Well well : plate) { aggregated.addAll(well.data().subList(begin, begin + length)); } results.put(clone, calculate(aggregated, p)); } return results; } /* --------------- Well percentiles for all wells in a set ------------- */ /** * Returns the percentile of each well in the well set. * @param WellSet the well set * @param int the percentile * @return map of wells and results */ public Map set(WellSet set, int p) { Preconditions.checkNotNull(set, "The set cannot be null."); Map result = new TreeMap(); for (Well well : set) { Well clone = new Well(well); result.put(clone, well(well, p)); } return result; } /** * Returns the percentile of each well in the well set using the values between * the beginning and ending indices. * @param WellSet the well set * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return map of wells and results */ public Map set(WellSet set, int begin, int length, int p) { Preconditions.checkNotNull(set, "The well set cannot be null."); Map result = new TreeMap(); for (Well well : set) { Well clone = new Well(well); result.put(clone, well(well, begin, length, p)); } return result; } /* --------------------- Aggregated set percentiles -------------------- */ /** * Returns the aggregated percentile for the well set. * @param WellSet the well set * @param int the percentile * @return the aggregated result */ public BigDecimal setsAggregated(WellSet set, int p) { Preconditions.checkNotNull(set, "The well set cannot be null."); List aggregated = new ArrayList(); for (Well well : set) { aggregated.addAll(well.data()); } return calculate(aggregated, p); } /** * Returns the aggregated percentile for each well set. * @param Collection collection of well sets * @param int the percentile * @return map of well sets and aggregated results */ public Map setsAggregated(Collection collection, int p) { Preconditions.checkNotNull(collection, "The well set collection cannot be null."); Map results = new TreeMap(); for(WellSet set : collection) { List aggregated = new ArrayList(); WellSet clone = new WellSet(set); for (Well well : set) { aggregated.addAll(well.data()); } results.put(clone, calculate(aggregated, p)); } return results; } /** * Returns the aggregated percentile for each well set. * @param WellSetBigDecimal[] array of well sets * @param int the percentile * @return map of well sets and aggregated results */ public Map setsAggregated(WellSet[] array, int p) { Preconditions.checkNotNull(array, "The well set array cannot be null."); Map results = new TreeMap(); for(WellSet set : array) { List aggregated = new ArrayList(); WellSet clone = new WellSet(set); for (Well well : set) { aggregated.addAll(well.data()); } results.put(clone, calculate(aggregated, p)); } return results; } /** * Returns the aggregated percentile for each well set using the values between the * indices. * @param WellSet the well set * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return the aggregated result */ public BigDecimal setsAggregated( WellSet set, int begin, int length, int p) { Preconditions.checkNotNull(set, "The well set cannot be null."); List aggregated = new ArrayList(); for (Well well : set) { aggregated.addAll(well.data().subList(begin, begin + length)); } return calculate(aggregated, p); } /** * Returns the aggregated percentile for each well set using the values between * the indices. * @param Collection collection of well sets * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return map of well sets and aggregated results */ public Map setsAggregated( Collection collection, int begin, int length, int p) { Preconditions.checkNotNull(collection, "The well set collection cannot be null."); Map results = new TreeMap(); for(WellSet set : collection) { List aggregated = new ArrayList(); WellSet clone = new WellSet(set); for (Well well : set) { aggregated.addAll(well.data().subList(begin, begin + length)); } results.put(clone, calculate(aggregated, p)); } return results; } /** * Returns the aggregated percentile for each well set using the values between * the indices. * @param WellSetBigDecimal[] array of well sets * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return map of well sets and aggregated results */ public Map setsAggregated( WellSet[] array, int begin, int length, int p) { Preconditions.checkNotNull(array, "The well set array cannot be null."); Map results = new TreeMap(); for(WellSet set : array) { List aggregated = new ArrayList(); WellSet clone = new WellSet(set); for (Well well : set) { aggregated.addAll(well.data().subList(begin, begin + length)); } results.put(clone, calculate(aggregated, p)); } return results; } /* -------------------------- Well percentiles ------------------------- */ /** * Returns the well percentile. * @param Well the well * @param int the percentile * @return the result */ public BigDecimal well(Well well, int p) { Preconditions.checkNotNull(well, "The well cannot be null."); Preconditions.checkArgument(p <= 100 || p > 0, "Percentile is outside the valid range: %d", p); return calculate(well.data(), p); } /** * Returns the well percentile for the values between the beginning and ending * indices. * @param Well the well * @param int beginning index of subset * @param int length of the subset * @param int the percentile * @return the result */ public BigDecimal well(Well well, int begin, int length, int p) { Preconditions.checkNotNull(well, "The well cannot be null."); Preconditions.checkArgument(p <= 100 || p > 0, "Percentile is outside the valid range: %d", p); Preconditions.checkArgument(begin <= well.data().size() && begin >= 0 && begin + length <= well.data().size()); return calculate(well.data(), begin, length, p); } /* -------- Methods for calculating the percentile of a data set ------- */ /** * Calculates the percentile. * @param List the list * @param int the percentile * @return the result */ public BigDecimal calculate(List list, int p) { int n = list.size(); if(n == 1) { return list.get(0); } Collections.sort(list); double pos = (p * (n + 1)) / 100.0; if(pos < 1) { return list.get(0); } if(pos >= n) { return list.get(list.size() - 1); } if(pos == Math.floor(pos) && !Double.isInfinite(pos)) { return list.get((int) pos - 1); } int lowerIndex = (int) Math.floor(pos) - 1; int upperIndex = lowerIndex + 1; BigDecimal lower = list.get(lowerIndex); BigDecimal upper = list.get(upperIndex); BigDecimal d = new BigDecimal((pos - 1 - lowerIndex) + ""); return upper.subtract(lower).multiply(d).add(lower); }; /** * Calculates the percentile of the values between the beginning and ending * indices. * @param List the list * @param int beginning index of subset * @param int length of subset * @param int the percentile * @return the result */ public BigDecimal calculate(List list, int begin, int length, int p) { return this.calculate(list.subList(begin, begin + length), p); }; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy