From 410a784eb795ae5d92d5c9740b9ab284ac402a65 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Sat, 15 Aug 2026 14:18:14 +0200 Subject: [PATCH 01/11] moving kdocs that can be shared with other statistics to CommonStatisticsDocs --- .../jetbrains/kotlinx/dataframe/api/max.kt | 90 +++++++++---------- .../jetbrains/kotlinx/dataframe/api/min.kt | 90 +++++++++---------- .../documentation/CommonMinMaxDocs.kt | 54 +---------- .../documentation/CommonStatisticsDocs.kt | 71 +++++++++++++++ 4 files changed, 165 insertions(+), 140 deletions(-) create mode 100644 core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonStatisticsDocs.kt diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt index a65376da48..92436bc951 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt @@ -127,7 +127,7 @@ private typealias SetMaxOrNullOperationArg = Nothing * df.weight.max() * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return The largest value in this column. * @throws NoSuchElementException if there are no values to compare. */ @@ -159,7 +159,7 @@ public fun > DataColumn.max(skipNaN: Boolean = skipNaNDefa * df.weight.maxOrNull() * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return The largest value in this column, or `null` if there are no values to compare. */ public fun > DataColumn.maxOrNull(skipNaN: Boolean = skipNaNDefault): T? = @@ -189,7 +189,7 @@ public fun > DataColumn.maxOrNull(skipNaN: Boolean = skipN * df.name.firstName.maxBy { it.length } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [selector] A function that returns the value to compare for each element of this column. * @return The first element for which [selector] returns the maximum value. * @throws NoSuchElementException if there are no values to compare. @@ -224,7 +224,7 @@ public inline fun ?> DataColumn.maxBy( * df.name.firstName.maxByOrNull { it.length } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [selector] A function that returns the value to compare for each element of this column. * @return The first element for which [selector] returns the maximum value, * or `null` if there are no values to compare. @@ -258,7 +258,7 @@ public inline fun ?> DataColumn.maxByOrNul * df.name.firstName.maxOf { it.length } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [selector] A function that returns the value to compare for each element of this column. * @return The maximum of the values [selector] returns. * @throws NoSuchElementException if there are no values to compare. @@ -293,7 +293,7 @@ public inline fun ?> DataColumn.maxOf( * df.name.firstName.maxOfOrNull { it.length } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [selector] A function that returns the value to compare for each element of this column. * @return The maximum of the values [selector] returns, * or `null` if there are no values to compare. @@ -339,7 +339,7 @@ public fun DataRow<*>.rowMax(): Nothing = error(ROW_MAX) * ``` * * @param [T] The type of the values to compare. Only columns of this type are taken into account. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return The largest value of type [T] in this row, or `null` if there are no values to compare. */ public inline fun > DataRow<*>.rowMaxOfOrNull(skipNaN: Boolean = skipNaNDefault): T? = @@ -371,7 +371,7 @@ public inline fun > DataRow<*>.rowMaxOfOrNull(skipNaN: * ``` * * @param [T] The type of the values to compare. Only columns of this type are taken into account. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return The largest value of type [T] in this row. * @throws NoSuchElementException if there are no values to compare. */ @@ -407,7 +407,7 @@ public inline fun > DataRow<*>.rowMaxOf(skipNaN: Boole * df.max() * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A single [DataRow] with the maximum of each suitable column of this [DataFrame]. */ @Refine @@ -444,7 +444,7 @@ public fun DataFrame.max(skipNaN: Boolean = skipNaNDefault): DataRow = * df.maxFor(skipNaN = true) { age into "maxAge" and (weight into "maxWeight") } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns of this [DataFrame] * to compute the maximum of. * @return A single [DataRow] with the maximum of each selected column. @@ -482,7 +482,7 @@ public fun ?> DataFrame.maxFor( * ``` * * @param [columns] The names of the columns of this [DataFrame] to compute the maximum of. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A single [DataRow] with the maximum of each selected column. */ @Refine @@ -531,7 +531,7 @@ public fun ?> DataFrame.maxFor( * df.max { age and weight } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] * to compute the maximum of. * @return The largest value among all the values in the selected columns. @@ -570,7 +570,7 @@ public fun ?> DataFrame.max( * ``` * * @param [columns] The names of the columns of this [DataFrame] to compute the maximum of. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return The largest value among all the values in the selected columns. * @throws NoSuchElementException if there are no values to compare. */ @@ -620,7 +620,7 @@ public fun ?> DataFrame.max( * df.maxOrNull { age and weight } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] * to compute the maximum of. * @return The largest value among all the values in the selected columns, @@ -661,7 +661,7 @@ public fun ?> DataFrame.maxOrNull( * ``` * * @param [columns] The names of the columns of this [DataFrame] to compute the maximum of. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return The largest value among all the values in the selected columns, * or `null` if there are no values to compare. */ @@ -710,7 +710,7 @@ public fun ?> DataFrame.maxOrNull( * df.maxOf { (weight ?: 0) / age } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return The maximum of the values [expression] returns. * @throws NoSuchElementException if there are no values to compare. @@ -748,7 +748,7 @@ public inline fun ?> DataFrame.maxOf( * df.maxOfOrNull { (weight ?: 0) / age } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return The maximum of the values [expression] returns, * or `null` if there are no values to compare. @@ -788,7 +788,7 @@ public inline fun ?> DataFrame.maxOfOrNull * df.maxBy { (weight ?: 0) / age } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return The first [DataRow] for which [expression] returns the maximum value. * @throws NoSuchElementException if there are no values to compare. @@ -826,7 +826,7 @@ public inline fun ?> DataFrame.maxBy( * ``` * * @param [column] The name of the column of this [DataFrame] to compare the rows by. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return The first [DataRow] with the largest value in the given column. * @throws NoSuchElementException if there are no values to compare. */ @@ -873,7 +873,7 @@ public inline fun ?> DataFrame.maxBy( * df.maxByOrNull { age } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return The first [DataRow] for which [expression] returns the maximum value, * or `null` if there are no values to compare. @@ -910,7 +910,7 @@ public inline fun ?> DataFrame.maxByOrNull * ``` * * @param [column] The name of the column of this [DataFrame] to compare the rows by. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return The first [DataRow] with the largest value in the given column, * or `null` if there are no values to compare. */ @@ -965,7 +965,7 @@ public inline fun ?> DataFrame.maxByOrNull * df.groupBy { city }.max() * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A new [DataFrame] with the group keys and the maximum of each suitable column per group. */ @Refine @@ -1007,7 +1007,7 @@ public fun Grouped.max(skipNaN: Boolean = skipNaNDefault): DataFrame = * df.groupBy { city }.maxFor { age and weight } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns * to compute the maximum of. * @return A new [DataFrame] with the group keys and the maximum of each selected column per group. @@ -1052,7 +1052,7 @@ public fun ?> Grouped.maxFor( * ``` * * @param [columns] The names of the columns to compute the maximum of. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A new [DataFrame] with the group keys and the maximum of each selected column per group. */ @Refine @@ -1112,7 +1112,7 @@ public fun ?> Grouped.maxFor( * @param [name] The name of the resulting column. * If `null` (the default), the name of the selected column is used if exactly one column * is selected, and `"max"` otherwise. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns to compute the maximum of. * @return A new [DataFrame] with the group keys and a single maximum per group. */ @@ -1163,7 +1163,7 @@ public fun ?> Grouped.max( * @param [name] The name of the resulting column. * If `null` (the default), the name of the selected column is used if exactly one column * is selected, and `"max"` otherwise. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A new [DataFrame] with the group keys and a single maximum per group. */ @Refine @@ -1222,7 +1222,7 @@ public fun ?> Grouped.max( * ``` * * @param [name] The name of the resulting column. If `null` (the default), `"max"` is used. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return A new [DataFrame] with the group keys and a single maximum per group. */ @@ -1261,7 +1261,7 @@ public inline fun ?> Grouped.maxOf( * df.groupBy { city }.maxBy { age }.concat() * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to compute the value to compare for each row. * @return A [ReducedGroupBy] with, for each group, the first row * for which [rowExpression] returns the maximum value. @@ -1306,7 +1306,7 @@ public inline fun ?> GroupBy.maxBy( * ``` * * @param [column] The name of the column to compare the rows by. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A [ReducedGroupBy] with, for each group, the first row * that has the largest value in the given column. */ @@ -1357,7 +1357,7 @@ public inline fun ?> GroupBy.maxBy( * ``` * * @include [MaxDocs.SeparateParam] - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A single [DataRow] with the maximum of each suitable column per [pivot] group. */ public fun Pivot.max(separate: Boolean = false, skipNaN: Boolean = skipNaNDefault): DataRow = @@ -1400,7 +1400,7 @@ public fun Pivot.max(separate: Boolean = false, skipNaN: Boolean = skipNa * ``` * * @include [MaxDocs.SeparateParam] - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns * to compute the maximum of. * @return A single [DataRow] with the maximum of each selected column per [pivot] group. @@ -1445,7 +1445,7 @@ public fun ?> Pivot.maxFor( * * @param [columns] The names of the columns to compute the maximum of. * @include [MaxDocs.SeparateParam] - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A single [DataRow] with the maximum of each selected column per [pivot] group. */ public fun Pivot.maxFor( @@ -1501,7 +1501,7 @@ public fun ?> Pivot.maxFor( * df.pivot { city }.max { age and weight } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns to compute the maximum of. * @return A single [DataRow] with, per [pivot] group, the largest value among all the values * in the selected columns. @@ -1543,7 +1543,7 @@ public fun ?> Pivot.max( * ``` * * @param [columns] The names of the columns to compute the maximum of. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A single [DataRow] with, per [pivot] group, the largest value among all the values * in the selected columns. */ @@ -1598,7 +1598,7 @@ public fun ?> Pivot.max( * df.pivot { city }.maxOf { (weight ?: 0) / age } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to evaluate for each row. * @return A single [DataRow] with, per [pivot] group, the maximum of the expression's results. */ @@ -1637,7 +1637,7 @@ public inline fun ?> Pivot.maxOf( * df.pivot { city }.maxBy { (weight ?: 0) / age }.with { name } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to evaluate for each row. * @return A [ReducedPivot] holding, per group, * the first row where the [rowExpression] produced the maximum result. @@ -1684,7 +1684,7 @@ public inline fun ?> Pivot.maxBy( * ``` * * @param [column] The name of the column to compare the rows by. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A [ReducedPivot] holding, per group, the first row with the largest value * in the given column. */ @@ -1736,7 +1736,7 @@ public inline fun ?> Pivot.maxBy( * ``` * * @include [MaxDocs.SeparateParam] - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A [DataFrame] with the maximum of each suitable column per group. */ public fun PivotGroupBy.max(separate: Boolean = false, skipNaN: Boolean = skipNaNDefault): DataFrame = @@ -1779,7 +1779,7 @@ public fun PivotGroupBy.max(separate: Boolean = false, skipNaN: Boolean = * ``` * * @include [MaxDocs.SeparateParam] - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns * to compute the maximum of. * @return A [DataFrame] with the maximum of each selected column per group. @@ -1826,7 +1826,7 @@ public fun ?> PivotGroupBy.maxFor( * * @param [columns] The names of the columns to compute the maximum of. * @include [MaxDocs.SeparateParam] - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A [DataFrame] with the maximum of each selected column per group. */ public fun PivotGroupBy.maxFor( @@ -1885,7 +1885,7 @@ public fun ?> PivotGroupBy.maxFor( * df.pivot { city }.groupBy { name.lastName }.max { age and weight } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns to compute the maximum of. * @return A [DataFrame] with, per group, the largest value among all the values * in the selected columns. @@ -1930,7 +1930,7 @@ public fun ?> PivotGroupBy.max( * ``` * * @param [columns] The names of the columns to compute the maximum of. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A [DataFrame] with, per group, the largest value among all the values * in the selected columns. */ @@ -1986,7 +1986,7 @@ public fun ?> PivotGroupBy.max( * df.pivot { city }.groupBy { name.lastName }.maxOf { (weight ?: 0) / age } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to evaluate for each row. * @return A [DataFrame] with, per group, the maximum of the expression's results. */ @@ -2026,7 +2026,7 @@ public inline fun ?> PivotGroupBy.maxOf( * df.pivot { city }.groupBy { name.lastName }.maxBy { (weight ?: 0) / age }.with { name.firstName } * ``` * - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to evaluate for each row. * @return A [ReducedPivotGroupBy] holding, per group, * the first row where the [rowExpression] produced the maximum result. @@ -2074,7 +2074,7 @@ public inline fun ?> PivotGroupBy.maxBy( * ``` * * @param [column] The name of the column to compare the rows by. - * @include [MaxDocs.SkipNaNParam] + * @include [MaxDocs.SkipNanParam] * @return A [ReducedPivotGroupBy] holding, per group, the first row with the largest value * in the given column. */ diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt index bd0c30baac..bd22e580aa 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt @@ -127,7 +127,7 @@ private typealias SetMinOrNullOperationArg = Nothing * df.weight.min() * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return The smallest value in this column. * @throws NoSuchElementException if there are no values to compare. */ @@ -159,7 +159,7 @@ public fun > DataColumn.min(skipNaN: Boolean = skipNaNDefa * df.weight.minOrNull() * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return The smallest value in this column, or `null` if there are no values to compare. */ public fun > DataColumn.minOrNull(skipNaN: Boolean = skipNaNDefault): T? = @@ -189,7 +189,7 @@ public fun > DataColumn.minOrNull(skipNaN: Boolean = skipN * df.name.firstName.minBy { it.length } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [selector] A function that returns the value to compare for each element of this column. * @return The first element for which [selector] returns the minimum value. * @throws NoSuchElementException if there are no values to compare. @@ -224,7 +224,7 @@ public inline fun ?> DataColumn.minBy( * df.name.firstName.minByOrNull { it.length } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [selector] A function that returns the value to compare for each element of this column. * @return The first element for which [selector] returns the minimum value, * or `null` if there are no values to compare. @@ -258,7 +258,7 @@ public inline fun ?> DataColumn.minByOrNul * df.name.firstName.minOf { it.length } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [selector] A function that returns the value to compare for each element of this column. * @return The minimum of the values [selector] returns. * @throws NoSuchElementException if there are no values to compare. @@ -293,7 +293,7 @@ public inline fun ?> DataColumn.minOf( * df.name.firstName.minOfOrNull { it.length } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [selector] A function that returns the value to compare for each element of this column. * @return The minimum of the values [selector] returns, * or `null` if there are no values to compare. @@ -339,7 +339,7 @@ public fun DataRow<*>.rowMin(): Nothing = error(ROW_MIN) * ``` * * @param [T] The type of the values to compare. Only columns of this type are taken into account. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return The smallest value of type [T] in this row, or `null` if there are no values to compare. */ public inline fun > DataRow<*>.rowMinOfOrNull(skipNaN: Boolean = skipNaNDefault): T? = @@ -371,7 +371,7 @@ public inline fun > DataRow<*>.rowMinOfOrNull(skipNaN: * ``` * * @param [T] The type of the values to compare. Only columns of this type are taken into account. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return The smallest value of type [T] in this row. * @throws NoSuchElementException if there are no values to compare. */ @@ -407,7 +407,7 @@ public inline fun > DataRow<*>.rowMinOf(skipNaN: Boole * df.min() * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A single [DataRow] with the minimum of each suitable column of this [DataFrame]. */ @Refine @@ -444,7 +444,7 @@ public fun DataFrame.min(skipNaN: Boolean = skipNaNDefault): DataRow = * df.minFor(skipNaN = true) { age into "minAge" and (weight into "minWeight") } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns of this [DataFrame] * to compute the minimum of. * @return A single [DataRow] with the minimum of each selected column. @@ -482,7 +482,7 @@ public fun ?> DataFrame.minFor( * ``` * * @param [columns] The names of the columns of this [DataFrame] to compute the minimum of. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A single [DataRow] with the minimum of each selected column. */ @Refine @@ -531,7 +531,7 @@ public fun ?> DataFrame.minFor( * df.min { age and weight } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] * to compute the minimum of. * @return The smallest value among all the values in the selected columns. @@ -570,7 +570,7 @@ public fun ?> DataFrame.min( * ``` * * @param [columns] The names of the columns of this [DataFrame] to compute the minimum of. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return The smallest value among all the values in the selected columns. * @throws NoSuchElementException if there are no values to compare. */ @@ -620,7 +620,7 @@ public fun ?> DataFrame.min( * df.minOrNull { age and weight } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] * to compute the minimum of. * @return The smallest value among all the values in the selected columns, @@ -661,7 +661,7 @@ public fun ?> DataFrame.minOrNull( * ``` * * @param [columns] The names of the columns of this [DataFrame] to compute the minimum of. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return The smallest value among all the values in the selected columns, * or `null` if there are no values to compare. */ @@ -710,7 +710,7 @@ public fun ?> DataFrame.minOrNull( * df.minOf { (weight ?: 0) / age } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return The minimum of the values [expression] returns. * @throws NoSuchElementException if there are no values to compare. @@ -748,7 +748,7 @@ public inline fun ?> DataFrame.minOf( * df.minOfOrNull { (weight ?: 0) / age } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return The minimum of the values [expression] returns, * or `null` if there are no values to compare. @@ -788,7 +788,7 @@ public inline fun ?> DataFrame.minOfOrNull * df.minBy { (weight ?: 0) / age } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return The first [DataRow] for which [expression] returns the minimum value. * @throws NoSuchElementException if there are no values to compare. @@ -826,7 +826,7 @@ public inline fun ?> DataFrame.minBy( * ``` * * @param [column] The name of the column of this [DataFrame] to compare the rows by. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return The first [DataRow] with the smallest value in the given column. * @throws NoSuchElementException if there are no values to compare. */ @@ -873,7 +873,7 @@ public inline fun ?> DataFrame.minBy( * df.minByOrNull { age } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return The first [DataRow] for which [expression] returns the minimum value, * or `null` if there are no values to compare. @@ -910,7 +910,7 @@ public inline fun ?> DataFrame.minByOrNull * ``` * * @param [column] The name of the column of this [DataFrame] to compare the rows by. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return The first [DataRow] with the smallest value in the given column, * or `null` if there are no values to compare. */ @@ -965,7 +965,7 @@ public inline fun ?> DataFrame.minByOrNull * df.groupBy { city }.min() * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A new [DataFrame] with the group keys and the minimum of each suitable column per group. */ @Refine @@ -1007,7 +1007,7 @@ public fun Grouped.min(skipNaN: Boolean = skipNaNDefault): DataFrame = * df.groupBy { city }.minFor { age and weight } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns * to compute the minimum of. * @return A new [DataFrame] with the group keys and the minimum of each selected column per group. @@ -1052,7 +1052,7 @@ public fun ?> Grouped.minFor( * ``` * * @param [columns] The names of the columns to compute the minimum of. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A new [DataFrame] with the group keys and the minimum of each selected column per group. */ @Refine @@ -1112,7 +1112,7 @@ public fun ?> Grouped.minFor( * @param [name] The name of the resulting column. * If `null` (the default), the name of the selected column is used if exactly one column * is selected, and `"min"` otherwise. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns to compute the minimum of. * @return A new [DataFrame] with the group keys and a single minimum per group. */ @@ -1163,7 +1163,7 @@ public fun ?> Grouped.min( * @param [name] The name of the resulting column. * If `null` (the default), the name of the selected column is used if exactly one column * is selected, and `"min"` otherwise. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A new [DataFrame] with the group keys and a single minimum per group. */ @Refine @@ -1222,7 +1222,7 @@ public fun ?> Grouped.min( * ``` * * @param [name] The name of the resulting column. If `null` (the default), `"min"` is used. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [expression] The [RowExpression] to compute the value to compare for each row. * @return A new [DataFrame] with the group keys and a single minimum per group. */ @@ -1261,7 +1261,7 @@ public inline fun ?> Grouped.minOf( * df.groupBy { city }.minBy { age }.concat() * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to compute the value to compare for each row. * @return A [ReducedGroupBy] with, for each group, the first row * for which [rowExpression] returns the minimum value. @@ -1306,7 +1306,7 @@ public inline fun ?> GroupBy.minBy( * ``` * * @param [column] The name of the column to compare the rows by. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A [ReducedGroupBy] with, for each group, the first row * that has the smallest value in the given column. */ @@ -1357,7 +1357,7 @@ public inline fun ?> GroupBy.minBy( * ``` * * @include [MinDocs.SeparateParam] - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A single [DataRow] with the minimum of each suitable column per [pivot] group. */ public fun Pivot.min(separate: Boolean = false, skipNaN: Boolean = skipNaNDefault): DataRow = @@ -1400,7 +1400,7 @@ public fun Pivot.min(separate: Boolean = false, skipNaN: Boolean = skipNa * ``` * * @include [MinDocs.SeparateParam] - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns * to compute the minimum of. * @return A single [DataRow] with the minimum of each selected column per [pivot] group. @@ -1445,7 +1445,7 @@ public fun ?> Pivot.minFor( * * @param [columns] The names of the columns to compute the minimum of. * @include [MinDocs.SeparateParam] - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A single [DataRow] with the minimum of each selected column per [pivot] group. */ public fun Pivot.minFor( @@ -1501,7 +1501,7 @@ public fun ?> Pivot.minFor( * df.pivot { city }.min { age and weight } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns to compute the minimum of. * @return A single [DataRow] with, per [pivot] group, the smallest value among all the values * in the selected columns. @@ -1543,7 +1543,7 @@ public fun ?> Pivot.min( * ``` * * @param [columns] The names of the columns to compute the minimum of. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A single [DataRow] with, per [pivot] group, the smallest value among all the values * in the selected columns. */ @@ -1598,7 +1598,7 @@ public fun ?> Pivot.min( * df.pivot { city }.minOf { (weight ?: 0) / age } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to evaluate for each row. * @return A single [DataRow] with, per [pivot] group, the minimum of the expression's results. */ @@ -1637,7 +1637,7 @@ public inline fun ?> Pivot.minOf( * df.pivot { city }.minBy { (weight ?: 0) / age }.with { name } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to evaluate for each row. * @return A [ReducedPivot] holding, per group, * the first row where the [rowExpression] produced the minimum result. @@ -1684,7 +1684,7 @@ public inline fun ?> Pivot.minBy( * ``` * * @param [column] The name of the column to compare the rows by. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A [ReducedPivot] holding, per group, the first row with the smallest value * in the given column. */ @@ -1736,7 +1736,7 @@ public inline fun ?> Pivot.minBy( * ``` * * @include [MinDocs.SeparateParam] - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A [DataFrame] with the minimum of each suitable column per group. */ public fun PivotGroupBy.min(separate: Boolean = false, skipNaN: Boolean = skipNaNDefault): DataFrame = @@ -1779,7 +1779,7 @@ public fun PivotGroupBy.min(separate: Boolean = false, skipNaN: Boolean = * ``` * * @include [MinDocs.SeparateParam] - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns * to compute the minimum of. * @return A [DataFrame] with the minimum of each selected column per group. @@ -1826,7 +1826,7 @@ public fun ?> PivotGroupBy.minFor( * * @param [columns] The names of the columns to compute the minimum of. * @include [MinDocs.SeparateParam] - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A [DataFrame] with the minimum of each selected column per group. */ public fun PivotGroupBy.minFor( @@ -1885,7 +1885,7 @@ public fun ?> PivotGroupBy.minFor( * df.pivot { city }.groupBy { name.lastName }.min { age and weight } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [columns] The [ColumnsSelector] used to select the columns to compute the minimum of. * @return A [DataFrame] with, per group, the smallest value among all the values * in the selected columns. @@ -1930,7 +1930,7 @@ public fun ?> PivotGroupBy.min( * ``` * * @param [columns] The names of the columns to compute the minimum of. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A [DataFrame] with, per group, the smallest value among all the values * in the selected columns. */ @@ -1986,7 +1986,7 @@ public fun ?> PivotGroupBy.min( * df.pivot { city }.groupBy { name.lastName }.minOf { (weight ?: 0) / age } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to evaluate for each row. * @return A [DataFrame] with, per group, the minimum of the expression's results. */ @@ -2026,7 +2026,7 @@ public inline fun ?> PivotGroupBy.minOf( * df.pivot { city }.groupBy { name.lastName }.minBy { (weight ?: 0) / age }.with { name.firstName } * ``` * - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @param [rowExpression] The [RowExpression] to evaluate for each row. * @return A [ReducedPivotGroupBy] holding, per group, * the first row where the [rowExpression] produced the minimum result. @@ -2074,7 +2074,7 @@ public inline fun ?> PivotGroupBy.minBy( * ``` * * @param [column] The name of the column to compare the rows by. - * @include [MinDocs.SkipNaNParam] + * @include [MinDocs.SkipNanParam] * @return A [ReducedPivotGroupBy] holding, per group, the first row with the smallest value * in the given column. */ diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt index 179af5b776..fae3c731fb 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt @@ -1,8 +1,6 @@ package org.jetbrains.kotlinx.dataframe.documentation import org.jetbrains.kotlinx.dataframe.DataFrame -import org.jetbrains.kotlinx.dataframe.RowExpression -import org.jetbrains.kotlinx.dataframe.aggregation.ColumnsForAggregateSelectionDsl import org.jetbrains.kotlinx.dataframe.api.GroupByDocs import org.jetbrains.kotlinx.dataframe.api.ReducedGroupBy import org.jetbrains.kotlinx.dataframe.api.ReducedPivot @@ -17,11 +15,13 @@ import org.jetbrains.kotlinx.dataframe.api.with * Holds all KDoc-snippets that the `min` and `max` operations have in common. * Both `MinDocs` and `MaxDocs` inherit from this interface, so the snippets can be * included from either of them, like `{@include [MaxDocs.SkipNaNParam]}`. + * The snippets that all summary statistics have in common are inherited from + * [CommonStatisticsDocs] and can be included in the same way. * * NOTE: this cannot be @ExcludedFromSources because `MinDocs` and `MaxDocs` use it as supertype. * } */ -internal interface CommonMinMaxDocs { +internal interface CommonMinMaxDocs : CommonStatisticsDocs { /** * {@comment Note about the self-comparability requirement and how `null` and `NaN` values @@ -31,10 +31,7 @@ internal interface CommonMinMaxDocs { * that are mutually comparable (like strings, primitive numbers, or dates). * This includes all primitive number types, but no mix of different number types. * - * `null` values in the input are always ignored. - * - * If the input contains {@include [NaNLink]} values, the result will be `NaN`, - * unless [skipNaN\] is set to `true`. + * {@include [CommonStatisticsDocs.NullAndNaNHandlingSnippet]} */ @ExcludeFromSources typealias InputValuesSnippet = Nothing @@ -72,29 +69,6 @@ internal interface CommonMinMaxDocs { @ExcludeFromSources typealias NullCellOnEmptySnippet = Nothing - /** - * {@comment Note about the row expression argument. KDoc-snippet.} - * - * The given [RowExpression] is evaluated for each row of the dataframe. - * The row is both the receiver and the argument (`it`) of the expression, - * so the values in it can be accessed directly. - * - * For more information: {@include [DocumentationUrls.DataRow.RowExpression]} - */ - @ExcludeFromSources - typealias RowExpressionSnippet = Nothing - - /** - * {@comment Note about the aggregate columns selector of the `-For` modes. KDoc-snippet.} - * - * The columns are selected with the [ColumnsForAggregateSelectionDsl] — an extension of the - * Columns Selection DSL which lets you rename the result of a column with - * [into][ColumnsForAggregateSelectionDsl.into] and supply a - * [default][ColumnsForAggregateSelectionDsl.default] value for columns without any values. - */ - @ExcludeFromSources - typealias AggregateColumnsSelectorSnippet = Nothing - /** * {@comment Note about [ReducedGroupBy] being an intermediate step. KDoc-snippet.} * @@ -127,24 +101,4 @@ internal interface CommonMinMaxDocs { */ @ExcludeFromSources typealias ReducedPivotGroupBySnippet = Nothing - - /** - * {@comment The shared `skipNaN` parameter documentation. KDoc-snippet.} - * - * @param [skipNaN\] If `true`, {@include [NaNLink]} values are ignored, just like `null` values. - * If `false` (the default), a {@include [NaNLink]} in the input is propagated to the result. - * Only has an effect on [Double] and [Float] values. - */ - @ExcludeFromSources - typealias SkipNaNParam = Nothing - - /** - * {@comment The shared `separate` parameter documentation. KDoc-snippet.} - * - * @param [separate\] If `false` (the default), the resulting columns are indexed - * first by the pivot key(s) and then by the names of the aggregated columns. - * If `true`, this order is reversed: the results are grouped by aggregated column first. - */ - @ExcludeFromSources - typealias SeparateParam = Nothing } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonStatisticsDocs.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonStatisticsDocs.kt new file mode 100644 index 0000000000..063fa6b2a6 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonStatisticsDocs.kt @@ -0,0 +1,71 @@ +package org.jetbrains.kotlinx.dataframe.documentation + +import org.jetbrains.kotlinx.dataframe.RowExpression +import org.jetbrains.kotlinx.dataframe.aggregation.ColumnsForAggregateSelectionDsl + +/** + * @comment + * Holds all KDoc-snippets that the summary statistics operations have in common. + * The KDoc-topic of each statistic (like [CommonMinMaxDocs] for `min`/`max`, or `SumDocs` for + * `sum`) inherits from this interface, so the snippets can be included from any of them, + * like `{@include [CommonMinMaxDocs.SkipNaNParam]}`. + * + * NOTE: this cannot be @ExcludedFromSources because [CommonMinMaxDocs] and the other statistics + * KDoc-topics use it as supertype. + */ +internal interface CommonStatisticsDocs { + + /** + * {@comment Note about how `null` and NaN values in the input are treated. KDoc-snippet.} + * + * `null` values in the input are always ignored. + * + * If the input contains {@include [NaNLink]} values, the result will be `NaN`, + * unless [skipNaN\] is set to `true`. + */ + @ExcludeFromSources + typealias NullAndNaNHandlingSnippet = Nothing + + /** + * {@comment Note about the row expression argument. KDoc-snippet.} + * + * The given [RowExpression] is evaluated for each row of the dataframe. + * The row is both the receiver and the argument (`it`) of the expression, + * so the values in it can be accessed directly. + * + * For more information: {@include [DocumentationUrls.DataRow.RowExpression]} + */ + @ExcludeFromSources + typealias RowExpressionSnippet = Nothing + + /** + * {@comment Note about the aggregate columns selector of the `-For` modes. KDoc-snippet.} + * + * The columns are selected with the [ColumnsForAggregateSelectionDsl] — an extension of the + * Columns Selection DSL which lets you rename the result of a column with + * [`into`][ColumnsForAggregateSelectionDsl.into] and supply a + * [`default`][ColumnsForAggregateSelectionDsl.default] value for columns without any values. + */ + @ExcludeFromSources + typealias AggregateColumnsSelectorSnippet = Nothing + + /** + * {@comment The shared `skipNaN` parameter documentation. KDoc-snippet.} + * + * @param [skipNaN\] If `true`, {@include [NaNLink]} values are ignored, just like `null` values. + * If `false` (the default), a {@include [NaNLink]} in the input is propagated to the result. + * This only has an effect on [Double] and [Float] values. + */ + @ExcludeFromSources + typealias SkipNanParam = Nothing + + /** + * {@comment The shared `separate` parameter documentation. KDoc-snippet.} + * + * @param [separate\] If `false` (the default), the resulting columns are indexed + * first by the pivot key(s) and then by the names of the aggregated columns. + * If `true`, this order is reversed: the results are grouped by aggregated column first. + */ + @ExcludeFromSources + typealias SeparateParam = Nothing +} From aa0aff39a25c1507454226bba25a90d22c329812 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Mon, 17 Aug 2026 20:43:44 +0200 Subject: [PATCH 02/11] writing kdocs for sum.kt, WIP collaboration with claude  Conflicts:  core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt --- core/api/core.api | 3 + .../jetbrains/kotlinx/dataframe/api/sum.kt | 1355 ++++++++++++++++- .../documentation/DocumentationUrls.kt | 10 + 3 files changed, 1361 insertions(+), 7 deletions(-) diff --git a/core/api/core.api b/core/api/core.api index 71f9b264e8..3af74af214 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -5399,6 +5399,9 @@ public abstract interface class org/jetbrains/kotlinx/dataframe/documentation/Do public abstract interface class org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls$NanAndNa { } +public abstract interface class org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls$Sum { +} + public abstract interface class org/jetbrains/kotlinx/dataframe/documentation/DslGrammarTemplateColumnsSelectionDsl { } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index 3be52e2bcc..3a935b8dd5 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -16,6 +16,12 @@ import org.jetbrains.kotlinx.dataframe.annotations.StringApiInterpretable import org.jetbrains.kotlinx.dataframe.columns.ColumnReference import org.jetbrains.kotlinx.dataframe.columns.toColumnSet import org.jetbrains.kotlinx.dataframe.columns.toColumnsSetOf +import org.jetbrains.kotlinx.dataframe.documentation.CommonStatisticsDocs +import org.jetbrains.kotlinx.dataframe.documentation.DocumentationUrls +import org.jetbrains.kotlinx.dataframe.documentation.ExcludeFromSources +import org.jetbrains.kotlinx.dataframe.documentation.SelectingColumns +import org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers +import org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregators import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor @@ -33,38 +39,294 @@ import kotlin.reflect.KType import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf -/* TODO KDocs - * Calculating the sum is supported for all primitive number types. - * Nulls are filtered out. - * The return type is always the same as the input type (never null), except for `Byte` and `Short`, - * which are converted to `Int`. - * Empty input will result in 0 in the supplied number type. - * For mixed primitive number types, the aggregator unifies the numbers before calculating the sum. +// region docs + +/** + * {@comment + * The Sum Operation KDoc-topic; it also holds all common `sum` KDoc-snippets. + * Link to it with `{@include [SumDocsLink]}`. + * } + * + * ## The Sum Operation + * + * Computes the [sum](https://en.wikipedia.org/wiki/Summation) of values. + * + * @include [SupportedTypesSnippet] + * + * ### Sum Modes + * + * Depending on what exactly you want the sum of, there are several modes. + * They are shown here for [DataFrame], but they exist for the other receivers too: + * + * - [`sum`][DataFrame.sum]`()` — the sum of each suitable column separately. + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in all selected columns. + * - [`sumFor`][DataFrame.sumFor]` { columns }` — the sum of each selected column separately. + * - [`sumOf`][DataFrame.sumOf]` { expression }` — the sum of the values that the given expression + * returns for each row. + * + * Related operations: + * - [`mean`][DataFrame.mean] — the sum divided by the number of values. + * - [`cumSum`][DataFrame.cumSum] — the running sum: each value plus all the values before it. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * For more information about [unifying numbers][UnifyingNumbers]: + * @include [DocumentationUrls.NumberUnification] + * + * See all summary statistics: + * @include [DocumentationUrls.Statistics] */ +internal interface SumDocs : CommonStatisticsDocs { + + /** + * {@comment Note about which values are supported, how `null` and `NaN` values are treated, + * and what type the result has. KDoc-snippet.} + * + * All primitive number types are supported: [Byte], [Short], [Int], [Long], [Float], and [Double]. + * "Mixed" [Number] input is supported too, as long as it consists solely of those primitive numbers; + * its values are then first converted to their common type using [UnifiedNumberTypeOptions.PRIMITIVES_ONLY], + * see [number unification][UnifyingNumbers]. + * Big numbers ([`BigInteger`][java.math.BigInteger], [`BigDecimal`][java.math.BigDecimal]) are not + * supported; [`convert`][DataFrame.convert] them to a primitive number type first. + * + * @include [CommonStatisticsDocs.NullAndNaNHandlingSnippet] + * + * The result is never `null` and has the same type as the input, except for [Byte] and [Short], + * which sum to [Int], and "mixed" [Number] input, which sums to the common type of its values. + * + * For more information about the resulting types: + * @include [DocumentationUrls.Sum.TypeConversion] + */ + @ExcludeFromSources + typealias SupportedTypesSnippet = Nothing + + /** + * {@comment Note about the behavior on empty input for the modes with a single result. KDoc-snippet.} + * + * When there is nothing to sum, for instance, when the input is empty or contains only `null` values, + * the result is `0` in the result type (defaulting to [Double] if there is no number type to speak of). + */ + @ExcludeFromSources + typealias ZeroOnEmptySnippet = Nothing + + /** + * {@comment Note about the behavior on empty input for the modes with multiple results. KDoc-snippet.} + * + * Result cells for which there is nothing to sum + * (for instance, because the input was empty or contained only `null` values) + * simply become `0` in the result type (defaulting to [Double] if there is no number type to speak of). + * + * For more information about the resulting types: + * @include [DocumentationUrls.Sum.TypeConversion] + */ + @ExcludeFromSources + typealias ZeroCellOnEmptySnippet = Nothing + + /** + * {@comment Version of [SelectingColumns] with correctly filled in examples} + * @include [SelectingColumns] {@include [SetSumOperationArg]} + */ + typealias SumSelectingOptions = Nothing + + /** + * {@comment Version of [SelectingColumns] with correctly filled in examples} + * @include [SelectingColumns] {@include [SetSumForOperationArg]} + */ + typealias SumForSelectingOptions = Nothing + + /** + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * See also: + * - [`sumOf`][DataColumn.sumOf] — the sum of the values a selector returns for each element. + * - [`mean`][DataColumn.mean] — the sum divided by the number of values. + * - [`cumSum`][DataColumn.cumSum] — the running sum of the values in this column. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: + * @include [DocumentationUrls.Sum] + * + * ### Example + */ + @ExcludeFromSources + typealias DataColumnSumSnippet = Nothing + + /** + * {@comment The parts all [DataColumn.sumOf] overloads have in common. KDoc-snippet.} + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * See also: + * - [`sum`][DataColumn.sum] — the sum of the values in this column itself. + * - [`meanOf`][DataColumn.meanOf] — the sum of those values divided by the number of values. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: + * @include [DocumentationUrls.Sum] + * + * ### Example + * $[EXAMPLE] + * + * @param [expression\] A function that returns the value to sum for each element of this column. + */ + @ExcludeFromSources + interface DataColumnSumOfSnippet { + + // The example to render for this sumOf overload + typealias EXAMPLE = Nothing + } + + /** + * {@comment The parts all [DataRow.rowSumOf] overloads have in common. KDoc-snippet.} + * + * @include [SumDocs.SupportedTypesSnippet] + * + * @include [SumDocs.ZeroOnEmptySnippet] + * + * See also: + * - [`rowSum`][DataRow.rowSum] — the sum of all the numbers in this row, of any number type. + * - [`sum`][DataFrame.sum] — the sum of the values in specific columns of a [DataFrame]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: + * @include [DocumentationUrls.RowStatistics] + * + * ### Example + */ + @ExcludeFromSources + typealias RowSumOfSnippet = Nothing + + /** + * {@comment [RowSumOfSnippet] plus the parameters that all reified [DataRow.rowSumOf] overloads + * have in common. KDoc-snippet.} + * + * @include [SumDocs.RowSumOfSnippet] + * $[EXAMPLE] + * @param [T\] The type of the values to sum. Only columns of this type are taken into account. + * @param [_kClass\] Technical parameter to distinguish this overload from the others; + * you never need to supply it. + */ + @ExcludeFromSources + interface ReifiedRowSumOfSnippet { + + // The example to render for this rowSumOf overload + typealias EXAMPLE = Nothing + } +} + +/** [The Sum Operation][SumDocs] */ +@ExcludeFromSources +private typealias SumDocsLink = Nothing + +/** {@set [SelectingColumns.OPERATION] [sum][sum]} */ +@ExcludeFromSources +private typealias SetSumOperationArg = Nothing + +/** {@set [SelectingColumns.OPERATION] [sumFor][sumFor]} */ +@ExcludeFromSources +private typealias SetSumForOperationArg = Nothing + +// endregion // region DataColumn +/** + * Returns the sum of the [Short] values in this [DataColumn], as an [Int]. + * + * @include [SumDocs.DataColumnSumSnippet] + * ```kotlin + * // The sum of all values in the "amount" column of `Short`s, as an `Int` + * df.amount.sum() + * ``` + * + * @return The sum of the values in this column, as an [Int]. + */ @JvmName("sumShort") public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingleColumn(this) as Int +/** + * Returns the sum of the [Byte] values in this [DataColumn], as an [Int]. + * + * @include [SumDocs.DataColumnSumSnippet] + * ```kotlin + * // The sum of all values in the "amount" column of `Byte`s, as an `Int` + * df.amount.sum() + * ``` + * + * @return The sum of the values in this column, as an [Int]. + */ @JvmName("sumByte") public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingleColumn(this) as Int +/** + * Returns the sum of the values in this [DataColumn]. + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.DataColumnSumSnippet] + * ```kotlin + * // The sum of all ages in the "age" Int column + * df.age.sum() + * // The sum of all weights in the "weight" `Double?` column, ignoring `null` values + * df.weight.sum() + * ``` + * + * @include [SumDocs.SkipNanParam] + * @return The sum of the values in this column. + */ @Suppress("UNCHECKED_CAST") @JvmName("sumNumber") public fun DataColumn.sum(skipNaN: Boolean = skipNaNDefault): T & Any = Aggregators.sum(skipNaN).aggregateSingleColumn(this) as (T & Any) +/** + * Returns the sum of the [Short] values that the given [expression] returns + * for each element of this [DataColumn], as an [Int]. + * + * @include [SumDocs.DataColumnSumOfSnippet] + * @set [SumDocs.DataColumnSumOfSnippet.EXAMPLE] + * ```kotlin + * // The sum of all halved values in the "amount" column of `Short`s, as an `Int` + * df.amount.sumOf { (it / 2).toShort() } + * ``` + * @return The sum of the values [expression] returns, as an [Int]. + */ @JvmName("sumOfShort") @OverloadResolutionByLambdaReturnType public inline fun DataColumn.sumOf(crossinline expression: (C) -> V): Int = Aggregators.sum(false).aggregateOf(this, expression) as Int +/** + * Returns the sum of the [Byte] values that the given [expression] returns + * for each element of this [DataColumn], as an [Int]. + * + * @include [SumDocs.DataColumnSumOfSnippet] + * @set [SumDocs.DataColumnSumOfSnippet.EXAMPLE] + * ```kotlin + * // The sum of all halved values in the "amount" column of `Byte`s, as an `Int` + * df.amount.sumOf { (it / 2).toByte() } + * ``` + * @return The sum of the values [expression] returns, as an [Int]. + */ @JvmName("sumOfByte") @OverloadResolutionByLambdaReturnType public inline fun DataColumn.sumOf(crossinline expression: (C) -> V): Int = Aggregators.sum(false).aggregateOf(this, expression) as Int +/** + * Returns the sum of the values that the given [expression] returns + * for each element of this [DataColumn]. + * + * @include [SumDocs.DataColumnSumOfSnippet] + * @set [SumDocs.DataColumnSumOfSnippet.EXAMPLE] + * ```kotlin + * // The total length of all first names in the "name"/"firstName" column + * df.name.firstName.sumOf { it.length } + * ``` + * @include [SumDocs.SkipNanParam] + * @return The sum of the values [expression] returns. + */ @Suppress("UNCHECKED_CAST") @JvmName("sumOfNumber") @OverloadResolutionByLambdaReturnType @@ -77,29 +339,130 @@ public inline fun DataColumn.sumOf( // region DataRow +/** + * Returns the sum of all the numbers in this [DataRow]. + * + * Only the values in the columns of a primitive number type (and in "mixed" [Number] columns) + * are taken into account; all other columns of the row are ignored. + * + * Since the values of different columns are summed together, the result is the sum of all those + * values converted to their common type. + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroOnEmptySnippet] + * + * See also: + * - [`rowSumOf()`][DataRow.rowSumOf] — the sum of the values of one specific number type in this row. + * - [`rowMean`][DataRow.rowMean] — the sum divided by the number of values. + * - [`sum`][DataFrame.sum] — the sum of the values in specific columns of a [DataFrame]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.RowStatistics]} + * + * ### Example + * ```kotlin + * // The sum of all numbers ("age" and "weight") in the first row + * // Columns of other types ("name" and "address") are ignored + * df[0].rowSum() + * ``` + * + * @include [SumDocs.SkipNanParam] + * @return The sum of all the numbers in this row. + */ public fun DataRow<*>.rowSum(skipNaN: Boolean = skipNaNDefault): Number = Aggregators.sum(skipNaN).aggregateOfRow(this, primitiveOrMixedNumberColumns()) +/** + * Returns the sum of the [Short] values in this [DataRow], as an [Int]. + * + * Only the values in the columns of type [Short] (or `Short?`) are taken into account; + * all other columns of the row are ignored. + * + * @include [SumDocs.ReifiedRowSumOfSnippet] + * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] + * ```kotlin + * // The sum of all `Short` values in the first row, as an `Int` + * df[0].rowSumOf() + * ``` + * @return The sum of the [Short] values in this row, as an [Int]. + */ @Suppress("FINAL_UPPER_BOUND") @JvmName("rowSumOfShort") public inline fun DataRow<*>.rowSumOf(_kClass: KClass = Short::class): Int = rowSumOf(typeOf(), false) as Int +/** + * Returns the sum of the [Byte] values in this [DataRow], as an [Int]. + * + * Only the values in the columns of type [Byte] (or `Byte?`) are taken into account; + * all other columns of the row are ignored. + * + * @include [SumDocs.ReifiedRowSumOfSnippet] + * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] + * ```kotlin + * // The sum of all `Byte` values in the first row, as an `Int` + * df[0].rowSumOf() + * ``` + * @return The sum of the [Byte] values in this row, as an [Int]. + */ @Suppress("FINAL_UPPER_BOUND") @JvmName("rowSumOfByte") public inline fun DataRow<*>.rowSumOf(_kClass: KClass = Byte::class): Int = rowSumOf(typeOf(), false) as Int +/** + * Returns the sum of the [Int] values in this [DataRow]. + * + * Only the values in the columns of type [Int] (or `Int?`) are taken into account; + * all other columns of the row are ignored. + * + * @include [SumDocs.ReifiedRowSumOfSnippet] + * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] + * ```kotlin + * // The sum of all `Int` values ("age" and "weight") in the first row + * df[0].rowSumOf() + * ``` + * @return The sum of the [Int] values in this row. + */ @Suppress("FINAL_UPPER_BOUND") @JvmName("rowSumOfInt") public inline fun DataRow<*>.rowSumOf(_kClass: KClass = Int::class): Int = rowSumOf(typeOf(), false) as Int +/** + * Returns the sum of the [Long] values in this [DataRow]. + * + * Only the values in the columns of type [Long] (or `Long?`) are taken into account; + * all other columns of the row are ignored. + * + * @include [SumDocs.ReifiedRowSumOfSnippet] + * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] + * ```kotlin + * // The sum of all `Long` values in the first row + * df[0].rowSumOf() + * ``` + * @return The sum of the [Long] values in this row. + */ @Suppress("FINAL_UPPER_BOUND") @JvmName("rowSumOfLong") public inline fun DataRow<*>.rowSumOf(_kClass: KClass = Long::class): Long = rowSumOf(typeOf(), false) as Long +/** + * Returns the sum of the [Float] values in this [DataRow]. + * + * Only the values in the columns of type [Float] (or `Float?`) are taken into account; + * all other columns of the row are ignored. + * + * @include [SumDocs.ReifiedRowSumOfSnippet] + * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] + * ```kotlin + * // The sum of all `Float` values in the first row, ignoring `NaN` values + * df[0].rowSumOf(skipNaN = true) + * ``` + * @include [SumDocs.SkipNanParam] + * @return The sum of the [Float] values in this row. + */ @Suppress("FINAL_UPPER_BOUND") @JvmName("rowSumOfFloat") public inline fun DataRow<*>.rowSumOf( @@ -107,6 +470,21 @@ public inline fun DataRow<*>.rowSumOf( _kClass: KClass = Float::class, ): Float = rowSumOf(typeOf(), skipNaN) as Float +/** + * Returns the sum of the [Double] values in this [DataRow]. + * + * Only the values in the columns of type [Double] (or `Double?`) are taken into account; + * all other columns of the row are ignored. + * + * @include [SumDocs.ReifiedRowSumOfSnippet] + * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] + * ```kotlin + * // The sum of all `Double` values in the first row, ignoring `NaN` values + * df[0].rowSumOf(skipNaN = true) + * ``` + * @include [SumDocs.SkipNanParam] + * @return The sum of the [Double] values in this row. + */ @Suppress("FINAL_UPPER_BOUND") @JvmName("rowSumOfDouble") public inline fun DataRow<*>.rowSumOf( @@ -115,6 +493,26 @@ public inline fun DataRow<*>.rowSumOf( ): Double = rowSumOf(typeOf(), skipNaN) as Double // unfortunately, we cannot make a `reified T : Number?` due to clashes + +/** + * Returns the sum of the values of the given [type] in this [DataRow]. + * + * Only the values in the columns of the given [type] (or its nullable variant) are taken into account; + * all other columns of the row are ignored. + * + * This overload takes the type as a [KType] argument; prefer the `reified` overloads, like + * [`rowSumOf`][DataRow.rowSumOf]`<`[`Int`][Int]`>()`, whenever the type is known at compile time. + * + * @include [SumDocs.RowSumOfSnippet] + * ```kotlin + * // The sum of all `Int` values ("age" and "weight") in the first row + * df[0].rowSumOf(typeOf()) + * ``` + * @param [type] The type of the values to sum. Only columns of this type are taken into account. + * @include [SumDocs.SkipNanParam] + * @return The sum of the values of the given [type] in this row. + * @throws IllegalArgumentException if [type] is not a primitive number type or [Number] itself. + */ public fun DataRow<*>.rowSumOf(type: KType, skipNaN: Boolean = skipNaNDefault): Number { require(type.isPrimitiveOrMixedNumber()) { "Type $type is not a primitive number type. Mean only supports primitive number types." @@ -126,11 +524,73 @@ public fun DataRow<*>.rowSumOf(type: KType, skipNaN: Boolean = skipNaNDefault): // endregion // region DataFrame + +/** + * Returns the sum of the values of each suitable column of this [DataFrame] separately. + * + * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; + * the other columns are simply left out of the result. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * See also: + * - [`sumFor`][DataFrame.sumFor] — the same, but for an explicit selection of columns. + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * - [`mean`][DataFrame.mean] — the sum of each column divided by its number of values. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * ### Example + * ```kotlin + * // A single row with the sum of each number column ("age" and "weight") + * df.sum() + * ``` + * + * @include [SumDocs.SkipNanParam] + * @return A single [DataRow] with the sum of each suitable column of this [DataFrame]. + */ @Refine @Interpretable("Sum0") public fun DataFrame.sum(skipNaN: Boolean = skipNaNDefault): DataRow = sumFor(skipNaN, primitiveOrMixedNumberColumns()) +/** + * Returns the sum of the values of each selected column of this [DataFrame] separately. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SumDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions]. + * + * See also: + * - [`sum`][DataFrame.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * - [`meanFor`][DataFrame.meanFor] — the sum of each selected column divided by its number of values. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * ### Example + * ```kotlin + * // A single row with the sum of the "age" values and the sum of the "weight" values + * df.sumFor { age and weight } + * // The same, ignoring `NaN` values, and naming the results explicitly + * df.sumFor(skipNaN = true) { age into "totalAge" and (weight into "totalWeight") } + * ``` + * + * @include [SumDocs.SkipNanParam] + * @param [columns] The [ColumnsForAggregateSelector] used to select the columns of this [DataFrame] + * to compute the sum of. + * @return A single [DataRow] with the sum of each selected column. + */ @Refine @Interpretable("Sum1") public fun DataFrame.sumFor( @@ -138,6 +598,35 @@ public fun DataFrame.sumFor( columns: ColumnsForAggregateSelector, ): DataRow = Aggregators.sum(skipNaN).aggregateFor(this, columns) +/** + * Returns the sum of the values of each selected column of this [DataFrame] separately. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions]. + * + * See also: + * - [`sum`][DataFrame.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * - [`meanFor`][DataFrame.meanFor] — the sum of each selected column divided by its number of values. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * ### Example + * ```kotlin + * // A single row with the sum of the "age" values and the sum of the "weight" values + * df.sumFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns of this [DataFrame] to compute the sum of. + * @include [SumDocs.SkipNanParam] + * @return A single [DataRow] with the sum of each selected column. + */ @Refine @StringApiInterpretable(interpreter = "Sum1", stringArgument = "columns", targetArgument = "columns") public fun DataFrame.sumFor(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataRow = @@ -157,16 +646,104 @@ public fun DataFrame.sumFor( skipNaN: Boolean = skipNaNDefault, ): DataRow = sumFor(skipNaN) { columns.toColumnSet() } +/** + * Returns a single sum of all the [Short] values in the selected columns of this [DataFrame], + * as an [Int]. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. + * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * @include [SelectingColumns.ColumnsSelectionDsl] + * + * ### Example + * ```kotlin + * // The sum of all values in the "amount" and "bonus" columns of `Short`s, as an `Int` + * df.sum { amount and bonus } + * ``` + * + * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] + * to compute the sum of. + * @return The sum of all the values in the selected columns, as an [Int]. + */ @JvmName("sumShort") @OverloadResolutionByLambdaReturnType public fun DataFrame.sum(columns: ColumnsSelector): Int = Aggregators.sum(false).aggregateAll(this, columns) as Int +/** + * Returns a single sum of all the [Byte] values in the selected columns of this [DataFrame], + * as an [Int]. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. + * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * @include [SelectingColumns.ColumnsSelectionDsl] + * + * ### Example + * ```kotlin + * // The sum of all values in the "amount" and "bonus" columns of `Byte`s, as an `Int` + * df.sum { amount and bonus } + * ``` + * + * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] + * to compute the sum of. + * @return The sum of all the values in the selected columns, as an [Int]. + */ @JvmName("sumByte") @OverloadResolutionByLambdaReturnType public fun DataFrame.sum(columns: ColumnsSelector): Int = Aggregators.sum(false).aggregateAll(this, columns) as Int +/** + * Returns a single sum of all the values in the selected columns of this [DataFrame]. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. + * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * - [`mean`][DataFrame.mean] — the sum divided by the number of values. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * @include [SelectingColumns.ColumnsSelectionDsl] + * + * ### Example + * ```kotlin + * // The sum of all values in the "age" and "weight" columns together + * df.sum { age and weight } + * ``` + * + * @include [SumDocs.SkipNanParam] + * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] + * to compute the sum of. + * @return The sum of all the values in the selected columns. + */ @Suppress("UNCHECKED_CAST") @JvmName("sumNumber") @OverloadResolutionByLambdaReturnType @@ -193,6 +770,35 @@ public fun DataFrame.sum( skipNaN: Boolean = skipNaNDefault, ): C & Any = sum(skipNaN) { columns.toColumnSet() } +/** + * Returns a single sum of all the values in the selected columns of this [DataFrame]. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. + * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * - [`mean`][DataFrame.mean] — the sum divided by the number of values. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * @include [SelectingColumns.ColumnNamesApi] + * + * ### Example + * ```kotlin + * // The sum of all values in the "age" and "weight" columns together + * df.sum("age", "weight") + * ``` + * + * @param [columns] The names of the columns of this [DataFrame] to compute the sum of. + * @include [SumDocs.SkipNanParam] + * @return The sum of all the values in the selected columns. + */ public fun DataFrame.sum(vararg columns: String, skipNaN: Boolean = skipNaNDefault): Number = sum(skipNaN) { columns.toColumnsSetOf() } @@ -214,16 +820,93 @@ public fun DataFrame.sum( vararg columns: KProperty, ): C & Any = sum(skipNaN) { columns.toColumnSet() } +/** + * Returns the sum of the [Short] values that the given [expression] returns + * for each row of this [DataFrame], as an [Int]. + * + * {@include [SumDocs.RowExpressionSnippet]} + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * See also: + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * ### Example + * ```kotlin + * // The sum of all halved "amount" values (of `Short`s), as an `Int` + * df.sumOf { (amount / 2).toShort() } + * ``` + * + * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @return The sum of the values [expression] returns, as an [Int]. + */ @JvmName("sumOfShort") @OverloadResolutionByLambdaReturnType public inline fun DataFrame.sumOf(crossinline expression: RowExpression): Int = Aggregators.sum(false).aggregateOf(this, expression) as Int +/** + * Returns the sum of the [Byte] values that the given [expression] returns + * for each row of this [DataFrame], as an [Int]. + * + * {@include [SumDocs.RowExpressionSnippet]} + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * See also: + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * ### Example + * ```kotlin + * // The sum of all halved "amount" values (of `Byte`s), as an `Int` + * df.sumOf { (amount / 2).toByte() } + * ``` + * + * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @return The sum of the values [expression] returns, as an [Int]. + */ @JvmName("sumOfByte") @OverloadResolutionByLambdaReturnType public inline fun DataFrame.sumOf(crossinline expression: RowExpression): Int = Aggregators.sum(false).aggregateOf(this, expression) as Int +/** + * Returns the sum of the values that the given [expression] returns + * for each row of this [DataFrame]. + * + * {@include [SumDocs.RowExpressionSnippet]} + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroOnEmptySnippet]} + * + * See also: + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * - [`meanOf`][DataFrame.meanOf] — the sum of those values divided by the number of values. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * ### Example + * ```kotlin + * // The sum of the weight-to-age ratios of all rows + * df.sumOf { (weight ?: 0) / age } + * ``` + * + * @include [SumDocs.SkipNanParam] + * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @return The sum of the values [expression] returns. + */ @Suppress("UNCHECKED_CAST") @JvmName("sumOfNumber") @OverloadResolutionByLambdaReturnType @@ -235,11 +918,82 @@ public inline fun DataFrame.sumOf( // endregion // region GroupBy + +/** + * Aggregates this [GroupBy] by computing the sum of the values of + * each suitable column separately, per group. + * + * Returns a new [DataFrame] with one row per group, containing the group key columns + * and a column with the sum for each suitable column. + * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; + * the other columns are simply left out of the result. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * See also: + * - [`sumFor`][Grouped.sumFor] — the same, but for an explicit selection of columns. + * - [`sum`][Grouped.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [`mean`][Grouped.mean] — the sum of each column divided by its number of values, per group. + * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]}, + * {@include [DocumentationUrls.GroupByAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of each number column ("age" and "weight") + * df.groupBy { city }.sum() + * ``` + * + * @include [SumDocs.SkipNanParam] + * @return A new [DataFrame] with the group keys and the sum of each suitable column per group. + */ @Refine @Interpretable("GroupBySum1") public fun Grouped.sum(skipNaN: Boolean = skipNaNDefault): DataFrame = sumFor(skipNaN, primitiveOrMixedNumberColumns()) +/** + * Aggregates this [GroupBy] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a new [DataFrame] with one row per group, containing the group key columns + * and a column with the sum for each selected column. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SumDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions]. + * + * See also: + * - [`sum`][Grouped.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][Grouped.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [`meanFor`][Grouped.meanFor] — the sum of each selected column divided by its number of values, + * per group. + * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]}, + * {@include [DocumentationUrls.GroupByAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of the "age" values and the sum of the "weight" values + * df.groupBy { city }.sumFor { age and weight } + * ``` + * + * @include [SumDocs.SkipNanParam] + * @param [columns] The [ColumnsForAggregateSelector] used to select the columns to compute the sum of. + * @return A new [DataFrame] with the group keys and the sum of each selected column per group. + */ @Refine @Interpretable("GroupBySum0") public fun Grouped.sumFor( @@ -247,6 +1001,42 @@ public fun Grouped.sumFor( columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, columns) +/** + * Aggregates this [GroupBy] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a new [DataFrame] with one row per group, containing the group key columns + * and a column with the sum for each selected column. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions]. + * + * See also: + * - [`sum`][Grouped.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][Grouped.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [`meanFor`][Grouped.meanFor] — the sum of each selected column divided by its number of values, + * per group. + * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]}, + * {@include [DocumentationUrls.GroupByAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of the "age" values and the sum of the "weight" values + * df.groupBy { city }.sumFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.SkipNanParam] + * @return A new [DataFrame] with the group keys and the sum of each selected column per group. + */ @Refine @StringApiInterpretable(interpreter = "GroupBySum0", stringArgument = "columns", targetArgument = "columns") public fun Grouped.sumFor(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataFrame = @@ -266,6 +1056,47 @@ public fun Grouped.sumFor( skipNaN: Boolean = skipNaNDefault, ): DataFrame = sumFor(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [GroupBy] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a new [DataFrame] with one row per group, containing the group key columns and + * a single column with the sum per group. + * That column is named [name], or, if [name] is `null`, after the selected column + * if exactly one column is selected, and `"sum"` otherwise. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumSelectingOptions]. + * + * See also: + * - [`sumFor`][Grouped.sumFor] — the sum of each selected column separately, per group. + * - [`sumOf`][Grouped.sumOf] — the sum of the values a row expression returns + * for each row of a group. + * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]}, + * {@include [DocumentationUrls.GroupByAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of all values in the "age" and "weight" columns, + * // in a column called "total" + * df.groupBy { city }.sum("total") { age and weight } + * ``` + * + * @param [name] The name of the resulting column. + * If `null` (the default), the name of the selected column is used if exactly one column + * is selected, and `"sum"` otherwise. + * @include [SumDocs.SkipNanParam] + * @param [columns] The [ColumnsSelector] used to select the columns to compute the sum of. + * @return A new [DataFrame] with the group keys and a single sum per group. + */ @Refine @Interpretable("GroupBySum2") public fun Grouped.sum( @@ -274,6 +1105,47 @@ public fun Grouped.sum( columns: ColumnsSelector, ): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, name, columns) +/** + * Aggregates this [GroupBy] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a new [DataFrame] with one row per group, containing the group key columns and + * a single column with the sum per group. + * That column is named [name], or, if [name] is `null`, after the selected column + * if exactly one column is selected, and `"sum"` otherwise. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumSelectingOptions]. + * + * See also: + * - [`sumFor`][Grouped.sumFor] — the sum of each selected column separately, per group. + * - [`sumOf`][Grouped.sumOf] — the sum of the values a row expression returns + * for each row of a group. + * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]}, + * {@include [DocumentationUrls.GroupByAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of all values in the "age" and "weight" columns, + * // in a column called "total" + * df.groupBy { city }.sum("age", "weight", name = "total") + * ``` + * + * @param [columns] The names of the columns to compute the sum of. + * @param [name] The name of the resulting column. + * If `null` (the default), the name of the selected column is used if exactly one column + * is selected, and `"sum"` otherwise. + * @include [SumDocs.SkipNanParam] + * @return A new [DataFrame] with the group keys and a single sum per group. + */ @Refine @StringApiInterpretable(interpreter = "GroupBySum2", stringArgument = "columns", targetArgument = "columns") public fun Grouped.sum( @@ -298,6 +1170,39 @@ public fun Grouped.sum( skipNaN: Boolean = skipNaNDefault, ): DataFrame = sum(name, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [GroupBy] by computing the sum of the values that the given [expression] + * returns for each row of a group. + * + * Returns a new [DataFrame] with one row per group, containing the group key columns and + * a single column with the sum per group, named [resultName] (or `"sum"` if [resultName] is `null`). + * + * {@include [SumDocs.RowExpressionSnippet]} + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * See also: + * - [`sum`][Grouped.sum] — a single sum of all values in the selected columns, per group. + * - [`meanOf`][Grouped.meanOf] — the sum of those values divided by the number of values, per group. + * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]}, + * {@include [DocumentationUrls.GroupByAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of the weight-to-age ratios, in a column called "totalRatio" + * df.groupBy { city }.sumOf("totalRatio") { (weight ?: 0) / age } + * ``` + * + * @param [resultName] The name of the resulting column. If `null` (the default), `"sum"` is used. + * @include [SumDocs.SkipNanParam] + * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @return A new [DataFrame] with the group keys and a single sum per group. + */ @Refine @Interpretable("GroupBySumOf") public inline fun Grouped.sumOf( @@ -310,15 +1215,125 @@ public inline fun Grouped.sumOf( // region Pivot +/** + * Aggregates this [Pivot] by computing the sum of the values of + * each suitable column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum + * of each suitable column of the corresponding group. + * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; + * the other columns are simply left out of the result. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * Check out the [`Pivot` Grammar][PivotDocs.Grammar]. + * + * See also: + * - [`sumFor`][Pivot.sumFor] — the same, but for an explicit selection of columns. + * - [`sum`][Pivot.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of each number column ("age" and "weight") + * df.pivot { city }.sum() + * ``` + * + * @include [SumDocs.SeparateParam] + * @include [SumDocs.SkipNanParam] + * @return A single [DataRow] with the sum of each suitable column per [pivot] group. + */ public fun Pivot.sum(separate: Boolean = false, skipNaN: Boolean = skipNaNDefault): DataRow = sumFor(separate, skipNaN, primitiveOrMixedNumberColumns()) +/** + * Aggregates this [Pivot] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum + * of each selected column of the corresponding group. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SumDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the + * [`Pivot` Grammar][PivotDocs.Grammar]. + * + * See also: + * - [`sum`][Pivot.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][Pivot.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of the "age" values and the sum of the "weight" values + * df.pivot { city }.sumFor { age and weight } + * // The same, but with the results grouped by aggregated column instead of by city + * df.pivot { city }.sumFor(separate = true) { age and weight } + * ``` + * + * @include [SumDocs.SeparateParam] + * @include [SumDocs.SkipNanParam] + * @param [columns] The [ColumnsForAggregateSelector] used to select the columns to compute the sum of. + * @return A single [DataRow] with the sum of each selected column per [pivot] group. + */ public fun Pivot.sumFor( separate: Boolean = false, skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, ): DataRow = delegate { sumFor(separate, skipNaN, columns) } +/** + * Aggregates this [Pivot] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum + * of each selected column of the corresponding group. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the + * [`Pivot` Grammar][PivotDocs.Grammar]. + * + * See also: + * - [`sum`][Pivot.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][Pivot.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of the "age" values and the sum of the "weight" values + * df.pivot { city }.sumFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.SeparateParam] + * @include [SumDocs.SkipNanParam] + * @return A single [DataRow] with the sum of each selected column per [pivot] group. + */ public fun Pivot.sumFor( vararg columns: String, separate: Boolean = false, @@ -341,11 +1356,83 @@ public fun Pivot.sumFor( skipNaN: Boolean = skipNaNDefault, ): DataRow = sumFor(separate, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [Pivot] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum of all + * the values in the selected columns of the corresponding group. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the + * [`Pivot` Grammar][PivotDocs.Grammar]. + * + * See also: + * - [`sum`][Pivot.sum]`()` — the sum of each suitable column separately, per group. + * - [`sumFor`][Pivot.sumFor] — the sum of each selected column separately, per group. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of all values in the "age" and "weight" columns + * df.pivot { city }.sum { age and weight } + * ``` + * + * @include [SumDocs.SkipNanParam] + * @param [columns] The [ColumnsSelector] used to select the columns to compute the sum of. + * @return A single [DataRow] with, per [pivot] group, the sum of all the values + * in the selected columns. + */ public fun Pivot.sum( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): DataRow = delegate { sum(skipNaN, columns) } +/** + * Aggregates this [Pivot] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum of all + * the values in the selected columns of the corresponding group. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the + * [`Pivot` Grammar][PivotDocs.Grammar]. + * + * See also: + * - [`sum`][Pivot.sum]`()` — the sum of each suitable column separately, per group. + * - [`sumFor`][Pivot.sumFor] — the sum of each selected column separately, per group. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of all values in the "age" and "weight" columns + * df.pivot { city }.sum("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.SkipNanParam] + * @return A single [DataRow] with, per [pivot] group, the sum of all the values + * in the selected columns. + */ public fun Pivot.sum(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataRow = sum(skipNaN) { columns.toNumberColumns() } @@ -361,6 +1448,39 @@ public fun Pivot.sum( public fun Pivot.sum(vararg columns: KProperty, skipNaN: Boolean = skipNaNDefault): DataRow = sum(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [Pivot] by computing the sum of the values that the given [expression] + * returns for each row, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum + * of the expression's results for the rows of the corresponding group. + * + * {@include [SumDocs.RowExpressionSnippet]} + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * Check out the [`Pivot` Grammar][PivotDocs.Grammar]. + * + * See also: + * - [`sum`][Pivot.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the sum of the weight-to-age ratios + * df.pivot { city }.sumOf { (weight ?: 0) / age } + * ``` + * + * @include [SumDocs.SkipNanParam] + * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @return A single [DataRow] with, per [pivot] group, the sum of the expression's results. + */ public inline fun Pivot.sumOf( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, @@ -370,15 +1490,129 @@ public inline fun Pivot.sumOf( // region PivotGroupBy +/** + * Aggregates this [PivotGroupBy] by computing the sum of the values of + * each suitable column separately, per group. + * + * Returns a [DataFrame] where each cell contains the sum of each suitable column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; + * the other columns are simply left out of the result. + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * Check out the [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. + * + * See also: + * - [`sumFor`][PivotGroupBy.sumFor] — the same, but for an explicit selection of columns. + * - [`sum`][PivotGroupBy.sum]` { columns }` — a single sum of all values in the selected columns, + * per group. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the sum of each number column ("age" and "weight") + * df.pivot { city }.groupBy { name.lastName }.sum() + * ``` + * + * @include [SumDocs.SeparateParam] + * @include [SumDocs.SkipNanParam] + * @return A [DataFrame] with the sum of each suitable column per group. + */ public fun PivotGroupBy.sum(separate: Boolean = false, skipNaN: Boolean = skipNaNDefault): DataFrame = sumFor(separate, skipNaN, primitiveOrMixedNumberColumns()) +/** + * Aggregates this [PivotGroupBy] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a [DataFrame] where each cell contains the sum of each selected column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SumDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the + * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. + * + * See also: + * - [`sum`][PivotGroupBy.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][PivotGroupBy.sum]` { columns }` — a single sum of all values in the selected columns, + * per group. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the sum of the "age" values and the sum of the "weight" values + * df.pivot { city }.groupBy { name.lastName }.sumFor { age and weight } + * ``` + * + * @include [SumDocs.SeparateParam] + * @include [SumDocs.SkipNanParam] + * @param [columns] The [ColumnsForAggregateSelector] used to select the columns to compute the sum of. + * @return A [DataFrame] with the sum of each selected column per group. + */ public fun PivotGroupBy.sumFor( separate: Boolean = false, skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, separate, columns) +/** + * Aggregates this [PivotGroupBy] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a [DataFrame] where each cell contains the sum of each selected column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the + * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. + * + * See also: + * - [`sum`][PivotGroupBy.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][PivotGroupBy.sum]` { columns }` — a single sum of all values in the selected columns, + * per group. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the sum of the "age" values and the sum of the "weight" values + * df.pivot { city }.groupBy { name.lastName }.sumFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.SeparateParam] + * @include [SumDocs.SkipNanParam] + * @return A [DataFrame] with the sum of each selected column per group. + */ public fun PivotGroupBy.sumFor( vararg columns: String, separate: Boolean = false, @@ -401,11 +1635,83 @@ public fun PivotGroupBy.sumFor( skipNaN: Boolean = skipNaNDefault, ): DataFrame = sumFor(separate, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [PivotGroupBy] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a [DataFrame] where each cell contains the sum of all the values in the selected columns + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the + * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. + * + * See also: + * - [`sum`][PivotGroupBy.sum]`()` — the sum of each suitable column separately, per group. + * - [`sumFor`][PivotGroupBy.sumFor] — the sum of each selected column separately, per group. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the sum of all values in the "age" and "weight" columns + * df.pivot { city }.groupBy { name.lastName }.sum { age and weight } + * ``` + * + * @include [SumDocs.SkipNanParam] + * @param [columns] The [ColumnsSelector] used to select the columns to compute the sum of. + * @return A [DataFrame] with, per group, the sum of all the values in the selected columns. + */ public fun PivotGroupBy.sum( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, columns) +/** + * Aggregates this [PivotGroupBy] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a [DataFrame] where each cell contains the sum of all the values in the selected columns + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the + * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. + * + * See also: + * - [`sum`][PivotGroupBy.sum]`()` — the sum of each suitable column separately, per group. + * - [`sumFor`][PivotGroupBy.sumFor] — the sum of each selected column separately, per group. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the sum of all values in the "age" and "weight" columns + * df.pivot { city }.groupBy { name.lastName }.sum("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.SkipNanParam] + * @return A [DataFrame] with, per group, the sum of all the values in the selected columns. + */ public fun PivotGroupBy.sum(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataFrame = sum(skipNaN) { columns.toNumberColumns() } @@ -423,6 +1729,41 @@ public fun PivotGroupBy.sum( skipNaN: Boolean = skipNaNDefault, ): DataFrame = sum(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [PivotGroupBy] by computing the sum of the values that the given [expression] + * returns for each row, per group. + * + * Returns a [DataFrame] where each cell contains the sum of the expression's results for the + * rows of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [SumDocs.RowExpressionSnippet]} + * + * {@include [SumDocs.SupportedTypesSnippet]} + * + * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * + * Check out the [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. + * + * See also: + * - [`sum`][PivotGroupBy.sum]` { columns }` — a single sum of all values in the selected columns, + * per group. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the sum of the weight-to-age ratios + * df.pivot { city }.groupBy { name.lastName }.sumOf { (weight ?: 0) / age } + * ``` + * + * @include [SumDocs.SkipNanParam] + * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @return A [DataFrame] with, per group, the sum of the expression's results. + */ public inline fun PivotGroupBy.sumOf( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls.kt index f4c6b52803..345b4035d2 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls.kt @@ -326,6 +326,16 @@ public interface DocumentationUrls { /** [See "Row statistics" on the documentation website.]({@include [Url]}/rowstats.html) */ public typealias RowStatistics = Nothing + /** [See "Number Unification" on the documentation website.]({@include [Url]}/numberunification.html) */ + public typealias NumberUnification = Nothing + + /** [See `sum` on the documentation website.]({@include [Url]}/sum.html) */ + public interface Sum { + + /** [See "`sum` Type Conversion" on the documentation website.]({@include [Url]}/sum.html#type-conversion) */ + public typealias TypeConversion = Nothing + } + /** [See "min / max" on the documentation website.]({@include [Url]}/minmax.html) */ public interface MinMax { From da7682446bd9eac11ab05d565b8f3f9310d6165a Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Sat, 29 Aug 2026 18:02:31 +0200 Subject: [PATCH 03/11] compressing sum kdocs with claude --- .../jetbrains/kotlinx/dataframe/api/sum.kt | 237 +++++++++--------- 1 file changed, 114 insertions(+), 123 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index 3a935b8dd5..2b88d4f682 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -21,7 +21,6 @@ import org.jetbrains.kotlinx.dataframe.documentation.DocumentationUrls import org.jetbrains.kotlinx.dataframe.documentation.ExcludeFromSources import org.jetbrains.kotlinx.dataframe.documentation.SelectingColumns import org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers -import org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregators import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor @@ -214,6 +213,89 @@ internal interface SumDocs : CommonStatisticsDocs { // The example to render for this rowSumOf overload typealias EXAMPLE = Nothing } + + /** + * {@comment The parts all [DataFrame.sumFor] overloads have in common. KDoc-snippet.} + * + * Returns the sum of the values of each selected column of this [DataFrame] separately. + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] + * $[NOTE] + * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions]. + * + * See also: + * - [`sum`][DataFrame.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * - [`meanFor`][DataFrame.meanFor] — the sum of each selected column divided by its number of values. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface DataFrameSumForSnippet { + + // The note about the aggregate columns selector; can be omitted + typealias NOTE = Nothing + + // The example to render for this sumFor overload + typealias EXAMPLE = Nothing + } + + /** + * @comment The parts all column-selecting [DataFrame.sum] overloads have in common. + * KDoc-snippet. + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroOnEmptySnippet] + * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] + * + * See also: + * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. + * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * $[SEE_ALSO_TAIL] + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * $[COLUMNS_API] + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface DataFrameSumSnippet { + + // The remaining "See also" bullets of this sum overload. + typealias SEE_ALSO_TAIL = Nothing + + // How this overload selects its columns: the Columns Selection DSL or column names + typealias COLUMNS_API = Nothing + + // The example to render for this sum overload + typealias EXAMPLE = Nothing + } + + /** + * {@comment The `columns` parameter of the [ColumnsSelector] overloads. KDoc-snippet.} + * + * @param [columns\] The [ColumnsSelector] used to select the columns of this [DataFrame] + * to compute the sum of. + */ + @ExcludeFromSources + typealias ColumnsSelectorParam = Nothing + + /** + * {@comment The `columns` parameter of the [String] overloads. KDoc-snippet.} + * + * @param [columns\] The names of the columns of this [DataFrame] to compute the sum of. + */ + @ExcludeFromSources + typealias ColumnNamesParam = Nothing } /** [The Sum Operation][SumDocs] */ @@ -531,9 +613,8 @@ public fun DataRow<*>.rowSumOf(type: KType, skipNaN: Boolean = skipNaNDefault): * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; * the other columns are simply left out of the result. * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] * * See also: * - [`sumFor`][DataFrame.sumFor] — the same, but for an explicit selection of columns. @@ -558,34 +639,15 @@ public fun DataFrame.sum(skipNaN: Boolean = skipNaNDefault): DataRow = sumFor(skipNaN, primitiveOrMixedNumberColumns()) /** - * Returns the sum of the values of each selected column of this [DataFrame] separately. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SumDocs.AggregateColumnsSelectorSnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumForSelectingOptions]. - * - * See also: - * - [`sum`][DataFrame.sum]`()` — the same, but for all suitable columns at once. - * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. - * - [`meanFor`][DataFrame.meanFor] — the sum of each selected column divided by its number of values. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * ### Example + * @include [SumDocs.DataFrameSumForSnippet] + * @set [SumDocs.DataFrameSumForSnippet.NOTE] {@include [SumDocs.AggregateColumnsSelectorSnippet]} + * @set [SumDocs.DataFrameSumForSnippet.EXAMPLE] * ```kotlin * // A single row with the sum of the "age" values and the sum of the "weight" values * df.sumFor { age and weight } * // The same, ignoring `NaN` values, and naming the results explicitly * df.sumFor(skipNaN = true) { age into "totalAge" and (weight into "totalWeight") } * ``` - * * @include [SumDocs.SkipNanParam] * @param [columns] The [ColumnsForAggregateSelector] used to select the columns of this [DataFrame] * to compute the sum of. @@ -599,31 +661,13 @@ public fun DataFrame.sumFor( ): DataRow = Aggregators.sum(skipNaN).aggregateFor(this, columns) /** - * Returns the sum of the values of each selected column of this [DataFrame] separately. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumForSelectingOptions]. - * - * See also: - * - [`sum`][DataFrame.sum]`()` — the same, but for all suitable columns at once. - * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. - * - [`meanFor`][DataFrame.meanFor] — the sum of each selected column divided by its number of values. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * ### Example + * @include [SumDocs.DataFrameSumForSnippet] + * @set [SumDocs.DataFrameSumForSnippet.EXAMPLE] * ```kotlin * // A single row with the sum of the "age" values and the sum of the "weight" values * df.sumFor("age", "weight") * ``` - * - * @param [columns] The names of the columns of this [DataFrame] to compute the sum of. + * @include [SumDocs.ColumnNamesParam] * @include [SumDocs.SkipNanParam] * @return A single [DataRow] with the sum of each selected column. */ @@ -650,29 +694,16 @@ public fun DataFrame.sumFor( * Returns a single sum of all the [Short] values in the selected columns of this [DataFrame], * as an [Int]. * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See also: - * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. - * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * @include [SumDocs.DataFrameSumSnippet] + * @set [SumDocs.DataFrameSumSnippet.SEE_ALSO_TAIL] * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * @include [SelectingColumns.ColumnsSelectionDsl] - * - * ### Example + * @set [SumDocs.DataFrameSumSnippet.COLUMNS_API] {@include [SelectingColumns.ColumnsSelectionDsl]} + * @set [SumDocs.DataFrameSumSnippet.EXAMPLE] * ```kotlin * // The sum of all values in the "amount" and "bonus" columns of `Short`s, as an `Int` * df.sum { amount and bonus } * ``` - * - * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] - * to compute the sum of. + * @include [SumDocs.ColumnsSelectorParam] * @return The sum of all the values in the selected columns, as an [Int]. */ @JvmName("sumShort") @@ -684,29 +715,16 @@ public fun DataFrame.sum(columns: ColumnsSelector): Int * Returns a single sum of all the [Byte] values in the selected columns of this [DataFrame], * as an [Int]. * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See also: - * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. - * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * @include [SumDocs.DataFrameSumSnippet] + * @set [SumDocs.DataFrameSumSnippet.SEE_ALSO_TAIL] * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * @include [SelectingColumns.ColumnsSelectionDsl] - * - * ### Example + * @set [SumDocs.DataFrameSumSnippet.COLUMNS_API] {@include [SelectingColumns.ColumnsSelectionDsl]} + * @set [SumDocs.DataFrameSumSnippet.EXAMPLE] * ```kotlin * // The sum of all values in the "amount" and "bonus" columns of `Byte`s, as an `Int` * df.sum { amount and bonus } * ``` - * - * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] - * to compute the sum of. + * @include [SumDocs.ColumnsSelectorParam] * @return The sum of all the values in the selected columns, as an [Int]. */ @JvmName("sumByte") @@ -717,31 +735,18 @@ public fun DataFrame.sum(columns: ColumnsSelector): Int /** * Returns a single sum of all the values in the selected columns of this [DataFrame]. * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See also: - * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. - * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * @include [SumDocs.DataFrameSumSnippet] + * @set [SumDocs.DataFrameSumSnippet.SEE_ALSO_TAIL] * - [`mean`][DataFrame.mean] — the sum divided by the number of values. * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * @include [SelectingColumns.ColumnsSelectionDsl] - * - * ### Example + * @set [SumDocs.DataFrameSumSnippet.COLUMNS_API] {@include [SelectingColumns.ColumnsSelectionDsl]} + * @set [SumDocs.DataFrameSumSnippet.EXAMPLE] * ```kotlin * // The sum of all values in the "age" and "weight" columns together * df.sum { age and weight } * ``` - * * @include [SumDocs.SkipNanParam] - * @param [columns] The [ColumnsSelector] used to select the columns of this [DataFrame] - * to compute the sum of. + * @include [SumDocs.ColumnsSelectorParam] * @return The sum of all the values in the selected columns. */ @Suppress("UNCHECKED_CAST") @@ -773,29 +778,17 @@ public fun DataFrame.sum( /** * Returns a single sum of all the values in the selected columns of this [DataFrame]. * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See also: - * - [`sumFor`][DataFrame.sumFor] — the sum of each selected column separately. - * - [`sumOf`][DataFrame.sumOf] — the sum of the values a row expression returns for each row. + * @include [SumDocs.DataFrameSumSnippet] + * @set [SumDocs.DataFrameSumSnippet.SEE_ALSO_TAIL] * - [`mean`][DataFrame.mean] — the sum divided by the number of values. * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * @include [SelectingColumns.ColumnNamesApi] - * - * ### Example + * @set [SumDocs.DataFrameSumSnippet.COLUMNS_API] {@include [SelectingColumns.ColumnNamesApi]} + * @set [SumDocs.DataFrameSumSnippet.EXAMPLE] * ```kotlin * // The sum of all values in the "age" and "weight" columns together * df.sum("age", "weight") * ``` - * - * @param [columns] The names of the columns of this [DataFrame] to compute the sum of. + * @include [SumDocs.ColumnNamesParam] * @include [SumDocs.SkipNanParam] * @return The sum of all the values in the selected columns. */ @@ -824,11 +817,9 @@ public fun DataFrame.sum( * Returns the sum of the [Short] values that the given [expression] returns * for each row of this [DataFrame], as an [Int]. * - * {@include [SumDocs.RowExpressionSnippet]} - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroOnEmptySnippet]} + * @include [SumDocs.RowExpressionSnippet] + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroOnEmptySnippet] * * See also: * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. From da3271fe3f40e5b7bc538119bf53a326db781ae5 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Sat, 29 Aug 2026 18:18:13 +0200 Subject: [PATCH 04/11] final kdocs bumped before running out of ai quotum --- .../jetbrains/kotlinx/dataframe/api/sum.kt | 832 ++++++++---------- 1 file changed, 391 insertions(+), 441 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index 2b88d4f682..e0bc7b5e28 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -121,6 +121,34 @@ internal interface SumDocs : CommonStatisticsDocs { @ExcludeFromSources typealias ZeroCellOnEmptySnippet = Nothing + /** + * {@comment Note about which columns the no-argument `sum` modes take into account. KDoc-snippet.} + * + * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; + * the other columns are simply left out of the result. + */ + @ExcludeFromSources + typealias AllSuitableColumnsSnippet = Nothing + + /** + * {@comment The documentation website links all [Grouped] `sum` KDocs end with. KDoc-snippet.} + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]}, + * {@include [DocumentationUrls.GroupByAggregationStatistics]} + */ + @ExcludeFromSources + typealias GroupByUrlsSnippet = Nothing + + /** + * {@comment The documentation website links all [Pivot] and [PivotGroupBy] `sum` KDocs end with. + * KDoc-snippet.} + * + * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * {@include [DocumentationUrls.PivotAggregationStatistics]} + */ + @ExcludeFromSources + typealias PivotUrlsSnippet = Nothing + /** * {@comment Version of [SelectingColumns] with correctly filled in examples} * @include [SelectingColumns] {@include [SetSumOperationArg]} @@ -280,22 +308,300 @@ internal interface SumDocs : CommonStatisticsDocs { typealias EXAMPLE = Nothing } + /** + * @comment The parts all [DataFrame.sumOf] overloads have in common. + * KDoc-snippet. + * + * @include [SumDocs.RowExpressionSnippet] + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroOnEmptySnippet] + * + * See also: + * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * $[SEE_ALSO_TAIL] + * + * For more information: {@include [DocumentationUrls.Sum]} + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface DataFrameSumOfSnippet { + + // The remaining "See also" bullets of this sumOf overload. + typealias SEE_ALSO_TAIL = Nothing + + // The example to render for this sumOf overload + typealias EXAMPLE = Nothing + } + + /** + * {@comment The parts all [Grouped.sumFor] overloads have in common. KDoc-snippet.} + * + * Aggregates this [GroupBy] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a new [DataFrame] with one row per group, containing the group key columns + * and a column with the sum for each selected column. + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] + * $[NOTE] + * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions]. + * + * See also: + * - [`sum`][Grouped.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][Grouped.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [`meanFor`][Grouped.meanFor] — the sum of each selected column divided by its number of values, + * per group. + * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * @include [SumDocs.GroupByUrlsSnippet] + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface GroupedSumForSnippet { + + // The note about the aggregate columns selector; can be omitted + typealias NOTE = Nothing + + // The example to render for this sumFor overload + typealias EXAMPLE = Nothing + } + + /** + * @comment The parts all column-selecting [Grouped.sum] overloads have in common. + * KDoc-snippet. + * + * Aggregates this [GroupBy] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a new [DataFrame] with one row per group, containing the group key columns and + * a single column with the sum per group. + * That column is named [name\], or, if [name\] is `null`, after the selected column + * if exactly one column is selected, and `"sum"` otherwise. + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] + * + * See [Selecting Columns][SumDocs.SumSelectingOptions]. + * + * See also: + * - [`sumFor`][Grouped.sumFor] — the sum of each selected column separately, per group. + * - [`sumOf`][Grouped.sumOf] — the sum of the values a row expression returns + * for each row of a group. + * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * @include [SumDocs.GroupByUrlsSnippet] + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface GroupedSumSnippet { + + // The example to render for this sum overload + typealias EXAMPLE = Nothing + } + + /** + * {@comment The parts all [Pivot.sumFor] overloads have in common. KDoc-snippet.} + * + * Aggregates this [Pivot] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum + * of each selected column of the corresponding group. + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] + * $[NOTE] + * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the + * [`Pivot` Grammar][PivotDocs.Grammar]. + * + * See also: + * - [`sum`][Pivot.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][Pivot.sum]` { columns }` — a single sum of all values in the selected columns, per group. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * @include [SumDocs.PivotUrlsSnippet] + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface PivotSumForSnippet { + + // The note about the aggregate columns selector; can be omitted + typealias NOTE = Nothing + + // The example to render for this sumFor overload + typealias EXAMPLE = Nothing + } + + /** + * @comment The parts all column-selecting [Pivot.sum] overloads have in common. + * KDoc-snippet. + * + * Aggregates this [Pivot] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum of all + * the values in the selected columns of the corresponding group. + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] + * + * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the + * [`Pivot` Grammar][PivotDocs.Grammar]. + * + * See also: + * - [`sum`][Pivot.sum]`()` — the sum of each suitable column separately, per group. + * - [`sumFor`][Pivot.sumFor] — the sum of each selected column separately, per group. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * @include [SumDocs.PivotUrlsSnippet] + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface PivotSumSnippet { + + // The example to render for this sum overload + typealias EXAMPLE = Nothing + } + + /** + * {@comment The parts all [PivotGroupBy.sumFor] overloads have in common. KDoc-snippet.} + * + * Aggregates this [PivotGroupBy] by computing the sum of the values of + * each selected column separately, per group. + * + * Returns a [DataFrame] where each cell contains the sum of each selected column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] + * $[NOTE] + * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] + * + * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the + * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. + * + * See also: + * - [`sum`][PivotGroupBy.sum]`()` — the same, but for all suitable columns at once. + * - [`sum`][PivotGroupBy.sum]` { columns }` — a single sum of all values in the selected columns, + * per group. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * @include [SumDocs.PivotUrlsSnippet] + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface PivotGroupBySumForSnippet { + + // The note about the aggregate columns selector; can be omitted + typealias NOTE = Nothing + + // The example to render for this sumFor overload + typealias EXAMPLE = Nothing + } + + /** + * @comment The parts all column-selecting [PivotGroupBy.sum] overloads have in common. + * KDoc-snippet. + * + * Aggregates this [PivotGroupBy] by computing a single sum of all the values + * in the selected columns, per group. + * + * Returns a [DataFrame] where each cell contains the sum of all the values in the selected columns + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] + * + * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the + * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. + * + * See also: + * - [`sum`][PivotGroupBy.sum]`()` — the sum of each suitable column separately, per group. + * - [`sumFor`][PivotGroupBy.sumFor] — the sum of each selected column separately, per group. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [SumDocsLink]} — an overview of all `sum` modes. + * + * @include [SumDocs.PivotUrlsSnippet] + * + * ### Example + * $[EXAMPLE] + */ + @ExcludeFromSources + interface PivotGroupBySumSnippet { + + // The example to render for this sum overload + typealias EXAMPLE = Nothing + } + /** * {@comment The `columns` parameter of the [ColumnsSelector] overloads. KDoc-snippet.} * - * @param [columns\] The [ColumnsSelector] used to select the columns of this [DataFrame] - * to compute the sum of. + * @param [columns\] The [ColumnsSelector] used to select the columns to compute the sum of. */ @ExcludeFromSources typealias ColumnsSelectorParam = Nothing + /** + * {@comment The `columns` parameter of the [ColumnsForAggregateSelector] overloads. KDoc-snippet.} + * + * @param [columns\] The [ColumnsForAggregateSelector] used to select the columns + * to compute the sum of. + */ + @ExcludeFromSources + typealias AggregateColumnsSelectorParam = Nothing + /** * {@comment The `columns` parameter of the [String] overloads. KDoc-snippet.} * - * @param [columns\] The names of the columns of this [DataFrame] to compute the sum of. + * @param [columns\] The names of the columns to compute the sum of. */ @ExcludeFromSources typealias ColumnNamesParam = Nothing + + /** + * {@comment The `expression` parameter of the `sumOf` overloads. KDoc-snippet.} + * + * @param [expression\] The [RowExpression] to compute the value to sum for each row. + */ + @ExcludeFromSources + typealias ExpressionParam = Nothing + + /** + * {@comment The `name` parameter of the [Grouped.sum] overloads. KDoc-snippet.} + * + * @param [name\] The name of the resulting column. + * If `null` (the default), the name of the selected column is used if exactly one column + * is selected, and `"sum"` otherwise. + */ + @ExcludeFromSources + typealias ResultColumnNameParam = Nothing } /** [The Sum Operation][SumDocs] */ @@ -610,9 +916,7 @@ public fun DataRow<*>.rowSumOf(type: KType, skipNaN: Boolean = skipNaNDefault): /** * Returns the sum of the values of each suitable column of this [DataFrame] separately. * - * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; - * the other columns are simply left out of the result. - * + * @include [SumDocs.AllSuitableColumnsSnippet] * @include [SumDocs.SupportedTypesSnippet] * @include [SumDocs.ZeroCellOnEmptySnippet] * @@ -649,8 +953,7 @@ public fun DataFrame.sum(skipNaN: Boolean = skipNaNDefault): DataRow = * df.sumFor(skipNaN = true) { age into "totalAge" and (weight into "totalWeight") } * ``` * @include [SumDocs.SkipNanParam] - * @param [columns] The [ColumnsForAggregateSelector] used to select the columns of this [DataFrame] - * to compute the sum of. + * @include [SumDocs.AggregateColumnsSelectorParam] * @return A single [DataRow] with the sum of each selected column. */ @Refine @@ -817,23 +1120,15 @@ public fun DataFrame.sum( * Returns the sum of the [Short] values that the given [expression] returns * for each row of this [DataFrame], as an [Int]. * - * @include [SumDocs.RowExpressionSnippet] - * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroOnEmptySnippet] - * - * See also: - * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * @include [SumDocs.DataFrameSumOfSnippet] + * @set [SumDocs.DataFrameSumOfSnippet.SEE_ALSO_TAIL] * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * ### Example + * @set [SumDocs.DataFrameSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of all halved "amount" values (of `Short`s), as an `Int` * df.sumOf { (amount / 2).toShort() } * ``` - * - * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @include [SumDocs.ExpressionParam] * @return The sum of the values [expression] returns, as an [Int]. */ @JvmName("sumOfShort") @@ -845,25 +1140,15 @@ public inline fun DataFrame.sumOf(crossinline express * Returns the sum of the [Byte] values that the given [expression] returns * for each row of this [DataFrame], as an [Int]. * - * {@include [SumDocs.RowExpressionSnippet]} - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroOnEmptySnippet]} - * - * See also: - * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * @include [SumDocs.DataFrameSumOfSnippet] + * @set [SumDocs.DataFrameSumOfSnippet.SEE_ALSO_TAIL] * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * ### Example + * @set [SumDocs.DataFrameSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of all halved "amount" values (of `Byte`s), as an `Int` * df.sumOf { (amount / 2).toByte() } * ``` - * - * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @include [SumDocs.ExpressionParam] * @return The sum of the values [expression] returns, as an [Int]. */ @JvmName("sumOfByte") @@ -875,27 +1160,17 @@ public inline fun DataFrame.sumOf(crossinline expressi * Returns the sum of the values that the given [expression] returns * for each row of this [DataFrame]. * - * {@include [SumDocs.RowExpressionSnippet]} - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroOnEmptySnippet]} - * - * See also: - * - [`sum`][DataFrame.sum]` { columns }` — a single sum of all values in the selected columns. + * @include [SumDocs.DataFrameSumOfSnippet] + * @set [SumDocs.DataFrameSumOfSnippet.SEE_ALSO_TAIL] * - [`meanOf`][DataFrame.meanOf] — the sum of those values divided by the number of values. * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.Sum]} - * - * ### Example + * @set [SumDocs.DataFrameSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of the weight-to-age ratios of all rows * df.sumOf { (weight ?: 0) / age } * ``` - * * @include [SumDocs.SkipNanParam] - * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @include [SumDocs.ExpressionParam] * @return The sum of the values [expression] returns. */ @Suppress("UNCHECKED_CAST") @@ -916,12 +1191,10 @@ public inline fun DataFrame.sumOf( * * Returns a new [DataFrame] with one row per group, containing the group key columns * and a column with the sum for each suitable column. - * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; - * the other columns are simply left out of the result. * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * @include [SumDocs.AllSuitableColumnsSnippet] + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] * * See also: * - [`sumFor`][Grouped.sumFor] — the same, but for an explicit selection of columns. @@ -930,8 +1203,7 @@ public inline fun DataFrame.sumOf( * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. * - {@include [SumDocsLink]} — an overview of all `sum` modes. * - * For more information: {@include [DocumentationUrls.GroupByStatistics]}, - * {@include [DocumentationUrls.GroupByAggregationStatistics]} + * @include [SumDocs.GroupByUrlsSnippet] * * ### Example * ```kotlin @@ -948,41 +1220,15 @@ public fun Grouped.sum(skipNaN: Boolean = skipNaNDefault): DataFrame = sumFor(skipNaN, primitiveOrMixedNumberColumns()) /** - * Aggregates this [GroupBy] by computing the sum of the values of - * each selected column separately, per group. - * - * Returns a new [DataFrame] with one row per group, containing the group key columns - * and a column with the sum for each selected column. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SumDocs.AggregateColumnsSelectorSnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumForSelectingOptions]. - * - * See also: - * - [`sum`][Grouped.sum]`()` — the same, but for all suitable columns at once. - * - [`sum`][Grouped.sum]` { columns }` — a single sum of all values in the selected columns, per group. - * - [`meanFor`][Grouped.meanFor] — the sum of each selected column divided by its number of values, - * per group. - * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.GroupByStatistics]}, - * {@include [DocumentationUrls.GroupByAggregationStatistics]} - * - * ### Example + * @include [SumDocs.GroupedSumForSnippet] + * @set [SumDocs.GroupedSumForSnippet.NOTE] {@include [SumDocs.AggregateColumnsSelectorSnippet]} + * @set [SumDocs.GroupedSumForSnippet.EXAMPLE] * ```kotlin * // For each city, the sum of the "age" values and the sum of the "weight" values * df.groupBy { city }.sumFor { age and weight } * ``` - * * @include [SumDocs.SkipNanParam] - * @param [columns] The [ColumnsForAggregateSelector] used to select the columns to compute the sum of. + * @include [SumDocs.AggregateColumnsSelectorParam] * @return A new [DataFrame] with the group keys and the sum of each selected column per group. */ @Refine @@ -993,38 +1239,13 @@ public fun Grouped.sumFor( ): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, columns) /** - * Aggregates this [GroupBy] by computing the sum of the values of - * each selected column separately, per group. - * - * Returns a new [DataFrame] with one row per group, containing the group key columns - * and a column with the sum for each selected column. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumForSelectingOptions]. - * - * See also: - * - [`sum`][Grouped.sum]`()` — the same, but for all suitable columns at once. - * - [`sum`][Grouped.sum]` { columns }` — a single sum of all values in the selected columns, per group. - * - [`meanFor`][Grouped.meanFor] — the sum of each selected column divided by its number of values, - * per group. - * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.GroupByStatistics]}, - * {@include [DocumentationUrls.GroupByAggregationStatistics]} - * - * ### Example + * @include [SumDocs.GroupedSumForSnippet] + * @set [SumDocs.GroupedSumForSnippet.EXAMPLE] * ```kotlin * // For each city, the sum of the "age" values and the sum of the "weight" values * df.groupBy { city }.sumFor("age", "weight") * ``` - * - * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.ColumnNamesParam] * @include [SumDocs.SkipNanParam] * @return A new [DataFrame] with the group keys and the sum of each selected column per group. */ @@ -1048,44 +1269,16 @@ public fun Grouped.sumFor( ): DataFrame = sumFor(skipNaN) { columns.toColumnSet() } /** - * Aggregates this [GroupBy] by computing a single sum of all the values - * in the selected columns, per group. - * - * Returns a new [DataFrame] with one row per group, containing the group key columns and - * a single column with the sum per group. - * That column is named [name], or, if [name] is `null`, after the selected column - * if exactly one column is selected, and `"sum"` otherwise. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumSelectingOptions]. - * - * See also: - * - [`sumFor`][Grouped.sumFor] — the sum of each selected column separately, per group. - * - [`sumOf`][Grouped.sumOf] — the sum of the values a row expression returns - * for each row of a group. - * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.GroupByStatistics]}, - * {@include [DocumentationUrls.GroupByAggregationStatistics]} - * - * ### Example + * @include [SumDocs.GroupedSumSnippet] + * @set [SumDocs.GroupedSumSnippet.EXAMPLE] * ```kotlin * // For each city, the sum of all values in the "age" and "weight" columns, * // in a column called "total" * df.groupBy { city }.sum("total") { age and weight } * ``` - * - * @param [name] The name of the resulting column. - * If `null` (the default), the name of the selected column is used if exactly one column - * is selected, and `"sum"` otherwise. + * @include [SumDocs.ResultColumnNameParam] * @include [SumDocs.SkipNanParam] - * @param [columns] The [ColumnsSelector] used to select the columns to compute the sum of. + * @include [SumDocs.ColumnsSelectorParam] * @return A new [DataFrame] with the group keys and a single sum per group. */ @Refine @@ -1097,43 +1290,15 @@ public fun Grouped.sum( ): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, name, columns) /** - * Aggregates this [GroupBy] by computing a single sum of all the values - * in the selected columns, per group. - * - * Returns a new [DataFrame] with one row per group, containing the group key columns and - * a single column with the sum per group. - * That column is named [name], or, if [name] is `null`, after the selected column - * if exactly one column is selected, and `"sum"` otherwise. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumSelectingOptions]. - * - * See also: - * - [`sumFor`][Grouped.sumFor] — the sum of each selected column separately, per group. - * - [`sumOf`][Grouped.sumOf] — the sum of the values a row expression returns - * for each row of a group. - * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.GroupByStatistics]}, - * {@include [DocumentationUrls.GroupByAggregationStatistics]} - * - * ### Example + * @include [SumDocs.GroupedSumSnippet] + * @set [SumDocs.GroupedSumSnippet.EXAMPLE] * ```kotlin * // For each city, the sum of all values in the "age" and "weight" columns, * // in a column called "total" * df.groupBy { city }.sum("age", "weight", name = "total") * ``` - * - * @param [columns] The names of the columns to compute the sum of. - * @param [name] The name of the resulting column. - * If `null` (the default), the name of the selected column is used if exactly one column - * is selected, and `"sum"` otherwise. + * @include [SumDocs.ColumnNamesParam] + * @include [SumDocs.ResultColumnNameParam] * @include [SumDocs.SkipNanParam] * @return A new [DataFrame] with the group keys and a single sum per group. */ @@ -1168,11 +1333,9 @@ public fun Grouped.sum( * Returns a new [DataFrame] with one row per group, containing the group key columns and * a single column with the sum per group, named [resultName] (or `"sum"` if [resultName] is `null`). * - * {@include [SumDocs.RowExpressionSnippet]} - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * @include [SumDocs.RowExpressionSnippet] + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] * * See also: * - [`sum`][Grouped.sum] — a single sum of all values in the selected columns, per group. @@ -1180,8 +1343,7 @@ public fun Grouped.sum( * - [`aggregate`][Grouped.aggregate] — the general way to aggregate groups. * - {@include [SumDocsLink]} — an overview of all `sum` modes. * - * For more information: {@include [DocumentationUrls.GroupByStatistics]}, - * {@include [DocumentationUrls.GroupByAggregationStatistics]} + * @include [SumDocs.GroupByUrlsSnippet] * * ### Example * ```kotlin @@ -1191,7 +1353,7 @@ public fun Grouped.sum( * * @param [resultName] The name of the resulting column. If `null` (the default), `"sum"` is used. * @include [SumDocs.SkipNanParam] - * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @include [SumDocs.ExpressionParam] * @return A new [DataFrame] with the group keys and a single sum per group. */ @Refine @@ -1212,12 +1374,10 @@ public inline fun Grouped.sumOf( * * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum * of each suitable column of the corresponding group. - * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; - * the other columns are simply left out of the result. - * - * {@include [SumDocs.SupportedTypesSnippet]} * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * @include [SumDocs.AllSuitableColumnsSnippet] + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] * * Check out the [`Pivot` Grammar][PivotDocs.Grammar]. * @@ -1227,8 +1387,7 @@ public inline fun Grouped.sumOf( * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. * - {@include [SumDocsLink]} — an overview of all `sum` modes. * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} + * @include [SumDocs.PivotUrlsSnippet] * * ### Example * ```kotlin @@ -1244,43 +1403,18 @@ public fun Pivot.sum(separate: Boolean = false, skipNaN: Boolean = skipNa sumFor(separate, skipNaN, primitiveOrMixedNumberColumns()) /** - * Aggregates this [Pivot] by computing the sum of the values of - * each selected column separately, per group. - * - * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum - * of each selected column of the corresponding group. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SumDocs.AggregateColumnsSelectorSnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the - * [`Pivot` Grammar][PivotDocs.Grammar]. - * - * See also: - * - [`sum`][Pivot.sum]`()` — the same, but for all suitable columns at once. - * - [`sum`][Pivot.sum]` { columns }` — a single sum of all values in the selected columns, per group. - * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} - * - * ### Example + * @include [SumDocs.PivotSumForSnippet] + * @set [SumDocs.PivotSumForSnippet.NOTE] {@include [SumDocs.AggregateColumnsSelectorSnippet]} + * @set [SumDocs.PivotSumForSnippet.EXAMPLE] * ```kotlin * // For each city, the sum of the "age" values and the sum of the "weight" values * df.pivot { city }.sumFor { age and weight } * // The same, but with the results grouped by aggregated column instead of by city * df.pivot { city }.sumFor(separate = true) { age and weight } * ``` - * * @include [SumDocs.SeparateParam] * @include [SumDocs.SkipNanParam] - * @param [columns] The [ColumnsForAggregateSelector] used to select the columns to compute the sum of. + * @include [SumDocs.AggregateColumnsSelectorParam] * @return A single [DataRow] with the sum of each selected column per [pivot] group. */ public fun Pivot.sumFor( @@ -1290,37 +1424,13 @@ public fun Pivot.sumFor( ): DataRow = delegate { sumFor(separate, skipNaN, columns) } /** - * Aggregates this [Pivot] by computing the sum of the values of - * each selected column separately, per group. - * - * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum - * of each selected column of the corresponding group. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the - * [`Pivot` Grammar][PivotDocs.Grammar]. - * - * See also: - * - [`sum`][Pivot.sum]`()` — the same, but for all suitable columns at once. - * - [`sum`][Pivot.sum]` { columns }` — a single sum of all values in the selected columns, per group. - * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} - * - * ### Example + * @include [SumDocs.PivotSumForSnippet] + * @set [SumDocs.PivotSumForSnippet.EXAMPLE] * ```kotlin * // For each city, the sum of the "age" values and the sum of the "weight" values * df.pivot { city }.sumFor("age", "weight") * ``` - * - * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.ColumnNamesParam] * @include [SumDocs.SeparateParam] * @include [SumDocs.SkipNanParam] * @return A single [DataRow] with the sum of each selected column per [pivot] group. @@ -1348,38 +1458,14 @@ public fun Pivot.sumFor( ): DataRow = sumFor(separate, skipNaN) { columns.toColumnSet() } /** - * Aggregates this [Pivot] by computing a single sum of all the values - * in the selected columns, per group. - * - * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum of all - * the values in the selected columns of the corresponding group. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the - * [`Pivot` Grammar][PivotDocs.Grammar]. - * - * See also: - * - [`sum`][Pivot.sum]`()` — the sum of each suitable column separately, per group. - * - [`sumFor`][Pivot.sumFor] — the sum of each selected column separately, per group. - * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} - * - * ### Example + * @include [SumDocs.PivotSumSnippet] + * @set [SumDocs.PivotSumSnippet.EXAMPLE] * ```kotlin * // For each city, the sum of all values in the "age" and "weight" columns * df.pivot { city }.sum { age and weight } * ``` - * * @include [SumDocs.SkipNanParam] - * @param [columns] The [ColumnsSelector] used to select the columns to compute the sum of. + * @include [SumDocs.ColumnsSelectorParam] * @return A single [DataRow] with, per [pivot] group, the sum of all the values * in the selected columns. */ @@ -1389,37 +1475,13 @@ public fun Pivot.sum( ): DataRow = delegate { sum(skipNaN, columns) } /** - * Aggregates this [Pivot] by computing a single sum of all the values - * in the selected columns, per group. - * - * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum of all - * the values in the selected columns of the corresponding group. - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the - * [`Pivot` Grammar][PivotDocs.Grammar]. - * - * See also: - * - [`sum`][Pivot.sum]`()` — the sum of each suitable column separately, per group. - * - [`sumFor`][Pivot.sumFor] — the sum of each selected column separately, per group. - * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} - * - * ### Example + * @include [SumDocs.PivotSumSnippet] + * @set [SumDocs.PivotSumSnippet.EXAMPLE] * ```kotlin * // For each city, the sum of all values in the "age" and "weight" columns * df.pivot { city }.sum("age", "weight") * ``` - * - * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.ColumnNamesParam] * @include [SumDocs.SkipNanParam] * @return A single [DataRow] with, per [pivot] group, the sum of all the values * in the selected columns. @@ -1446,11 +1508,9 @@ public fun Pivot.sum(vararg columns: KProperty, skipNaN: * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the sum * of the expression's results for the rows of the corresponding group. * - * {@include [SumDocs.RowExpressionSnippet]} - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * @include [SumDocs.RowExpressionSnippet] + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] * * Check out the [`Pivot` Grammar][PivotDocs.Grammar]. * @@ -1459,8 +1519,7 @@ public fun Pivot.sum(vararg columns: KProperty, skipNaN: * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. * - {@include [SumDocsLink]} — an overview of all `sum` modes. * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} + * @include [SumDocs.PivotUrlsSnippet] * * ### Example * ```kotlin @@ -1469,7 +1528,7 @@ public fun Pivot.sum(vararg columns: KProperty, skipNaN: * ``` * * @include [SumDocs.SkipNanParam] - * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @include [SumDocs.ExpressionParam] * @return A single [DataRow] with, per [pivot] group, the sum of the expression's results. */ public inline fun Pivot.sumOf( @@ -1487,12 +1546,10 @@ public inline fun Pivot.sumOf( * * Returns a [DataFrame] where each cell contains the sum of each suitable column * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). - * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; - * the other columns are simply left out of the result. * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * @include [SumDocs.AllSuitableColumnsSnippet] + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] * * Check out the [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. * @@ -1504,8 +1561,7 @@ public inline fun Pivot.sumOf( * a [PivotGroupBy]. * - {@include [SumDocsLink]} — an overview of all `sum` modes. * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} + * @include [SumDocs.PivotUrlsSnippet] * * ### Example * ```kotlin @@ -1521,43 +1577,16 @@ public fun PivotGroupBy.sum(separate: Boolean = false, skipNaN: Boolean = sumFor(separate, skipNaN, primitiveOrMixedNumberColumns()) /** - * Aggregates this [PivotGroupBy] by computing the sum of the values of - * each selected column separately, per group. - * - * Returns a [DataFrame] where each cell contains the sum of each selected column - * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SumDocs.AggregateColumnsSelectorSnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the - * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. - * - * See also: - * - [`sum`][PivotGroupBy.sum]`()` — the same, but for all suitable columns at once. - * - [`sum`][PivotGroupBy.sum]` { columns }` — a single sum of all values in the selected columns, - * per group. - * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate - * a [PivotGroupBy]. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} - * - * ### Example + * @include [SumDocs.PivotGroupBySumForSnippet] + * @set [SumDocs.PivotGroupBySumForSnippet.NOTE] {@include [SumDocs.AggregateColumnsSelectorSnippet]} + * @set [SumDocs.PivotGroupBySumForSnippet.EXAMPLE] * ```kotlin * // Per city and last name, the sum of the "age" values and the sum of the "weight" values * df.pivot { city }.groupBy { name.lastName }.sumFor { age and weight } * ``` - * * @include [SumDocs.SeparateParam] * @include [SumDocs.SkipNanParam] - * @param [columns] The [ColumnsForAggregateSelector] used to select the columns to compute the sum of. + * @include [SumDocs.AggregateColumnsSelectorParam] * @return A [DataFrame] with the sum of each selected column per group. */ public fun PivotGroupBy.sumFor( @@ -1567,39 +1596,13 @@ public fun PivotGroupBy.sumFor( ): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, separate, columns) /** - * Aggregates this [PivotGroupBy] by computing the sum of the values of - * each selected column separately, per group. - * - * Returns a [DataFrame] where each cell contains the sum of each selected column - * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumForSelectingOptions], or check out the - * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. - * - * See also: - * - [`sum`][PivotGroupBy.sum]`()` — the same, but for all suitable columns at once. - * - [`sum`][PivotGroupBy.sum]` { columns }` — a single sum of all values in the selected columns, - * per group. - * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate - * a [PivotGroupBy]. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} - * - * ### Example + * @include [SumDocs.PivotGroupBySumForSnippet] + * @set [SumDocs.PivotGroupBySumForSnippet.EXAMPLE] * ```kotlin * // Per city and last name, the sum of the "age" values and the sum of the "weight" values * df.pivot { city }.groupBy { name.lastName }.sumFor("age", "weight") * ``` - * - * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.ColumnNamesParam] * @include [SumDocs.SeparateParam] * @include [SumDocs.SkipNanParam] * @return A [DataFrame] with the sum of each selected column per group. @@ -1627,39 +1630,14 @@ public fun PivotGroupBy.sumFor( ): DataFrame = sumFor(separate, skipNaN) { columns.toColumnSet() } /** - * Aggregates this [PivotGroupBy] by computing a single sum of all the values - * in the selected columns, per group. - * - * Returns a [DataFrame] where each cell contains the sum of all the values in the selected columns - * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the - * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. - * - * See also: - * - [`sum`][PivotGroupBy.sum]`()` — the sum of each suitable column separately, per group. - * - [`sumFor`][PivotGroupBy.sumFor] — the sum of each selected column separately, per group. - * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate - * a [PivotGroupBy]. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} - * - * ### Example + * @include [SumDocs.PivotGroupBySumSnippet] + * @set [SumDocs.PivotGroupBySumSnippet.EXAMPLE] * ```kotlin * // Per city and last name, the sum of all values in the "age" and "weight" columns * df.pivot { city }.groupBy { name.lastName }.sum { age and weight } * ``` - * * @include [SumDocs.SkipNanParam] - * @param [columns] The [ColumnsSelector] used to select the columns to compute the sum of. + * @include [SumDocs.ColumnsSelectorParam] * @return A [DataFrame] with, per group, the sum of all the values in the selected columns. */ public fun PivotGroupBy.sum( @@ -1668,38 +1646,13 @@ public fun PivotGroupBy.sum( ): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, columns) /** - * Aggregates this [PivotGroupBy] by computing a single sum of all the values - * in the selected columns, per group. - * - * Returns a [DataFrame] where each cell contains the sum of all the values in the selected columns - * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} - * - * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} - * - * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the - * [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. - * - * See also: - * - [`sum`][PivotGroupBy.sum]`()` — the sum of each suitable column separately, per group. - * - [`sumFor`][PivotGroupBy.sumFor] — the sum of each selected column separately, per group. - * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate - * a [PivotGroupBy]. - * - {@include [SumDocsLink]} — an overview of all `sum` modes. - * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} - * - * ### Example + * @include [SumDocs.PivotGroupBySumSnippet] + * @set [SumDocs.PivotGroupBySumSnippet.EXAMPLE] * ```kotlin * // Per city and last name, the sum of all values in the "age" and "weight" columns * df.pivot { city }.groupBy { name.lastName }.sum("age", "weight") * ``` - * - * @param [columns] The names of the columns to compute the sum of. + * @include [SumDocs.ColumnNamesParam] * @include [SumDocs.SkipNanParam] * @return A [DataFrame] with, per group, the sum of all the values in the selected columns. */ @@ -1727,11 +1680,9 @@ public fun PivotGroupBy.sum( * Returns a [DataFrame] where each cell contains the sum of the expression's results for the * rows of the group corresponding to that [pivot] key (column) and [groupBy] key (row). * - * {@include [SumDocs.RowExpressionSnippet]} - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroCellOnEmptySnippet]} + * @include [SumDocs.RowExpressionSnippet] + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroCellOnEmptySnippet] * * Check out the [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. * @@ -1742,8 +1693,7 @@ public fun PivotGroupBy.sum( * a [PivotGroupBy]. * - {@include [SumDocsLink]} — an overview of all `sum` modes. * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, - * {@include [DocumentationUrls.PivotAggregationStatistics]} + * @include [SumDocs.PivotUrlsSnippet] * * ### Example * ```kotlin @@ -1752,7 +1702,7 @@ public fun PivotGroupBy.sum( * ``` * * @include [SumDocs.SkipNanParam] - * @param [expression] The [RowExpression] to compute the value to sum for each row. + * @include [SumDocs.ExpressionParam] * @return A [DataFrame] with, per group, the sum of the expression's results. */ public inline fun PivotGroupBy.sumOf( From d6ffffcbc3a9e1eec3c067f176cc8543adeb8ad4 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Tue, 15 Sep 2026 15:53:33 +0200 Subject: [PATCH 05/11] tiny fixes kdocs sum --- .../main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index e0bc7b5e28..1974b09743 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -83,7 +83,8 @@ internal interface SumDocs : CommonStatisticsDocs { * * All primitive number types are supported: [Byte], [Short], [Int], [Long], [Float], and [Double]. * "Mixed" [Number] input is supported too, as long as it consists solely of those primitive numbers; - * its values are then first converted to their common type using [UnifiedNumberTypeOptions.PRIMITIVES_ONLY], + * its values are then first converted to their common type using + * [UnifiedNumberTypeOptions.PRIMITIVES_ONLY][org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions.PRIMITIVES_ONLY], * see [number unification][UnifyingNumbers]. * Big numbers ([`BigInteger`][java.math.BigInteger], [`BigDecimal`][java.math.BigDecimal]) are not * supported; [`convert`][DataFrame.convert] them to a primitive number type first. @@ -133,7 +134,7 @@ internal interface SumDocs : CommonStatisticsDocs { /** * {@comment The documentation website links all [Grouped] `sum` KDocs end with. KDoc-snippet.} * - * For more information: {@include [DocumentationUrls.GroupByStatistics]}, + * For more information: {@include [DocumentationUrls.GroupByStatistics]}, and * {@include [DocumentationUrls.GroupByAggregationStatistics]} */ @ExcludeFromSources @@ -143,7 +144,7 @@ internal interface SumDocs : CommonStatisticsDocs { * {@comment The documentation website links all [Pivot] and [PivotGroupBy] `sum` KDocs end with. * KDoc-snippet.} * - * For more information: {@include [DocumentationUrls.PivotStatistics]}, + * For more information: {@include [DocumentationUrls.PivotStatistics]}, and * {@include [DocumentationUrls.PivotAggregationStatistics]} */ @ExcludeFromSources From 5372bff5841617a21cd64ebc44927cd09b08490b Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Tue, 15 Sep 2026 16:32:25 +0200 Subject: [PATCH 06/11] tiny fixes kdocs sum and removed nan message from functions without skipNaN parameter --- .../jetbrains/kotlinx/dataframe/api/sum.kt | 72 ++++++++++--------- .../documentation/CommonStatisticsDocs.kt | 25 +++++-- 2 files changed, 59 insertions(+), 38 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index 1974b09743..8779d5b5ce 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -89,7 +89,8 @@ internal interface SumDocs : CommonStatisticsDocs { * Big numbers ([`BigInteger`][java.math.BigInteger], [`BigDecimal`][java.math.BigDecimal]) are not * supported; [`convert`][DataFrame.convert] them to a primitive number type first. * - * @include [CommonStatisticsDocs.NullAndNaNHandlingSnippet] + * @include [CommonStatisticsDocs.NullHandlingSnippet] + * {@get [NAN_NOTE] {@include [CommonStatisticsDocs.NaNHandlingSnippet]}} * * The result is never `null` and has the same type as the input, except for [Byte] and [Short], * which sum to [Int], and "mixed" [Number] input, which sums to the common type of its values. @@ -98,7 +99,12 @@ internal interface SumDocs : CommonStatisticsDocs { * @include [DocumentationUrls.Sum.TypeConversion] */ @ExcludeFromSources - typealias SupportedTypesSnippet = Nothing + interface SupportedTypesSnippet { + + // The note about `NaN` handling. Filled in by default; must be set to nothing for the + // overloads of a fixed integer type, as those have no `skipNaN` parameter to refer to. + typealias NAN_NOTE = Nothing + } /** * {@comment Note about the behavior on empty input for the modes with a single result. KDoc-snippet.} @@ -151,19 +157,19 @@ internal interface SumDocs : CommonStatisticsDocs { typealias PivotUrlsSnippet = Nothing /** - * {@comment Version of [SelectingColumns] with correctly filled in examples} + * @comment Version of [SelectingColumns] with correctly filled in examples * @include [SelectingColumns] {@include [SetSumOperationArg]} */ typealias SumSelectingOptions = Nothing /** - * {@comment Version of [SelectingColumns] with correctly filled in examples} + * @comment Version of [SelectingColumns] with correctly filled in examples * @include [SelectingColumns] {@include [SetSumForOperationArg]} */ typealias SumForSelectingOptions = Nothing /** - * {@include [SumDocs.ZeroOnEmptySnippet]} + * @include [SumDocs.ZeroOnEmptySnippet] * * See also: * - [`sumOf`][DataColumn.sumOf] — the sum of the values a selector returns for each element. @@ -180,11 +186,9 @@ internal interface SumDocs : CommonStatisticsDocs { typealias DataColumnSumSnippet = Nothing /** - * {@comment The parts all [DataColumn.sumOf] overloads have in common. KDoc-snippet.} - * - * {@include [SumDocs.SupportedTypesSnippet]} - * - * {@include [SumDocs.ZeroOnEmptySnippet]} + * @comment The parts all [DataColumn.sumOf] overloads have in common. KDoc-snippet. + * @include [SumDocs.SupportedTypesSnippet] + * @include [SumDocs.ZeroOnEmptySnippet] * * See also: * - [`sum`][DataColumn.sum] — the sum of the values in this column itself. @@ -207,10 +211,9 @@ internal interface SumDocs : CommonStatisticsDocs { } /** - * {@comment The parts all [DataRow.rowSumOf] overloads have in common. KDoc-snippet.} + * @comment The parts all [DataRow.rowSumOf] overloads have in common. KDoc-snippet. * * @include [SumDocs.SupportedTypesSnippet] - * * @include [SumDocs.ZeroOnEmptySnippet] * * See also: @@ -227,8 +230,8 @@ internal interface SumDocs : CommonStatisticsDocs { typealias RowSumOfSnippet = Nothing /** - * {@comment [RowSumOfSnippet] plus the parameters that all reified [DataRow.rowSumOf] overloads - * have in common. KDoc-snippet.} + * @comment [RowSumOfSnippet] plus the parameters that all reified [DataRow.rowSumOf] overloads + * have in common. KDoc-snippet. * * @include [SumDocs.RowSumOfSnippet] * $[EXAMPLE] @@ -376,8 +379,8 @@ internal interface SumDocs : CommonStatisticsDocs { } /** - * @comment The parts all column-selecting [Grouped.sum] overloads have in common. - * KDoc-snippet. + * {@comment The parts all column-selecting [Grouped.sum] overloads have in common. + * KDoc-snippet.} * * Aggregates this [GroupBy] by computing a single sum of all the values * in the selected columns, per group. @@ -451,8 +454,8 @@ internal interface SumDocs : CommonStatisticsDocs { } /** - * @comment The parts all column-selecting [Pivot.sum] overloads have in common. - * KDoc-snippet. + * {@comment The parts all column-selecting [Pivot.sum] overloads have in common. + * KDoc-snippet.} * * Aggregates this [Pivot] by computing a single sum of all the values * in the selected columns, per group. @@ -526,8 +529,8 @@ internal interface SumDocs : CommonStatisticsDocs { } /** - * @comment The parts all column-selecting [PivotGroupBy.sum] overloads have in common. - * KDoc-snippet. + * {@comment The parts all column-selecting [PivotGroupBy.sum] overloads have in common. + * KDoc-snippet.} * * Aggregates this [PivotGroupBy] by computing a single sum of all the values * in the selected columns, per group. @@ -562,7 +565,7 @@ internal interface SumDocs : CommonStatisticsDocs { } /** - * {@comment The `columns` parameter of the [ColumnsSelector] overloads. KDoc-snippet.} + * @comment The `columns` parameter of the [ColumnsSelector] overloads. KDoc-snippet. * * @param [columns\] The [ColumnsSelector] used to select the columns to compute the sum of. */ @@ -570,7 +573,7 @@ internal interface SumDocs : CommonStatisticsDocs { typealias ColumnsSelectorParam = Nothing /** - * {@comment The `columns` parameter of the [ColumnsForAggregateSelector] overloads. KDoc-snippet.} + * @comment The `columns` parameter of the [ColumnsForAggregateSelector] overloads. KDoc-snippet. * * @param [columns\] The [ColumnsForAggregateSelector] used to select the columns * to compute the sum of. @@ -579,7 +582,7 @@ internal interface SumDocs : CommonStatisticsDocs { typealias AggregateColumnsSelectorParam = Nothing /** - * {@comment The `columns` parameter of the [String] overloads. KDoc-snippet.} + * @comment The `columns` parameter of the [String] overloads. KDoc-snippet. * * @param [columns\] The names of the columns to compute the sum of. */ @@ -587,7 +590,7 @@ internal interface SumDocs : CommonStatisticsDocs { typealias ColumnNamesParam = Nothing /** - * {@comment The `expression` parameter of the `sumOf` overloads. KDoc-snippet.} + * @comment The `expression` parameter of the `sumOf` overloads. KDoc-snippet. * * @param [expression\] The [RowExpression] to compute the value to sum for each row. */ @@ -595,7 +598,7 @@ internal interface SumDocs : CommonStatisticsDocs { typealias ExpressionParam = Nothing /** - * {@comment The `name` parameter of the [Grouped.sum] overloads. KDoc-snippet.} + * @comment The `name` parameter of the [Grouped.sum] overloads. KDoc-snippet. * * @param [name\] The name of the resulting column. * If `null` (the default), the name of the selected column is used if exactly one column @@ -673,7 +676,7 @@ public fun DataColumn.sum(skipNaN: Boolean = skipNaNDefault): T * Returns the sum of the [Short] values that the given [expression] returns * for each element of this [DataColumn], as an [Int]. * - * @include [SumDocs.DataColumnSumOfSnippet] + * @include [SumDocs.DataColumnSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.DataColumnSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of all halved values in the "amount" column of `Short`s, as an `Int` @@ -690,7 +693,7 @@ public inline fun DataColumn.sumOf(crossinline expres * Returns the sum of the [Byte] values that the given [expression] returns * for each element of this [DataColumn], as an [Int]. * - * @include [SumDocs.DataColumnSumOfSnippet] + * @include [SumDocs.DataColumnSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.DataColumnSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of all halved values in the "amount" column of `Byte`s, as an `Int` @@ -767,7 +770,7 @@ public fun DataRow<*>.rowSum(skipNaN: Boolean = skipNaNDefault): Number = * Only the values in the columns of type [Short] (or `Short?`) are taken into account; * all other columns of the row are ignored. * - * @include [SumDocs.ReifiedRowSumOfSnippet] + * @include [SumDocs.ReifiedRowSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of all `Short` values in the first row, as an `Int` @@ -786,7 +789,7 @@ public inline fun DataRow<*>.rowSumOf(_kClass: KClass * Only the values in the columns of type [Byte] (or `Byte?`) are taken into account; * all other columns of the row are ignored. * - * @include [SumDocs.ReifiedRowSumOfSnippet] + * @include [SumDocs.ReifiedRowSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of all `Byte` values in the first row, as an `Int` @@ -805,7 +808,7 @@ public inline fun DataRow<*>.rowSumOf(_kClass: KClass = * Only the values in the columns of type [Int] (or `Int?`) are taken into account; * all other columns of the row are ignored. * - * @include [SumDocs.ReifiedRowSumOfSnippet] + * @include [SumDocs.ReifiedRowSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of all `Int` values ("age" and "weight") in the first row @@ -824,7 +827,7 @@ public inline fun DataRow<*>.rowSumOf(_kClass: KClass = I * Only the values in the columns of type [Long] (or `Long?`) are taken into account; * all other columns of the row are ignored. * - * @include [SumDocs.ReifiedRowSumOfSnippet] + * @include [SumDocs.ReifiedRowSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] * ```kotlin * // The sum of all `Long` values in the first row @@ -999,6 +1002,7 @@ public fun DataFrame.sumFor( * as an [Int]. * * @include [SumDocs.DataFrameSumSnippet] + * {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.DataFrameSumSnippet.SEE_ALSO_TAIL] * - {@include [SumDocsLink]} — an overview of all `sum` modes. * @set [SumDocs.DataFrameSumSnippet.COLUMNS_API] {@include [SelectingColumns.ColumnsSelectionDsl]} @@ -1019,7 +1023,7 @@ public fun DataFrame.sum(columns: ColumnsSelector): Int * Returns a single sum of all the [Byte] values in the selected columns of this [DataFrame], * as an [Int]. * - * @include [SumDocs.DataFrameSumSnippet] + * @include [SumDocs.DataFrameSumSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.DataFrameSumSnippet.SEE_ALSO_TAIL] * - {@include [SumDocsLink]} — an overview of all `sum` modes. * @set [SumDocs.DataFrameSumSnippet.COLUMNS_API] {@include [SelectingColumns.ColumnsSelectionDsl]} @@ -1121,7 +1125,7 @@ public fun DataFrame.sum( * Returns the sum of the [Short] values that the given [expression] returns * for each row of this [DataFrame], as an [Int]. * - * @include [SumDocs.DataFrameSumOfSnippet] + * @include [SumDocs.DataFrameSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.DataFrameSumOfSnippet.SEE_ALSO_TAIL] * - {@include [SumDocsLink]} — an overview of all `sum` modes. * @set [SumDocs.DataFrameSumOfSnippet.EXAMPLE] @@ -1141,7 +1145,7 @@ public inline fun DataFrame.sumOf(crossinline express * Returns the sum of the [Byte] values that the given [expression] returns * for each row of this [DataFrame], as an [Int]. * - * @include [SumDocs.DataFrameSumOfSnippet] + * @include [SumDocs.DataFrameSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.DataFrameSumOfSnippet.SEE_ALSO_TAIL] * - {@include [SumDocsLink]} — an overview of all `sum` modes. * @set [SumDocs.DataFrameSumOfSnippet.EXAMPLE] diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonStatisticsDocs.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonStatisticsDocs.kt index 063fa6b2a6..b63d63f63b 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonStatisticsDocs.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonStatisticsDocs.kt @@ -8,7 +8,7 @@ import org.jetbrains.kotlinx.dataframe.aggregation.ColumnsForAggregateSelectionD * Holds all KDoc-snippets that the summary statistics operations have in common. * The KDoc-topic of each statistic (like [CommonMinMaxDocs] for `min`/`max`, or `SumDocs` for * `sum`) inherits from this interface, so the snippets can be included from any of them, - * like `{@include [CommonMinMaxDocs.SkipNaNParam]}`. + * like `{@include [CommonMinMaxDocs.SkipNanParam]}`. * * NOTE: this cannot be @ExcludedFromSources because [CommonMinMaxDocs] and the other statistics * KDoc-topics use it as supertype. @@ -16,14 +16,31 @@ import org.jetbrains.kotlinx.dataframe.aggregation.ColumnsForAggregateSelectionD internal interface CommonStatisticsDocs { /** - * {@comment Note about how `null` and NaN values in the input are treated. KDoc-snippet.} + * {@comment Note about how `null` values in the input are treated. KDoc-snippet.} * * `null` values in the input are always ignored. + */ + @ExcludeFromSources + typealias NullHandlingSnippet = Nothing + + /** + * {@comment Note about how NaN values in the input are treated. KDoc-snippet. + * Only include this in the KDoc of overloads that actually have a `skipNaN` parameter; + * overloads of a fixed integer type ([Byte], [Short], [Int], [Long]) have none, + * as those types have no `NaN`.} * * If the input contains {@include [NaNLink]} values, the result will be `NaN`, * unless [skipNaN\] is set to `true`. */ @ExcludeFromSources + typealias NaNHandlingSnippet = Nothing + + /** + * @comment [NullHandlingSnippet] and [NaNHandlingSnippet] combined. KDoc-snippet. + * @include [NullHandlingSnippet] + * @include [NaNHandlingSnippet] + */ + @ExcludeFromSources typealias NullAndNaNHandlingSnippet = Nothing /** @@ -50,7 +67,7 @@ internal interface CommonStatisticsDocs { typealias AggregateColumnsSelectorSnippet = Nothing /** - * {@comment The shared `skipNaN` parameter documentation. KDoc-snippet.} + * @comment The shared `skipNaN` parameter documentation. KDoc-snippet. * * @param [skipNaN\] If `true`, {@include [NaNLink]} values are ignored, just like `null` values. * If `false` (the default), a {@include [NaNLink]} in the input is propagated to the result. @@ -60,7 +77,7 @@ internal interface CommonStatisticsDocs { typealias SkipNanParam = Nothing /** - * {@comment The shared `separate` parameter documentation. KDoc-snippet.} + * @comment The shared `separate` parameter documentation. KDoc-snippet. * * @param [separate\] If `false` (the default), the resulting columns are indexed * first by the pivot key(s) and then by the names of the aggregated columns. From e5973a83fcafd50e3888f8d93f109dcf4ac8e7e6 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Mon, 21 Sep 2026 16:46:15 +0200 Subject: [PATCH 07/11] fixing kdocs of sum based on feedback --- .../jetbrains/kotlinx/dataframe/api/sum.kt | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index 8779d5b5ce..47ad35fe37 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -7,6 +7,7 @@ import org.jetbrains.kotlinx.dataframe.ColumnsSelector import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataRow +import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.RowExpression import org.jetbrains.kotlinx.dataframe.aggregation.ColumnsForAggregateSelector import org.jetbrains.kotlinx.dataframe.annotations.AccessApiOverload @@ -110,11 +111,20 @@ internal interface SumDocs : CommonStatisticsDocs { * {@comment Note about the behavior on empty input for the modes with a single result. KDoc-snippet.} * * When there is nothing to sum, for instance, when the input is empty or contains only `null` values, - * the result is `0` in the result type (defaulting to [Double] if there is no number type to speak of). + * the result is `0` in the result type */ @ExcludeFromSources typealias ZeroOnEmptySnippet = Nothing + /** + * {@comment Note about the behavior on empty input for the modes + * with a single result with comment about defaulting to Double. KDoc-snippet.} + * + * @include [ZeroOnEmptySnippet] (defaulting to [Double] if there is no number type to speak of) + */ + @ExcludeFromSources + typealias ZeroOnEmptyDefaultDoubleSnippet = Nothing + /** * {@comment Note about the behavior on empty input for the modes with multiple results. KDoc-snippet.} * @@ -169,10 +179,10 @@ internal interface SumDocs : CommonStatisticsDocs { typealias SumForSelectingOptions = Nothing /** - * @include [SumDocs.ZeroOnEmptySnippet] + * @include [SumDocs.ZeroOnEmptyDefaultDoubleSnippet] * * See also: - * - [`sumOf`][DataColumn.sumOf] — the sum of the values a selector returns for each element. + * - [`sumOf`][DataColumn.sumOf] — the sum of the values an expression returns for each element. * - [`mean`][DataColumn.mean] — the sum divided by the number of values. * - [`cumSum`][DataColumn.cumSum] — the running sum of the values in this column. * - {@include [SumDocsLink]} — an overview of all `sum` modes. @@ -188,7 +198,7 @@ internal interface SumDocs : CommonStatisticsDocs { /** * @comment The parts all [DataColumn.sumOf] overloads have in common. KDoc-snippet. * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroOnEmptySnippet] + * @include [SumDocs.ZeroOnEmptyDefaultDoubleSnippet] * * See also: * - [`sum`][DataColumn.sum] — the sum of the values in this column itself. @@ -284,7 +294,7 @@ internal interface SumDocs : CommonStatisticsDocs { * KDoc-snippet. * * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroOnEmptySnippet] + * @include [SumDocs.ZeroOnEmptyDefaultDoubleSnippet] * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] * * See also: @@ -585,6 +595,7 @@ internal interface SumDocs : CommonStatisticsDocs { * @comment The `columns` parameter of the [String] overloads. KDoc-snippet. * * @param [columns\] The names of the columns to compute the sum of. + * These must be primitive number columns, else an [IllegalArgumentException] is thrown. */ @ExcludeFromSources typealias ColumnNamesParam = Nothing @@ -736,12 +747,14 @@ public inline fun DataColumn.sumOf( * * Only the values in the columns of a primitive number type (and in "mixed" [Number] columns) * are taken into account; all other columns of the row are ignored. + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. * * Since the values of different columns are summed together, the result is the sum of all those * values converted to their common type. * * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroOnEmptySnippet] + * @include [SumDocs.ZeroOnEmptyDefaultDoubleSnippet] * * See also: * - [`rowSumOf()`][DataRow.rowSumOf] — the sum of the values of one specific number type in this row. @@ -769,6 +782,8 @@ public fun DataRow<*>.rowSum(skipNaN: Boolean = skipNaNDefault): Number = * * Only the values in the columns of type [Short] (or `Short?`) are taken into account; * all other columns of the row are ignored. + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. * * @include [SumDocs.ReifiedRowSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] @@ -788,6 +803,8 @@ public inline fun DataRow<*>.rowSumOf(_kClass: KClass * * Only the values in the columns of type [Byte] (or `Byte?`) are taken into account; * all other columns of the row are ignored. + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. * * @include [SumDocs.ReifiedRowSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] @@ -807,6 +824,8 @@ public inline fun DataRow<*>.rowSumOf(_kClass: KClass = * * Only the values in the columns of type [Int] (or `Int?`) are taken into account; * all other columns of the row are ignored. + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. * * @include [SumDocs.ReifiedRowSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] @@ -826,6 +845,8 @@ public inline fun DataRow<*>.rowSumOf(_kClass: KClass = I * * Only the values in the columns of type [Long] (or `Long?`) are taken into account; * all other columns of the row are ignored. + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. * * @include [SumDocs.ReifiedRowSumOfSnippet] {@set [SumDocs.SupportedTypesSnippet.NAN_NOTE]} * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] @@ -845,6 +866,8 @@ public inline fun DataRow<*>.rowSumOf(_kClass: KClass = * * Only the values in the columns of type [Float] (or `Float?`) are taken into account; * all other columns of the row are ignored. + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. * * @include [SumDocs.ReifiedRowSumOfSnippet] * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] @@ -867,6 +890,8 @@ public inline fun DataRow<*>.rowSumOf( * * Only the values in the columns of type [Double] (or `Double?`) are taken into account; * all other columns of the row are ignored. + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. * * @include [SumDocs.ReifiedRowSumOfSnippet] * @set [SumDocs.ReifiedRowSumOfSnippet.EXAMPLE] @@ -891,6 +916,8 @@ public inline fun DataRow<*>.rowSumOf( * * Only the values in the columns of the given [type] (or its nullable variant) are taken into account; * all other columns of the row are ignored. + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. * * This overload takes the type as a [KType] argument; prefer the `reified` overloads, like * [`rowSumOf`][DataRow.rowSumOf]`<`[`Int`][Int]`>()`, whenever the type is known at compile time. @@ -907,7 +934,7 @@ public inline fun DataRow<*>.rowSumOf( */ public fun DataRow<*>.rowSumOf(type: KType, skipNaN: Boolean = skipNaNDefault): Number { require(type.isPrimitiveOrMixedNumber()) { - "Type $type is not a primitive number type. Mean only supports primitive number types." + "Type $type is not a primitive number type. Sum only supports primitive number types." } return Aggregators.sum(skipNaN).aggregateOfRow(this) { colsOf(type.withNullability(true)) @@ -1357,6 +1384,7 @@ public fun Grouped.sum( * ``` * * @param [resultName] The name of the resulting column. If `null` (the default), `"sum"` is used. + * This name needs to be unique, else a [DuplicateColumnPathInsertException] is thrown. * @include [SumDocs.SkipNanParam] * @include [SumDocs.ExpressionParam] * @return A new [DataFrame] with the group keys and a single sum per group. From 32e8467fc417da5dc882c6f50fcd59cbaba32a14 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Mon, 21 Sep 2026 20:53:34 +0200 Subject: [PATCH 08/11] Fixed bug of empty Number column throwing exceptions in mean, sum, and std, while it should return 0.0 or Double.NaN --- .../aggregators/inputHandlers/NumberInputHandler.kt | 4 ++++ .../org/jetbrains/kotlinx/dataframe/statistics/sum.kt | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt index 653f285d6d..af01679d62 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt @@ -100,8 +100,12 @@ internal class NumberInputHandler : AggregatorInputHandler): ValueType { + if (valueTypes.isEmpty()) { + return typeOf().toValueType() + } val unifiedType = valueTypes.unifiedNumberTypeOrNull(UnifiedNumberTypeOptions.PRIMITIVES_ONLY) ?: typeOf().withNullability(valueTypes.any { it.isMarkedNullable }) if (!unifiedType.isPrimitiveOrMixedNumber() && !unifiedType.isNothing) { diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt index f27395f910..8ec603175f 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlinx.dataframe.api.rowSumOf import org.jetbrains.kotlinx.dataframe.api.sum import org.jetbrains.kotlinx.dataframe.api.sumFor import org.jetbrains.kotlinx.dataframe.api.sumOf +import org.jetbrains.kotlinx.dataframe.api.take import org.jetbrains.kotlinx.dataframe.api.toDataFrame import org.jetbrains.kotlinx.dataframe.impl.nullableNothingType import org.junit.Test @@ -136,6 +137,16 @@ class SumTests { shouldThrow { columnOf(1.0, 2, 3.0.toBigDecimal()).toDataFrame().sum()[0] }.message?.lowercase() shouldContain "primitive" + + // empty column of Number should be treated as Double + columnOf(1.0, 2) + .take(0) + .sum() shouldBe 0.0 + + // empty column in DF + columnOf(1.0, 2).toDataFrame() + .take(0) + .sum()[0] shouldBe 0.0 } @Test From 3f797c63b04592196f57c47d251fa7caad8824a4 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Mon, 21 Sep 2026 21:04:41 +0200 Subject: [PATCH 09/11] fixing kdocs of sum based on feedback --- .../jetbrains/kotlinx/dataframe/api/sum.kt | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index 47ad35fe37..6041dc3713 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -7,13 +7,13 @@ import org.jetbrains.kotlinx.dataframe.ColumnsSelector import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataRow -import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.RowExpression import org.jetbrains.kotlinx.dataframe.aggregation.ColumnsForAggregateSelector import org.jetbrains.kotlinx.dataframe.annotations.AccessApiOverload import org.jetbrains.kotlinx.dataframe.annotations.Interpretable import org.jetbrains.kotlinx.dataframe.annotations.Refine import org.jetbrains.kotlinx.dataframe.annotations.StringApiInterpretable +import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.columns.ColumnReference import org.jetbrains.kotlinx.dataframe.columns.toColumnSet import org.jetbrains.kotlinx.dataframe.columns.toColumnsSetOf @@ -138,6 +138,20 @@ internal interface SumDocs : CommonStatisticsDocs { @ExcludeFromSources typealias ZeroCellOnEmptySnippet = Nothing + /** + * {@comment Note about the behavior on empty input for the Pivot functions. KDoc-snippet.} + * + * Result cells for which there exists a group, but there is nothing to sum + * (for instance, because the group was empty or contained only `null` values) + * simply become `0` in the result type (defaulting to [Double] if there is no number type to speak of). + * For more information about the resulting types: + * @include [DocumentationUrls.Sum.TypeConversion] + * + * For empty pivot intersections, `null` or the [set default][PivotGroupBy.default] are used. + */ + @ExcludeFromSources + typealias ZeroCellOnEmptyPivotSnippet = Nothing + /** * {@comment Note about which columns the no-argument `sum` modes take into account. KDoc-snippet.} * @@ -196,7 +210,9 @@ internal interface SumDocs : CommonStatisticsDocs { typealias DataColumnSumSnippet = Nothing /** - * @comment The parts all [DataColumn.sumOf] overloads have in common. KDoc-snippet. + * {@comment The parts all [DataColumn.sumOf] overloads have in common. KDoc-snippet.} + * + * The result of [expression\] is treated as the 'input' of this operation. * @include [SumDocs.SupportedTypesSnippet] * @include [SumDocs.ZeroOnEmptyDefaultDoubleSnippet] * @@ -327,6 +343,8 @@ internal interface SumDocs : CommonStatisticsDocs { * KDoc-snippet. * * @include [SumDocs.RowExpressionSnippet] + * + * The result of the [expression\] is considered the 'input' of this operation. * @include [SumDocs.SupportedTypesSnippet] * @include [SumDocs.ZeroOnEmptySnippet] * @@ -435,7 +453,7 @@ internal interface SumDocs : CommonStatisticsDocs { * of each selected column of the corresponding group. * * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SumDocs.ZeroCellOnEmptyPivotSnippet] * $[NOTE] * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] * @@ -474,7 +492,7 @@ internal interface SumDocs : CommonStatisticsDocs { * the values in the selected columns of the corresponding group. * * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SumDocs.ZeroCellOnEmptyPivotSnippet] * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] * * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the @@ -508,7 +526,7 @@ internal interface SumDocs : CommonStatisticsDocs { * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). * * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SumDocs.ZeroCellOnEmptyPivotSnippet] * $[NOTE] * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] * @@ -549,7 +567,7 @@ internal interface SumDocs : CommonStatisticsDocs { * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). * * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SumDocs.ZeroCellOnEmptyPivotSnippet] * @include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet] * * See [Selecting Columns][SumDocs.SumSelectingOptions], or check out the @@ -1366,6 +1384,8 @@ public fun Grouped.sum( * a single column with the sum per group, named [resultName] (or `"sum"` if [resultName] is `null`). * * @include [SumDocs.RowExpressionSnippet] + * + * The result of the [expression\] is considered the 'input' of this operation. * @include [SumDocs.SupportedTypesSnippet] * @include [SumDocs.ZeroCellOnEmptySnippet] * @@ -1582,7 +1602,7 @@ public inline fun Pivot.sumOf( * * @include [SumDocs.AllSuitableColumnsSnippet] * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SumDocs.ZeroCellOnEmptyPivotSnippet] * * Check out the [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. * @@ -1714,8 +1734,10 @@ public fun PivotGroupBy.sum( * rows of the group corresponding to that [pivot] key (column) and [groupBy] key (row). * * @include [SumDocs.RowExpressionSnippet] + * + * The result of the [expression\] is considered the 'input' of this operation. * @include [SumDocs.SupportedTypesSnippet] - * @include [SumDocs.ZeroCellOnEmptySnippet] + * @include [SumDocs.ZeroCellOnEmptyPivotSnippet] * * Check out the [`PivotGroupBy` Grammar][PivotGroupByDocs.Grammar]. * From bb8a9787d2a3c460c1ebceaf1cc907d0fd6ddd59 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Tue, 22 Sep 2026 15:02:55 +0200 Subject: [PATCH 10/11] better fix for setting a type for empty aggregation input using `valueTypeIfEmpty`. This is especially important for functions like `rowSumOf()` --- .../jetbrains/kotlinx/dataframe/api/sum.kt | 42 +++++++++---------- .../aggregation/aggregators/Aggregator.kt | 2 +- .../aggregators/AggregatorInputHandler.kt | 11 +++++ .../aggregation/aggregators/Aggregators.kt | 30 ++++++++----- .../inputHandlers/AnyInputHandler.kt | 14 +++++-- .../inputHandlers/NumberInputHandler.kt | 21 ++++++---- .../kotlinx/dataframe/statistics/sum.kt | 14 +++++++ 7 files changed, 91 insertions(+), 43 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index 6041dc3713..5ac7c920d6 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -665,7 +665,7 @@ private typealias SetSumForOperationArg = Nothing * @return The sum of the values in this column, as an [Int]. */ @JvmName("sumShort") -public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingleColumn(this) as Int +public fun DataColumn.sum(): Int = Aggregators.sum(false, typeOf()).aggregateSingleColumn(this) as Int /** * Returns the sum of the [Byte] values in this [DataColumn], as an [Int]. @@ -679,7 +679,7 @@ public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingl * @return The sum of the values in this column, as an [Int]. */ @JvmName("sumByte") -public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingleColumn(this) as Int +public fun DataColumn.sum(): Int = Aggregators.sum(false, typeOf()).aggregateSingleColumn(this) as Int /** * Returns the sum of the values in this [DataColumn]. @@ -699,7 +699,7 @@ public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingle @Suppress("UNCHECKED_CAST") @JvmName("sumNumber") public fun DataColumn.sum(skipNaN: Boolean = skipNaNDefault): T & Any = - Aggregators.sum(skipNaN).aggregateSingleColumn(this) as (T & Any) + Aggregators.sum(skipNaN, typeOf()).aggregateSingleColumn(this) as (T & Any) /** * Returns the sum of the [Short] values that the given [expression] returns @@ -716,7 +716,7 @@ public fun DataColumn.sum(skipNaN: Boolean = skipNaNDefault): T @JvmName("sumOfShort") @OverloadResolutionByLambdaReturnType public inline fun DataColumn.sumOf(crossinline expression: (C) -> V): Int = - Aggregators.sum(false).aggregateOf(this, expression) as Int + Aggregators.sum(false, typeOf()).aggregateOf(this, expression) as Int /** * Returns the sum of the [Byte] values that the given [expression] returns @@ -733,7 +733,7 @@ public inline fun DataColumn.sumOf(crossinline expres @JvmName("sumOfByte") @OverloadResolutionByLambdaReturnType public inline fun DataColumn.sumOf(crossinline expression: (C) -> V): Int = - Aggregators.sum(false).aggregateOf(this, expression) as Int + Aggregators.sum(false, typeOf()).aggregateOf(this, expression) as Int /** * Returns the sum of the values that the given [expression] returns @@ -754,7 +754,7 @@ public inline fun DataColumn.sumOf(crossinline express public inline fun DataColumn.sumOf( skipNaN: Boolean = skipNaNDefault, crossinline expression: (C) -> V, -): V & Any = Aggregators.sum(skipNaN).aggregateOf(this, expression) as (V & Any) +): V & Any = Aggregators.sum(skipNaN, typeOf()).aggregateOf(this, expression) as (V & Any) // endregion @@ -793,7 +793,7 @@ public inline fun DataColumn.sumOf( * @return The sum of all the numbers in this row. */ public fun DataRow<*>.rowSum(skipNaN: Boolean = skipNaNDefault): Number = - Aggregators.sum(skipNaN).aggregateOfRow(this, primitiveOrMixedNumberColumns()) + Aggregators.sum(skipNaN, typeOf()).aggregateOfRow(this, primitiveOrMixedNumberColumns()) /** * Returns the sum of the [Short] values in this [DataRow], as an [Int]. @@ -954,7 +954,7 @@ public fun DataRow<*>.rowSumOf(type: KType, skipNaN: Boolean = skipNaNDefault): require(type.isPrimitiveOrMixedNumber()) { "Type $type is not a primitive number type. Sum only supports primitive number types." } - return Aggregators.sum(skipNaN).aggregateOfRow(this) { + return Aggregators.sum(skipNaN, type).aggregateOfRow(this) { colsOf(type.withNullability(true)) } } @@ -1010,7 +1010,7 @@ public fun DataFrame.sum(skipNaN: Boolean = skipNaNDefault): DataRow = public fun DataFrame.sumFor( skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, -): DataRow = Aggregators.sum(skipNaN).aggregateFor(this, columns) +): DataRow = Aggregators.sum(skipNaN, typeOf()).aggregateFor(this, columns) /** * @include [SumDocs.DataFrameSumForSnippet] @@ -1062,7 +1062,7 @@ public fun DataFrame.sumFor( @JvmName("sumShort") @OverloadResolutionByLambdaReturnType public fun DataFrame.sum(columns: ColumnsSelector): Int = - Aggregators.sum(false).aggregateAll(this, columns) as Int + Aggregators.sum(false, typeOf()).aggregateAll(this, columns) as Int /** * Returns a single sum of all the [Byte] values in the selected columns of this [DataFrame], @@ -1083,7 +1083,7 @@ public fun DataFrame.sum(columns: ColumnsSelector): Int @JvmName("sumByte") @OverloadResolutionByLambdaReturnType public fun DataFrame.sum(columns: ColumnsSelector): Int = - Aggregators.sum(false).aggregateAll(this, columns) as Int + Aggregators.sum(false, typeOf()).aggregateAll(this, columns) as Int /** * Returns a single sum of all the values in the selected columns of this [DataFrame]. @@ -1108,7 +1108,7 @@ public fun DataFrame.sum(columns: ColumnsSelector): Int public fun DataFrame.sum( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, -): C & Any = Aggregators.sum(skipNaN).aggregateAll(this, columns) as (C & Any) +): C & Any = Aggregators.sum(skipNaN, typeOf()).aggregateAll(this, columns) as (C & Any) @JvmName("sumShort") @Deprecated(DEPRECATED_ACCESS_API) @@ -1184,7 +1184,7 @@ public fun DataFrame.sum( @JvmName("sumOfShort") @OverloadResolutionByLambdaReturnType public inline fun DataFrame.sumOf(crossinline expression: RowExpression): Int = - Aggregators.sum(false).aggregateOf(this, expression) as Int + Aggregators.sum(false, typeOf()).aggregateOf(this, expression) as Int /** * Returns the sum of the [Byte] values that the given [expression] returns @@ -1204,7 +1204,7 @@ public inline fun DataFrame.sumOf(crossinline express @JvmName("sumOfByte") @OverloadResolutionByLambdaReturnType public inline fun DataFrame.sumOf(crossinline expression: RowExpression): Int = - Aggregators.sum(false).aggregateOf(this, expression) as Int + Aggregators.sum(false, typeOf()).aggregateOf(this, expression) as Int /** * Returns the sum of the values that the given [expression] returns @@ -1229,7 +1229,7 @@ public inline fun DataFrame.sumOf(crossinline expressi public inline fun DataFrame.sumOf( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, -): C & Any = Aggregators.sum(skipNaN).aggregateOf(this, expression) as (C & Any) +): C & Any = Aggregators.sum(skipNaN, typeOf()).aggregateOf(this, expression) as (C & Any) // endregion @@ -1286,7 +1286,7 @@ public fun Grouped.sum(skipNaN: Boolean = skipNaNDefault): DataFrame = public fun Grouped.sumFor( skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, columns) +): DataFrame = Aggregators.sum(skipNaN, typeOf()).aggregateFor(this, columns) /** * @include [SumDocs.GroupedSumForSnippet] @@ -1337,7 +1337,7 @@ public fun Grouped.sum( name: String? = null, skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, -): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, name, columns) +): DataFrame = Aggregators.sum(skipNaN, typeOf()).aggregateAll(this, name, columns) /** * @include [SumDocs.GroupedSumSnippet] @@ -1415,7 +1415,7 @@ public inline fun Grouped.sumOf( resultName: String? = null, skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, -): DataFrame = Aggregators.sum(skipNaN).aggregateOf(this, resultName, expression) +): DataFrame = Aggregators.sum(skipNaN, typeOf()).aggregateOf(this, resultName, expression) // endregion @@ -1646,7 +1646,7 @@ public fun PivotGroupBy.sumFor( separate: Boolean = false, skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, separate, columns) +): DataFrame = Aggregators.sum(skipNaN, typeOf()).aggregateFor(this, separate, columns) /** * @include [SumDocs.PivotGroupBySumForSnippet] @@ -1696,7 +1696,7 @@ public fun PivotGroupBy.sumFor( public fun PivotGroupBy.sum( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, -): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, columns) +): DataFrame = Aggregators.sum(skipNaN, typeOf()).aggregateAll(this, columns) /** * @include [SumDocs.PivotGroupBySumSnippet] @@ -1763,7 +1763,7 @@ public fun PivotGroupBy.sum( public inline fun PivotGroupBy.sumOf( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, -): DataFrame = Aggregators.sum(skipNaN).aggregateOf(this, expression) +): DataFrame = Aggregators.sum(skipNaN, typeOf()).aggregateOf(this, expression) // endregion diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt index 4746df815b..dcda080988 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt @@ -123,7 +123,7 @@ internal fun Aggregator.aggregate( internal fun Aggregator.calculateValueType( values: Sequence, valueTypes: Set? = null, -) = if (valueTypes != null && valueTypes.isNotEmpty()) { +) = if (!valueTypes.isNullOrEmpty()) { calculateValueType(valueTypes) } else { calculateValueType(values) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler.kt index 73c0dcde4b..7bc671d909 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators +import org.jetbrains.kotlinx.dataframe.impl.nothingType import kotlin.reflect.KType /** @@ -10,9 +11,17 @@ import kotlin.reflect.KType */ public interface AggregatorInputHandler : AggregatorHandler { + /** + * The type of the value if the input is empty. + */ + public val valueTypeIfEmpty: KType + get() = nothingType + /** * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], * this function can be called to calculate it by combining the set of known [valueTypes]. + * + * Returns [valueTypeIfEmpty] if [valueTypes] is empty. */ public fun calculateValueType(valueTypes: Set): ValueType @@ -22,6 +31,8 @@ public interface AggregatorInputHandler : Agg * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], * this function can be called to calculate it by getting the types of [values] at runtime. * This is heavy because it uses reflection on each value. + * + * Returns [valueTypeIfEmpty] if [values] is empty. */ public fun calculateValueType(values: Sequence): ValueType diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt index 5cdede84f2..5dd388f806 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt @@ -26,6 +26,8 @@ import org.jetbrains.kotlinx.dataframe.math.std import org.jetbrains.kotlinx.dataframe.math.stdTypeConversion import org.jetbrains.kotlinx.dataframe.math.sum import org.jetbrains.kotlinx.dataframe.math.sumTypeConversion +import kotlin.reflect.KType +import kotlin.reflect.typeOf public object Aggregators { @@ -89,23 +91,25 @@ public object Aggregators { ) private fun flattenReducingForNumbers( + valueTypeIfEmpty: KType, getReturnType: CalculateReturnType, statisticsParameters: Map, reducer: Reducer, ) = Aggregator( aggregationHandler = ReducingAggregationHandler(reducer, getReturnType), - inputHandler = NumberInputHandler(), + inputHandler = NumberInputHandler(valueTypeIfEmpty), multipleColumnsHandler = FlatteningMultipleColumnsHandler(), statisticsParameters = statisticsParameters, ) private fun twoStepReducingForNumbers( + valueTypeIfEmpty: KType, getReturnType: CalculateReturnType, statisticsParameters: Map, reducer: Reducer, ) = Aggregator( aggregationHandler = ReducingAggregationHandler(reducer, getReturnType), - inputHandler = NumberInputHandler(), + inputHandler = NumberInputHandler(valueTypeIfEmpty), multipleColumnsHandler = TwoStepMultipleColumnsHandler(), statisticsParameters = statisticsParameters, ) @@ -154,6 +158,7 @@ public object Aggregators { ddof: Int, -> flattenReducingForNumbers( + valueTypeIfEmpty = typeOf(), getReturnType = stdTypeConversion, statisticsParameters = mapOf( "skipNaN" to skipNaN, @@ -169,6 +174,7 @@ public object Aggregators { // step two: Double -> Double public val mean: AggregatorOptionSwitch1 by withOneOption { skipNaN: Boolean -> twoStepReducingForNumbers( + valueTypeIfEmpty = typeOf(), getReturnType = meanTypeConversion, statisticsParameters = mapOf("skipNaN" to skipNaN), reducer = { type -> @@ -251,13 +257,15 @@ public object Aggregators { // Byte -> Int // Short -> Int // Nothing -> Double - public val sum: AggregatorOptionSwitch1 by withOneOption { skipNaN: Boolean -> - twoStepReducingForNumbers( - getReturnType = sumTypeConversion, - statisticsParameters = mapOf("skipNaN" to skipNaN), - reducer = { type -> - sum(type, skipNaN) - }, - ) - } + public val sum: AggregatorOptionSwitch2 + by withTwoOptions { skipNaN: Boolean, valueTypeIfEmpty: KType -> + twoStepReducingForNumbers( + valueTypeIfEmpty = valueTypeIfEmpty, + getReturnType = sumTypeConversion, + statisticsParameters = mapOf("skipNaN" to skipNaN), + reducer = { type -> + sum(type, skipNaN) + }, + ) + } } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/AnyInputHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/AnyInputHandler.kt index b18592e1bf..a7de0a57c1 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/AnyInputHandler.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/AnyInputHandler.kt @@ -14,7 +14,8 @@ import kotlin.reflect.KType * * When calculating the value type, it will try to find the common type in terms of inheritance. */ -internal class AnyInputHandler : AggregatorInputHandler { +internal class AnyInputHandler(override val valueTypeIfEmpty: KType = nothingType) : + AggregatorInputHandler { /** No preprocessing is done on the input values. */ override fun preprocessAggregation( @@ -26,7 +27,14 @@ internal class AnyInputHandler : AggregatorIn * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], * this function can be called to calculate it in terms of inheritance by combining the set of known [valueTypes]. */ - override fun calculateValueType(valueTypes: Set): ValueType = valueTypes.commonType(false).toValueType() + override fun calculateValueType(valueTypes: Set): ValueType = + if (valueTypes.isEmpty()) { + valueTypeIfEmpty.toValueType() + } else { + valueTypes + .commonType(false) + .toValueType() + } /** * WARNING: HEAVY! @@ -46,7 +54,7 @@ internal class AnyInputHandler : AggregatorIn } }.toSet() return if (classes.isEmpty()) { - nothingType(hasNulls) + valueTypeIfEmpty } else { classes.commonType(hasNulls) }.toValueType() diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt index af01679d62..b1f965823b 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt @@ -28,7 +28,8 @@ import kotlin.reflect.typeOf * it will try to find the common type in terms of [number unification][UnifyingNumbers]. * Preprocessing will handle the conversion of the values in the input to this unified number type. */ -internal class NumberInputHandler : AggregatorInputHandler { +internal class NumberInputHandler(override val valueTypeIfEmpty: KType) : + AggregatorInputHandler { /** * Preprocesses the input values before aggregation. @@ -100,12 +101,11 @@ internal class NumberInputHandler : AggregatorInputHandler): ValueType { - if (valueTypes.isEmpty()) { - return typeOf().toValueType() - } + if (valueTypes.isEmpty()) return valueTypeIfEmpty.toValueType() + val unifiedType = valueTypes.unifiedNumberTypeOrNull(UnifiedNumberTypeOptions.PRIMITIVES_ONLY) ?: typeOf().withNullability(valueTypes.any { it.isMarkedNullable }) if (!unifiedType.isPrimitiveOrMixedNumber() && !unifiedType.isNothing) { @@ -130,9 +130,16 @@ internal class NumberInputHandler : AggregatorInputHandler): ValueType = - calculateValueType(values.asIterable().types().toSet()) + override fun calculateValueType(values: Sequence): ValueType { + val list = values.toList() + return if (list.isEmpty()) { + valueTypeIfEmpty.toValueType() + } else { + calculateValueType(list.types().toSet()) + } + } override var aggregator: Aggregator? = null } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt index 8ec603175f..a0d2f08231 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt @@ -8,15 +8,18 @@ import io.kotest.matchers.string.shouldContain import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.api.cast import org.jetbrains.kotlinx.dataframe.api.columnOf +import org.jetbrains.kotlinx.dataframe.api.convert import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.isEmpty import org.jetbrains.kotlinx.dataframe.api.rowSum import org.jetbrains.kotlinx.dataframe.api.rowSumOf +import org.jetbrains.kotlinx.dataframe.api.single import org.jetbrains.kotlinx.dataframe.api.sum import org.jetbrains.kotlinx.dataframe.api.sumFor import org.jetbrains.kotlinx.dataframe.api.sumOf import org.jetbrains.kotlinx.dataframe.api.take import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.dataframe.api.toFloat import org.jetbrains.kotlinx.dataframe.impl.nullableNothingType import org.junit.Test import kotlin.reflect.typeOf @@ -205,6 +208,17 @@ class SumTests { row2.rowSumOf().shouldBeNaN() } + @Test + fun `rowSumOf with empty input`() { + val df = dataFrameOf("a", "b")(1.0, 2.0) + df.single().rowSumOf() shouldBe 0 + df.single().rowSumOf() shouldBe 0 + df.single().rowSumOf() shouldBe 0 + df.single().rowSumOf() shouldBe 0f + df.convert { all() }.toFloat() + .single().rowSumOf() shouldBe 0.0 + } + @Test fun `test sumFor with skipNaN`() { val value1 by columnOf(1.0, 2.0, 3.0) From 8c6a6a84a0e0c8016bcb6ac10c187b2f580b41e1 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Tue, 22 Sep 2026 15:19:17 +0200 Subject: [PATCH 11/11] small fixes based on feedback for sum.kt --- core/api/core.api | 4 +++- .../main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt | 7 +++++++ .../kotlinx/dataframe/documentation/CommonMinMaxDocs.kt | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/core/api/core.api b/core/api/core.api index 3af74af214..452611ed6c 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -5589,6 +5589,7 @@ public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ public final fun getMultipleColumnsHandler ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorMultipleColumnsHandler; public final fun getName ()Ljava/lang/String; public final fun getStatisticsParameters ()Ljava/util/Map; + public fun getValueTypeIfEmpty ()Lkotlin/reflect/KType; public fun indexOfAggregationResultSingleSequence (Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)I public fun init (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;)V public fun preprocessAggregation (Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)Lkotlin/Pair; @@ -5612,6 +5613,7 @@ public abstract interface class org/jetbrains/kotlinx/dataframe/impl/aggregation public abstract interface class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler : org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorHandler { public abstract fun calculateValueType (Ljava/util/Set;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType; public abstract fun calculateValueType (Lkotlin/sequences/Sequence;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType; + public fun getValueTypeIfEmpty ()Lkotlin/reflect/KType; public abstract fun preprocessAggregation (Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)Lkotlin/Pair; } @@ -5663,7 +5665,7 @@ public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ public final fun getMin ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1; public final fun getPercentile ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2; public final fun getStd ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2; - public final fun getSum ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1; + public final fun getSum ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2; public final fun max (Z)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; public final fun medianCommon (Z)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; public final fun medianComparables ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index 5ac7c920d6..1266c39431 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -144,6 +144,7 @@ internal interface SumDocs : CommonStatisticsDocs { * Result cells for which there exists a group, but there is nothing to sum * (for instance, because the group was empty or contained only `null` values) * simply become `0` in the result type (defaulting to [Double] if there is no number type to speak of). + * * For more information about the resulting types: * @include [DocumentationUrls.Sum.TypeConversion] * @@ -157,6 +158,9 @@ internal interface SumDocs : CommonStatisticsDocs { * * All columns of a primitive number type (and all "mixed" [Number] columns) are taken into account; * the other columns are simply left out of the result. + * + * This includes columns inside [column groups][ColumnGroup]. + * To include those in the sum, [flatten][DataFrame.flatten] the DataFrame first. */ @ExcludeFromSources typealias AllSuitableColumnsSnippet = Nothing @@ -632,6 +636,7 @@ internal interface SumDocs : CommonStatisticsDocs { * @param [name\] The name of the resulting column. * If `null` (the default), the name of the selected column is used if exactly one column * is selected, and `"sum"` otherwise. + * This name needs to be unique, else a [DuplicateColumnPathInsertException] is thrown. */ @ExcludeFromSources typealias ResultColumnNameParam = Nothing @@ -1562,6 +1567,8 @@ public fun Pivot.sum(vararg columns: KProperty, skipNaN: * of the expression's results for the rows of the corresponding group. * * @include [SumDocs.RowExpressionSnippet] + * + * The result of [expression\] is treated as the 'input' of this operation. * @include [SumDocs.SupportedTypesSnippet] * @include [SumDocs.ZeroCellOnEmptySnippet] * diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt index fae3c731fb..5a7c7c630b 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlinx.dataframe.api.with * {@comment * Holds all KDoc-snippets that the `min` and `max` operations have in common. * Both `MinDocs` and `MaxDocs` inherit from this interface, so the snippets can be - * included from either of them, like `{@include [MaxDocs.SkipNaNParam]}`. + * included from either of them, like `{@include [MaxDocs.SkipNanParam]}`. * The snippets that all summary statistics have in common are inherited from * [CommonStatisticsDocs] and can be included in the same way. *