Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.tradefed.util;
     17 
     18 import java.util.Collection;
     19 import java.util.Collections;
     20 import java.util.LinkedList;
     21 import java.util.List;
     22 
     23 /**
     24  * A small utility class that calculates a few statistical measures given a numerical dataset.  The
     25  * values are stored internally as {@link Double}s.
     26  */
     27 public class SimpleStats {
     28     private List<Double> mData = new LinkedList<Double>();
     29 
     30     // cached values
     31     private double mSum = 0;
     32 
     33     /**
     34      * Add a number of measurements to the dataset.
     35      *
     36      * @throws NullPointerException if the collection contains any {@code null} elements
     37      */
     38     public void addAll(Collection<? extends Double> c) {
     39         for (Double meas : c) {
     40             if (meas == null) {
     41                 throw new NullPointerException();
     42             }
     43             add(meas);
     44         }
     45     }
     46 
     47     /**
     48      * Add a measurement to the dataset.
     49      */
     50     public void add(double meas) {
     51         mData.add(meas);
     52         mSum += meas;
     53     }
     54 
     55     /**
     56      * Retrieve the dataset.
     57      */
     58     public List<Double> getData() {
     59         return mData;
     60     }
     61 
     62     /**
     63      * Check if the dataset is empty.
     64      */
     65     public boolean isEmpty() {
     66         return mData.isEmpty();
     67     }
     68 
     69     /**
     70      * Check how many elements are in the dataset.
     71      */
     72     public int size() {
     73         return mData.size();
     74     }
     75 
     76     /**
     77      * Calculate and return the mean of the dataset, or {@code null} if the dataset is empty.
     78      */
     79     public Double mean() {
     80         if (isEmpty()) {
     81             return null;
     82         }
     83 
     84         return mSum / size();
     85     }
     86 
     87     /**
     88      * Calculate and return the median of the dataset, or {@code null} if the dataset is empty.
     89      */
     90     public Double median() {
     91         if (isEmpty()) {
     92             return null;
     93         }
     94 
     95         Collections.sort(mData);
     96         if ((mData.size() & 0x1) == 1) {
     97             // odd count of items, pick the middle element.  Note that we don't +1 since indices
     98             // are zero-based rather than one-based
     99             int idx = size() / 2;
    100             return mData.get(idx);
    101         } else {
    102             // even count of items, average the two middle elements
    103             int idx = size() / 2;
    104             return (mData.get(idx - 1) + mData.get(idx)) / 2;
    105         }
    106     }
    107 
    108     /**
    109      * Return the minimum value in the dataset, or {@code null} if the dataset is empty.
    110      */
    111     public Double min() {
    112         if (isEmpty()) {
    113             return null;
    114         }
    115 
    116         Collections.sort(mData);
    117         return mData.get(0);
    118     }
    119 
    120     /**
    121      * Return the maximum value in the dataset, or {@code null} if the dataset is empty.
    122      */
    123     public Double max() {
    124         if (isEmpty()) {
    125             return null;
    126         }
    127 
    128         Collections.sort(mData);
    129         return mData.get(size() - 1);
    130     }
    131 
    132     /**
    133      * Return the standard deviation of the dataset, or {@code null} if the dataset is empty.
    134      * <p />
    135      * Note that this method calculates the population standard deviation, not the sample standard
    136      * deviation.  That is, it assumes that the dataset is entirely contained in the
    137      * {@link SimpleStats} instance.
    138      */
    139     public Double stdev() {
    140         if (isEmpty()) {
    141             return null;
    142         }
    143 
    144         Double avg = mean();
    145         Double ssd = 0.0;  // sum of squared differences
    146         for (Double meas : mData) {
    147             Double diff = meas - avg;
    148             ssd += diff * diff;
    149         }
    150 
    151         return Math.sqrt(ssd / size());
    152     }
    153 
    154     /**
    155      * return the average value of the samples that are within one stdev
    156      * e.g
    157      * 2.55 50.3 50.4 48.5 50.1 29.8 30 46 48 49
    158      * average: 40.45, stdev: 15.54
    159      * average of the values within one stdev is: 44.67
    160      */
    161     public Double meanOverOneStandardDeviationRange() {
    162         if (isEmpty()) {
    163             return null;
    164         }
    165 
    166         Double avg = mean();
    167         Double std = stdev();
    168         Double upper = avg + std;
    169         Double lower = avg - std;
    170         Double sum = 0.0;
    171         int count = 0;
    172         for (Double meas : mData) {
    173             if (meas > lower && meas < upper) {
    174                 sum += meas;
    175                 count++;
    176             }
    177         }
    178         return sum / count;
    179     }
    180 }
    181 
    182