Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ internal interface ConvertDocs {
* {@include [DslGrammarLink]}
* {@include [LineBreak]}
*
* **[`convert`][convert]**` { columnsSelector: `[`ColumnsSelector`][ColumnsSelector]` }`
* **[`convert`][DataFrame.convert]**` { columnsSelector: `[`ColumnsSelector`][ColumnsSelector]` }`
*
* {@include [Indent]}
* __`.`__[**`with`**][Convert.with]`(infer: `[`Infer`][Infer]`, rowExpression: `[`RowValueExpression`][RowValueExpression]`)`
Expand Down
228 changes: 219 additions & 9 deletions core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/rename.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ import org.jetbrains.kotlinx.dataframe.columns.FrameColumn
import org.jetbrains.kotlinx.dataframe.columns.renamedReference
import org.jetbrains.kotlinx.dataframe.columns.toColumnSet
import org.jetbrains.kotlinx.dataframe.documentation.AccessApiLink
import org.jetbrains.kotlinx.dataframe.documentation.DocumentationUrls
import org.jetbrains.kotlinx.dataframe.documentation.DslGrammarLink
import org.jetbrains.kotlinx.dataframe.documentation.DslGrammarTemplateColumnsSelectionDsl.DslGrammarTemplate
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.impl.api.renameImpl
import org.jetbrains.kotlinx.dataframe.impl.columnName
import org.jetbrains.kotlinx.dataframe.impl.toCamelCaseByDelimiters
Expand All @@ -23,12 +29,108 @@ import kotlin.reflect.KProperty

// region DataFrame

/**
* Renames the specified [columns\] keeping their original values and location within the [DataFrame].
*
* This function does not immediately rename the columns but instead selects columns to rename and
* returns a [RenameClause],
* which serves as an intermediate step.
* The [RenameClause] object provides methods to rename selected columns using:
* - [into(name)][RenameClause.into] - renames selected columns to the specified names.
* - [into { nameExpression }][RenameClause.into] - renames selected columns using a provided
* expression assuming column with its path and returning a new name.
* - [toCamelCase()][RenameClause.toCamelCase] - renames all selected columns to "camelCase".
*
* Each method returns a new [DataFrame] with the renamed columns.
*
* Check out [Grammar].
*
* @include [SelectingColumns.ColumnGroupsAndNestedColumnsMention]
*
* See [Selecting Columns][RenameSelectingOptions].
*
* For more information: {@include [DocumentationUrls.Rename]}
*
* See also [renameToCamelCase] which renames all columns to "camelCase" format.
*/
internal interface RenameDocs {

/**
* {@comment Version of [SelectingColumns] with correctly filled in examples}
* @include [SelectingColumns] {@include [SetRenameOperationArg]}
*/
interface RenameSelectingOptions

/**
* ## Rename Operation Grammar
* {@include [LineBreak]}
* {@include [DslGrammarLink]}
* {@include [LineBreak]}
*
* [**`rename`**][rename]**` { `**`columnsSelector: `[`ColumnsSelector`][ColumnsSelector]` `**`}`**
*
* {@include [Indent]}
* `| `__`.`__[**`into`**][RenameClause.into]**`(`**`name: `[`String`][String]**`)`**
*
* {@include [Indent]}
* `| `__`.`__[**`into`**][RenameClause.into]**` { `**`nameExpression: (`[`ColumnWithPath`][ColumnWithPath]`) -> `[String]` `**`}`**
*
* {@include [Indent]}
* `| `__`.`__[**`toCamelCase`**][RenameClause.toCamelCase]**`()`**
*/
interface Grammar
}

/** {@set [SelectingColumns.OPERATION] [rename][rename]} */
@ExcludeFromSources
private interface SetRenameOperationArg

/**
* {@include [RenameDocs]}
* ### This Rename Overload
*/
@ExcludeFromSources
private interface CommonRenameDocs

/**
* Renames columns in the [DataFrame].
*
* This function allows renaming multiple columns in a single call by supplying a list of name pairs.
* Each pair consists of the current column name and the desired new name.
*
* See also [renameToCamelCase] which renames all columns to "camelCase" format.
*
* Example:
* ```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kt

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd still mark examples with kotlin or kt so the highlighting is correct

* df.rename("oldName1" to "newName1", "oldName2" to "newName2")
* ```
*
* @param mappings A vararg of pairs where each pair consists of the original column name (`first`)
* and the new column name (`second`).
* @return A new [DataFrame] with the renamed columns.
*/
@Refine
@Interpretable("RenameMapping")
public fun <T> DataFrame<T>.rename(vararg mappings: Pair<String, String>): DataFrame<T> =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this one be mentioned in the grammar as well?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe also renameToCamelCase?

Copy link
Collaborator Author

@AndreiKingsley AndreiKingsley Aug 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe they're out of grammar. I mean we should mention them, but not as part of operation grammar

rename { mappings.map { it.first.toColumnAccessor() }.toColumnSet() }
.into(*mappings.map { it.second }.toTypedArray())

/**
* @include [CommonRenameDocs]
* @include [SelectingColumns.Dsl] {@include [SetRenameOperationArg]}
* ### Examples:
* ```kotlin
* // Rename "col1" to "width" and "col2" to "length"
* df.rename { col1 and col2 }.into("width", "length")
*
* // Rename all columns using their full path, delimited by "->"
* df.rename { colsAtAnyDepth() }.into { it.path.joinToString("->") }
*
* // Renames all numeric columns to "camelCase"
* df.rename { colsOf<Number>() }.toCamelCase()
* ```
* @param [columns\] The [Columns Selector][ColumnsSelector] used to select the columns of this [DataFrame] to group.
*/
@Interpretable("Rename")
public fun <T, C> DataFrame<T>.rename(columns: ColumnsSelector<T, C>): RenameClause<T, C> = RenameClause(this, columns)

Expand All @@ -41,17 +143,47 @@ public fun <T, C> DataFrame<T>.rename(vararg cols: ColumnReference<C>): RenameCl
@AccessApiOverload
public fun <T, C> DataFrame<T>.rename(vararg cols: KProperty<C>): RenameClause<T, C> = rename { cols.toColumnSet() }

/**
* @include [CommonRenameDocs]
* @include [SelectingColumns.ColumnNames] {@include [SetRenameOperationArg]}
* ### Examples:
* ```kotlin
* // Rename "col1" to "width" and "col2" to "length"
* df.rename("col1", "col2").into("width", "length")
*
* // Renames "arrival_date" and "passport-ID" columns to "camelCase"
* df.rename("arrival_date", "passport-ID").toCamelCase()
* ```
* @param [columns\] The [Columns Names][String] used to select the columns of this [DataFrame] to group.
*/
public fun <T> DataFrame<T>.rename(vararg cols: String): RenameClause<T, Any?> = rename { cols.toColumnSet() }

/**
* An intermediate class used in the [rename] operation.
*
* This class itself does not perform any renaming — it is a transitional step
* before specifying how to rename the selected columns.
* It must be followed by one of the renaming methods
* to produce a new [DataFrame] with renamed columns.
*
* The resulting columns will keep their original values and positions
* in the [DataFrame], but their names will be changed.
*
* Use the following methods to perform the conversion:
* - [into(name)][RenameClause.into] — renames selected columns to the specified names.
* - [into { nameExpression }][RenameClause.into] — renames selected columns using a custom expression,
* which takes the column and its path and returns a new name.
* - [toCamelCase()][RenameClause.toCamelCase] — renames all selected columns to `camelCase`.
*
* See [Grammar][RenameDocs.Grammar] for more details.
*/
@HasSchema(schemaArg = 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we need a catalogue / design doc with all annotations, invented this year @koperagen ?
Could you create a simple md doc with them?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recently updated the kdoc for HasSchema, should be clear now. They're all in the same file

public class RenameClause<T, C>(internal val df: DataFrame<T>, internal val columns: ColumnsSelector<T, C>) {
override fun toString(): String = "RenameClause(df=$df, columns=$columns)"
}

/**
* ## Rename to "camelCase"
*
* This function renames all columns in this [DataFrame] to the "camelCase" format.
* Renames all columns in this [DataFrame] to the "camelCase" format.
*
* Removes all delimiters between words and capitalizes each word except the first one.
* Adds an underscore between consecutive numbers.
Expand All @@ -64,14 +196,15 @@ public class RenameClause<T, C>(internal val df: DataFrame<T>, internal val colu
*
* Returns a [DataFrame] with updated column names.
*
* ### Examples:
* ### Renaming Examples
* ```
* "snake_case_name" -> "snakeCaseName"
* "PascalCaseName" -> "pascalCaseName"
* "doner-case-name" -> "donerCaseName"
* "UPPER_CASE_NAME -> upperCaseName"
* ```
*
* @see [rename]
* @return a [DataFrame] with column names converted to "camelCase" format.
*/
@Refine
Expand All @@ -93,6 +226,30 @@ public fun <T> DataFrame<T>.renameToCamelCase(): DataFrame<T> =
public fun <T, C> RenameClause<T, C>.into(vararg newColumns: ColumnReference<*>): DataFrame<T> =
into(*newColumns.map { it.name() }.toTypedArray())

/**
* Renames the columns selected with [rename] to the specified [newNames],
* preserving their values and positions within the [DataFrame].
*
* The mapping is positional: [newNames] are applied in the order
* the columns were selected — the first selected column is renamed to the first name,
* the second to the second, and so on.
*
* For more information: {@include [DocumentationUrls.Rename]}
*
* Check out [Grammar][RenameDocs.Grammar].
*
* ### Examples:
* ```kotlin
* // Rename "col1" to "width" and "col2" to "length"
* df.rename("col1", "col2").into("width", "length")
*
* // Rename "col1" to "width" and "col2" to "length"
* df.rename { col1 and col2 }.into("width", "length")
* ```
*
* @param newNames The new names for the selected columns, applied in order of selecting.
* @return A new [DataFrame] with the columns renamed.
*/
@Refine
@Interpretable("RenameInto")
public fun <T, C> RenameClause<T, C>.into(vararg newNames: String): DataFrame<T> = renameImpl(newNames)
Expand All @@ -102,13 +259,35 @@ public fun <T, C> RenameClause<T, C>.into(vararg newNames: String): DataFrame<T>
public fun <T, C> RenameClause<T, C>.into(vararg newNames: KProperty<*>): DataFrame<T> =
into(*newNames.map { it.name }.toTypedArray())

/**
* Renames the columns selected with [rename] by applying the [transform] expression
* to each of them. This expression receives the column together with its full path
* (as [ColumnWithPath]) and must return the new name for that column.
* The operation preserves the original columns’ values and their positions within the [DataFrame].
*
* For more information: {@include [DocumentationUrls.Rename]}
*
* Check out [Grammar][RenameDocs.Grammar] for more details.
*
* ### Examples:
* ```kotlin
* // Rename all columns using their full path, delimited by "->"
* df.rename { colsAtAnyDepth() }.into { it.path.joinToString("->") }
*
* // Rename all `String` columns with uppercase
* df.rename { colsOf<String>() }.into { it.name.uppercase() }
* ```
*
* @param transform A function that takes a [ColumnWithPath] for each selected column
* and returns the new column name.
* @return A new [DataFrame] with the columns renamed.
*/
public fun <T, C> RenameClause<T, C>.into(transform: (ColumnWithPath<C>) -> String): DataFrame<T> =
renameImpl(transform)

/**
* ## Rename to "camelCase"
*
* Renames the columns, previously selected with [rename] to "camelCase" format.
*
* All delimiters between words are removed, words are capitalized except for the first one.
* Places underscore between numbers.
* If the string does not contain any letters or numbers, it remains unchanged.
Expand All @@ -118,7 +297,15 @@ public fun <T, C> RenameClause<T, C>.into(transform: (ColumnWithPath<C>) -> Stri
* This function supports converting names from `snake_case`, `PascalCase`, and other delimited formats
* into a consistent "camelCase" representation.
*
* ### Examples:
* ### Examples
* ```kotlin
* // Renames "arrival_date" and "passport-ID" columns to "camelCase"
* df.rename("arrival_date", "passport-ID").toCamelCase()
* // Renames all numeric columns to "camelCase"
* df.rename { colsOf<Number>() }.toCamelCase()
* ```
*
* #### Renaming Examples
* ```
* "snake_case_name" -> "snakeCaseName"
* "PascalCaseName" -> "pascalCaseName"
Expand All @@ -137,7 +324,6 @@ public fun <T, C> RenameClause<T, C>.toCamelCase(): DataFrame<T> = into { it.ren
// region DataColumn

/**
* ## Rename to camelCase
*
* Renames this column to "camelCase" format.
* All delimiters between words are removed, words are capitalized except for the first one.
Expand All @@ -149,7 +335,7 @@ public fun <T, C> RenameClause<T, C>.toCamelCase(): DataFrame<T> = into { it.ren
* This function supports converting names from `snake_case`, `PascalCase`, and other delimited formats
* into a consistent "camelCase" representation.
*
* ### Examples:
* #### Renaming Examples
* ```
* "snake_case_name" -> "snakeCaseName"
* "PascalCaseName" -> "pascalCaseName"
Expand All @@ -165,20 +351,44 @@ public fun <T, C : ColumnReference<T>> C.renameToCamelCase(): C =
) as C

@Suppress("UNCHECKED_CAST")
@AccessApiOverload
@Deprecated(DEPRECATED_ACCESS_API)
public fun <T, C : ColumnReference<T>> C.rename(column: KProperty<T>): C = rename(column.columnName) as C

@Suppress("UNCHECKED_CAST")
@AccessApiOverload
@Deprecated(DEPRECATED_ACCESS_API)
public fun <T, C : ColumnReference<T>> C.rename(column: ColumnAccessor<T>): C = rename(column.name()) as C

// endregion

// region named

/**
* Returns a new column reference with the original column values but a new [name].
*
* This is useful when you want to specify an existing column
* (for example, in `select`, `update`, or `rename` operations)
* but give it a different name in the resulting [DataFrame].
*
* ### Example:
* ```kotlin
* // Select "size" column as "dimensions"
* df.select { size named "dimensions" }
* ```
*
* @param name The new name to assign to the column.
* @return A new column with the original structure and values but with the specified [name].
*/
@Suppress("UNCHECKED_CAST")
public infix fun <T, C : ColumnReference<T>> C.named(name: String): C = rename(name) as C

@AccessApiOverload
@Deprecated(DEPRECATED_ACCESS_API)
public infix fun <T, C : ColumnReference<T>> C.named(name: KProperty<*>): C = rename(name)

@AccessApiOverload
@Deprecated(DEPRECATED_ACCESS_API)
public infix fun <T, C : ColumnReference<T>> C.named(name: ColumnAccessor<*>): C = rename(name)

// endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,7 @@ internal interface DocumentationUrls {

/** [See `format` on the documentation website.]({@include [Url]}/format.html) */
interface Format

/** [See `rename` on the documentation website.]({@include [Url]}/rename.html) */
interface Rename
}