@Override public Centroid next() { final Centroid next = new Centroid(mean(nextNode), count(nextNode)); final List<Double> data = data(nextNode); if (data != null) { for (Double x : data) { next.insertData(x); } } nextNode = tree.next(nextNode); return next; }
summary.add(Centroid.createWeighted(x, w, base.data())); count = w; } else { int i = 0; for (Centroid neighbor : neighbors) { double z = Math.abs(neighbor.mean() - x); if (z <= minDistance) { minDistance = z; break; double z = Math.abs(neighbor.mean() - x); double q = (sum + neighbor.count() / 2.0) / count; double k = 4 * count * q * (1 - q) / compression; if (z == minDistance && neighbor.count() + w <= k) { if (gen.nextDouble() < 1 / n) { closest = neighbor; sum += neighbor.count(); i++; summary.add(Centroid.createWeighted(x, w, base.data())); } else { closest.add(x, w, base.data()); summary.add(closest);
/** * Calculates percentile from {@link TDigest}. * <p>Handles cases where only one value in TDigest object. */ public static double calculatePercentile(@Nonnull TDigest tDigest, int percentile) { if (tDigest.size() == 1) { // Specialize cases where only one value in TDigest (cannot use quantile method) return tDigest.centroids().iterator().next().mean(); } else { return tDigest.quantile(percentile / 100.0); } }
public void checkBalance() { if (left != null) { if(Math.abs(left.depth() - right.depth()) >= 2) { throw new IllegalStateException("Imbalanced"); } int l = left.depth(); int r = right.depth(); if(depth != Math.max(l, r) + 1){ throw new IllegalStateException( "Depth doesn't match children"); } if(size != left.size + right.size){ throw new IllegalStateException( "Sizes don't match children"); } if(count != left.count + right.count){ throw new IllegalStateException( "Counts don't match children"); } if(leaf.compareTo(right.first()) != 0){ throw new IllegalStateException(String.format( "Split is wrong %.5f != %.5f or %d != %d", leaf.mean(), right.first().mean(), leaf.id(), right.first().id())); } left.checkBalance(); right.checkBalance(); } }
if(base.compareTo(leaf) != 0) { throw new IllegalStateException(String.format("Element %s not found", base)); leaf = null; } else { if (base.compareTo(leaf) < 0) { if (left.size > 1) { left.remove(base); count -= base.count(); size--; rebalance(); right.remove(base); leaf = right.first(); count -= base.count(); size--; rebalance();
public GroupTree(Centroid leaf) { size = depth = 1; this.leaf = leaf; count = leaf.count(); left = right = null; }
protected Centroid createCentroid(double mean, int id) { return new Centroid(mean, id, recordAllData); } }
@Override void add(double x, int w, Centroid base) { add(x, w, base.data()); }
public Centroid(double x, int id, boolean record) { this(record); start(x, 1, id); }
/** * Modify an existing value in the tree subject to the constraint that the change will not alter the * ordering of the tree. * @param x New value to add to Centroid * @param count Weight of new value * @param v The value to modify * @param data The recorded data */ public void move(double x, int count, Centroid v, Iterable<? extends Double> data) { if (size <= 0) { throw new IllegalStateException("Cannot move element of empty tree"); } if (size == 1) { if(leaf != v) { throw new IllegalStateException("Cannot move element that is not in tree"); } leaf.add(x, count, data); } else if (v.compareTo(leaf) < 0) { left.move(x, count, v, data); } else { right.move(x, count, v, data); } this.count += count; }
private void start(double x, int w, int id) { this.id = id; add(x, w); }
private static double nextValue(TDigest d, Iterator<Centroid> ix, double x) { if (ix.hasNext()) { return ix.next().mean(); } else if (x < d.getMax()) { return d.getMax(); } else { return d.getMax() + 1; } } }
public void add(Centroid centroid) { if (size == 0) { leaf = centroid; depth = 1; count = centroid.count(); size = 1; return; } else if (size == 1) { int order = centroid.compareTo(leaf); if (order < 0) { left = new GroupTree(centroid); right = new GroupTree(leaf); } else if (order > 0) { left = new GroupTree(leaf); right = new GroupTree(centroid); leaf = centroid; } } else if (centroid.compareTo(leaf) < 0) { left.add(centroid); } else { right.add(centroid); } count += centroid.count(); size++; depth = Math.max(left.depth, right.depth) + 1; rebalance(); }
protected Centroid createCentroid(double mean, int id) { return new Centroid(mean, id, recordAllData); } }