Skip to content

Commit f532475

Browse files
committed
[jOOQ#389] Add Agg.covarianceDouble
1 parent 879eab9 commit f532475

File tree

4 files changed

+122
-16
lines changed

4 files changed

+122
-16
lines changed

jOOL-java-8/src/main/java/org/jooq/lambda/Agg.java

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,18 +1069,40 @@ private static int percentileIndex(double percentile, int size) {
10691069
}
10701070

10711071
private static <T> double variance0(List<T> l, ToDoubleFunction<? super T> function) {
1072-
double sum = 0.0;
1073-
double sumVariance = 0.0;
1072+
double average = avg0(l, function);
1073+
return avg0(l, t -> Math.pow(function.applyAsDouble(t) - average, 2));
1074+
}
1075+
1076+
/**
1077+
* Get a {@link Collector} that calculates the <code>COVAR_POP()</code> function.
1078+
*/
1079+
public static Collector<Tuple2<Double, Double>, ?, Optional<Double>> covarianceDouble() {
1080+
return covarianceDouble(t -> t.v1, t -> t.v2);
1081+
}
10741082

1075-
for (T o : l)
1076-
sum += function.applyAsDouble(o);
1083+
/**
1084+
* Get a {@link Collector} that calculates the <code>COVAR_POP()</code> function.
1085+
*/
1086+
public static <T> Collector<T, ?, Optional<Double>> covarianceDouble(ToDoubleFunction<? super T> functionX, ToDoubleFunction<? super T> functionY) {
1087+
return collectingAndThen(toList(), l -> {
1088+
if (l.isEmpty())
1089+
return Optional.empty();
1090+
else if (l.size() == 1)
1091+
return Optional.of(0.0);
1092+
1093+
double avgX = avg0(l, functionX);
1094+
double avgY = avg0(l, functionY);
1095+
return Optional.of(avg0(l, t -> (functionX.applyAsDouble(t) - avgX) * (functionY.applyAsDouble(t) - avgY)));
1096+
});
1097+
}
10771098

1078-
double average = sum / l.size();
1099+
private static <T> double avg0(List<T> list, ToDoubleFunction<? super T> function) {
1100+
double result = 0.0;
10791101

1080-
for (T o : l)
1081-
sumVariance += Math.pow(function.applyAsDouble(o) - average, 2);
1102+
for (T t : list)
1103+
result += function.applyAsDouble(t);
10821104

1083-
return sumVariance / l.size();
1105+
return result / list.size();
10841106
}
10851107

10861108
/**

jOOL-java-8/src/test/java/org/jooq/lambda/CollectorTests.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.stream.Stream;
3131

3232
import org.jooq.lambda.tuple.Tuple;
33+
import org.jooq.lambda.tuple.Tuple2;
3334
import org.jooq.lambda.tuple.Tuple9;
3435
import org.junit.Test;
3536

@@ -1335,4 +1336,34 @@ public void testStddevAndVarianceWithObject() {
13351336
assertEquals(Optional.of(1.0), Seq.of(new Item(1), new Item(1), new Item(3), new Item(3)).collect(Agg.stddevDouble(e -> (double) e.val)));
13361337
assertEquals(Optional.of(1.250), Seq.of(new Item(1), new Item(2), new Item(3), new Item(4)).collect(Agg.varianceDouble(e -> (double) e.val)));
13371338
}
1339+
1340+
@Test
1341+
public void testCovarianceWithNumbers() {
1342+
assertEquals(Optional.empty(), Seq.<Tuple2<Double, Double>>of().collect(Agg.covarianceDouble()));
1343+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0)).collect(Agg.covarianceDouble()));
1344+
assertEquals(Optional.of(0.0), Seq.of(tuple(2.0, 2.0)).collect(Agg.covarianceDouble()));
1345+
1346+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0), tuple(1.0, 1.0)).collect(Agg.covarianceDouble()));
1347+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0), tuple(1.0, 2.0)).collect(Agg.covarianceDouble()));
1348+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 2.0), tuple(1.0, 2.0)).collect(Agg.covarianceDouble()));
1349+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 2.0), tuple(1.0, 1.0)).collect(Agg.covarianceDouble()));
1350+
1351+
assertEquals(Optional.of(0.25), Seq.of(tuple(1.0, 1.0), tuple(2.0, 2.0)).collect(Agg.covarianceDouble()));
1352+
assertEquals(Optional.of(0.5), Seq.of(tuple(1.0, 1.0), tuple(2.0, 3.0)).collect(Agg.covarianceDouble()));
1353+
}
1354+
1355+
@Test
1356+
public void testCovarianceWithObjects() {
1357+
assertEquals(Optional.empty(), Seq.<Tuple2<Double, Double>>of().collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1358+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1359+
assertEquals(Optional.of(0.0), Seq.of(tuple(2.0, 2.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1360+
1361+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0), tuple(1.0, 1.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1362+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0), tuple(1.0, 2.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1363+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 2.0), tuple(1.0, 2.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1364+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 2.0), tuple(1.0, 1.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1365+
1366+
assertEquals(Optional.of(0.25), Seq.of(tuple(1.0, 1.0), tuple(2.0, 2.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1367+
assertEquals(Optional.of(0.5), Seq.of(tuple(1.0, 1.0), tuple(2.0, 3.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1368+
}
13381369
}

jOOL/src/main/java/org/jooq/lambda/Agg.java

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,18 +1069,40 @@ private static int percentileIndex(double percentile, int size) {
10691069
}
10701070

10711071
private static <T> double variance0(List<T> l, ToDoubleFunction<? super T> function) {
1072-
double sum = 0.0;
1073-
double sumVariance = 0.0;
1072+
double average = avg0(l, function);
1073+
return avg0(l, t -> Math.pow(function.applyAsDouble(t) - average, 2));
1074+
}
1075+
1076+
/**
1077+
* Get a {@link Collector} that calculates the <code>COVAR_POP()</code> function.
1078+
*/
1079+
public static Collector<Tuple2<Double, Double>, ?, Optional<Double>> covarianceDouble() {
1080+
return covarianceDouble(t -> t.v1, t -> t.v2);
1081+
}
10741082

1075-
for (T o : l)
1076-
sum += function.applyAsDouble(o);
1083+
/**
1084+
* Get a {@link Collector} that calculates the <code>COVAR_POP()</code> function.
1085+
*/
1086+
public static <T> Collector<T, ?, Optional<Double>> covarianceDouble(ToDoubleFunction<? super T> functionX, ToDoubleFunction<? super T> functionY) {
1087+
return collectingAndThen(toList(), l -> {
1088+
if (l.isEmpty())
1089+
return Optional.empty();
1090+
else if (l.size() == 1)
1091+
return Optional.of(0.0);
1092+
1093+
double avgX = avg0(l, functionX);
1094+
double avgY = avg0(l, functionY);
1095+
return Optional.of(avg0(l, t -> (functionX.applyAsDouble(t) - avgX) * (functionY.applyAsDouble(t) - avgY)));
1096+
});
1097+
}
10771098

1078-
double average = sum / l.size();
1099+
private static <T> double avg0(List<T> list, ToDoubleFunction<? super T> function) {
1100+
double result = 0.0;
10791101

1080-
for (T o : l)
1081-
sumVariance += Math.pow(function.applyAsDouble(o) - average, 2);
1102+
for (T t : list)
1103+
result += function.applyAsDouble(t);
10821104

1083-
return sumVariance / l.size();
1105+
return result / list.size();
10841106
}
10851107

10861108
/**

jOOL/src/test/java/org/jooq/lambda/CollectorTests.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.stream.Stream;
3131

3232
import org.jooq.lambda.tuple.Tuple;
33+
import org.jooq.lambda.tuple.Tuple2;
3334
import org.jooq.lambda.tuple.Tuple9;
3435
import org.junit.Test;
3536

@@ -1335,4 +1336,34 @@ public void testStddevAndVarianceWithObject() {
13351336
assertEquals(Optional.of(1.0), Seq.of(new Item(1), new Item(1), new Item(3), new Item(3)).collect(Agg.stddevDouble(e -> (double) e.val)));
13361337
assertEquals(Optional.of(1.250), Seq.of(new Item(1), new Item(2), new Item(3), new Item(4)).collect(Agg.varianceDouble(e -> (double) e.val)));
13371338
}
1339+
1340+
@Test
1341+
public void testCovarianceWithNumbers() {
1342+
assertEquals(Optional.empty(), Seq.<Tuple2<Double, Double>>of().collect(Agg.covarianceDouble()));
1343+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0)).collect(Agg.covarianceDouble()));
1344+
assertEquals(Optional.of(0.0), Seq.of(tuple(2.0, 2.0)).collect(Agg.covarianceDouble()));
1345+
1346+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0), tuple(1.0, 1.0)).collect(Agg.covarianceDouble()));
1347+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0), tuple(1.0, 2.0)).collect(Agg.covarianceDouble()));
1348+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 2.0), tuple(1.0, 2.0)).collect(Agg.covarianceDouble()));
1349+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 2.0), tuple(1.0, 1.0)).collect(Agg.covarianceDouble()));
1350+
1351+
assertEquals(Optional.of(0.25), Seq.of(tuple(1.0, 1.0), tuple(2.0, 2.0)).collect(Agg.covarianceDouble()));
1352+
assertEquals(Optional.of(0.5), Seq.of(tuple(1.0, 1.0), tuple(2.0, 3.0)).collect(Agg.covarianceDouble()));
1353+
}
1354+
1355+
@Test
1356+
public void testCovarianceWithObjects() {
1357+
assertEquals(Optional.empty(), Seq.<Tuple2<Double, Double>>of().collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1358+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1359+
assertEquals(Optional.of(0.0), Seq.of(tuple(2.0, 2.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1360+
1361+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0), tuple(1.0, 1.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1362+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 1.0), tuple(1.0, 2.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1363+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 2.0), tuple(1.0, 2.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1364+
assertEquals(Optional.of(0.0), Seq.of(tuple(1.0, 2.0), tuple(1.0, 1.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1365+
1366+
assertEquals(Optional.of(0.25), Seq.of(tuple(1.0, 1.0), tuple(2.0, 2.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1367+
assertEquals(Optional.of(0.5), Seq.of(tuple(1.0, 1.0), tuple(2.0, 3.0)).collect(Agg.covarianceDouble(Tuple2::v1, Tuple2::v2)));
1368+
}
13381369
}

0 commit comments

Comments
 (0)