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 */ addAll(Collection<? extends Double> c)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 */ add(double meas)50 public void add(double meas) { 51 mData.add(meas); 52 mSum += meas; 53 } 54 55 /** 56 * Retrieve the dataset. 57 */ getData()58 public List<Double> getData() { 59 return mData; 60 } 61 62 /** 63 * Check if the dataset is empty. 64 */ isEmpty()65 public boolean isEmpty() { 66 return mData.isEmpty(); 67 } 68 69 /** 70 * Check how many elements are in the dataset. 71 */ size()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 */ mean()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 */ median()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 */ min()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 */ max()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 */ stdev()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 */ meanOverOneStandardDeviationRange()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