diff --git a/core/api/core.api b/core/api/core.api index bb76090655..34e3eb629f 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -5376,6 +5376,9 @@ public abstract interface class org/jetbrains/kotlinx/dataframe/documentation/Do public abstract interface class org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls$Fill { } +public abstract interface class org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls$MinMax { +} + public abstract interface class org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls$NanAndNa { } 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 2c212fbb95..39897f4e8e 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 @@ -11,6 +11,11 @@ import org.jetbrains.kotlinx.dataframe.annotations.Interpretable import org.jetbrains.kotlinx.dataframe.annotations.Refine import org.jetbrains.kotlinx.dataframe.columns.ColumnReference import org.jetbrains.kotlinx.dataframe.columns.toColumnSet +import org.jetbrains.kotlinx.dataframe.documentation.CommonMinMaxDocs +import org.jetbrains.kotlinx.dataframe.documentation.CommonMinMaxDocs.InputValuesSnippet +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.impl.aggregation.aggregators.Aggregators import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll @@ -26,29 +31,268 @@ import org.jetbrains.kotlinx.dataframe.util.ROW_MAX import org.jetbrains.kotlinx.dataframe.util.ROW_MAX_OR_NULL import kotlin.reflect.KProperty +// region docs + +/** + * {@comment + * The Max Operation KDoc-topic; it also holds all common `max` KDoc-snippets. + * Link to it with `{@include [MaxDocsLink]}`. + * } + * + * ## The Max Operation + * + * Computes the [maximum](https://en.wikipedia.org/wiki/Maximum_and_minimum) of values. + * + * @include [InputValuesSnippet] + * + * ### Max Modes + * + * Depending on what exactly you want the maximum of, there are several modes. + * They are shown here for [DataFrame], but they exist for the other receivers too: + * + * - [max][DataFrame.max]`()` — the maximum of each suitable column separately. + * - [max][DataFrame.max]` { columns }` — a single maximum of all values in all selected columns. + * - [maxFor][DataFrame.maxFor]` { columns }` — the maximum of each selected column separately. + * - [maxOf][DataFrame.maxOf]` { expression }` — the maximum of the values that the given expression + * returns for each row. + * - [maxBy][DataFrame.maxBy]` { expression }` — the first row for which the given expression returns + * the maximum value. + * + * [max][DataFrame.max], [maxOf][DataFrame.maxOf], and [maxBy][DataFrame.maxBy] all have an `-OrNull` + * counterpart which returns `null` instead of throwing an exception when there's nothing to compare. + * + * Mirror operation: [min][DataFrame.min]. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * See all summary statistics: {@include [DocumentationUrls.Statistics]} + */ +internal interface MaxDocs : CommonMinMaxDocs { + + /** + * {@comment Version of [SelectingColumns] with correctly filled in examples} + * @include [SelectingColumns] {@include [SetMaxOperationArg]} + */ + typealias MaxSelectingOptions = Nothing + + /** + * {@comment Version of [SelectingColumns] with correctly filled in examples} + * @include [SelectingColumns] {@include [SetMaxForOperationArg]} + */ + typealias MaxForSelectingOptions = Nothing +} + +/** [The Max Operation][MaxDocs] */ +@ExcludeFromSources +private typealias MaxDocsLink = Nothing + +/** {@set [SelectingColumns.OPERATION] [max][max]} */ +@ExcludeFromSources +private typealias SetMaxOperationArg = Nothing + +/** {@set [SelectingColumns.OPERATION] [maxFor][maxFor]} */ +@ExcludeFromSources +private typealias SetMaxForOperationArg = Nothing + +/** {@set [SelectingColumns.OPERATION] [maxOrNull][maxOrNull]} */ +@ExcludeFromSources +private typealias SetMaxOrNullOperationArg = Nothing + +// endregion + // region DataColumn +/** + * Returns the maximum of the values in this [DataColumn]. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [maxOrNull][DataColumn.maxOrNull] — returns `null` instead of throwing for an empty column. + * - [maxOf][DataColumn.maxOf] — the maximum of the values a selector returns for each element. + * - [maxBy][DataColumn.maxBy] — the element for which a selector returns the maximum value. + * - [min][DataColumn.min] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The largest age in the "age" column + * df.age.max() + * // The largest weight in the "weight" column, ignoring `null` values + * df.weight.max() + * ``` + * + * @include [MaxDocs.SkipNaNParam] + * @return The largest value in this column. + * @throws NoSuchElementException if there are no values to compare. + */ public fun > DataColumn.max(skipNaN: Boolean = skipNaNDefault): T = maxOrNull(skipNaN).suggestIfNull("max") +/** + * Returns the maximum of the values in this [DataColumn], or `null` if there is nothing to compare. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * See also: + * - [max][DataColumn.max] — throws instead of returning `null` for an empty column. + * - [maxOfOrNull][DataColumn.maxOfOrNull] — the maximum of the values a selector returns + * for each element. + * - [maxByOrNull][DataColumn.maxByOrNull] — the element for which a selector returns + * the maximum value. + * - [minOrNull][DataColumn.minOrNull] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The largest weight in the "weight" column, + * // or `null` if the column contains no values other than `null` + * df.weight.maxOrNull() + * ``` + * + * @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? = Aggregators.max(skipNaN).aggregateSingleColumn(this) +/** + * Returns the first element of this [DataColumn] for which the given [selector] + * returns the maximum value. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [maxByOrNull][DataColumn.maxByOrNull] — returns `null` instead of throwing for an empty column. + * - [maxOf][DataColumn.maxOf] — returns the maximum [selector] value itself + * instead of the element it belongs to. + * - [minBy][DataColumn.minBy] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // The longest first name in the "name"/"firstName" column + * df.name.firstName.maxBy { it.length } + * ``` + * + * @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. + */ public inline fun ?> DataColumn.maxBy( skipNaN: Boolean = skipNaNDefault, crossinline selector: (T) -> R, ): T & Any = maxByOrNull(skipNaN, selector).suggestIfNull("maxBy") +/** + * Returns the first element of this [DataColumn] for which the given [selector] + * returns the maximum value, or `null` if there is nothing to compare. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * See also: + * - [maxBy][DataColumn.maxBy] — throws instead of returning `null` for an empty column. + * - [maxOfOrNull][DataColumn.maxOfOrNull] — returns the maximum [selector] value itself + * instead of the element it belongs to. + * - [minByOrNull][DataColumn.minByOrNull] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // The longest first name in the "name"/"firstName" column, + * // or `null` if the column is empty + * df.name.firstName.maxByOrNull { it.length } + * ``` + * + * @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. + */ public inline fun ?> DataColumn.maxByOrNull( skipNaN: Boolean = skipNaNDefault, crossinline selector: (T) -> R, ): T? = Aggregators.max(skipNaN).aggregateByOrNull(this, selector) +/** + * Returns the maximum of the values that the given [selector] returns + * for each element of this [DataColumn]. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [maxOfOrNull][DataColumn.maxOfOrNull] — returns `null` instead of throwing for an empty column. + * - [maxBy][DataColumn.maxBy] — returns the element the maximum [selector] value belongs to + * instead of that value. + * - [minOf][DataColumn.minOf] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The length of the longest first name in the "name"/"firstName" column + * df.name.firstName.maxOf { it.length } + * ``` + * + * @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. + */ public inline fun ?> DataColumn.maxOf( skipNaN: Boolean = skipNaNDefault, crossinline selector: (T) -> R, ): R & Any = maxOfOrNull(skipNaN, selector).suggestIfNull("maxOf") +/** + * Returns the maximum of the values that the given [selector] returns + * for each element of this [DataColumn], or `null` if there is nothing to compare. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * See also: + * - [maxOf][DataColumn.maxOf] — throws instead of returning `null` for an empty column. + * - [maxByOrNull][DataColumn.maxByOrNull] — returns the element the maximum [selector] value + * belongs to instead of that value. + * - [minOfOrNull][DataColumn.minOfOrNull] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The length of the longest first name in the "name"/"firstName" column, + * // or `null` if the column is empty + * df.name.firstName.maxOfOrNull { it.length } + * ``` + * + * @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. + */ public inline fun ?> DataColumn.maxOfOrNull( skipNaN: Boolean = skipNaNDefault, crossinline selector: (T) -> R, @@ -64,20 +308,144 @@ public fun DataRow<*>.rowMaxOrNull(): Nothing? = error(ROW_MAX_OR_NULL) @Deprecated(ROW_MAX, level = DeprecationLevel.ERROR) public fun DataRow<*>.rowMax(): Nothing = error(ROW_MAX) +/** + * Returns the maximum of the values of type [T] in this [DataRow], + * or `null` if there is nothing to compare. + * + * Only the values in the columns of type [T] (or `T?`) are taken into account; + * all other columns of the row are ignored. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * See also: + * - [rowMaxOf][DataRow.rowMaxOf] — throws instead of returning `null` when there's nothing to compare. + * - [rowMinOfOrNull][DataRow.rowMinOfOrNull] — the mirror operation. + * - [maxOrNull][DataFrame.maxOrNull] — the maximum of the values in specific columns of a [DataFrame]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.RowStatistics]} + * + * ### Example + * ```kotlin + * // The largest of all `Int` values in the first row + * // (so, in the "age" and "weight" columns), or `null` if there are none + * df[0].rowMaxOfOrNull() + * ``` + * + * @param [T] The type of the values to compare. Only columns of this type are taken into account. + * @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? = Aggregators.max(skipNaN).aggregateOfRow(this) { colsOf() } +/** + * Returns the maximum of the values of type [T] in this [DataRow]. + * + * Only the values in the columns of type [T] (or `T?`) are taken into account; + * all other columns of the row are ignored. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [rowMaxOfOrNull][DataRow.rowMaxOfOrNull] — returns `null` instead of throwing + * when there's nothing to compare. + * - [rowMinOf][DataRow.rowMinOf] — the mirror operation. + * - [max][DataFrame.max] — the maximum of the values in specific columns of a [DataFrame]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.RowStatistics]} + * + * ### Example + * ```kotlin + * // The largest of all `Int` values in the first row + * // (so, in the "age" and "weight" columns) + * df[0].rowMaxOf() + * ``` + * + * @param [T] The type of the values to compare. Only columns of this type are taken into account. + * @include [MaxDocs.SkipNaNParam] + * @return The largest value of type [T] in this row. + * @throws NoSuchElementException if there are no values to compare. + */ public inline fun > DataRow<*>.rowMaxOf(skipNaN: Boolean = skipNaNDefault): T = rowMaxOfOrNull(skipNaN).suggestIfNull("rowMaxOf") // endregion // region DataFrame + +/** + * Returns the maximum of the values of each suitable column of this [DataFrame] separately. + * + * All columns whose values are mutually comparable are taken into account; + * the other columns are simply left out of the result. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [maxFor][DataFrame.maxFor] — the same, but for an explicit selection of columns. + * - [max][DataFrame.max]` { columns }` — a single maximum of all values in the selected columns. + * - [min][DataFrame.min] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // A single row with the largest value of each comparable column + * // ("name"/"firstName", "name"/"lastName", "age", "city", "weight", and "isHappy") + * df.max() + * ``` + * + * @include [MaxDocs.SkipNaNParam] + * @return A single [DataRow] with the maximum of each suitable column of this [DataFrame]. + */ @Refine @Interpretable("Max0") public fun DataFrame.max(skipNaN: Boolean = skipNaNDefault): DataRow = maxFor(skipNaN, intraComparableColumns()) +/** + * Returns the maximum of the values of each selected column of this [DataFrame] separately. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [MaxDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxForSelectingOptions]. + * + * See also: + * - [max][DataFrame.max]`()` — the same, but for all suitable columns at once. + * - [max][DataFrame.max]` { columns }` — a single maximum of all values in the selected columns. + * - [minFor][DataFrame.minFor] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // A single row with the largest "age" and the largest "weight" + * df.maxFor { age and weight } + * // The same, ignoring `NaN` values, and naming the results explicitly + * df.maxFor(skipNaN = true) { age into "maxAge" and (weight into "maxWeight") } + * ``` + * + * @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. + */ @Refine @Interpretable("Max1") public fun ?> DataFrame.maxFor( @@ -85,6 +453,35 @@ public fun ?> DataFrame.maxFor( columns: ColumnsForAggregateSelector, ): DataRow = Aggregators.max.invoke(skipNaN).aggregateFor(this, columns) +/** + * Returns the maximum of the values of each selected column of this [DataFrame] separately. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxForSelectingOptions]. + * + * See also: + * - [max][DataFrame.max]`()` — the same, but for all suitable columns at once. + * - [max][DataFrame.max]` { columns }` — a single maximum of all values in the selected columns. + * - [minFor][DataFrame.minFor] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // A single row with the largest "age" and the largest "weight" + * df.maxFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns of this [DataFrame] to compute the maximum of. + * @include [MaxDocs.SkipNaNParam] + * @return A single [DataRow] with the maximum of each selected column. + */ public fun DataFrame.maxFor(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataRow = maxFor(skipNaN) { columns.toComparableColumns() } @@ -102,11 +499,76 @@ public fun ?> DataFrame.maxFor( skipNaN: Boolean = skipNaNDefault, ): DataRow = maxFor(skipNaN) { columns.toColumnSet() } +/** + * Returns a single maximum of all the values in the selected columns of this [DataFrame]. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [maxOrNull][DataFrame.maxOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [maxFor][DataFrame.maxFor] — the maximum of each selected column separately. + * - [maxOf][DataFrame.maxOf] — the maximum of the values a row expression returns for each row. + * - [min][DataFrame.min] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * @include [SelectingColumns.ColumnsSelectionDsl.ColumnsSelectionDslWithExample] {@include [SetMaxOperationArg]} + * + * ### Example + * ```kotlin + * // The largest of all values in the "age" and "weight" columns + * df.max { age and weight } + * ``` + * + * @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. + * @throws NoSuchElementException if there are no values to compare. + */ public fun ?> DataFrame.max( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): C & Any = maxOrNull(skipNaN, columns).suggestIfNull("max") +/** + * Returns a single maximum of all the values in the selected columns of this [DataFrame]. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [maxOrNull][DataFrame.maxOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [maxFor][DataFrame.maxFor] — the maximum of each selected column separately. + * - [maxOf][DataFrame.maxOf] — the maximum of the values a row expression returns for each row. + * - [min][DataFrame.min] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * @include [SelectingColumns.ColumnNamesApi.ColumnNamesApiWithExample] {@include [SetMaxOperationArg]} + * + * ### Example + * ```kotlin + * // The largest of all values in the "age" and "weight" columns + * df.max("age", "weight") + * ``` + * + * @param [columns] The names of the columns of this [DataFrame] to compute the maximum of. + * @include [MaxDocs.SkipNaNParam] + * @return The largest value among all the values in the selected columns. + * @throws NoSuchElementException if there are no values to compare. + */ public fun DataFrame.max(vararg columns: String, skipNaN: Boolean = skipNaNDefault): Comparable = maxOrNull(*columns, skipNaN = skipNaN).suggestIfNull("max") @@ -124,11 +586,80 @@ public fun ?> DataFrame.max( skipNaN: Boolean = skipNaNDefault, ): C & Any = maxOrNull(*columns, skipNaN = skipNaN).suggestIfNull("max") +/** + * Returns a single maximum of all the values in the selected columns of this [DataFrame], + * or `null` if there is nothing to compare. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [max][DataFrame.max] — throws instead of returning `null` when there's nothing to compare. + * - [maxFor][DataFrame.maxFor] — the maximum of each selected column separately. + * - [maxOfOrNull][DataFrame.maxOfOrNull] — the maximum of the values a row expression + * returns for each row. + * - [minOrNull][DataFrame.minOrNull] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * @include [SelectingColumns.ColumnsSelectionDsl.ColumnsSelectionDslWithExample] {@include [SetMaxOrNullOperationArg]} + * + * ### Example + * ```kotlin + * // The largest of all values in the "age" and "weight" columns, + * // or `null` if there are no values to compare + * df.maxOrNull { age and weight } + * ``` + * + * @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, + * or `null` if there are no values to compare. + */ public fun ?> DataFrame.maxOrNull( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): C? = Aggregators.max(skipNaN).aggregateAll(this, columns) +/** + * Returns a single maximum of all the values in the selected columns of this [DataFrame], + * or `null` if there is nothing to compare. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [max][DataFrame.max] — throws instead of returning `null` when there's nothing to compare. + * - [maxFor][DataFrame.maxFor] — the maximum of each selected column separately. + * - [maxOfOrNull][DataFrame.maxOfOrNull] — the maximum of the values a row expression + * returns for each row. + * - [minOrNull][DataFrame.minOrNull] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * @include [SelectingColumns.ColumnNamesApi.ColumnNamesApiWithExample] {@include [SetMaxOrNullOperationArg]} + * + * ### Example + * ```kotlin + * // The largest of all values in the "age" and "weight" columns, + * // or `null` if there are no values to compare + * df.maxOrNull("age", "weight") + * ``` + * + * @param [columns] The names of the columns of this [DataFrame] to compute the maximum of. + * @include [MaxDocs.SkipNaNParam] + * @return The largest value among all the values in the selected columns, + * or `null` if there are no values to compare. + */ public fun DataFrame.maxOrNull(vararg columns: String, skipNaN: Boolean = skipNaNDefault): Comparable? = maxOrNull(skipNaN) { columns.toComparableColumns() } @@ -146,21 +677,148 @@ public fun ?> DataFrame.maxOrNull( skipNaN: Boolean = skipNaNDefault, ): C? = maxOrNull(skipNaN) { columns.toColumnSet() } +/** + * Returns the maximum of the values that the given [expression] returns + * for each row of this [DataFrame]. + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [maxOfOrNull][DataFrame.maxOfOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [maxBy][DataFrame.maxBy] — returns the row the maximum [expression] value belongs to + * instead of that value. + * - [max][DataFrame.max] — a single maximum of all values in the selected columns. + * - [minOf][DataFrame.minOf] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The largest weight-to-age ratio of all rows + * df.maxOf { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> DataFrame.maxOf( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, ): C & Any = maxOfOrNull(skipNaN, expression).suggestIfNull("maxOf") +/** + * Returns the maximum of the values that the given [expression] returns + * for each row of this [DataFrame], or `null` if there is nothing to compare. + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * See also: + * - [maxOf][DataFrame.maxOf] — throws instead of returning `null` when there's nothing to compare. + * - [maxByOrNull][DataFrame.maxByOrNull] — returns the row the maximum [expression] value + * belongs to instead of that value. + * - [maxOrNull][DataFrame.maxOrNull] — a single maximum of all values in the selected columns. + * - [minOfOrNull][DataFrame.minOfOrNull] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The largest weight-to-age ratio of all rows, + * // or `null` if this dataframe is empty + * df.maxOfOrNull { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> DataFrame.maxOfOrNull( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, ): C? = Aggregators.max(skipNaN).aggregateOf(this, expression) +/** + * Returns the first row of this [DataFrame] for which the given [expression] + * returns the maximum value. + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [maxByOrNull][DataFrame.maxByOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [maxOf][DataFrame.maxOf] — returns the maximum [expression] value itself + * instead of the row it belongs to. + * - [minBy][DataFrame.minBy] — the mirror operation. + * - [sortByDesc][DataFrame.sortByDesc] — orders all rows instead of taking just the largest one. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // The row with the largest "age" + * df.maxBy { age } + * // The row with the largest weight-to-age ratio + * df.maxBy { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> DataFrame.maxBy( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, ): DataRow = maxByOrNull(skipNaN, expression).suggestIfNull("maxBy") +/** + * Returns the first row of this [DataFrame] that has the largest value + * in the column with the given name. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [maxByOrNull][DataFrame.maxByOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [max][DataFrame.max] — returns the largest value itself instead of the row it belongs to. + * - [minBy][DataFrame.minBy] — the mirror operation. + * - [sortByDesc][DataFrame.sortByDesc] — orders all rows instead of taking just the largest one. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // The row with the largest "age" + * df.maxBy("age") + * ``` + * + * @param [column] The name of the column of this [DataFrame] to compare the rows by. + * @include [MaxDocs.SkipNaNParam] + * @return The first [DataRow] with the largest value in the given column. + * @throws NoSuchElementException if there are no values to compare. + */ public fun DataFrame.maxBy(column: String, skipNaN: Boolean = skipNaNDefault): DataRow = maxByOrNull(column, skipNaN).suggestIfNull("maxBy") @@ -178,11 +836,69 @@ public inline fun ?> DataFrame.maxBy( skipNaN: Boolean = skipNaNDefault, ): DataRow = maxByOrNull(column, skipNaN).suggestIfNull("maxBy") +/** + * Returns the first row of this [DataFrame] for which the given [expression] returns + * the maximum value, or `null` if there is nothing to compare. + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * See also: + * - [maxBy][DataFrame.maxBy] — throws instead of returning `null` when there's nothing to compare. + * - [maxOfOrNull][DataFrame.maxOfOrNull] — returns the maximum [expression] value itself + * instead of the row it belongs to. + * - [minByOrNull][DataFrame.minByOrNull] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // The row with the largest "age", or `null` if this dataframe is empty + * df.maxByOrNull { age } + * ``` + * + * @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. + */ public inline fun ?> DataFrame.maxByOrNull( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, ): DataRow? = Aggregators.max(skipNaN).aggregateByOrNull(this, expression) +/** + * Returns the first row of this [DataFrame] that has the largest value in the column with + * the given name, or `null` if there is nothing to compare. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullOnEmptySnippet]} + * + * See also: + * - [maxBy][DataFrame.maxBy] — throws instead of returning `null` when there's nothing to compare. + * - [maxOrNull][DataFrame.maxOrNull] — returns the largest value itself instead of + * the row it belongs to. + * - [minByOrNull][DataFrame.minByOrNull] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // The row with the largest "age", or `null` if this dataframe is empty + * df.maxByOrNull("age") + * ``` + * + * @param [column] The name of the column of this [DataFrame] to compare the rows by. + * @include [MaxDocs.SkipNaNParam] + * @return The first [DataRow] with the largest value in the given column, + * or `null` if there are no values to compare. + */ public fun DataFrame.maxByOrNull(column: String, skipNaN: Boolean = skipNaNDefault): DataRow? = maxByOrNull(column.toColumnOf?>(), skipNaN) @@ -204,11 +920,81 @@ public inline fun ?> DataFrame.maxByOrNull // region GroupBy +/** + * Aggregates this [GroupBy] by computing the maximum 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 maximum for each suitable column. + * All columns whose values are mutually comparable are taken into account; + * the other columns are simply left out of the result. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [maxFor][Grouped.maxFor] — the same, but for an explicit selection of columns. + * - [max][Grouped.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [min][Grouped.min] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest value of each comparable column + * df.groupBy { city }.max() + * ``` + * + * @include [MaxDocs.SkipNaNParam] + * @return A new [DataFrame] with the group keys and the maximum of each suitable column per group. + */ @Refine @Interpretable("GroupByMax1") public fun Grouped.max(skipNaN: Boolean = skipNaNDefault): DataFrame = maxFor(skipNaN, intraComparableColumns()) +/** + * Aggregates this [GroupBy] by computing the maximum 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 maximum for each selected column. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [MaxDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxForSelectingOptions]. + * + * See also: + * - [max][Grouped.max]`()` — the same, but for all suitable columns at once. + * - [max][Grouped.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [minFor][Grouped.minFor] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest "age" and the largest "weight" + * df.groupBy { city }.maxFor { age and weight } + * ``` + * + * @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. + */ @Refine @Interpretable("GroupByMax0") public fun ?> Grouped.maxFor( @@ -216,6 +1002,41 @@ public fun ?> Grouped.maxFor( columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.max.invoke(skipNaN).aggregateFor(this, columns) +/** + * Aggregates this [GroupBy] by computing the maximum 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 maximum for each selected column. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxForSelectingOptions]. + * + * See also: + * - [max][Grouped.max]`()` — the same, but for all suitable columns at once. + * - [max][Grouped.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [minFor][Grouped.minFor] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest "age" and the largest "weight" + * df.groupBy { city }.maxFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the maximum of. + * @include [MaxDocs.SkipNaNParam] + * @return A new [DataFrame] with the group keys and the maximum of each selected column per group. + */ public fun Grouped.maxFor(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataFrame = maxFor(skipNaN) { columns.toComparableColumns() } @@ -233,6 +1054,47 @@ public fun ?> Grouped.maxFor( skipNaN: Boolean = skipNaNDefault, ): DataFrame = maxFor(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [GroupBy] by computing a single maximum 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 maximum per group. + * That column is named [name], or, if [name] is `null`, after the selected column + * if exactly one column is selected, and `"max"` otherwise. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxSelectingOptions]. + * + * See also: + * - [maxFor][Grouped.maxFor] — the maximum of each selected column separately, per group. + * - [maxOf][Grouped.maxOf] — the maximum of the values a row expression returns + * for each row of a group. + * - [min][Grouped.min] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest of all values in the "age" and "weight" columns, + * // in a column called "maxValue" + * df.groupBy { city }.max("maxValue") { 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 `"max"` otherwise. + * @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. + */ @Refine @Interpretable("GroupByMax2") public fun ?> Grouped.max( @@ -241,6 +1103,47 @@ public fun ?> Grouped.max( columns: ColumnsSelector, ): DataFrame = Aggregators.max(skipNaN).aggregateAll(this, name, columns) +/** + * Aggregates this [GroupBy] by computing a single maximum 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 maximum per group. + * That column is named [name], or, if [name] is `null`, after the selected column + * if exactly one column is selected, and `"max"` otherwise. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxSelectingOptions]. + * + * See also: + * - [maxFor][Grouped.maxFor] — the maximum of each selected column separately, per group. + * - [maxOf][Grouped.maxOf] — the maximum of the values a row expression returns + * for each row of a group. + * - [min][Grouped.min] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest of all values in the "age" and "weight" columns, + * // in a column called "maxValue" + * df.groupBy { city }.max("age", "weight", name = "maxValue") + * ``` + * + * @param [columns] The names of the columns to compute the maximum 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 `"max"` otherwise. + * @include [MaxDocs.SkipNaNParam] + * @return A new [DataFrame] with the group keys and a single maximum per group. + */ public fun Grouped.max( vararg columns: String, name: String? = null, @@ -263,6 +1166,40 @@ public fun ?> Grouped.max( skipNaN: Boolean = skipNaNDefault, ): DataFrame = max(name, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [GroupBy] by computing the maximum 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 maximum per group, named [name] (or `"max"` if [name] is `null`). + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [max][Grouped.max] — a single maximum of all values in the selected columns, per group. + * - [maxBy][GroupBy.maxBy] — the row of each group for which the expression returns + * the maximum value. + * - [minOf][Grouped.minOf] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest weight-to-age ratio, in a column called "maxRatio" + * df.groupBy { city }.maxOf("maxRatio") { (weight ?: 0) / age } + * ``` + * + * @param [name] The name of the resulting column. If `null` (the default), `"max"` is used. + * @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. + */ @Refine @Interpretable("GroupByMaxOf") public inline fun ?> Grouped.maxOf( @@ -271,6 +1208,36 @@ public inline fun ?> Grouped.maxOf( crossinline expression: RowExpression, ): DataFrame = Aggregators.max(skipNaN).aggregateOf(this, name, expression) +/** + * Reduces each group of this [GroupBy] to the first row for which the given [rowExpression] + * returns the maximum value. + * + * {@include [MaxDocs.ReducedGroupBySnippet]} + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * See also: + * - [maxOf][Grouped.maxOf] — the maximum value itself instead of the row it belongs to. + * - [minBy][GroupBy.minBy] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // For each city, the full row of the person with the largest "age" + * df.groupBy { city }.maxBy { age }.concat() + * ``` + * + * @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. + */ @Interpretable("GroupByReduceExpression") public inline fun ?> GroupBy.maxBy( skipNaN: Boolean = skipNaNDefault, @@ -284,6 +1251,34 @@ public inline fun ?> GroupBy.maxBy( skipNaN: Boolean = skipNaNDefault, ): ReducedGroupBy = reduce { maxByOrNull(column, skipNaN) } +/** + * Reduces each group of this [GroupBy] to the first row that has the largest value + * in the column with the given name. + * + * {@include [MaxDocs.ReducedGroupBySnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * See also: + * - [max][Grouped.max] — the maximum value itself instead of the row it belongs to. + * - [minBy][GroupBy.minBy] — the mirror operation. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // For each city, the full row of the person with the largest "age" + * df.groupBy { city }.maxBy("age").concat() + * ``` + * + * @param [column] The name of the column to compare the rows by. + * @include [MaxDocs.SkipNaNParam] + * @return A [ReducedGroupBy] with, for each group, the first row + * that has the largest value in the given column. + */ public fun GroupBy.maxBy(column: String, skipNaN: Boolean = skipNaNDefault): ReducedGroupBy = maxBy(column.toColumnAccessor().cast?>(), skipNaN) @@ -298,15 +1293,125 @@ public inline fun ?> GroupBy.maxBy( // region Pivot +/** + * Aggregates this [Pivot] by computing the maximum of the values of + * each suitable column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the maximum + * of each suitable column of the corresponding group. + * All columns whose values are mutually comparable are taken into account; + * the other columns are simply left out of the result. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [maxFor][Pivot.maxFor] — the same, but for an explicit selection of columns. + * - [max][Pivot.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [min][Pivot.min] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest value of each comparable column + * df.pivot { city }.max() + * ``` + * + * @include [MaxDocs.SeparateParam] + * @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 = delegate { max(separate, skipNaN) } +/** + * Aggregates this [Pivot] by computing the maximum of the values of + * each selected column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the maximum + * of each selected column of the corresponding group. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [MaxDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxForSelectingOptions]. + * + * See also: + * - [max][Pivot.max]`()` — the same, but for all suitable columns at once. + * - [max][Pivot.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [minFor][Pivot.minFor] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest "age" and the largest "weight" + * df.pivot { city }.maxFor { age and weight } + * // The same, but with the results grouped by aggregated column instead of by city + * df.pivot { city }.maxFor(separate = true) { age and weight } + * ``` + * + * @include [MaxDocs.SeparateParam] + * @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. + */ public fun ?> Pivot.maxFor( separate: Boolean = false, skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, ): DataRow = delegate { maxFor(separate, skipNaN, columns) } +/** + * Aggregates this [Pivot] by computing the maximum of the values of + * each selected column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the maximum + * of each selected column of the corresponding group. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxForSelectingOptions]. + * + * See also: + * - [max][Pivot.max]`()` — the same, but for all suitable columns at once. + * - [max][Pivot.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [minFor][Pivot.minFor] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest "age" and the largest "weight" + * df.pivot { city }.maxFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the maximum of. + * @include [MaxDocs.SeparateParam] + * @include [MaxDocs.SkipNaNParam] + * @return A single [DataRow] with the maximum of each selected column per [pivot] group. + */ public fun Pivot.maxFor( vararg columns: String, separate: Boolean = false, @@ -329,11 +1434,81 @@ public fun ?> Pivot.maxFor( skipNaN: Boolean = skipNaNDefault, ): DataRow = maxFor(separate, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [Pivot] by computing a single maximum of all the values + * in the selected columns, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the largest + * value among all the values in the selected columns of the corresponding group. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxSelectingOptions]. + * + * See also: + * - [max][Pivot.max]`()` — the maximum of each suitable column separately, per group. + * - [maxFor][Pivot.maxFor] — the maximum of each selected column separately, per group. + * - [min][Pivot.min] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest of all values in the "age" and "weight" columns + * df.pivot { city }.max { age and weight } + * ``` + * + * @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. + */ public fun ?> Pivot.max( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): DataRow = delegate { max(skipNaN, columns) } +/** + * Aggregates this [Pivot] by computing a single maximum of all the values + * in the selected columns, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the largest + * value among all the values in the selected columns of the corresponding group. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxSelectingOptions]. + * + * See also: + * - [max][Pivot.max]`()` — the maximum of each suitable column separately, per group. + * - [maxFor][Pivot.maxFor] — the maximum of each selected column separately, per group. + * - [min][Pivot.min] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest of all values in the "age" and "weight" columns + * df.pivot { city }.max("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the maximum of. + * @include [MaxDocs.SkipNaNParam] + * @return A single [DataRow] with, per [pivot] group, the largest value among all the values + * in the selected columns. + */ public fun Pivot.max(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataRow = max(skipNaN) { columns.toComparableColumns() } @@ -351,11 +1526,75 @@ public fun ?> Pivot.max( skipNaN: Boolean = skipNaNDefault, ): DataRow = max(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [Pivot] by computing the maximum of the values that the given [rowExpression] + * returns for each row, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the maximum + * of the expression's results for the rows of the corresponding group. + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [max][Pivot.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [maxBy][Pivot.maxBy] — the first row of each group for which the expression returns + * the maximum value. + * - [minOf][Pivot.minOf] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the largest weight-to-age ratio + * df.pivot { city }.maxOf { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> Pivot.maxOf( skipNaN: Boolean = skipNaNDefault, crossinline rowExpression: RowExpression, ): DataRow = delegate { maxOf(skipNaN, rowExpression) } +/** + * [Reduces][PivotDocs.Reducing] this [Pivot] by taking from each group the first [row][DataRow] + * for which the given [rowExpression] returns the maximum value. + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * {@include [MaxDocs.ReducedPivotSnippet]} + * + * See also: + * - [maxOf][Pivot.maxOf] — the maximum value the expression returns itself, instead of the row. + * - [minBy][Pivot.minBy] — the mirror operation. + * - [Pivot reducing][PivotDocs.Reducing] — all other ways to reduce a [Pivot]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // For each city, the "name" of the person with the largest weight-to-age ratio + * df.pivot { city }.maxBy { (weight ?: 0) / age }.with { name } + * ``` + * + * @include [MaxDocs.SkipNaNParam] + * @param [rowExpression] The [RowExpression] to evaluate for each row. + * @return A [ReducedPivot] holding, per group, the first row with the maximum expression result. + */ public inline fun ?> Pivot.maxBy( skipNaN: Boolean = skipNaNDefault, crossinline rowExpression: RowExpression, @@ -368,6 +1607,35 @@ public inline fun ?> Pivot.maxBy( skipNaN: Boolean = skipNaNDefault, ): ReducedPivot = reduce { maxByOrNull(column, skipNaN) } +/** + * [Reduces][PivotDocs.Reducing] this [Pivot] by taking from each group the first [row][DataRow] + * that has the largest value in the given [column]. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * {@include [MaxDocs.ReducedPivotSnippet]} + * + * See also: + * - [max][Pivot.max]` { columns }` — the maximum value itself, instead of the row. + * - [minBy][Pivot.minBy] — the mirror operation. + * - [Pivot reducing][PivotDocs.Reducing] — all other ways to reduce a [Pivot]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // For each city, the "name" of the oldest person + * df.pivot { city }.maxBy("age").with { name } + * ``` + * + * @param [column] The name of the column to compare the rows by. + * @include [MaxDocs.SkipNaNParam] + * @return A [ReducedPivot] holding, per group, the first row with the largest value + * in the given column. + */ public fun Pivot.maxBy(column: String, skipNaN: Boolean = skipNaNDefault): ReducedPivot = maxBy(column.toColumnAccessor().cast?>(), skipNaN) @@ -382,15 +1650,126 @@ public inline fun ?> Pivot.maxBy( // region PivotGroupBy +/** + * Aggregates this [PivotGroupBy] by computing the maximum of the values of + * each suitable column separately, per group. + * + * Returns a [DataFrame] where each cell contains the maximum of each suitable column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * All columns whose values are mutually comparable are taken into account; + * the other columns are simply left out of the result. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [maxFor][PivotGroupBy.maxFor] — the same, but for an explicit selection of columns. + * - [max][PivotGroupBy.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [min][PivotGroupBy.min] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the largest value of each comparable column + * df.pivot { city }.groupBy { name.lastName }.max() + * ``` + * + * @include [MaxDocs.SeparateParam] + * @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 = maxFor(separate, skipNaN, intraComparableColumns()) +/** + * Aggregates this [PivotGroupBy] by computing the maximum of the values of + * each selected column separately, per group. + * + * Returns a [DataFrame] where each cell contains the maximum of each selected column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [MaxDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxForSelectingOptions]. + * + * See also: + * - [max][PivotGroupBy.max]`()` — the same, but for all suitable columns at once. + * - [max][PivotGroupBy.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [minFor][PivotGroupBy.minFor] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the largest "age" and the largest "weight" + * df.pivot { city }.groupBy { name.lastName }.maxFor { age and weight } + * ``` + * + * @include [MaxDocs.SeparateParam] + * @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. + */ public fun ?> PivotGroupBy.maxFor( separate: Boolean = false, skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.max.invoke(skipNaN).aggregateFor(this, separate, columns) +/** + * Aggregates this [PivotGroupBy] by computing the maximum of the values of + * each selected column separately, per group. + * + * Returns a [DataFrame] where each cell contains the maximum of each selected column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxForSelectingOptions]. + * + * See also: + * - [max][PivotGroupBy.max]`()` — the same, but for all suitable columns at once. + * - [max][PivotGroupBy.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [minFor][PivotGroupBy.minFor] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the largest "age" and the largest "weight" + * df.pivot { city }.groupBy { name.lastName }.maxFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the maximum of. + * @include [MaxDocs.SeparateParam] + * @include [MaxDocs.SkipNaNParam] + * @return A [DataFrame] with the maximum of each selected column per group. + */ public fun PivotGroupBy.maxFor( vararg columns: String, separate: Boolean = false, @@ -413,14 +1792,90 @@ public fun ?> PivotGroupBy.maxFor( skipNaN: Boolean = skipNaNDefault, ): DataFrame = maxFor(separate, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [PivotGroupBy] by computing a single maximum of all the values + * in the selected columns, per group. + * + * Returns a [DataFrame] where each cell contains the largest value among all the values in the + * selected columns of the group corresponding to that [pivot] key (column) + * and [groupBy] key (row). + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxSelectingOptions]. + * + * See also: + * - [max][PivotGroupBy.max]`()` — the maximum of each suitable column separately, per group. + * - [maxFor][PivotGroupBy.maxFor] — the maximum of each selected column separately, per group. + * - [min][PivotGroupBy.min] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the largest of all values in the "age" and "weight" columns + * df.pivot { city }.groupBy { name.lastName }.max { age and weight } + * ``` + * + * @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. + */ public fun ?> PivotGroupBy.max( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): DataFrame = Aggregators.max(skipNaN).aggregateAll(this, columns) +/** + * Aggregates this [PivotGroupBy] by computing a single maximum of all the values + * in the selected columns, per group. + * + * Returns a [DataFrame] where each cell contains the largest value among all the values in the + * selected columns of the group corresponding to that [pivot] key (column) + * and [groupBy] key (row). + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MaxDocs.MaxSelectingOptions]. + * + * See also: + * - [max][PivotGroupBy.max]`()` — the maximum of each suitable column separately, per group. + * - [maxFor][PivotGroupBy.maxFor] — the maximum of each selected column separately, per group. + * - [min][PivotGroupBy.min] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the largest of all values in the "age" and "weight" columns + * df.pivot { city }.groupBy { name.lastName }.max("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the maximum of. + * @include [MaxDocs.SkipNaNParam] + * @return A [DataFrame] with, per group, the largest value among all the values + * in the selected columns. + */ public fun PivotGroupBy.max(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataFrame = max(skipNaN) { columns.toComparableColumns() } +@Deprecated(DEPRECATED_ACCESS_API) +@AccessApiOverload public fun ?> PivotGroupBy.max( vararg columns: ColumnReference, skipNaN: Boolean = skipNaNDefault, @@ -433,11 +1888,79 @@ public fun ?> PivotGroupBy.max( skipNaN: Boolean = skipNaNDefault, ): DataFrame = max(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [PivotGroupBy] by computing the maximum of the values that the given + * [rowExpression] returns for each row, per group. + * + * Returns a [DataFrame] where each cell contains the maximum of the expression's results for the + * rows of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * {@include [MaxDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [max][PivotGroupBy.max]` { columns }` — a single maximum of all values in the selected columns, + * per group. + * - [maxBy][PivotGroupBy.maxBy] — the first row of each group for which the expression returns + * the maximum value. + * - [minOf][PivotGroupBy.minOf] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the largest weight-to-age ratio + * df.pivot { city }.groupBy { name.lastName }.maxOf { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> PivotGroupBy.maxOf( skipNaN: Boolean = skipNaNDefault, crossinline rowExpression: RowExpression, ): DataFrame = aggregate { maxOf(skipNaN, rowExpression) } +/** + * [Reduces][PivotGroupByDocs.Reducing] this [PivotGroupBy] by taking from each group + * the first [row][DataRow] for which the given [rowExpression] returns the maximum value. + * + * {@include [MaxDocs.RowExpressionSnippet]} + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * {@include [MaxDocs.ReducedPivotGroupBySnippet]} + * + * See also: + * - [maxOf][PivotGroupBy.maxOf] — the maximum value the expression returns itself, + * instead of the row. + * - [minBy][PivotGroupBy.minBy] — the mirror operation. + * - [PivotGroupBy reducing][PivotGroupByDocs.Reducing] — all other ways to reduce + * a [PivotGroupBy]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // Per city and last name, the "firstName" of the person with the largest weight-to-age ratio + * df.pivot { city }.groupBy { name.lastName }.maxBy { (weight ?: 0) / age }.with { name.firstName } + * ``` + * + * @include [MaxDocs.SkipNaNParam] + * @param [rowExpression] The [RowExpression] to evaluate for each row. + * @return A [ReducedPivotGroupBy] holding, per group, the first row with the maximum + * expression result. + */ public inline fun ?> PivotGroupBy.maxBy( skipNaN: Boolean = skipNaNDefault, crossinline rowExpression: RowExpression, @@ -450,6 +1973,36 @@ public inline fun ?> PivotGroupBy.maxBy( skipNaN: Boolean = skipNaNDefault, ): ReducedPivotGroupBy = reduce { maxByOrNull(column, skipNaN) } +/** + * [Reduces][PivotGroupByDocs.Reducing] this [PivotGroupBy] by taking from each group + * the first [row][DataRow] that has the largest value in the given [column]. + * + * {@include [MaxDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * {@include [MaxDocs.ReducedPivotGroupBySnippet]} + * + * See also: + * - [max][PivotGroupBy.max]` { columns }` — the maximum value itself, instead of the row. + * - [minBy][PivotGroupBy.minBy] — the mirror operation. + * - [PivotGroupBy reducing][PivotGroupByDocs.Reducing] — all other ways to reduce + * a [PivotGroupBy]. + * - {@include [MaxDocsLink]} — an overview of all `max` modes. + * + * For more information: {@include [DocumentationUrls.MaxBy]} + * + * ### Example + * ```kotlin + * // Per city and last name, the "firstName" of the oldest person + * df.pivot { city }.groupBy { name.lastName }.maxBy("age").with { name.firstName } + * ``` + * + * @param [column] The name of the column to compare the rows by. + * @include [MaxDocs.SkipNaNParam] + * @return A [ReducedPivotGroupBy] holding, per group, the first row with the largest value + * in the given column. + */ public fun PivotGroupBy.maxBy(column: String, skipNaN: Boolean = skipNaNDefault): ReducedPivotGroupBy = maxBy(column.toColumnAccessor().cast?>(), skipNaN) 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 eed20c37f8..acaf490fec 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 @@ -11,6 +11,11 @@ import org.jetbrains.kotlinx.dataframe.annotations.Interpretable import org.jetbrains.kotlinx.dataframe.annotations.Refine import org.jetbrains.kotlinx.dataframe.columns.ColumnReference import org.jetbrains.kotlinx.dataframe.columns.toColumnSet +import org.jetbrains.kotlinx.dataframe.documentation.CommonMinMaxDocs +import org.jetbrains.kotlinx.dataframe.documentation.CommonMinMaxDocs.InputValuesSnippet +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.impl.aggregation.aggregators.Aggregators import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll @@ -26,29 +31,268 @@ import org.jetbrains.kotlinx.dataframe.util.ROW_MIN import org.jetbrains.kotlinx.dataframe.util.ROW_MIN_OR_NULL import kotlin.reflect.KProperty +// region docs + +/** + * {@comment + * The Min Operation KDoc-topic; it also holds all common `min` KDoc-snippets. + * Link to it with `{@include [MinDocsLink]}`. + * } + * + * ## The Min Operation + * + * Computes the [minimum](https://en.wikipedia.org/wiki/Maximum_and_minimum) of values. + * + * @include [InputValuesSnippet] + * + * ### Min Modes + * + * Depending on what exactly you want the minimum of, there are several modes. + * They are shown here for [DataFrame], but they exist for the other receivers too: + * + * - [min][DataFrame.min]`()` — the minimum of each suitable column separately. + * - [min][DataFrame.min]` { columns }` — a single minimum of all values in all selected columns. + * - [minFor][DataFrame.minFor]` { columns }` — the minimum of each selected column separately. + * - [minOf][DataFrame.minOf]` { expression }` — the minimum of the values that the given expression + * returns for each row. + * - [minBy][DataFrame.minBy]` { expression }` — the first row for which the given expression returns + * the minimum value. + * + * [min][DataFrame.min], [minOf][DataFrame.minOf], and [minBy][DataFrame.minBy] all have an `-OrNull` + * counterpart which returns `null` instead of throwing an exception when there's nothing to compare. + * + * Mirror operation: [max][DataFrame.max]. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * See all summary statistics: {@include [DocumentationUrls.Statistics]} + */ +internal interface MinDocs : CommonMinMaxDocs { + + /** + * {@comment Version of [SelectingColumns] with correctly filled in examples} + * @include [SelectingColumns] {@include [SetMinOperationArg]} + */ + typealias MinSelectingOptions = Nothing + + /** + * {@comment Version of [SelectingColumns] with correctly filled in examples} + * @include [SelectingColumns] {@include [SetMinForOperationArg]} + */ + typealias MinForSelectingOptions = Nothing +} + +/** [The Min Operation][MinDocs] */ +@ExcludeFromSources +private typealias MinDocsLink = Nothing + +/** {@set [SelectingColumns.OPERATION] [min][min]} */ +@ExcludeFromSources +private typealias SetMinOperationArg = Nothing + +/** {@set [SelectingColumns.OPERATION] [minFor][minFor]} */ +@ExcludeFromSources +private typealias SetMinForOperationArg = Nothing + +/** {@set [SelectingColumns.OPERATION] [minOrNull][minOrNull]} */ +@ExcludeFromSources +private typealias SetMinOrNullOperationArg = Nothing + +// endregion + // region DataColumn +/** + * Returns the minimum of the values in this [DataColumn]. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [minOrNull][DataColumn.minOrNull] — returns `null` instead of throwing for an empty column. + * - [minOf][DataColumn.minOf] — the minimum of the values a selector returns for each element. + * - [minBy][DataColumn.minBy] — the element for which a selector returns the minimum value. + * - [max][DataColumn.max] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The smallest age in the "age" column + * df.age.min() + * // The smallest weight in the "weight" column, ignoring `null` values + * df.weight.min() + * ``` + * + * @include [MinDocs.SkipNaNParam] + * @return The smallest value in this column. + * @throws NoSuchElementException if there are no values to compare. + */ public fun > DataColumn.min(skipNaN: Boolean = skipNaNDefault): T = minOrNull(skipNaN).suggestIfNull("min") +/** + * Returns the minimum of the values in this [DataColumn], or `null` if there is nothing to compare. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * See also: + * - [min][DataColumn.min] — throws instead of returning `null` for an empty column. + * - [minOfOrNull][DataColumn.minOfOrNull] — the minimum of the values a selector returns + * for each element. + * - [minByOrNull][DataColumn.minByOrNull] — the element for which a selector returns + * the minimum value. + * - [maxOrNull][DataColumn.maxOrNull] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The smallest weight in the "weight" column, + * // or `null` if the column contains no values other than `null` + * df.weight.minOrNull() + * ``` + * + * @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? = Aggregators.min(skipNaN).aggregateSingleColumn(this) +/** + * Returns the first element of this [DataColumn] for which the given [selector] + * returns the minimum value. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [minByOrNull][DataColumn.minByOrNull] — returns `null` instead of throwing for an empty column. + * - [minOf][DataColumn.minOf] — returns the minimum [selector] value itself + * instead of the element it belongs to. + * - [maxBy][DataColumn.maxBy] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // The shortest first name in the "name"/"firstName" column + * df.name.firstName.minBy { it.length } + * ``` + * + * @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. + */ public inline fun ?> DataColumn.minBy( skipNaN: Boolean = skipNaNDefault, crossinline selector: (T) -> R, ): T & Any = minByOrNull(skipNaN, selector).suggestIfNull("minBy") +/** + * Returns the first element of this [DataColumn] for which the given [selector] + * returns the minimum value, or `null` if there is nothing to compare. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * See also: + * - [minBy][DataColumn.minBy] — throws instead of returning `null` for an empty column. + * - [minOfOrNull][DataColumn.minOfOrNull] — returns the minimum [selector] value itself + * instead of the element it belongs to. + * - [maxByOrNull][DataColumn.maxByOrNull] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // The shortest first name in the "name"/"firstName" column, + * // or `null` if the column is empty + * df.name.firstName.minByOrNull { it.length } + * ``` + * + * @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. + */ public inline fun ?> DataColumn.minByOrNull( skipNaN: Boolean = skipNaNDefault, crossinline selector: (T) -> R, ): T? = Aggregators.min(skipNaN).aggregateByOrNull(this, selector) +/** + * Returns the minimum of the values that the given [selector] returns + * for each element of this [DataColumn]. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [minOfOrNull][DataColumn.minOfOrNull] — returns `null` instead of throwing for an empty column. + * - [minBy][DataColumn.minBy] — returns the element the minimum [selector] value belongs to + * instead of that value. + * - [maxOf][DataColumn.maxOf] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The length of the shortest first name in the "name"/"firstName" column + * df.name.firstName.minOf { it.length } + * ``` + * + * @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. + */ public inline fun ?> DataColumn.minOf( skipNaN: Boolean = skipNaNDefault, crossinline selector: (T) -> R, ): R & Any = minOfOrNull(skipNaN, selector).suggestIfNull("minOf") +/** + * Returns the minimum of the values that the given [selector] returns + * for each element of this [DataColumn], or `null` if there is nothing to compare. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * See also: + * - [minOf][DataColumn.minOf] — throws instead of returning `null` for an empty column. + * - [minByOrNull][DataColumn.minByOrNull] — returns the element the minimum [selector] value + * belongs to instead of that value. + * - [maxOfOrNull][DataColumn.maxOfOrNull] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The length of the shortest first name in the "name"/"firstName" column, + * // or `null` if the column is empty + * df.name.firstName.minOfOrNull { it.length } + * ``` + * + * @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. + */ public inline fun ?> DataColumn.minOfOrNull( skipNaN: Boolean = skipNaNDefault, crossinline selector: (T) -> R, @@ -64,20 +308,144 @@ public fun DataRow<*>.rowMinOrNull(): Nothing? = error(ROW_MIN_OR_NULL) @Deprecated(ROW_MIN, level = DeprecationLevel.ERROR) public fun DataRow<*>.rowMin(): Nothing = error(ROW_MIN) +/** + * Returns the minimum of the values of type [T] in this [DataRow], + * or `null` if there is nothing to compare. + * + * Only the values in the columns of type [T] (or `T?`) are taken into account; + * all other columns of the row are ignored. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * See also: + * - [rowMinOf][DataRow.rowMinOf] — throws instead of returning `null` when there's nothing to compare. + * - [rowMaxOfOrNull][DataRow.rowMaxOfOrNull] — the mirror operation. + * - [minOrNull][DataFrame.minOrNull] — the minimum of the values in specific columns of a [DataFrame]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.RowStatistics]} + * + * ### Example + * ```kotlin + * // The smallest of all `Int` values in the first row + * // (so, in the "age" and "weight" columns), or `null` if there are none + * df[0].rowMinOfOrNull() + * ``` + * + * @param [T] The type of the values to compare. Only columns of this type are taken into account. + * @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? = Aggregators.min(skipNaN).aggregateOfRow(this) { colsOf() } +/** + * Returns the minimum of the values of type [T] in this [DataRow]. + * + * Only the values in the columns of type [T] (or `T?`) are taken into account; + * all other columns of the row are ignored. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [rowMinOfOrNull][DataRow.rowMinOfOrNull] — returns `null` instead of throwing + * when there's nothing to compare. + * - [rowMaxOf][DataRow.rowMaxOf] — the mirror operation. + * - [min][DataFrame.min] — the minimum of the values in specific columns of a [DataFrame]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.RowStatistics]} + * + * ### Example + * ```kotlin + * // The smallest of all `Int` values in the first row + * // (so, in the "age" and "weight" columns) + * df[0].rowMinOf() + * ``` + * + * @param [T] The type of the values to compare. Only columns of this type are taken into account. + * @include [MinDocs.SkipNaNParam] + * @return The smallest value of type [T] in this row. + * @throws NoSuchElementException if there are no values to compare. + */ public inline fun > DataRow<*>.rowMinOf(skipNaN: Boolean = skipNaNDefault): T = rowMinOfOrNull(skipNaN).suggestIfNull("rowMinOf") // endregion // region DataFrame + +/** + * Returns the minimum of the values of each suitable column of this [DataFrame] separately. + * + * All columns whose values are mutually comparable are taken into account; + * the other columns are simply left out of the result. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [minFor][DataFrame.minFor] — the same, but for an explicit selection of columns. + * - [min][DataFrame.min]` { columns }` — a single minimum of all values in the selected columns. + * - [max][DataFrame.max] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // A single row with the smallest value of each comparable column + * // ("name"/"firstName", "name"/"lastName", "age", "city", "weight", and "isHappy") + * df.min() + * ``` + * + * @include [MinDocs.SkipNaNParam] + * @return A single [DataRow] with the minimum of each suitable column of this [DataFrame]. + */ @Refine @Interpretable("Min0") public fun DataFrame.min(skipNaN: Boolean = skipNaNDefault): DataRow = minFor(skipNaN, intraComparableColumns()) +/** + * Returns the minimum of the values of each selected column of this [DataFrame] separately. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [MinDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinForSelectingOptions]. + * + * See also: + * - [min][DataFrame.min]`()` — the same, but for all suitable columns at once. + * - [min][DataFrame.min]` { columns }` — a single minimum of all values in the selected columns. + * - [maxFor][DataFrame.maxFor] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // A single row with the smallest "age" and the smallest "weight" + * df.minFor { age and weight } + * // The same, ignoring `NaN` values, and naming the results explicitly + * df.minFor(skipNaN = true) { age into "minAge" and (weight into "minWeight") } + * ``` + * + * @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. + */ @Refine @Interpretable("Min1") public fun ?> DataFrame.minFor( @@ -85,6 +453,35 @@ public fun ?> DataFrame.minFor( columns: ColumnsForAggregateSelector, ): DataRow = Aggregators.min.invoke(skipNaN).aggregateFor(this, columns) +/** + * Returns the minimum of the values of each selected column of this [DataFrame] separately. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinForSelectingOptions]. + * + * See also: + * - [min][DataFrame.min]`()` — the same, but for all suitable columns at once. + * - [min][DataFrame.min]` { columns }` — a single minimum of all values in the selected columns. + * - [maxFor][DataFrame.maxFor] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // A single row with the smallest "age" and the smallest "weight" + * df.minFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns of this [DataFrame] to compute the minimum of. + * @include [MinDocs.SkipNaNParam] + * @return A single [DataRow] with the minimum of each selected column. + */ public fun DataFrame.minFor(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataRow = minFor(skipNaN) { columns.toComparableColumns() } @@ -102,11 +499,76 @@ public fun ?> DataFrame.minFor( skipNaN: Boolean = skipNaNDefault, ): DataRow = minFor(skipNaN) { columns.toColumnSet() } +/** + * Returns a single minimum of all the values in the selected columns of this [DataFrame]. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [minOrNull][DataFrame.minOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [minFor][DataFrame.minFor] — the minimum of each selected column separately. + * - [minOf][DataFrame.minOf] — the minimum of the values a row expression returns for each row. + * - [max][DataFrame.max] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * @include [SelectingColumns.ColumnsSelectionDsl.ColumnsSelectionDslWithExample] {@include [SetMinOperationArg]} + * + * ### Example + * ```kotlin + * // The smallest of all values in the "age" and "weight" columns + * df.min { age and weight } + * ``` + * + * @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. + * @throws NoSuchElementException if there are no values to compare. + */ public fun ?> DataFrame.min( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): C & Any = minOrNull(skipNaN, columns).suggestIfNull("min") +/** + * Returns a single minimum of all the values in the selected columns of this [DataFrame]. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [minOrNull][DataFrame.minOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [minFor][DataFrame.minFor] — the minimum of each selected column separately. + * - [minOf][DataFrame.minOf] — the minimum of the values a row expression returns for each row. + * - [max][DataFrame.max] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * @include [SelectingColumns.ColumnNamesApi.ColumnNamesApiWithExample] {@include [SetMinOperationArg]} + * + * ### Example + * ```kotlin + * // The smallest of all values in the "age" and "weight" columns + * df.min("age", "weight") + * ``` + * + * @param [columns] The names of the columns of this [DataFrame] to compute the minimum of. + * @include [MinDocs.SkipNaNParam] + * @return The smallest value among all the values in the selected columns. + * @throws NoSuchElementException if there are no values to compare. + */ public fun DataFrame.min(vararg columns: String, skipNaN: Boolean = skipNaNDefault): Comparable = minOrNull(*columns, skipNaN = skipNaN).suggestIfNull("min") @@ -124,11 +586,80 @@ public fun ?> DataFrame.min( skipNaN: Boolean = skipNaNDefault, ): C & Any = minOrNull(*columns, skipNaN = skipNaN).suggestIfNull("min") +/** + * Returns a single minimum of all the values in the selected columns of this [DataFrame], + * or `null` if there is nothing to compare. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [min][DataFrame.min] — throws instead of returning `null` when there's nothing to compare. + * - [minFor][DataFrame.minFor] — the minimum of each selected column separately. + * - [minOfOrNull][DataFrame.minOfOrNull] — the minimum of the values a row expression + * returns for each row. + * - [maxOrNull][DataFrame.maxOrNull] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * @include [SelectingColumns.ColumnsSelectionDsl.ColumnsSelectionDslWithExample] {@include [SetMinOrNullOperationArg]} + * + * ### Example + * ```kotlin + * // The smallest of all values in the "age" and "weight" columns, + * // or `null` if there are no values to compare + * df.minOrNull { age and weight } + * ``` + * + * @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, + * or `null` if there are no values to compare. + */ public fun ?> DataFrame.minOrNull( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): C? = Aggregators.min(skipNaN).aggregateAll(this, columns) +/** + * Returns a single minimum of all the values in the selected columns of this [DataFrame], + * or `null` if there is nothing to compare. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See also: + * - [min][DataFrame.min] — throws instead of returning `null` when there's nothing to compare. + * - [minFor][DataFrame.minFor] — the minimum of each selected column separately. + * - [minOfOrNull][DataFrame.minOfOrNull] — the minimum of the values a row expression + * returns for each row. + * - [maxOrNull][DataFrame.maxOrNull] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * @include [SelectingColumns.ColumnNamesApi.ColumnNamesApiWithExample] {@include [SetMinOrNullOperationArg]} + * + * ### Example + * ```kotlin + * // The smallest of all values in the "age" and "weight" columns, + * // or `null` if there are no values to compare + * df.minOrNull("age", "weight") + * ``` + * + * @param [columns] The names of the columns of this [DataFrame] to compute the minimum of. + * @include [MinDocs.SkipNaNParam] + * @return The smallest value among all the values in the selected columns, + * or `null` if there are no values to compare. + */ public fun DataFrame.minOrNull(vararg columns: String, skipNaN: Boolean = skipNaNDefault): Comparable? = minOrNull(skipNaN) { columns.toComparableColumns() } @@ -146,21 +677,148 @@ public fun ?> DataFrame.minOrNull( skipNaN: Boolean = skipNaNDefault, ): C? = minOrNull(skipNaN) { columns.toColumnSet() } +/** + * Returns the minimum of the values that the given [expression] returns + * for each row of this [DataFrame]. + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [minOfOrNull][DataFrame.minOfOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [minBy][DataFrame.minBy] — returns the row the minimum [expression] value belongs to + * instead of that value. + * - [min][DataFrame.min] — a single minimum of all values in the selected columns. + * - [maxOf][DataFrame.maxOf] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The smallest weight-to-age ratio of all rows + * df.minOf { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> DataFrame.minOf( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, ): C & Any = minOfOrNull(skipNaN, expression).suggestIfNull("minOf") +/** + * Returns the minimum of the values that the given [expression] returns + * for each row of this [DataFrame], or `null` if there is nothing to compare. + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * See also: + * - [minOf][DataFrame.minOf] — throws instead of returning `null` when there's nothing to compare. + * - [minByOrNull][DataFrame.minByOrNull] — returns the row the minimum [expression] value + * belongs to instead of that value. + * - [minOrNull][DataFrame.minOrNull] — a single minimum of all values in the selected columns. + * - [maxOfOrNull][DataFrame.maxOfOrNull] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinMax]} + * + * ### Example + * ```kotlin + * // The smallest weight-to-age ratio of all rows, + * // or `null` if this dataframe is empty + * df.minOfOrNull { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> DataFrame.minOfOrNull( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, ): C? = Aggregators.min(skipNaN).aggregateOf(this, expression) +/** + * Returns the first row of this [DataFrame] for which the given [expression] + * returns the minimum value. + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [minByOrNull][DataFrame.minByOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [minOf][DataFrame.minOf] — returns the minimum [expression] value itself + * instead of the row it belongs to. + * - [maxBy][DataFrame.maxBy] — the mirror operation. + * - [sortBy][DataFrame.sortBy] — orders all rows instead of taking just the smallest one. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // The row with the smallest "age" + * df.minBy { age } + * // The row with the smallest weight-to-age ratio + * df.minBy { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> DataFrame.minBy( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, ): DataRow = minByOrNull(skipNaN, expression).suggestIfNull("minBy") +/** + * Returns the first row of this [DataFrame] that has the smallest value + * in the column with the given name. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.ThrowsOnEmptySnippet]} + * + * See also: + * - [minByOrNull][DataFrame.minByOrNull] — returns `null` instead of throwing when there's + * nothing to compare. + * - [min][DataFrame.min] — returns the smallest value itself instead of the row it belongs to. + * - [maxBy][DataFrame.maxBy] — the mirror operation. + * - [sortBy][DataFrame.sortBy] — orders all rows instead of taking just the smallest one. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // The row with the smallest "age" + * df.minBy("age") + * ``` + * + * @param [column] The name of the column of this [DataFrame] to compare the rows by. + * @include [MinDocs.SkipNaNParam] + * @return The first [DataRow] with the smallest value in the given column. + * @throws NoSuchElementException if there are no values to compare. + */ public fun DataFrame.minBy(column: String, skipNaN: Boolean = skipNaNDefault): DataRow = minByOrNull(column, skipNaN).suggestIfNull("minBy") @@ -178,11 +836,69 @@ public inline fun ?> DataFrame.minBy( skipNaN: Boolean = skipNaNDefault, ): DataRow = minByOrNull(column, skipNaN).suggestIfNull("minBy") +/** + * Returns the first row of this [DataFrame] for which the given [expression] returns + * the minimum value, or `null` if there is nothing to compare. + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * See also: + * - [minBy][DataFrame.minBy] — throws instead of returning `null` when there's nothing to compare. + * - [minOfOrNull][DataFrame.minOfOrNull] — returns the minimum [expression] value itself + * instead of the row it belongs to. + * - [maxByOrNull][DataFrame.maxByOrNull] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // The row with the smallest "age", or `null` if this dataframe is empty + * df.minByOrNull { age } + * ``` + * + * @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. + */ public inline fun ?> DataFrame.minByOrNull( skipNaN: Boolean = skipNaNDefault, crossinline expression: RowExpression, ): DataRow? = Aggregators.min(skipNaN).aggregateByOrNull(this, expression) +/** + * Returns the first row of this [DataFrame] that has the smallest value in the column with + * the given name, or `null` if there is nothing to compare. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullOnEmptySnippet]} + * + * See also: + * - [minBy][DataFrame.minBy] — throws instead of returning `null` when there's nothing to compare. + * - [minOrNull][DataFrame.minOrNull] — returns the smallest value itself instead of + * the row it belongs to. + * - [maxByOrNull][DataFrame.maxByOrNull] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // The row with the smallest "age", or `null` if this dataframe is empty + * df.minByOrNull("age") + * ``` + * + * @param [column] The name of the column of this [DataFrame] to compare the rows by. + * @include [MinDocs.SkipNaNParam] + * @return The first [DataRow] with the smallest value in the given column, + * or `null` if there are no values to compare. + */ public fun DataFrame.minByOrNull(column: String, skipNaN: Boolean = skipNaNDefault): DataRow? = minByOrNull(column.toColumnOf?>(), skipNaN) @@ -204,11 +920,81 @@ public inline fun ?> DataFrame.minByOrNull // region GroupBy +/** + * Aggregates this [GroupBy] by computing the minimum 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 minimum for each suitable column. + * All columns whose values are mutually comparable are taken into account; + * the other columns are simply left out of the result. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [minFor][Grouped.minFor] — the same, but for an explicit selection of columns. + * - [min][Grouped.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [max][Grouped.max] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest value of each comparable column + * df.groupBy { city }.min() + * ``` + * + * @include [MinDocs.SkipNaNParam] + * @return A new [DataFrame] with the group keys and the minimum of each suitable column per group. + */ @Refine @Interpretable("GroupByMin1") public fun Grouped.min(skipNaN: Boolean = skipNaNDefault): DataFrame = minFor(skipNaN, intraComparableColumns()) +/** + * Aggregates this [GroupBy] by computing the minimum 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 minimum for each selected column. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [MinDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinForSelectingOptions]. + * + * See also: + * - [min][Grouped.min]`()` — the same, but for all suitable columns at once. + * - [min][Grouped.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [maxFor][Grouped.maxFor] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest "age" and the smallest "weight" + * df.groupBy { city }.minFor { age and weight } + * ``` + * + * @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. + */ @Refine @Interpretable("GroupByMin0") public fun ?> Grouped.minFor( @@ -216,6 +1002,41 @@ public fun ?> Grouped.minFor( columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.min.invoke(skipNaN).aggregateFor(this, columns) +/** + * Aggregates this [GroupBy] by computing the minimum 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 minimum for each selected column. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinForSelectingOptions]. + * + * See also: + * - [min][Grouped.min]`()` — the same, but for all suitable columns at once. + * - [min][Grouped.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [maxFor][Grouped.maxFor] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest "age" and the smallest "weight" + * df.groupBy { city }.minFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the minimum of. + * @include [MinDocs.SkipNaNParam] + * @return A new [DataFrame] with the group keys and the minimum of each selected column per group. + */ public fun Grouped.minFor(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataFrame = minFor(skipNaN) { columns.toComparableColumns() } @@ -233,6 +1054,47 @@ public fun ?> Grouped.minFor( skipNaN: Boolean = skipNaNDefault, ): DataFrame = minFor(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [GroupBy] by computing a single minimum 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 minimum per group. + * That column is named [name], or, if [name] is `null`, after the selected column + * if exactly one column is selected, and `"min"` otherwise. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinSelectingOptions]. + * + * See also: + * - [minFor][Grouped.minFor] — the minimum of each selected column separately, per group. + * - [minOf][Grouped.minOf] — the minimum of the values a row expression returns + * for each row of a group. + * - [max][Grouped.max] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest of all values in the "age" and "weight" columns, + * // in a column called "minValue" + * df.groupBy { city }.min("minValue") { 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 `"min"` otherwise. + * @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. + */ @Refine @Interpretable("GroupByMin2") public fun ?> Grouped.min( @@ -241,6 +1103,47 @@ public fun ?> Grouped.min( columns: ColumnsSelector, ): DataFrame = Aggregators.min(skipNaN).aggregateAll(this, name, columns) +/** + * Aggregates this [GroupBy] by computing a single minimum 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 minimum per group. + * That column is named [name], or, if [name] is `null`, after the selected column + * if exactly one column is selected, and `"min"` otherwise. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinSelectingOptions]. + * + * See also: + * - [minFor][Grouped.minFor] — the minimum of each selected column separately, per group. + * - [minOf][Grouped.minOf] — the minimum of the values a row expression returns + * for each row of a group. + * - [max][Grouped.max] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest of all values in the "age" and "weight" columns, + * // in a column called "minValue" + * df.groupBy { city }.min("age", "weight", name = "minValue") + * ``` + * + * @param [columns] The names of the columns to compute the minimum 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 `"min"` otherwise. + * @include [MinDocs.SkipNaNParam] + * @return A new [DataFrame] with the group keys and a single minimum per group. + */ public fun Grouped.min( vararg columns: String, name: String? = null, @@ -263,6 +1166,40 @@ public fun ?> Grouped.min( skipNaN: Boolean = skipNaNDefault, ): DataFrame = min(name, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [GroupBy] by computing the minimum 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 minimum per group, named [name] (or `"min"` if [name] is `null`). + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [min][Grouped.min] — a single minimum of all values in the selected columns, per group. + * - [minBy][GroupBy.minBy] — the row of each group for which the expression returns + * the minimum value. + * - [maxOf][Grouped.maxOf] — the mirror operation. + * - [aggregate][Grouped.aggregate] — the general way to aggregate groups. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.GroupByStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest weight-to-age ratio, in a column called "minRatio" + * df.groupBy { city }.minOf("minRatio") { (weight ?: 0) / age } + * ``` + * + * @param [name] The name of the resulting column. If `null` (the default), `"min"` is used. + * @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. + */ @Refine @Interpretable("GroupByMinOf") public inline fun ?> Grouped.minOf( @@ -271,6 +1208,36 @@ public inline fun ?> Grouped.minOf( crossinline expression: RowExpression, ): DataFrame = Aggregators.min(skipNaN).aggregateOf(this, name, expression) +/** + * Reduces each group of this [GroupBy] to the first row for which the given [rowExpression] + * returns the minimum value. + * + * {@include [MinDocs.ReducedGroupBySnippet]} + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * See also: + * - [minOf][Grouped.minOf] — the minimum value itself instead of the row it belongs to. + * - [maxBy][GroupBy.maxBy] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // For each city, the full row of the person with the smallest "age" + * df.groupBy { city }.minBy { age }.concat() + * ``` + * + * @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. + */ @Interpretable("GroupByReduceExpression") public inline fun ?> GroupBy.minBy( skipNaN: Boolean = skipNaNDefault, @@ -284,6 +1251,34 @@ public inline fun ?> GroupBy.minBy( skipNaN: Boolean = skipNaNDefault, ): ReducedGroupBy = reduce { minByOrNull(column, skipNaN) } +/** + * Reduces each group of this [GroupBy] to the first row that has the smallest value + * in the column with the given name. + * + * {@include [MinDocs.ReducedGroupBySnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * See also: + * - [min][Grouped.min] — the minimum value itself instead of the row it belongs to. + * - [maxBy][GroupBy.maxBy] — the mirror operation. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // For each city, the full row of the person with the smallest "age" + * df.groupBy { city }.minBy("age").concat() + * ``` + * + * @param [column] The name of the column to compare the rows by. + * @include [MinDocs.SkipNaNParam] + * @return A [ReducedGroupBy] with, for each group, the first row + * that has the smallest value in the given column. + */ public fun GroupBy.minBy(column: String, skipNaN: Boolean = skipNaNDefault): ReducedGroupBy = minBy(column.toColumnAccessor().cast?>(), skipNaN) @@ -298,15 +1293,125 @@ public inline fun ?> GroupBy.minBy( // region Pivot +/** + * Aggregates this [Pivot] by computing the minimum of the values of + * each suitable column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the minimum + * of each suitable column of the corresponding group. + * All columns whose values are mutually comparable are taken into account; + * the other columns are simply left out of the result. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [minFor][Pivot.minFor] — the same, but for an explicit selection of columns. + * - [min][Pivot.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [max][Pivot.max] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest value of each comparable column + * df.pivot { city }.min() + * ``` + * + * @include [MinDocs.SeparateParam] + * @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 = delegate { min(separate, skipNaN) } +/** + * Aggregates this [Pivot] by computing the minimum of the values of + * each selected column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the minimum + * of each selected column of the corresponding group. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [MinDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinForSelectingOptions]. + * + * See also: + * - [min][Pivot.min]`()` — the same, but for all suitable columns at once. + * - [min][Pivot.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [maxFor][Pivot.maxFor] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest "age" and the smallest "weight" + * df.pivot { city }.minFor { age and weight } + * // The same, but with the results grouped by aggregated column instead of by city + * df.pivot { city }.minFor(separate = true) { age and weight } + * ``` + * + * @include [MinDocs.SeparateParam] + * @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. + */ public fun ?> Pivot.minFor( separate: Boolean = false, skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, ): DataRow = delegate { minFor(separate, skipNaN, columns) } +/** + * Aggregates this [Pivot] by computing the minimum of the values of + * each selected column separately, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the minimum + * of each selected column of the corresponding group. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinForSelectingOptions]. + * + * See also: + * - [min][Pivot.min]`()` — the same, but for all suitable columns at once. + * - [min][Pivot.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [maxFor][Pivot.maxFor] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest "age" and the smallest "weight" + * df.pivot { city }.minFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the minimum of. + * @include [MinDocs.SeparateParam] + * @include [MinDocs.SkipNaNParam] + * @return A single [DataRow] with the minimum of each selected column per [pivot] group. + */ public fun Pivot.minFor( vararg columns: String, separate: Boolean = false, @@ -329,11 +1434,81 @@ public fun ?> Pivot.minFor( skipNaN: Boolean = skipNaNDefault, ): DataRow = minFor(separate, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [Pivot] by computing a single minimum of all the values + * in the selected columns, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the smallest + * value among all the values in the selected columns of the corresponding group. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinSelectingOptions]. + * + * See also: + * - [min][Pivot.min]`()` — the minimum of each suitable column separately, per group. + * - [minFor][Pivot.minFor] — the minimum of each selected column separately, per group. + * - [max][Pivot.max] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest of all values in the "age" and "weight" columns + * df.pivot { city }.min { age and weight } + * ``` + * + * @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. + */ public fun ?> Pivot.min( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): DataRow = delegate { min(skipNaN, columns) } +/** + * Aggregates this [Pivot] by computing a single minimum of all the values + * in the selected columns, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the smallest + * value among all the values in the selected columns of the corresponding group. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinSelectingOptions]. + * + * See also: + * - [min][Pivot.min]`()` — the minimum of each suitable column separately, per group. + * - [minFor][Pivot.minFor] — the minimum of each selected column separately, per group. + * - [max][Pivot.max] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest of all values in the "age" and "weight" columns + * df.pivot { city }.min("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the minimum of. + * @include [MinDocs.SkipNaNParam] + * @return A single [DataRow] with, per [pivot] group, the smallest value among all the values + * in the selected columns. + */ public fun Pivot.min(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataRow = min(skipNaN) { columns.toComparableColumns() } @@ -351,11 +1526,75 @@ public fun ?> Pivot.min( skipNaN: Boolean = skipNaNDefault, ): DataRow = min(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [Pivot] by computing the minimum of the values that the given [rowExpression] + * returns for each row, per group. + * + * Returns a single [DataRow] with the [pivot] keys as (nested) columns, containing the minimum + * of the expression's results for the rows of the corresponding group. + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [min][Pivot.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [minBy][Pivot.minBy] — the first row of each group for which the expression returns + * the minimum value. + * - [maxOf][Pivot.maxOf] — the mirror operation. + * - [Pivot aggregation][PivotDocs.Aggregation] — all other ways to aggregate a [Pivot]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // For each city, the smallest weight-to-age ratio + * df.pivot { city }.minOf { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> Pivot.minOf( skipNaN: Boolean = skipNaNDefault, crossinline rowExpression: RowExpression, ): DataRow = delegate { minOf(skipNaN, rowExpression) } +/** + * [Reduces][PivotDocs.Reducing] this [Pivot] by taking from each group the first [row][DataRow] + * for which the given [rowExpression] returns the minimum value. + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * {@include [MinDocs.ReducedPivotSnippet]} + * + * See also: + * - [minOf][Pivot.minOf] — the minimum value the expression returns itself, instead of the row. + * - [maxBy][Pivot.maxBy] — the mirror operation. + * - [Pivot reducing][PivotDocs.Reducing] — all other ways to reduce a [Pivot]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // For each city, the "name" of the person with the smallest weight-to-age ratio + * df.pivot { city }.minBy { (weight ?: 0) / age }.with { name } + * ``` + * + * @include [MinDocs.SkipNaNParam] + * @param [rowExpression] The [RowExpression] to evaluate for each row. + * @return A [ReducedPivot] holding, per group, the first row with the minimum expression result. + */ public inline fun ?> Pivot.minBy( skipNaN: Boolean = skipNaNDefault, crossinline rowExpression: RowExpression, @@ -368,6 +1607,35 @@ public inline fun ?> Pivot.minBy( skipNaN: Boolean = skipNaNDefault, ): ReducedPivot = reduce { minByOrNull(column, skipNaN) } +/** + * [Reduces][PivotDocs.Reducing] this [Pivot] by taking from each group the first [row][DataRow] + * that has the smallest value in the given [column]. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * {@include [MinDocs.ReducedPivotSnippet]} + * + * See also: + * - [min][Pivot.min]` { columns }` — the minimum value itself, instead of the row. + * - [maxBy][Pivot.maxBy] — the mirror operation. + * - [Pivot reducing][PivotDocs.Reducing] — all other ways to reduce a [Pivot]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // For each city, the "name" of the youngest person + * df.pivot { city }.minBy("age").with { name } + * ``` + * + * @param [column] The name of the column to compare the rows by. + * @include [MinDocs.SkipNaNParam] + * @return A [ReducedPivot] holding, per group, the first row with the smallest value + * in the given column. + */ public fun Pivot.minBy(column: String, skipNaN: Boolean = skipNaNDefault): ReducedPivot = minBy(column.toColumnAccessor().cast?>(), skipNaN) @@ -382,15 +1650,126 @@ public inline fun ?> Pivot.minBy( // region PivotGroupBy +/** + * Aggregates this [PivotGroupBy] by computing the minimum of the values of + * each suitable column separately, per group. + * + * Returns a [DataFrame] where each cell contains the minimum of each suitable column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * All columns whose values are mutually comparable are taken into account; + * the other columns are simply left out of the result. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [minFor][PivotGroupBy.minFor] — the same, but for an explicit selection of columns. + * - [min][PivotGroupBy.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [max][PivotGroupBy.max] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the smallest value of each comparable column + * df.pivot { city }.groupBy { name.lastName }.min() + * ``` + * + * @include [MinDocs.SeparateParam] + * @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 = minFor(separate, skipNaN, intraComparableColumns()) +/** + * Aggregates this [PivotGroupBy] by computing the minimum of the values of + * each selected column separately, per group. + * + * Returns a [DataFrame] where each cell contains the minimum of each selected column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [MinDocs.AggregateColumnsSelectorSnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinForSelectingOptions]. + * + * See also: + * - [min][PivotGroupBy.min]`()` — the same, but for all suitable columns at once. + * - [min][PivotGroupBy.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [maxFor][PivotGroupBy.maxFor] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the smallest "age" and the smallest "weight" + * df.pivot { city }.groupBy { name.lastName }.minFor { age and weight } + * ``` + * + * @include [MinDocs.SeparateParam] + * @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. + */ public fun ?> PivotGroupBy.minFor( separate: Boolean = false, skipNaN: Boolean = skipNaNDefault, columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.min.invoke(skipNaN).aggregateFor(this, separate, columns) +/** + * Aggregates this [PivotGroupBy] by computing the minimum of the values of + * each selected column separately, per group. + * + * Returns a [DataFrame] where each cell contains the minimum of each selected column + * of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinForSelectingOptions]. + * + * See also: + * - [min][PivotGroupBy.min]`()` — the same, but for all suitable columns at once. + * - [min][PivotGroupBy.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [maxFor][PivotGroupBy.maxFor] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the smallest "age" and the smallest "weight" + * df.pivot { city }.groupBy { name.lastName }.minFor("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the minimum of. + * @include [MinDocs.SeparateParam] + * @include [MinDocs.SkipNaNParam] + * @return A [DataFrame] with the minimum of each selected column per group. + */ public fun PivotGroupBy.minFor( vararg columns: String, separate: Boolean = false, @@ -413,14 +1792,90 @@ public fun ?> PivotGroupBy.minFor( skipNaN: Boolean = skipNaNDefault, ): DataFrame = minFor(separate, skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [PivotGroupBy] by computing a single minimum of all the values + * in the selected columns, per group. + * + * Returns a [DataFrame] where each cell contains the smallest value among all the values in the + * selected columns of the group corresponding to that [pivot] key (column) + * and [groupBy] key (row). + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinSelectingOptions]. + * + * See also: + * - [min][PivotGroupBy.min]`()` — the minimum of each suitable column separately, per group. + * - [minFor][PivotGroupBy.minFor] — the minimum of each selected column separately, per group. + * - [max][PivotGroupBy.max] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the smallest of all values in the "age" and "weight" columns + * df.pivot { city }.groupBy { name.lastName }.min { age and weight } + * ``` + * + * @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. + */ public fun ?> PivotGroupBy.min( skipNaN: Boolean = skipNaNDefault, columns: ColumnsSelector, ): DataFrame = Aggregators.min(skipNaN).aggregateAll(this, columns) +/** + * Aggregates this [PivotGroupBy] by computing a single minimum of all the values + * in the selected columns, per group. + * + * Returns a [DataFrame] where each cell contains the smallest value among all the values in the + * selected columns of the group corresponding to that [pivot] key (column) + * and [groupBy] key (row). + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * {@include [SelectingColumns.ColumnGroupsAndNestedColumnsSnippet]} + * + * See [Selecting Columns][MinDocs.MinSelectingOptions]. + * + * See also: + * - [min][PivotGroupBy.min]`()` — the minimum of each suitable column separately, per group. + * - [minFor][PivotGroupBy.minFor] — the minimum of each selected column separately, per group. + * - [max][PivotGroupBy.max] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the smallest of all values in the "age" and "weight" columns + * df.pivot { city }.groupBy { name.lastName }.min("age", "weight") + * ``` + * + * @param [columns] The names of the columns to compute the minimum of. + * @include [MinDocs.SkipNaNParam] + * @return A [DataFrame] with, per group, the smallest value among all the values + * in the selected columns. + */ public fun PivotGroupBy.min(vararg columns: String, skipNaN: Boolean = skipNaNDefault): DataFrame = min(skipNaN) { columns.toComparableColumns() } +@Deprecated(DEPRECATED_ACCESS_API) +@AccessApiOverload public fun ?> PivotGroupBy.min( vararg columns: ColumnReference, skipNaN: Boolean = skipNaNDefault, @@ -433,11 +1888,79 @@ public fun ?> PivotGroupBy.min( skipNaN: Boolean = skipNaNDefault, ): DataFrame = min(skipNaN) { columns.toColumnSet() } +/** + * Aggregates this [PivotGroupBy] by computing the minimum of the values that the given + * [rowExpression] returns for each row, per group. + * + * Returns a [DataFrame] where each cell contains the minimum of the expression's results for the + * rows of the group corresponding to that [pivot] key (column) and [groupBy] key (row). + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * {@include [MinDocs.NullCellOnEmptySnippet]} + * + * See also: + * - [min][PivotGroupBy.min]` { columns }` — a single minimum of all values in the selected columns, + * per group. + * - [minBy][PivotGroupBy.minBy] — the first row of each group for which the expression returns + * the minimum value. + * - [maxOf][PivotGroupBy.maxOf] — the mirror operation. + * - [PivotGroupBy aggregation][PivotGroupByDocs.Aggregation] — all other ways to aggregate + * a [PivotGroupBy]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.PivotStatistics]} + * + * ### Example + * ```kotlin + * // Per city and last name, the smallest weight-to-age ratio + * df.pivot { city }.groupBy { name.lastName }.minOf { (weight ?: 0) / age } + * ``` + * + * @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. + */ public inline fun ?> PivotGroupBy.minOf( skipNaN: Boolean = skipNaNDefault, crossinline rowExpression: RowExpression, ): DataFrame = aggregate { minOf(skipNaN, rowExpression) } +/** + * [Reduces][PivotGroupByDocs.Reducing] this [PivotGroupBy] by taking from each group + * the first [row][DataRow] for which the given [rowExpression] returns the minimum value. + * + * {@include [MinDocs.RowExpressionSnippet]} + * + * {@include [MinDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * {@include [MinDocs.ReducedPivotGroupBySnippet]} + * + * See also: + * - [minOf][PivotGroupBy.minOf] — the minimum value the expression returns itself, + * instead of the row. + * - [maxBy][PivotGroupBy.maxBy] — the mirror operation. + * - [PivotGroupBy reducing][PivotGroupByDocs.Reducing] — all other ways to reduce + * a [PivotGroupBy]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // Per city and last name, the "firstName" of the person with the smallest weight-to-age ratio + * df.pivot { city }.groupBy { name.lastName }.minBy { (weight ?: 0) / age }.with { name.firstName } + * ``` + * + * @include [MinDocs.SkipNaNParam] + * @param [rowExpression] The [RowExpression] to evaluate for each row. + * @return A [ReducedPivotGroupBy] holding, per group, the first row with the minimum + * expression result. + */ public inline fun ?> PivotGroupBy.minBy( skipNaN: Boolean = skipNaNDefault, crossinline rowExpression: RowExpression, @@ -450,6 +1973,36 @@ public inline fun ?> PivotGroupBy.minBy( skipNaN: Boolean = skipNaNDefault, ): ReducedPivotGroupBy = reduce { minByOrNull(column, skipNaN) } +/** + * [Reduces][PivotGroupByDocs.Reducing] this [PivotGroupBy] by taking from each group + * the first [row][DataRow] that has the smallest value in the given [column]. + * + * {@include [MinDocs.InputValuesSnippet]} + * + * Groups that have no values to compare cannot select a row, and produce `null` values instead. + * + * {@include [MinDocs.ReducedPivotGroupBySnippet]} + * + * See also: + * - [min][PivotGroupBy.min]` { columns }` — the minimum value itself, instead of the row. + * - [maxBy][PivotGroupBy.maxBy] — the mirror operation. + * - [PivotGroupBy reducing][PivotGroupByDocs.Reducing] — all other ways to reduce + * a [PivotGroupBy]. + * - {@include [MinDocsLink]} — an overview of all `min` modes. + * + * For more information: {@include [DocumentationUrls.MinBy]} + * + * ### Example + * ```kotlin + * // Per city and last name, the "firstName" of the youngest person + * df.pivot { city }.groupBy { name.lastName }.minBy("age").with { name.firstName } + * ``` + * + * @param [column] The name of the column to compare the rows by. + * @include [MinDocs.SkipNaNParam] + * @return A [ReducedPivotGroupBy] holding, per group, the first row with the smallest value + * in the given column. + */ public fun PivotGroupBy.minBy(column: String, skipNaN: Boolean = skipNaNDefault): ReducedPivotGroupBy = minBy(column.toColumnAccessor().cast?>(), skipNaN) 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 new file mode 100644 index 0000000000..5d2fdf8a53 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/CommonMinMaxDocs.kt @@ -0,0 +1,150 @@ +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 +import org.jetbrains.kotlinx.dataframe.api.ReducedPivotGroupBy +import org.jetbrains.kotlinx.dataframe.api.concat +import org.jetbrains.kotlinx.dataframe.api.into +import org.jetbrains.kotlinx.dataframe.api.values +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]}`. + * + * NOTE: this cannot be @ExcludedFromSources because `MinDocs` and `MaxDocs` use it as supertype. + * } + */ +internal interface CommonMinMaxDocs { + + /** + * {@comment Note about the self-comparability requirement and how `null` and `NaN` values + * are treated. KDoc-snippet.} + * + * Only self-comparable values are supported: values of a type `T : Comparable` + * 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 [`NaN`][NaN] values, the result will be `NaN`, + * unless `skipNaN` is set to `true`. + */ + @ExcludeFromSources + typealias InputValuesSnippet = Nothing + + /** + * {@comment Note about the behavior on empty input for non-`-OrNull` overloads. KDoc-snippet.} + * + * Throws a [NoSuchElementException] when there is nothing left to compare, + * for instance when the input is empty or contains only `null` + * (or, if `skipNaN` is `true`, only `null` and [`NaN`][NaN]) values. + */ + @ExcludeFromSources + typealias ThrowsOnEmptySnippet = Nothing + + /** + * {@comment Note about the behavior on empty input for `-OrNull` overloads. KDoc-snippet.} + * + * Returns `null` when there is nothing left to compare, + * for instance when the input is empty or contains only `null` + * (or, if `skipNaN` is `true`, only `null` and [`NaN`][NaN]) values. + */ + @ExcludeFromSources + typealias NullOnEmptySnippet = Nothing + + /** + * {@comment Note about the behavior on empty input for the modes with multiple results.} + * + * Result cells for which there is nothing left to compare + * (for instance, because the input was empty or contained only `null` values) + * simply become `null`. + * + * For more information about the resulting types: + * {@include [DocumentationUrls.MinMax.TypeConversion]} + */ + @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.} + * + * This operation does not produce a result right away. + * Instead, it returns a [ReducedGroupBy] — an intermediate step which can be finished with + * [concat][ReducedGroupBy.concat] (to get a [DataFrame] with the selected rows), + * [values][ReducedGroupBy.values], or [into][ReducedGroupBy.into]. + * + * See [GroupBy reducing][GroupByDocs.Reducing] for more details. + */ + @ExcludeFromSources + typealias ReducedGroupBySnippet = Nothing + + /** + * {@comment Note about [ReducedPivot] being an intermediate step. KDoc-snippet.} + * + * This operation does not produce a result right away. + * Instead, it returns a [ReducedPivot] — an intermediate step which can be finished with + * [values][ReducedPivot.values] or [with][ReducedPivot.with]. + */ + @ExcludeFromSources + typealias ReducedPivotSnippet = Nothing + + /** + * {@comment Note about [ReducedPivotGroupBy] being an intermediate step. KDoc-snippet.} + * + * This operation does not produce a result right away. + * Instead, it returns a [ReducedPivotGroupBy] — an intermediate step which can be finished with + * [values][ReducedPivotGroupBy.values] or [with][ReducedPivotGroupBy.with]. + */ + @ExcludeFromSources + typealias ReducedPivotGroupBySnippet = Nothing + + /** + * {@comment The shared `skipNaN` parameter documentation. KDoc-snippet.} + * + * @param [skipNaN\] If `true`, [`NaN`][NaN] values are ignored, just like `null` values. + * If `false` (the default), a [`NaN`][NaN] 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/DocumentationUrls.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/DocumentationUrls.kt index 1078309e8c..c1571d5c9e 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 @@ -203,6 +203,22 @@ public interface DocumentationUrls { /** [See "Summary statistics" on the documentation website.]({@include [Url]}/summarystatistics.html) */ public typealias Statistics = Nothing + /** [See "Row statistics" on the documentation website.]({@include [Url]}/rowstats.html) */ + public typealias RowStatistics = Nothing + + /** [See "min / max" on the documentation website.]({@include [Url]}/minmax.html) */ + public interface MinMax { + + /** [See "min / max Type Conversion" on the documentation website.]({@include [Url]}/minmax.html#type-conversion) */ + public typealias TypeConversion = Nothing + } + + /** [See `maxBy` on the documentation website.]({@include [Url]}/maxby.html) */ + public typealias MaxBy = Nothing + + /** [See `minBy` on the documentation website.]({@include [Url]}/minby.html) */ + public typealias MinBy = Nothing + /** [See `concat` on the documentation website.]({@include [Url]}/concat.html) */ public typealias Concat = Nothing