/** Returns an immutable snapshot of the current statistics. */ public Stats snapshot() { return new Stats(count, mean, sumOfSquaresOfDeltas, min, max); }
/** * Adds the given statistics to the dataset, as if the individual values used to compute the * statistics had been added directly. */ public void addAll(Stats values) { if (values.count() == 0) { return; } if (count == 0) { count = values.count(); mean = values.mean(); sumOfSquaresOfDeltas = values.sumOfSquaresOfDeltas(); min = values.min(); max = values.max(); } else { count += values.count(); if (isFinite(mean) && isFinite(values.mean())) { // This is a generalized version of the calculation in add(double) above. double delta = values.mean() - mean; mean += delta * values.count() / count; sumOfSquaresOfDeltas += values.sumOfSquaresOfDeltas() + delta * (values.mean() - mean) * values.count(); } else { mean = calculateNewMeanNonFinite(mean, values.mean()); sumOfSquaresOfDeltas = NaN; } min = Math.min(min, values.min()); max = Math.max(max, values.max()); } }
/** * Returns the <a href="http://en.wikipedia.org/wiki/Arithmetic_mean">arithmetic mean</a> of the * values. The count must be non-zero. * * <p>The definition of the mean is the same as {@link Stats#mean}. * * @param values a series of values, which will be converted to {@code double} values (this may * cause loss of precision) * @throws IllegalArgumentException if the dataset is empty */ public static double meanOf(Iterable<? extends Number> values) { return meanOf(values.iterator()); }
@Override public String toString() { if (count() > 0) { return MoreObjects.toStringHelper(this) .add("count", count) .add("mean", mean) .add("populationStandardDeviation", populationStandardDeviation()) .add("min", min) .add("max", max) .toString(); } else { return MoreObjects.toStringHelper(this).add("count", count).toString(); } }
public void testToString() { assertThat(EMPTY_STATS_VARARGS.toString()).isEqualTo("Stats{count=0}"); assertThat(MANY_VALUES_STATS_ITERABLE.toString()) .isEqualTo( "Stats{count=" + MANY_VALUES_STATS_ITERABLE.count() + ", mean=" + MANY_VALUES_STATS_ITERABLE.mean() + ", populationStandardDeviation=" + MANY_VALUES_STATS_ITERABLE.populationStandardDeviation() + ", min=" + MANY_VALUES_STATS_ITERABLE.min() + ", max=" + MANY_VALUES_STATS_ITERABLE.max() + "}"); }
public void testEquivalentStreams() { // For datasets of many double values created from an array, we test many combinations of finite // and non-finite values: for (ManyValues values : ALL_MANY_VALUES) { double[] array = values.asArray(); Stats stats = Stats.of(array); // instance methods on Stats vs on instance methods on DoubleStream assertThat(stats.count()).isEqualTo(stream(array).count()); assertEquivalent(stats.mean(), stream(array).average().getAsDouble()); assertEquivalent(stats.sum(), stream(array).sum()); assertEquivalent(stats.max(), stream(array).max().getAsDouble()); assertEquivalent(stats.min(), stream(array).min().getAsDouble()); // static method on Stats vs on instance method on DoubleStream assertEquivalent(Stats.meanOf(array), stream(array).average().getAsDouble()); // instance methods on Stats vs instance methods on DoubleSummaryStatistics DoubleSummaryStatistics streamStats = stream(array).summaryStatistics(); assertThat(stats.count()).isEqualTo(streamStats.getCount()); assertEquivalent(stats.mean(), streamStats.getAverage()); assertEquivalent(stats.sum(), streamStats.getSum()); assertEquivalent(stats.max(), streamStats.getMax()); assertEquivalent(stats.min(), streamStats.getMin()); } }
static void assertStatsApproxEqual(Stats expectedStats, Stats actualStats) { assertThat(actualStats.count()).isEqualTo(expectedStats.count()); if (expectedStats.count() == 0) { try { actualStats.mean(); fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { actualStats.populationVariance(); fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { actualStats.min(); fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { actualStats.max(); fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { } else if (expectedStats.count() == 1) { assertThat(actualStats.mean()).isWithin(ALLOWED_ERROR).of(expectedStats.mean()); assertThat(actualStats.populationVariance()).isWithin(0.0).of(0.0); assertThat(actualStats.min()).isWithin(ALLOWED_ERROR).of(expectedStats.min()); assertThat(actualStats.max()).isWithin(ALLOWED_ERROR).of(expectedStats.max()); } else { assertThat(actualStats.mean()).isWithin(ALLOWED_ERROR).of(expectedStats.mean()); assertThat(actualStats.populationVariance()) .isWithin(ALLOWED_ERROR) .of(expectedStats.populationVariance());
twoValuesAccumulator.xStats().mean(), twoValuesAccumulator.yStats().mean(), twoValuesAccumulator.xStats().populationVariance(), twoValuesAccumulator.populationCovariance()); assertDiagonalLinearTransformation( twoValuesAccumulatorByAddAllPartitionedPairedStats.leastSquaresFit(), twoValuesAccumulatorByAddAllPartitionedPairedStats.xStats().mean(), twoValuesAccumulatorByAddAllPartitionedPairedStats.yStats().mean(), twoValuesAccumulatorByAddAllPartitionedPairedStats.xStats().populationVariance(), twoValuesAccumulatorByAddAllPartitionedPairedStats.populationCovariance()); assertDiagonalLinearTransformation( manyValuesAccumulator.leastSquaresFit(), manyValuesAccumulator.xStats().mean(), manyValuesAccumulator.yStats().mean(), manyValuesAccumulator.xStats().populationVariance(), manyValuesAccumulator.populationCovariance()); assertDiagonalLinearTransformation( manyValuesAccumulatorByAddAllPartitionedPairedStats.leastSquaresFit(), manyValuesAccumulatorByAddAllPartitionedPairedStats.xStats().mean(), manyValuesAccumulatorByAddAllPartitionedPairedStats.yStats().mean(), manyValuesAccumulatorByAddAllPartitionedPairedStats.xStats().populationVariance(), manyValuesAccumulatorByAddAllPartitionedPairedStats.populationCovariance()); assertDiagonalLinearTransformation( fit, accumulator.xStats().mean(), accumulator.yStats().mean(), accumulator.xStats().populationVariance(), accumulator.populationCovariance());
/** Returns the number of pairs in the dataset. */ public long count() { return xStats.count(); }
return LinearTransformation.forNaN(); double xSumOfSquaresOfDeltas = xStats.sumOfSquaresOfDeltas(); if (xSumOfSquaresOfDeltas > 0.0) { if (yStats.sumOfSquaresOfDeltas() > 0.0) { return LinearTransformation.mapping(xStats.mean(), yStats.mean()) .withSlope(sumOfProductsOfDeltas / xSumOfSquaresOfDeltas); } else { return LinearTransformation.horizontal(yStats.mean()); checkState(yStats.sumOfSquaresOfDeltas() > 0.0); return LinearTransformation.vertical(xStats.mean());
/** * Returns the <a * href="http://en.wikipedia.org/wiki/Standard_deviation#Corrected_sample_standard_deviation"> * corrected sample standard deviation</a> of the values. If this dataset is a sample drawn from a * population, this is an estimator of the population standard deviation of the population which * is less biased than {@link #populationStandardDeviation()} (the unbiased estimator depends on * the distribution). The count must be greater than one. * * <p>This is not guaranteed to return zero when the dataset consists of the same value multiple * times, due to numerical errors. However, it is guaranteed never to return a negative result. * * <h3>Non-finite values</h3> * * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. * * @throws IllegalStateException if the dataset is empty or contains a single value */ public double sampleStandardDeviation() { return Math.sqrt(sampleVariance()); }
public void testPopulationStandardDeviation() { try { EMPTY_STATS_VARARGS.populationStandardDeviation(); fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { EMPTY_STATS_ITERABLE.populationStandardDeviation(); fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { assertThat(ONE_VALUE_STATS.populationStandardDeviation()).isWithin(0.0).of(0.0); assertThat(TWO_VALUES_STATS.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(TWO_VALUES_SUM_OF_SQUARES_OF_DELTAS / 2)); assertThat(MANY_VALUES_STATS_VARARGS.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); assertThat(MANY_VALUES_STATS_ITERABLE.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); assertThat(MANY_VALUES_STATS_ITERATOR.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); assertThat(MANY_VALUES_STATS_SNAPSHOT.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / MANY_VALUES_COUNT)); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.populationStandardDeviation()) .isWithin(ALLOWED_ERROR) .of(sqrt(INTEGER_MANY_VALUES_SUM_OF_SQUARES_OF_DELTAS / INTEGER_MANY_VALUES_COUNT)); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.populationStandardDeviation())
/** * Returns the <a * href="http://en.wikipedia.org/wiki/Standard_deviation#Definition_of_population_values"> * population standard deviation</a> of the values. The count must be non-zero. * * <p>This is guaranteed to return zero if the dataset contains only exactly one finite value. It * is not guaranteed to return zero when the dataset consists of the same value multiple times, * due to numerical errors. However, it is guaranteed never to return a negative result. * * <h3>Non-finite values</h3> * * <p>If the dataset contains any non-finite values ({@link Double#POSITIVE_INFINITY}, {@link * Double#NEGATIVE_INFINITY}, or {@link Double#NaN}) then the result is {@link Double#NaN}. * * @throws IllegalStateException if the dataset is empty */ public double populationStandardDeviation() { return Math.sqrt(populationVariance()); }
/** * Adds the given statistics to the dataset, as if the individual values used to compute the * statistics had been added directly. */ public void addAll(PairedStats values) { if (values.count() == 0) { return; } xStats.addAll(values.xStats()); if (yStats.count() == 0) { sumOfProductsOfDeltas = values.sumOfProductsOfDeltas(); } else { // This is a generalized version of the calculation in add(double, double) above. Note that // non-finite inputs will have sumOfProductsOfDeltas = NaN, so non-finite values will result // in NaN naturally. sumOfProductsOfDeltas += values.sumOfProductsOfDeltas() + (values.xStats().mean() - xStats.mean()) * (values.yStats().mean() - yStats.mean()) * values.count(); } yStats.addAll(values.yStats()); }
public void testEqualsAndHashCode() { new EqualsTester() .addEqualityGroup( Stats.of(1.0, 1.0, 5.0, 5.0), Stats.of(1.0, 1.0, 5.0, 5.0), Stats.of(ImmutableList.of(1.0, 1.0, 5.0, 5.0)), Stats.of(ImmutableList.of(1.0, 1.0, 5.0, 5.0).iterator()), SerializableTester.reserialize(Stats.of(1.0, 1.0, 5.0, 5.0))) .addEqualityGroup(Stats.of(1.0, 5.0)) .addEqualityGroup(Stats.of(1.0, 5.0, 1.0, 6.0)) .addEqualityGroup(Stats.of(2.0, 6.0, 2.0, 6.0)) .addEqualityGroup( new Stats(5, -5.5, 55.5, -5.55, 5.55), new Stats(5, -5.5, 55.5, -5.55, 5.55)) .addEqualityGroup(new Stats(6, -5.5, 55.5, -5.55, 5.55)) .addEqualityGroup(new Stats(5, -5.6, 55.5, -5.55, 5.55)) .addEqualityGroup(new Stats(5, -5.5, 55.6, -5.55, 5.55)) .addEqualityGroup(new Stats(5, -5.5, 55.5, -5.56, 5.55)) .addEqualityGroup(new Stats(5, -5.5, 55.5, -5.55, 5.56)) .testEquals(); }
Stats stats = new Stats(); documentRelivency.forEach(relevant -> { stats.add(relevant); System.out.format("%9.2f\t%.2f\t%.2f\t\n", stats.getPrecision(), stats.getRecall(), stats.getFMeasure()); });
/** * {@inheritDoc} * * <p><b>Note:</b> This tests exact equality of the calculated statistics, including the floating * point values. Two instances are guaranteed to be considered equal if one is copied from the * other using {@code second = new PairedStatsAccumulator().addAll(first).snapshot()}, if both * were obtained by calling {@code snapshot()} on the same {@link PairedStatsAccumulator} without * adding any values in between the two calls, or if one is obtained from the other after * round-tripping through java serialization. However, floating point rounding errors mean that it * may be false for some instances where the statistics are mathematically equal, including * instances constructed from the same values in a different order... or (in the general case) * even in the same order. (It is guaranteed to return true for instances constructed from the * same values in the same order if {@code strictfp} is in effect, or if the system architecture * guarantees {@code strictfp}-like semantics.) */ @Override public boolean equals(@Nullable Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } PairedStats other = (PairedStats) obj; return xStats.equals(other.xStats) && yStats.equals(other.yStats) && doubleToLongBits(sumOfProductsOfDeltas) == doubleToLongBits(other.sumOfProductsOfDeltas); }
public class DBView extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.view_stats); TextView tv = (TextView) findViewById(R.id.tvDBInfo); Stats dbInfo = new Stats(this); dbInfo.open(); dbInfo.createEntry("weight", "waist", "chest", "legs", "arms"); String data = dbInfo.getData(); dbInfo.close(); if (!TextUtils.isEmpty(data)) { tv.setText(data); } } }
public void testMax() { try { EMPTY_STATS_VARARGS.max(); fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { EMPTY_STATS_ITERABLE.max(); fail("Expected IllegalStateException"); } catch (IllegalStateException expected) { assertThat(ONE_VALUE_STATS.max()).isWithin(ALLOWED_ERROR).of(ONE_VALUE); assertThat(Stats.of(POSITIVE_INFINITY).max()).isPositiveInfinity(); assertThat(Stats.of(NEGATIVE_INFINITY).max()).isNegativeInfinity(); assertThat(Stats.of(NaN).max()).isNaN(); assertThat(TWO_VALUES_STATS.max()).isWithin(ALLOWED_ERROR).of(TWO_VALUES_MAX); assertThat(MANY_VALUES_STATS_VARARGS.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); assertThat(MANY_VALUES_STATS_ITERABLE.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); double max = Stats.of(values.asIterable().iterator()).max(); if (values.hasAnyNaN()) { assertThat(max).named("max of " + values).isNaN(); assertThat(MANY_VALUES_STATS_SNAPSHOT.max()).isWithin(ALLOWED_ERROR).of(MANY_VALUES_MAX); assertThat(INTEGER_MANY_VALUES_STATS_VARARGS.max()) .isWithin(ALLOWED_ERROR) .of(INTEGER_MANY_VALUES_MAX); assertThat(INTEGER_MANY_VALUES_STATS_ITERABLE.max()) .isWithin(ALLOWED_ERROR) .of(INTEGER_MANY_VALUES_MAX); assertThat(LONG_MANY_VALUES_STATS_ITERATOR.max())