You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/01/16 15:39:48 UTC
[groovy] branch master updated: Add built-in `stdevp` function to
GINQ
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/master by this push:
new 799b771 Add built-in `stdevp` function to GINQ
799b771 is described below
commit 799b7719cbba2c6a7536d83ed4274c0706953ca2
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat Jan 16 23:38:25 2021 +0800
Add built-in `stdevp` function to GINQ
---
.../ginq/provider/collection/GinqAstWalker.groovy | 5 +++--
.../provider/collection/runtime/Queryable.java | 11 +++++++++-
.../collection/runtime/QueryableCollection.java | 11 +++++++++-
.../groovy-ginq/src/spec/doc/ginq-userguide.adoc | 14 +++++++++++--
.../test/org/apache/groovy/ginq/GinqTest.groovy | 24 ++++++++++++++++++++++
5 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
index 462d4f5..801deb0 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/GinqAstWalker.groovy
@@ -1548,8 +1548,9 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
private static final String FUNCTION_AVG = 'avg'
private static final String FUNCTION_MEDIAN = 'median'
private static final String FUNCTION_STDEV = 'stdev'
+ private static final String FUNCTION_STDEVP = 'stdevp'
private static final String FUNCTION_AGG = 'agg'
- private static final List<String> AGG_FUNCTION_NAME_LIST = [FUNCTION_COUNT, FUNCTION_MIN, FUNCTION_MAX, FUNCTION_SUM, FUNCTION_AVG, FUNCTION_MEDIAN, FUNCTION_STDEV, FUNCTION_AGG]
+ private static final List<String> AGG_FUNCTION_NAME_LIST = [FUNCTION_COUNT, FUNCTION_MIN, FUNCTION_MAX, FUNCTION_SUM, FUNCTION_AVG, FUNCTION_MEDIAN, FUNCTION_STDEV, FUNCTION_STDEVP, FUNCTION_AGG]
private static final String FUNCTION_ROW_NUMBER = 'rowNumber'
private static final String FUNCTION_LEAD = 'lead'
@@ -1558,7 +1559,7 @@ class GinqAstWalker implements GinqAstVisitor<Expression>, SyntaxErrorReportable
private static final String FUNCTION_LAST_VALUE = 'lastValue'
private static final String FUNCTION_RANK = 'rank'
private static final String FUNCTION_DENSE_RANK = 'denseRank'
- private static final List<String> WINDOW_FUNCTION_LIST = [FUNCTION_COUNT, FUNCTION_MIN, FUNCTION_MAX, FUNCTION_SUM, FUNCTION_AVG, FUNCTION_MEDIAN, FUNCTION_STDEV,
+ private static final List<String> WINDOW_FUNCTION_LIST = [FUNCTION_COUNT, FUNCTION_MIN, FUNCTION_MAX, FUNCTION_SUM, FUNCTION_AVG, FUNCTION_MEDIAN, FUNCTION_STDEV, FUNCTION_STDEVP,
FUNCTION_ROW_NUMBER, FUNCTION_LEAD, FUNCTION_LAG, FUNCTION_FIRST_VALUE, FUNCTION_LAST_VALUE, FUNCTION_RANK, FUNCTION_DENSE_RANK]
private static final String NAMEDRECORD_CLASS_NAME = NamedRecord.class.name
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
index 36e0d6e..b73d995 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/Queryable.java
@@ -421,12 +421,21 @@ public interface Queryable<T> {
* Aggregate function {@code stdev}, similar to SQL's {@code stdev}
*
* @param mapper choose the field to calculate the statistical standard deviation
- * @return statistical standard deviation result
+ * @return statistical standard deviation
* @since 4.0.0
*/
BigDecimal stdev(Function<? super T, ? extends Number> mapper);
/**
+ * Aggregate function {@code stdevp}, similar to SQL's {@code stdevp}
+ *
+ * @param mapper choose the field to calculate the statistical standard deviation for the population
+ * @return statistical standard deviation for the population
+ * @since 4.0.0
+ */
+ BigDecimal stdevp(Function<? super T, ? extends Number> mapper);
+
+ /**
* The most powerful aggregate function in GINQ, it will receive the grouped result({@link Queryable} instance) and apply any processing
*
* @param mapper map the grouped result({@link Queryable} instance) to aggregate result
diff --git a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableCollection.java b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableCollection.java
index 06c9fec..44d5a49 100644
--- a/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableCollection.java
+++ b/subprojects/groovy-ginq/src/main/groovy/org/apache/groovy/ginq/provider/collection/runtime/QueryableCollection.java
@@ -428,6 +428,15 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
@Override
public BigDecimal stdev(Function<? super T, ? extends Number> mapper) {
+ return sd(mapper, 0);
+ }
+
+ @Override
+ public BigDecimal stdevp(Function<? super T, ? extends Number> mapper) {
+ return sd(mapper, 1);
+ }
+
+ private BigDecimal sd(Function<? super T, ? extends Number> mapper, int diff) {
BigDecimal avg = this.avg(mapper);
Object[] result = agg(q -> q.stream()
.map(mapper)
@@ -440,7 +449,7 @@ class QueryableCollection<T> implements Queryable<T>, Serializable {
}, (o1, o2) -> o1));
// `BigDecimal.sqrt` is introduced since Java9, so we can not use it for now.
- return toBigDecimal(sqrt(((BigDecimal) result[1]).divide(toBigDecimal((Long) result[0]), 16, RoundingMode.HALF_UP).doubleValue()));
+ return toBigDecimal(sqrt(((BigDecimal) result[1]).divide(toBigDecimal((Long) result[0] - diff), 16, RoundingMode.HALF_UP).doubleValue()));
}
@Override
diff --git a/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc b/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
index a161b36..3ac9260 100644
--- a/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
+++ b/subprojects/groovy-ginq/src/spec/doc/ginq-userguide.adoc
@@ -284,7 +284,7 @@ include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_grouping_09,in
===== Aggregate Functions
GINQ provides some built-in aggregate functions, e.g.
-`count`, `min`, `max`, `sum`, `avg`, `median`, `stdev` and the most powerful function `agg`.
+`count`, `min`, `max`, `sum`, `avg`, `median`, `stdev`, `stdevp` and the most powerful function `agg`.
[NOTE]
`count(...)`, `min(...)`, `max(...)`, `avg(...)`, `median(...)` and `stdev(...)` just operate on non-`null` values,
and `count()` is similar to `count(*)` in SQL.
@@ -343,6 +343,11 @@ include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_aggfunction_01
include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_aggfunction_03,indent=0]
----
+[source, groovy]
+----
+include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_aggfunction_04,indent=0]
+----
+
==== Sorting
`orderby` is equivalent to SQL's `ORDER BY`
@@ -587,7 +592,7 @@ include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_15
include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_11,indent=0]
----
-===== `min`, `max`, `count`, `sum`, `avg`, `median` and `stdev`
+===== `min`, `max`, `count`, `sum`, `avg`, `median`, `stdev` and `stdevp`
[source, groovy]
----
include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_22,indent=0]
@@ -643,6 +648,11 @@ include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_30
include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_35,indent=0]
----
+[source, groovy]
+----
+include::../test/org/apache/groovy/ginq/GinqTest.groovy[tags=ginq_winfunction_36,indent=0]
+----
+
=== GINQ Tips
==== Row Number
`_rn` is the implicit variable representing row number for each record in the result set. It starts with `0`
diff --git a/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy b/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
index e634e28..5bfc10d 100644
--- a/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
+++ b/subprojects/groovy-ginq/src/spec/test/org/apache/groovy/ginq/GinqTest.groovy
@@ -4687,6 +4687,18 @@ class GinqTest {
}
@Test
+ void "testGinq - aggregate function - 14"() {
+ assertGinqScript '''
+// tag::ginq_aggfunction_04[]
+ assert [1] == GQ {
+ from n in [1, 2, 3]
+ select stdevp(n)
+ }.toList()
+// end::ginq_aggfunction_04[]
+ '''
+ }
+
+ @Test
void "testGinq - parallel - 1"() {
assertGinqScript '''
// tag::ginq_tips_08[]
@@ -5710,6 +5722,18 @@ class GinqTest {
}
@Test
+ void "testGinq - window - 79"() {
+ assertGinqScript '''
+// tag::ginq_winfunction_36[]
+ assert [[1, 1], [2, 1], [3, 1]] == GQ {
+ from n in [1, 2, 3]
+ select n, (stdevp(n) over())
+ }.toList()
+// end::ginq_winfunction_36[]
+ '''
+ }
+
+ @Test
void "testGinq - shutdown - 0"() {
assertScript '''
import org.apache.groovy.ginq.provider.collection.runtime.QueryableHelper