From d297a79663ea90622254cd1581a814b531e86e78 Mon Sep 17 00:00:00 2001 From: "andrei.kislitsyn" Date: Mon, 20 Jul 2026 16:37:46 +0400 Subject: [PATCH 1/4] Add GroupBy transformation and sort KDocs --- .../jetbrains/kotlinx/dataframe/api/add.kt | 7 +- .../kotlinx/dataframe/api/groupBy.kt | 19 +- .../jetbrains/kotlinx/dataframe/api/sort.kt | 594 +++++++++++++++++- .../documentation/SelectingColumns.kt | 5 + .../dataframe/util/deprecationMessages.kt | 3 + docs/StardustDocs/topics/groupBy.md | 11 +- 6 files changed, 619 insertions(+), 20 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/add.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/add.kt index 6549f06f5c..e588dd8314 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/add.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/add.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlinx.dataframe.annotations.AccessApiOverload import org.jetbrains.kotlinx.dataframe.annotations.HasSchema import org.jetbrains.kotlinx.dataframe.annotations.Interpretable import org.jetbrains.kotlinx.dataframe.annotations.Refine +import org.jetbrains.kotlinx.dataframe.api.GroupByDocs.Grammar import org.jetbrains.kotlinx.dataframe.columns.BaseColumn import org.jetbrains.kotlinx.dataframe.columns.ColumnAccessor import org.jetbrains.kotlinx.dataframe.columns.ColumnPath @@ -429,6 +430,10 @@ public fun DataFrame.add(body: AddDsl.() -> Unit): DataFrame { * Returns a new [GroupBy] with the new column * appended to each group [DataFrame] to the original list of [DataFrame.columns]. * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * * ## Example * * ```kotlin @@ -445,8 +450,6 @@ public fun DataFrame.add(body: AddDsl.() -> Unit): DataFrame { * } * ``` * - * For more information: {@include [DocumentationUrls.Add]}. - * * @param name name for a new column. * If it is empty, a unique column name will be generated. * Otherwise, it should be unique for original group [DataFrame]s. diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt index 6f77aacc94..fa33e49ab4 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt @@ -109,6 +109,8 @@ internal interface GroupByDocs { * {@include [Indent]} * `\[ `__`.`__[**`add`**][GroupBy.add]**`(`**`column: `[`DataColumn`][DataColumn]**`) { `**`rowExpression: `[`RowExpression`][RowExpression]**` } `**`]` * + * See [GroupBy Transformations][Transformation]. + * * ### Reduce [GroupBy] into [DataFrame] * * {@include [Indent]} @@ -138,6 +140,8 @@ internal interface GroupByDocs { * {@include [Indent]} * `| `__`.`__[**`values`**][ReducedGroupBy.values]**` { `**`valueColumns: `[`ColumnsSelector`][ColumnsSelector]**` }`** * + * See [GroupBy Reducing][Reducing]. + * * ### Aggregate [GroupBy] into [DataFrame] * * {@include [Indent]} @@ -164,6 +168,8 @@ internal interface GroupByDocs { * {@include [Indent]} * `| `__`.`__[][AggregationStatistics] * + * See [GroupBy Aggregations][Aggregation]. + * * ### Pivot [GroupBy] into [PivotGroupBy] and reduce / aggregate it * * {@include [Indent]} @@ -240,11 +246,14 @@ internal interface GroupByDocs { * * [sortBy][GroupBy.sortBy] / [sortByDesc][GroupBy.sortByDesc] — sorts the **order of rows within each group** * by one or more column values; * * [updateGroups][GroupBy.updateGroups] — transforms each group into a new one; - * * [filter][GroupBy.filter] — filters group rows by the given predicate (as usual [DataFrame.filter]); + * * [filter][GroupBy.filter] — filters out keys and corresponding groups that + * do not satisfy the given key-group predicate; * * [add][GroupBy.add] — adds a new column to each group. * * Each method returns a new [GroupBy] with updated group order or modified group content. * + * Check out [`GroupBy grammar`][Grammar]. + * * For more information: {@include [DocumentationUrls.GroupByTransformation]} */ typealias Transformation = Nothing @@ -545,6 +554,10 @@ public interface GroupBy : Grouped { * Creates a new [GroupBy] by transforming each group’s [DataFrame] * using the provided [transform] function. * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * * __NOTE:__ This operation removes key-column status from each column in the group. * In other words, each column in the group is treated as a new column, * and not omitted when [`.values()`][Grouped.values] or other aggregations are called. @@ -561,6 +574,10 @@ public interface GroupBy : Grouped { * The [predicate] is a [GroupedRowFilter], which behaves similarly to a [RowFilter] used in [DataFrame.filter], * but also provides access to the [group][GroupedDataRow.group] in the current row. * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * * ### Example * ```kotlin * // Keep only key–group pairs where the "category" key equals "Engineer" diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sort.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sort.kt index bb7e05607c..b9c2ec71c7 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sort.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sort.kt @@ -1,11 +1,13 @@ package org.jetbrains.kotlinx.dataframe.api +import org.jetbrains.kotlinx.dataframe.ColumnsSelector import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataFrameExpression import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.Selector import org.jetbrains.kotlinx.dataframe.annotations.AccessApiOverload +import org.jetbrains.kotlinx.dataframe.api.GroupByDocs.Grammar import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.columns.ColumnReference import org.jetbrains.kotlinx.dataframe.columns.ColumnSet @@ -15,36 +17,130 @@ import org.jetbrains.kotlinx.dataframe.columns.SingleColumn import org.jetbrains.kotlinx.dataframe.columns.UnresolvedColumnsPolicy import org.jetbrains.kotlinx.dataframe.columns.ValueColumn import org.jetbrains.kotlinx.dataframe.columns.toColumnSet +import org.jetbrains.kotlinx.dataframe.documentation.DocumentationUrls +import org.jetbrains.kotlinx.dataframe.documentation.ExcludeFromSources import org.jetbrains.kotlinx.dataframe.documentation.Indent import org.jetbrains.kotlinx.dataframe.documentation.LineBreak +import org.jetbrains.kotlinx.dataframe.documentation.SelectingColumns +import org.jetbrains.kotlinx.dataframe.documentation.SelectingColumns.CSDslLink import org.jetbrains.kotlinx.dataframe.impl.api.SortFlag import org.jetbrains.kotlinx.dataframe.impl.api.addFlag import org.jetbrains.kotlinx.dataframe.impl.api.sortByImpl import org.jetbrains.kotlinx.dataframe.impl.columns.newColumnWithActualType import org.jetbrains.kotlinx.dataframe.impl.columns.toColumnSet import org.jetbrains.kotlinx.dataframe.index +import org.jetbrains.kotlinx.dataframe.name import org.jetbrains.kotlinx.dataframe.nrow import org.jetbrains.kotlinx.dataframe.type import org.jetbrains.kotlinx.dataframe.util.DEPRECATED_ACCESS_API +import org.jetbrains.kotlinx.dataframe.util.DESC_TO_REVERSED import kotlin.reflect.KProperty +/** + * [SortDsl] allows selecting columns to sort rows by (the order in which columns are selected + * determines the sort priority). + * It also allows reversing the sort order for individual columns or column sets, + * and controlling the position of `null` values. + * + * The order in which columns are selected determines the sort priority. + * + * By default, all selected columns are sorted in the original order + * (ascending in [sortBy][DataFrame.sortBy] and descending in [sortByDesc][DataFrame.sortByDesc]). + * Use [\reversed] to impose the reverse ordering for a column or column set. + * + * By default, `null` values are considered the smallest values when sorting. + * Use [nullsLast] to treat them as the largest values. + */ +@ExcludeFromSources +private typealias SortDslSnippet = Nothing + +/** + * A specialized [ColumnsSelectionDsl] for selecting columns to sort rows by + * and specifying how each column should be sorted. + * + * @include [SortDslSnippet] + * + * ### Examples + * ```kotlin + * // Sort rows by "age" column values ascending + * df.sortBy { age } + * // Sort rows by "age" column values descending + * // and then by the ("name"/"firstName") column values ascending + * df.sortBy { age.reversed() and name.firstName } + * // Sort rows by "weight" column values ascending with nulls last + * df.sortBy { weight.nullsLast() } + * ``` + * + * Sorting values can also be computed inline using [expr]. + * ``` + * // Sort rows by the product of "volume" and "quantity" descending + * df.sortBy { expr { volume * quantity }.reversed() } + * ``` + */ public interface SortDsl : ColumnsSelectionDsl { + + /** + * Marks the selected columns to be sorted in reversed order. + */ + public fun ColumnSet.reversed(): ColumnSet = addFlag(SortFlag.Reversed) + + /** + * Marks the selected column to be sorted in reversed order. + */ + public fun SingleColumn.reversed(): SingleColumn = addFlag(SortFlag.Reversed).single() + + /** + * Marks the selected column to be sorted in reversed order. + */ + public fun String.reversed(): SingleColumn?> = invoke>().desc() + + @Deprecated( + message = "Inside the sorting DSL, reverse() reverses the sorting order. Use reversed() instead.", + replaceWith = ReplaceWith("reversed()"), + level = DeprecationLevel.ERROR, + ) + public fun DataColumn.reverse(): SingleColumn = reversed() + + @Deprecated(DESC_TO_REVERSED, ReplaceWith("reversed()"), DeprecationLevel.WARNING) public fun ColumnSet.desc(): ColumnSet = addFlag(SortFlag.Reversed) + @Deprecated(DESC_TO_REVERSED, ReplaceWith("reversed()"), DeprecationLevel.WARNING) public fun SingleColumn.desc(): SingleColumn = addFlag(SortFlag.Reversed).single() + @Deprecated(DESC_TO_REVERSED, ReplaceWith("reversed()"), DeprecationLevel.WARNING) public fun String.desc(): SingleColumn?> = invoke>().desc() @Deprecated(DEPRECATED_ACCESS_API) @AccessApiOverload public fun KProperty.desc(): SingleColumn = toColumnAccessor().desc() + /** + * Places `null` values after non-null values when sorting by the selected columns. + * + * When [flag] is `false`, the selected columns remain unchanged. + * + * @param flag whether `null` values should be placed last. + */ public fun ColumnSet.nullsLast(flag: Boolean = true): ColumnSet = if (flag) addFlag(SortFlag.NullsLast) else this + /** + * Places `null` values after non-null values when sorting by this column. + * + * When [flag] is `false`, the column remains unchanged. + * + * @param flag whether `null` values should be placed last. + */ public fun SingleColumn.nullsLast(flag: Boolean = true): SingleColumn = if (flag) addFlag(SortFlag.NullsLast).single() else this + /** + * Places `null` values after non-null values when sorting by this column. + * + * When [flag] is `false`, the default `null` ordering is used. + * + * @param flag whether `null` values should be placed last. + */ public fun String.nullsLast(flag: Boolean = true): SingleColumn?> = invoke>().nullsLast(flag) @@ -54,28 +150,48 @@ public interface SortDsl : ColumnsSelectionDsl { } /** - * [SortColumnsSelector] is used to express or select multiple columns to sort by, represented by [ColumnsResolver]``, - * using the context of [SortDsl]`` as `this` and `it`. + * A specialized [ColumnsSelector] used for selecting columns for sorting. * - * So: - * ```kotlin - * SortDsl.(it: SortDsl) -> ColumnSet - * ``` + * Provides [SortDsl] both as the receiver (`this`) and the lambda parameter (`it`), and expects + * a [ColumnsResolver] as the return value. + * + * Enables defining the descending ordering of sort columns using [desc][SortDsl.desc] + * and specifiyng `null`s place using [nullsLast][SortDsl.nullsLast]. */ public typealias SortColumnsSelector = Selector, ColumnsResolver> // region DataColumn +/** + * Sorts the values in this [column][DataColumn] in ascending order. + * + * Accepts only [Comparable] values. + * + * See also + * - [sortDesc][DataColumn.sortDesc] for sorting in descending order; + * - [sortWith][DataColumn.sortWith] for sorting by providing a custom comparator. + * + * @return A new [ValueColumn] containing the sorted values from the original column. + */ public fun > DataColumn.sort(): ValueColumn = DataColumn.createValueColumn(name, values().sorted(), type, defaultValue = defaultValue()) +/** + * Sorts the values in this [column][DataColumn] in descengind order. + * + * Accepts only [Comparable] values. + * + * See also + * - [sort][DataColumn.sort] for sorting in ascending order; + * - [sortWith][DataColumn.sortWith] for sorting by providing a custom comparator. + * + * @return A new [ValueColumn] containing the sorted values from the original column. + */ public fun > DataColumn.sortDesc(): ValueColumn = DataColumn.createValueColumn(name, values().sortedDescending(), type, defaultValue = defaultValue()) /** - * ## Sort [DataColumn] With - * - * This function returns the sorted version of the current [ValueColumn], [FrameColumn], or [ColumnGroup] based + * Returns the sorted version of the current [ValueColumn], [FrameColumn], or [ColumnGroup] based * on the given [Comparator]. The [comparator\] can either be given as an instance of [Comparator], or directly * as a lambda. * @@ -96,19 +212,56 @@ public fun > DataColumn.sortDesc(): ValueColumn = * a lambda of type `(`[T][T\]`, `[T][T\]`) -> `[Int][Int]. * @return The sorted [DataColumn] [this\] of the same type as the receiver. */ -private typealias CommonDataColumnSortWithDocs = Nothing +@ExcludeFromSources +private typealias CommonDataColumnSortWithDocsSnippet = Nothing -/** @include [CommonDataColumnSortWithDocs] */ +/** @include [CommonDataColumnSortWithDocsSnippet] */ public fun > C.sortWith(comparator: Comparator): C = DataColumn.createByType(name, values().sortedWith(comparator), type) as C -/** @include [CommonDataColumnSortWithDocs] */ +/** @include [CommonDataColumnSortWithDocsSnippet] */ public fun > C.sortWith(comparator: (T, T) -> Int): C = sortWith(Comparator(comparator)) // endregion // region DataFrame +/** + * Sorts this [DataFrame] rows by the specified [columns] in ascending (default) or descending order. + * + * Returns a new [DataFrame] containing the same rows, sorted according to the selected columns. + * + * Select columns to sort by, adjust sorting order and `null`s position using [SortDsl]. + * + * @include [SortDslSnippet] + * + * See {@include [CSDslLink]}. + * + * See also + * - [sortByDesc][DataFrame.sortByDesc] that sorts rows in descending order by default. + * - [sortWith][DataFrame.sortWith] that sorts rows using a custom comparator. + * + * ### Examples + * ```kotlin + * // Sort rows by "age" column values ascending + * df.sortBy { age } + * // Sort rows by "age" column values descending + * // and then by the ("name"/"firstName") column values ascending + * df.sortBy { age.reversed() and name.firstName } + * // Sort rows by "weight" column values ascending with nulls last + * df.sortBy { weight.nullsLast() } + * ``` + * + * Sorting values can also be computed inline using [expr]. + * ``` + * // Sort rows by the product of "volume" and "quantity" descending + * df.sortBy { expr { volume * quantity }.reversed() } + * ``` + * + * @param columns The [Sort Columns Selector][SortColumnsSelector] that defines which columns are used + * for sorting, in which order and direction. + * @return A new [DataFrame] with the original rows sorted based on the specified columns and directions. + */ public fun DataFrame.sortBy(columns: SortColumnsSelector): DataFrame = sortByImpl(UnresolvedColumnsPolicy.Fail, columns) @@ -116,20 +269,131 @@ public fun DataFrame.sortBy(columns: SortColumnsSelector): DataF @AccessApiOverload public fun DataFrame.sortBy(vararg cols: ColumnReference<*>): DataFrame = sortBy { cols.toColumnSet() } +/** + * Sorts this [DataFrame] rows by the specified [columns] in ascending order. + * + * Returns a new [DataFrame] containing the same rows, sorted according to the selected columns. + * + * @include [SelectingColumns.ColumnNamesApi] + * + * The order in which columns are selected determines the sort priority. + * + * See also + * - [`sortBy { }`][DataFrame.sortBy] overload that uses [SortDsl] + * for selecting columns, allowing specifying sort directions and `null`s position. + * - [sortByDesc][DataFrame.sortByDesc] that sorts rows in descending order. + * - [sortWith][DataFrame.sortWith] that sorts rows using a custom comparator. + * + * ### Examples + * ```kotlin + * df.sortBy("age") + * // Sort rows by "age" column values ascending + * // and then by the ("name") column values ascending + * df.sortBy("age", "name") + * ``` + * + * @param cols The [Column Names][String] that defines which columns are used for sorting. + * @return A new [DataFrame] with the original rows sorted based on the specified columns. + */ public fun DataFrame.sortBy(vararg cols: String): DataFrame = sortBy { cols.toColumnSet() } @Deprecated(DEPRECATED_ACCESS_API) @AccessApiOverload public fun DataFrame.sortBy(vararg cols: KProperty?>): DataFrame = sortBy { cols.toColumnSet() } +/** + * Sorts the rows of this [DataFrame] using the specified row [comparator]. + * + * Returns a new [DataFrame] containing the same rows sorted according to the provided [Comparator]. + * + * See also [sortBy][DataFrame.sortBy] and [sortByDesc][DataFrame.sortByDesc], which sort + * rows by selected columns. + * + * ### Example + * ```kotlin + * // Provide a comparator for `DataRow` that sorts + * // by `age` in ascending order first + * // and then by `salary` in descending order + * df.sortWith( + * compareBy> { it.age } + * .thenByDescending { it.salary } + * ) + * ``` + * + * @param comparator The [Comparator] used to determine the order of rows. + * @return A new [DataFrame] containing the same rows sorted according to the provided comparator. + */ public fun DataFrame.sortWith(comparator: Comparator>): DataFrame { val permutation = rows().sortedWith(comparator).map { it.index } return this[permutation] } +/** + * Sorts the rows of this [DataFrame] using the specified row [comparator]. + * + * The [comparator] is a comparison lambda that takes two [DataRow]s and returns + * a negative, zero, or positive value depending on their relative order. + * + * Returns a new [DataFrame] containing the same rows sorted according to the provided comparator. + * + * See also [sortBy][DataFrame.sortBy] and [sortByDesc][DataFrame.sortByDesc], which sort + * rows by selected columns. + * + * ### Example + * ```kotlin + * // Sort by `age` in ascending order, + * // then by `salary` in ascending order + * df.sortWith { row1, row2 -> + * when { + * row1.age != row2.age -> row1.age.compareTo(row2.age) + * else -> row1.salary.compareTo(row2.salary) + * } + * } + * ``` + * + * @param comparator A function that compares two rows and returns a negative, zero, + * or positive value depending on their relative order. + * @return A new [DataFrame] containing the same rows sorted according to the provided comparator. + */ public fun DataFrame.sortWith(comparator: (DataRow, DataRow) -> Int): DataFrame = sortWith(Comparator(comparator)) +/** + * Sorts this [DataFrame] rows by the specified [columns] in ascending or descending (default) order. + * + * Returns a new [DataFrame] containing the same rows, sorted according to the selected columns. + * + * Select columns to sort by, adjust sorting order and `null`s position using [SortDsl]. + * + * @include [SortDslSnippet] + * + * See {@include [CSDslLink]}. + * + * See also + * - [sortBy][DataFrame.sortBy] that sorts rows in ascending order by default. + * - [sortWith][DataFrame.sortWith] that sorts rows using a custom comparator. + * + * ### Examples + * ```kotlin + * // Sort rows by "age" column values descending + * df.sortByDesc { age } + * // Sort rows by "age" column values descending + * // and then by the ("name"/"firstName") column values ascending + * df.sortByDesc { age and name.firstName.reversed() } + * // Sort rows by "weight" column values descending with nulls first + * df.sortByDesc { weight.nullsLast() } + * ``` + * + * Sorting values can also be computed inline using [expr]. + * ``` + * // Sort rows by the product of "volume" and "quantity" descending + * df.sortByDesc { expr { volume * quantity } } + * ``` + * + * @param columns The [Sort Columns Selector][SortColumnsSelector] that defines which columns are used + * for sorting, in which order and direction. + * @return A new [DataFrame] with the original rows sorted based on the specified columns and directions. + */ public fun DataFrame.sortByDesc(columns: SortColumnsSelector): DataFrame { val set = columns.toColumnSet() return sortByImpl { set.desc() } @@ -140,6 +404,32 @@ public fun DataFrame.sortByDesc(columns: SortColumnsSelector): D public fun DataFrame.sortByDesc(vararg columns: KProperty?>): DataFrame = sortByDesc { columns.toColumnSet() } +/** + * Sorts this [DataFrame] rows by the specified [columns] in descending order. + * + * Returns a new [DataFrame] containing the same rows, sorted according to the selected columns. + * + * @include [SelectingColumns.ColumnNamesApi] + * + * The order in which columns are selected determines the sort priority. + * + * See also + * - [`sortByDesc { }`][DataFrame.sortByDesc] overload that uses [SortDsl] + * for selecting columns, allowing specifying sort directions and `null`s position. + * - [sortBy][DataFrame.sortBy] that sorts rows in ascending order. + * - [sortWith][DataFrame.sortWith] that sorts rows using a custom comparator. + * + * ### Examples + * ```kotlin + * df.sortByDesc("age") + * // Sort rows by "age" column values descending + * // and then by the ("name") column values descending + * df.sortByDesc("age", "name") + * ``` + * + * @param columns The [Column Names][String] that defines which columns are used for sorting. + * @return A new [DataFrame] with the original rows sorted based on the specified columns. + */ public fun DataFrame.sortByDesc(vararg columns: String): DataFrame = sortByDesc { columns.toColumnSet() } @Deprecated(DEPRECATED_ACCESS_API) @@ -151,6 +441,38 @@ public fun DataFrame.sortByDesc(vararg columns: ColumnReference<*>): Data // region GroupBy +/** + * Sorts this [GroupBy] group rows by the specified [columns][cols] in asending order. + * + * Returns a new [GroupBy] containing the same keys and groups, + * with the groups sorted according to the selected columns. + * + * @include [SelectingColumns.ColumnNamesApi] + * + * The order in which columns are selected determines the sort priority. + * + * Don't confuse this with [sortByGroup] and [sortByKey] that sort key-group pairs order. + * + * See also + * - [`sortBy { }`][GroupBy.sortBy] overload that uses [SortDsl] + * for selecting columns, allowing specifying sort directions and `null`s position. + * - [sortByDesc][GroupBy.sortByDesc] that sorts rows in descending order. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * ### Examples + * ```kotlin + * gb.sortBy("age") + * // Sort group rows by "age" column values descending + * // and then by the ("name") column values descending + * gb.sortByDesc("age", "name") + * ``` + * + * @param cols The [Column Names][String] that defines which columns are used for sorting. + * @return A new [GroupBy] with same keys and groups with the original rows sorted based on the specified columns. + */ public fun GroupBy.sortBy(vararg cols: String): GroupBy = sortBy { cols.toColumnSet() } @Deprecated(DEPRECATED_ACCESS_API) @@ -162,8 +484,77 @@ public fun GroupBy.sortBy(vararg cols: ColumnReference<*>): GroupBy public fun GroupBy.sortBy(vararg cols: KProperty?>): GroupBy = sortBy { cols.toColumnSet() } +/** + * Sorts this [GroupBy] group rows by the specified [columns][selector] in ascending (default) or descending order. + * + * Returns a new [GroupBy] containing the same keys and groups, + * with the groups sorted according to the selected columns. + * + * Select columns to sort by, adjust sorting order and `null`s position using [SortDsl]. + * + * @include [SortDslSnippet] + * + * See {@include [CSDslLink]}. + * + * See also [sortByDesc][GroupBy.sortByDesc] that sorts rows in descending order by default. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * ### Examples + * ```kotlin + * // Sort group rows by "age" column values ascending + * gb.sortBy { age } + * // Sort group rows by "age" column values descending + * // and then by the ("name"/"firstName") column values ascending + * gb.sortBy { age.reversed() and name.firstName } + * // Sort group rows by "weight" column values ascending with nulls last + * gb.sortBy { weight.nullsLast() } + * ``` + * + * Sorting values can also be computed inline using [expr]. + * ``` + * // Sort rows by the product of "volume" and "quantity" descending + * gb.sortBy { expr { volume * quantity }.reversed() } + * ``` + * + * @param selector The [Sort Columns Selector][SortColumnsSelector] that defines which columns are used + * for sorting, in which order and direction. + * @return A new [GroupBy] with same keys and groups with the original rows sorted based on the specified columns. + */ public fun GroupBy.sortBy(selector: SortColumnsSelector): GroupBy = sortByImpl(selector) +/** + * Sorts this [DataFrame] rows by the specified [columns][cols] in descending order. + * + * Returns a new [GroupBy] containing the same keys and groups, + * with the groups sorted according to the selected columns. + * + * @include [SelectingColumns.ColumnNamesApi] + * + * The order in which columns are selected determines the sort priority. + * + * See also + * - [`sortByDesc { }`][GroupBy.sortByDesc] overload that uses [SortDsl] + * for selecting columns, allowing specifying sort directions and `null`s position. + * - [sortBy][GroupBy.sortBy] that sorts rows in ascending order. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * ### Examples + * ```kotlin + * gb.sortByDesc("age") + * // Sort group rows by "age" column values descending + * // and then by the ("name") column values descending + * gb.sortByDesc("age", "name") + * ``` + * + * @param cols The [Column Names][String] that defines which columns are used for sorting. + * @return A new [GroupBy] with same keys and groups with the original rows sorted based on the specified columns. + */ public fun GroupBy.sortByDesc(vararg cols: String): GroupBy = sortByDesc { cols.toColumnSet() } @Deprecated(DEPRECATED_ACCESS_API) @@ -176,6 +567,45 @@ public fun GroupBy.sortByDesc(vararg cols: ColumnReference<*>): Gro public fun GroupBy.sortByDesc(vararg cols: KProperty?>): GroupBy = sortByDesc { cols.toColumnSet() } +/** + * Sorts this [GroupBy] group rows by the specified [columns][selector] in ascending or descending (default) order. + * + * Returns a new [GroupBy] containing the same keys and groups, + * with the groups sorted according to the selected columns. + * + * Select columns to sort by, adjust sorting order and `null`s position using [SortDsl]. + * + * @include [SortDslSnippet] + * + * See {@include [CSDslLink]}. + * + * See also [sortBy][GroupBy.sortBy] that sorts rows in asending order by default. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * ### Examples + * ```kotlin + * // Sort group rows by "age" column values descending + * gb.sortByDesc { age } + * // Sort group rows by "age" column values ase + * // and then by the ("name"/"firstName") column values ascending + * gb.sortByDesc { age and name.firstName.reversed() } + * // Sort group rows by "weight" column values descending with nulls first + * gb.sortByDesc { weight.nullsLast() } + * ``` + * + * Sorting values can also be computed inline using [expr]. + * ``` + * // Sort rows by the product of "volume" and "quantity" descending + * gb.sortByDesc { expr { volume * quantity } } + * ``` + * + * @param selector The [Sort Columns Selector][SortColumnsSelector] that defines which columns are used + * for sorting, in which order and direction. + * @return A new [GroupBy] with same keys and groups with the original rows sorted based on the specified columns. + */ public fun GroupBy.sortByDesc(selector: SortColumnsSelector): GroupBy { val set = selector.toColumnSet() return sortByImpl { set.desc() } @@ -190,6 +620,37 @@ private fun GroupBy.createColumnFromGroupExpression( expression(group, group) } +/** + * Sorts the key-group pairs of this [GroupBy] by a value computed for each group + * using the specified [expression] ascending. + * + * [DataFrameExpression] is a lambda that receives each group as a [DataFrame], both as the receiver (`this`) + * and as the lambda argument (`it`), and returns the value used to order the groups. + * + * Returns a new [GroupBy] containing the same keys and groups in the resulting order. + * The contents of the groups remain unchanged. + * + * Don't confuse this with [sortBy][GroupBy.sortBy] that sorts the group rows. + * + * See also + * - [sortByGroupDesc] that sorts the key-group pairs of this [GroupBy] based on computed values desending. + * - [sortByCount] and [sortByCountAsc] that sort the key-group pairs of this [GroupBy] by the group sizes. + * - [sortByKey] and [sortByKeyDesc] that sort the key-group pairs of this [GroupBy] by the key values. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * ### Example + * ```kotlin + * // Sorts groups by the product of their size and the maximum value of the "quantity" column ascending + * gb.sortByGroup { group -> group.rowsCount() * group.quantity.max() } + * ``` + * + * @param [nullsLast] Whether `null` values should be placed after non-null values. + * @param [expression] The expression used to compute the sorting value for each group. + * @return A new [GroupBy] with its key-group pairs sorted by the values produced by [expression]. + */ public fun GroupBy.sortByGroup( nullsLast: Boolean = false, expression: DataFrameExpression, @@ -198,6 +659,37 @@ public fun GroupBy.sortByGroup( createColumnFromGroupExpression(this, expression).nullsLast(nullsLast) }.asGroupBy(groups) +/** + * Sorts the key-group pairs of this [GroupBy] by a value computed for each group + * using the specified [expression] descending. + * + * [DataFrameExpression] is a lambda that receives each group as a [DataFrame], both as the receiver (`this`) + * and as the lambda argument (`it`), and returns the value used to order the groups. + * + * Returns a new [GroupBy] containing the same keys and groups in the resulting order. + * The contents of the groups remain unchanged. + * + * Don't confuse this with [sortByDesc][GroupBy.sortByDesc] that sorts the group rows. + * + * See also + * - [sortByGroup] that sorts the key-group pairs of this [GroupBy] based on computed values asending. + * - [sortByCount] and [sortByCountAsc] that sort the key-group pairs of this [GroupBy] by the group sizes. + * - [sortByKey] and [sortByKeyDesc] that sort the key-group pairs of this [GroupBy] by the key values. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * ### Example + * ```kotlin + * // Sorts groups by the product of their size and the maximum value of the "quantity" column descending + * gb.sortByGroupDesc { group -> group.rowsCount() * group.quantity.max() } + * ``` + * + * @param [nullsLast] Whether `null` values should be placed after non-null values. + * @param [expression] The expression used to compute the sorting value for each group. + * @return A new [GroupBy] with its key-group pairs sorted by the values produced by [expression]. + */ public fun GroupBy.sortByGroupDesc( nullsLast: Boolean = false, expression: DataFrameExpression, @@ -206,15 +698,93 @@ public fun GroupBy.sortByGroupDesc( createColumnFromGroupExpression(this, expression).desc().nullsLast(nullsLast) }.asGroupBy(groups) +/** + * Sorts the key-group pairs of this [GroupBy] by the numer of rows in groups asending. + * + * Returns a new [GroupBy] containing the same keys and groups in the resulting order. + * The contents of the groups remain unchanged. + * + * Don't confuse this with [sortBy][GroupBy.sortBy] that sorts the group rows. + * + * See also + * - [sortByCount] that sort the key-group pairs of this [GroupBy] by the group sizes descending. + * - [sortByGroup] and [sortByGroupDesc] that sorts the key-group pairs of this [GroupBy] d on computed values. + * - [sortByKey] and [sortByKeyDesc] that sort the key-group pairs of this [GroupBy] by the key values. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * @return A new [GroupBy] with its key-group pairs sorted by the group sizes. + */ public fun GroupBy.sortByCountAsc(): GroupBy = sortByGroup { nrow } +/** + * Sorts the key-group pairs of this [GroupBy] by the numer of rows in groups descending. + * + * Returns a new [GroupBy] containing the same keys and groups in the resulting order. + * The contents of the groups remain unchanged. + * + * Don't confuse this with [sortBy][GroupBy.sortBy] that sorts the group rows. + * + * See also + * - [sortByCountAsc] that sort the key-group pairs of this [GroupBy] by the group sizes asdending. + * - [sortByGroup] and [sortByGroupDesc] that sorts the key-group pairs of this [GroupBy] based on computed values. + * - [sortByKey] and [sortByKeyDesc] that sort the key-group pairs of this [GroupBy] by the key values. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * @return A new [GroupBy] with its key-group pairs sorted by the group sizes. + */ public fun GroupBy.sortByCount(): GroupBy = sortByGroupDesc { nrow } +/** + * Sorts the key-group pairs of this [GroupBy] by the keys descending. + * + * Returns a new [GroupBy] containing the same keys and groups in the resulting order. + * The contents of the groups remain unchanged. + * + * Don't confuse this with [sortBy][GroupBy.sortBy] that sorts the group rows. + * + * See also + * - [sortByKey] that sorts the key-group pairs of this [GroupBy] by the key values asending. + * - [sortByCount] and [sortByCountAsc] that sort the key-group pairs of this [GroupBy] by the group sizes. + * - [sortByGroup] and [sortByGroupDesc] that sorts the key-group pairs of this [GroupBy] based on computed values. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * @param [nullsLast] Whether `null` values should be placed after non-null values. + * @return A new [GroupBy] with its key-group pairs sorted by the keys. + */ public fun GroupBy.sortByKeyDesc(nullsLast: Boolean = false): GroupBy = toDataFrame() .sortBy { keys.columns().toColumnSet().desc().nullsLast(nullsLast) } .asGroupBy(groups) +/** + * Sorts the key-group pairs of this [GroupBy] by the keys asending. + * + * Returns a new [GroupBy] containing the same keys and groups in the resulting order. + * The contents of the groups remain unchanged. + * + * Don't confuse this with [sortBy][GroupBy.sortBy] that sorts the group rows. + * + * See also + * - [sortByKeyDesc] that sorts the key-group pairs of this [GroupBy] by the key values descending. + * - [sortByCount] and [sortByCountAsc] that sort the key-group pairs of this [GroupBy] by the group sizes. + * - [sortByGroup] and [sortByGroupDesc] that sorts the key-group pairs of this [GroupBy] based on computed values. + * + * Check out [`GroupBy grammar`][Grammar]. + * + * For more information: {@include [DocumentationUrls.GroupByTransformation]} + * + * @param [nullsLast] Whether `null` values should be placed after non-null values. + * @return A new [GroupBy] with its key-group pairs sorted by the keys. + */ public fun GroupBy.sortByKey(nullsLast: Boolean = false): GroupBy = toDataFrame() .sortBy { keys.columns().toColumnSet().nullsLast(nullsLast) } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/SelectingColumns.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/SelectingColumns.kt index 5468b71490..436f708d45 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/SelectingColumns.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/SelectingColumns.kt @@ -81,6 +81,9 @@ internal interface SelectingColumns { * This is an entity formed by calling any (combination) of the functions * in the DSL that is or can be resolved into one or more columns. * + * Columns Selection DSL allows using [Extension Properties][AccessApis.ExtensionPropertiesApi] + * for specifying columns type- and name-safe. + * * Check out: [Columns Selection DSL Grammar][ColumnsSelectionDsl.DslGrammar] * {@include [LineBreak]} * @include [DocumentationUrls.ColumnSelectors] @@ -134,6 +137,8 @@ internal interface SelectingColumns { * This is an entity formed by calling any (combination) of the functions * in the DSL that is or can be resolved into a single column. * + * Column Selection DSL allows using [Extension Properties][AccessApis.ExtensionPropertiesApi] + * for specifying column type- and name-safe. * * {@include [LineBreak]} * @include [DocumentationUrls.ColumnSelectors] diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt index fed730edcb..7027d7e4b7 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt @@ -296,6 +296,9 @@ internal const val KEY_VALUE_PROPERTY_KEY = internal const val NAME_REPAIR_STRATEGY: String = "NameRepairStrategy is deprecated. Name repair is now always applied via ColumnNameGenerator, consistent with other IO readers. $MESSAGE_1_1" +internal const val DESC_TO_REVERSED: String = + "This function is deprecated and renamed to `reversed()` to better reflect its purpose. $MESSAGE_1_1" + // endregion // region keep across releases diff --git a/docs/StardustDocs/topics/groupBy.md b/docs/StardustDocs/topics/groupBy.md index 122fa8ace0..fba2fb1fdc 100644 --- a/docs/StardustDocs/topics/groupBy.md +++ b/docs/StardustDocs/topics/groupBy.md @@ -175,12 +175,13 @@ Returns `GroupBy` object. A `GroupBy` can be transformed into a new `GroupBy` using one of the following methods: -* `sortByGroup` / `sortByGroupDesc` — sorts the order of groups (and their corresponding keys) by values computed with a `DataFrameExpression` applied to each group; -* `sortByCount` / `sortByCountAsc` — sorts the order of groups (and their corresponding keys) by the number of rows they contain; -* `sortByKey` / `sortByKeyDesc` — sorts the order of groups (and their corresponding keys) by the grouping key values; -* [`sortBy`](sortBy.md) / [`sortByDesc`](sortBy.md#sortbydesc) — sorts the order of rows within each group by one or more column values; +* `sortByGroup` / `sortByGroupDesc` — sorts the **order of groups** (and their corresponding keys) by values computed with a `DataFrameExpression` applied to each group; +* `sortByCount` / `sortByCountAsc` — sorts the **order of groups** (and their corresponding keys) by the number of rows they contain; +* `sortByKey` / `sortByKeyDesc` — sorts the **order of groups** (and their corresponding keys) by the grouping key values; +* [`sortBy`](sortBy.md) / [`sortByDesc`](sortBy.md#sortbydesc) — sorts the **order of rows within each group** by one or more column values; * `updateGroups` — transforms each group into a new one using the provided transforming function; -* [`filter`](filter.md) — filters group rows by the given predicate; +* [`filter`](filter.md) — filters out keys and corresponding groups that +do not satisfy the given key-group predicate; * [`add`](add.md) — adds a new column to each group. Any [`DataFrame`](DataFrame.md) with [FrameColumn](DataColumn.md#framecolumn) can be reinterpreted as a `GroupBy`: From ca01ff22637fee814aa407daa790128e79d46aca Mon Sep 17 00:00:00 2001 From: "andrei.kislitsyn" Date: Thu, 23 Jul 2026 00:02:15 +0400 Subject: [PATCH 2/4] Document `df.sortBy { col.desc() }` renaming in Migration Guide --- docs/StardustDocs/topics/MigrationTo_1_0.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/StardustDocs/topics/MigrationTo_1_0.md b/docs/StardustDocs/topics/MigrationTo_1_0.md index b70dbb2cf9..f2e897ecc4 100644 --- a/docs/StardustDocs/topics/MigrationTo_1_0.md +++ b/docs/StardustDocs/topics/MigrationTo_1_0.md @@ -187,6 +187,7 @@ The next functions and classes raise `WARNING` in 1.0 and `ERROR` in 1.1. | `df.copy()` | `df.columns().toDataFrame().cast()` | Removed a shortcut to clarify the behaviour; | | `KeyValueProperty` | `NameValueProperty` | Removed duplicated functionality. | | `rename { columns }.into(..)` (will remain WARNING) | `rename { columns }.to(..)` | Renamed to better reflect the English sentence "rename this column to that". | +| `df.sortBy { col.desc() }` | `df.sortBy { col.reversed() }` | Renamed to better reflect its purpose. | ## Parsing and Converting Date-Time From 5d528e38255ef0ed57c42d5881b13469614e07e8 Mon Sep 17 00:00:00 2001 From: "andrei.kislitsyn" Date: Wed, 29 Jul 2026 19:29:44 +0400 Subject: [PATCH 3/4] fix nullsLast description --- .../jetbrains/kotlinx/dataframe/api/sort.kt | 51 +++++++++++++------ .../documentation/SelectingColumns.kt | 4 +- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sort.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sort.kt index b9c2ec71c7..4f288f5ec7 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sort.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sort.kt @@ -37,8 +37,8 @@ import org.jetbrains.kotlinx.dataframe.util.DESC_TO_REVERSED import kotlin.reflect.KProperty /** - * [SortDsl] allows selecting columns to sort rows by (the order in which columns are selected - * determines the sort priority). + * The [Sort DSL][SortDsl] allows selecting columns to sort rows by + * values in these columns. * It also allows reversing the sort order for individual columns or column sets, * and controlling the position of `null` values. * @@ -55,7 +55,7 @@ import kotlin.reflect.KProperty private typealias SortDslSnippet = Nothing /** - * A specialized [ColumnsSelectionDsl] for selecting columns to sort rows by + * A specialized {@include [ColumnsSelectionDslLink]} for selecting columns to sort rows by * and specifying how each column should be sorted. * * @include [SortDslSnippet] @@ -92,7 +92,7 @@ public interface SortDsl : ColumnsSelectionDsl { /** * Marks the selected column to be sorted in reversed order. */ - public fun String.reversed(): SingleColumn?> = invoke>().desc() + public fun String.reversed(): SingleColumn?> = invoke?>().reversed() @Deprecated( message = "Inside the sorting DSL, reverse() reverses the sorting order. Use reversed() instead.", @@ -115,7 +115,11 @@ public interface SortDsl : ColumnsSelectionDsl { public fun KProperty.desc(): SingleColumn = toColumnAccessor().desc() /** - * Places `null` values after non-null values when sorting by the selected columns. + * Places `null` values after non-null values when sorting in ascending order, + * or before non-null values when sorting in descending order by these columns. + * + * By default, `null` values are considered the smallest values when sorting. + * Use this method to treat them as the largest values. * * When [flag] is `false`, the selected columns remain unchanged. * @@ -125,7 +129,11 @@ public interface SortDsl : ColumnsSelectionDsl { if (flag) addFlag(SortFlag.NullsLast) else this /** - * Places `null` values after non-null values when sorting by this column. + * Places `null` values after non-null values when sorting in ascending order, + * or before non-null values when sorting in descending order by this column. + * + * By default, `null` values are considered the smallest values when sorting. + * Use this method to treat them as the largest values. * * When [flag] is `false`, the column remains unchanged. * @@ -135,7 +143,11 @@ public interface SortDsl : ColumnsSelectionDsl { if (flag) addFlag(SortFlag.NullsLast).single() else this /** - * Places `null` values after non-null values when sorting by this column. + * Places `null` values after non-null values when sorting in ascending order, + * or before non-null values when sorting in descending order by this column. + * + * By default, `null` values are considered the smallest values when sorting. + * Use this method to treat them as the largest values. * * When [flag] is `false`, the default `null` ordering is used. * @@ -155,8 +167,10 @@ public interface SortDsl : ColumnsSelectionDsl { * Provides [SortDsl] both as the receiver (`this`) and the lambda parameter (`it`), and expects * a [ColumnsResolver] as the return value. * - * Enables defining the descending ordering of sort columns using [desc][SortDsl.desc] + * Enables defining the descending ordering of sort columns using [reversed][SortDsl.reversed] * and specifiyng `null`s place using [nullsLast][SortDsl.nullsLast]. + * + * See {@include [CSDslLink]}. */ public typealias SortColumnsSelector = Selector, ColumnsResolver> @@ -177,7 +191,7 @@ public fun > DataColumn.sort(): ValueColumn = DataColumn.createValueColumn(name, values().sorted(), type, defaultValue = defaultValue()) /** - * Sorts the values in this [column][DataColumn] in descengind order. + * Sorts the values in this [column][DataColumn] in descending order. * * Accepts only [Comparable] values. * @@ -552,7 +566,7 @@ public fun GroupBy.sortBy(selector: SortColumnsSelector): * gb.sortByDesc("age", "name") * ``` * - * @param cols The [Column Names][String] that defines which columns are used for sorting. + * @param cols The [Column Names][String] that define which columns are used for sorting. * @return A new [GroupBy] with same keys and groups with the original rows sorted based on the specified columns. */ public fun GroupBy.sortByDesc(vararg cols: String): GroupBy = sortByDesc { cols.toColumnSet() } @@ -620,6 +634,13 @@ private fun GroupBy.createColumnFromGroupExpression( expression(group, group) } +/** + * @param [\nullsLast] Whether `null` values are considered as the largest values when sorting. + * Default is `false`. + */ +@ExcludeFromSources +private typealias NullsLastArgumentDescription = Nothing + /** * Sorts the key-group pairs of this [GroupBy] by a value computed for each group * using the specified [expression] ascending. @@ -647,7 +668,7 @@ private fun GroupBy.createColumnFromGroupExpression( * gb.sortByGroup { group -> group.rowsCount() * group.quantity.max() } * ``` * - * @param [nullsLast] Whether `null` values should be placed after non-null values. + * @include [NullsLastArgumentDescription] * @param [expression] The expression used to compute the sorting value for each group. * @return A new [GroupBy] with its key-group pairs sorted by the values produced by [expression]. */ @@ -686,7 +707,7 @@ public fun GroupBy.sortByGroup( * gb.sortByGroupDesc { group -> group.rowsCount() * group.quantity.max() } * ``` * - * @param [nullsLast] Whether `null` values should be placed after non-null values. + * @include [NullsLastArgumentDescription] * @param [expression] The expression used to compute the sorting value for each group. * @return A new [GroupBy] with its key-group pairs sorted by the values produced by [expression]. */ @@ -757,12 +778,12 @@ public fun GroupBy.sortByCount(): GroupBy = sortByGroupDesc { * * For more information: {@include [DocumentationUrls.GroupByTransformation]} * - * @param [nullsLast] Whether `null` values should be placed after non-null values. + * @include [NullsLastArgumentDescription] * @return A new [GroupBy] with its key-group pairs sorted by the keys. */ public fun GroupBy.sortByKeyDesc(nullsLast: Boolean = false): GroupBy = toDataFrame() - .sortBy { keys.columns().toColumnSet().desc().nullsLast(nullsLast) } + .sortBy { keys.columns().toColumnSet().reversed().nullsLast(nullsLast) } .asGroupBy(groups) /** @@ -782,7 +803,7 @@ public fun GroupBy.sortByKeyDesc(nullsLast: Boolean = false): Group * * For more information: {@include [DocumentationUrls.GroupByTransformation]} * - * @param [nullsLast] Whether `null` values should be placed after non-null values. + * @include [NullsLastArgumentDescription] * @return A new [GroupBy] with its key-group pairs sorted by the keys. */ public fun GroupBy.sortByKey(nullsLast: Boolean = false): GroupBy = diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/SelectingColumns.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/SelectingColumns.kt index 436f708d45..fa098418ca 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/SelectingColumns.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/SelectingColumns.kt @@ -81,7 +81,7 @@ internal interface SelectingColumns { * This is an entity formed by calling any (combination) of the functions * in the DSL that is or can be resolved into one or more columns. * - * Columns Selection DSL allows using [Extension Properties][AccessApis.ExtensionPropertiesApi] + * The Columns Selection DSL allows using [Extension Properties][AccessApis.ExtensionPropertiesApi] * for specifying columns type- and name-safe. * * Check out: [Columns Selection DSL Grammar][ColumnsSelectionDsl.DslGrammar] @@ -137,7 +137,7 @@ internal interface SelectingColumns { * This is an entity formed by calling any (combination) of the functions * in the DSL that is or can be resolved into a single column. * - * Column Selection DSL allows using [Extension Properties][AccessApis.ExtensionPropertiesApi] + * The Column Selection DSL allows using [Extension Properties][AccessApis.ExtensionPropertiesApi] * for specifying column type- and name-safe. * * {@include [LineBreak]} From bd6761e7ec9446f466185a74c84dc800baf6502a Mon Sep 17 00:00:00 2001 From: "andrei.kislitsyn" Date: Wed, 29 Jul 2026 19:34:34 +0400 Subject: [PATCH 4/4] api dump --- core/api/core.api | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/api/core.api b/core/api/core.api index bb76090655..a90d8396c8 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -4048,6 +4048,10 @@ public abstract interface class org/jetbrains/kotlinx/dataframe/api/SortDsl : or public static synthetic fun nullsLast$default (Lorg/jetbrains/kotlinx/dataframe/api/SortDsl;Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn; public static synthetic fun nullsLast$default (Lorg/jetbrains/kotlinx/dataframe/api/SortDsl;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnSet;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/columns/ColumnSet; public static synthetic fun nullsLast$default (Lorg/jetbrains/kotlinx/dataframe/api/SortDsl;Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn; + public fun reverse (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn; + public fun reversed (Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn; + public fun reversed (Lorg/jetbrains/kotlinx/dataframe/columns/ColumnSet;)Lorg/jetbrains/kotlinx/dataframe/columns/ColumnSet; + public fun reversed (Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn;)Lorg/jetbrains/kotlinx/dataframe/columns/SingleColumn; } public final class org/jetbrains/kotlinx/dataframe/api/SortKt {