Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import org.jetbrains.kotlinx.dataframe.DataFrame
import org.jetbrains.kotlinx.dataframe.DataRow
import org.jetbrains.kotlinx.dataframe.RowExpression
import org.jetbrains.kotlinx.dataframe.annotations.AccessApiOverload
import org.jetbrains.kotlinx.dataframe.annotations.CandidateForRemoval
import org.jetbrains.kotlinx.dataframe.annotations.DataSchema
import org.jetbrains.kotlinx.dataframe.columns.ColumnReference
import org.jetbrains.kotlinx.dataframe.impl.columnName
Expand All @@ -18,14 +17,16 @@ import org.jetbrains.kotlinx.dataframe.indices
import org.jetbrains.kotlinx.dataframe.ncol
import org.jetbrains.kotlinx.dataframe.nrow
import org.jetbrains.kotlinx.dataframe.util.DEPRECATED_ACCESS_API
import org.jetbrains.kotlinx.dataframe.util.MESSAGE_SHORTCUT_1_0
import kotlin.experimental.ExperimentalTypeInference
import kotlin.reflect.KProperty
import kotlin.reflect.KType

@CandidateForRemoval
@Deprecated(MESSAGE_SHORTCUT_1_0, ReplaceWith("values().all { it == null }"), DeprecationLevel.ERROR)
public fun AnyRow.isEmpty(): Boolean = owner.columns().all { it[index] == null }

@CandidateForRemoval
@Suppress("DEPRECATION_ERROR")
@Deprecated(MESSAGE_SHORTCUT_1_0, ReplaceWith("values().any { it != null }"), DeprecationLevel.ERROR)
public fun AnyRow.isNotEmpty(): Boolean = !isEmpty()

public inline fun <reified R> AnyRow.valuesOf(): List<R> = values().filterIsInstance<R>()
Expand Down Expand Up @@ -178,35 +179,50 @@ public fun AnyRow.columnNames(): List<String> = df().columnNames()

public fun AnyRow.columnTypes(): List<KType> = df().columnTypes()

@CandidateForRemoval
@Suppress("DEPRECATION_ERROR")
@Deprecated(MESSAGE_SHORTCUT_1_0, ReplaceWith("df().getRow(index)"), DeprecationLevel.ERROR)
public fun <T> DataRow<T>.getRow(index: Int): DataRow<T> = getRowOrNull(index)!!

@CandidateForRemoval
@Deprecated(MESSAGE_SHORTCUT_1_0, ReplaceWith("df().getRows(indices)"), DeprecationLevel.ERROR)
public fun <T> DataRow<T>.getRows(indices: Iterable<Int>): DataFrame<T> = df().getRows(indices)

@CandidateForRemoval
@Deprecated(MESSAGE_SHORTCUT_1_0, ReplaceWith("df().getRows(indices)"), DeprecationLevel.ERROR)
public fun <T> DataRow<T>.getRows(indices: IntRange): DataFrame<T> = df().getRows(indices)

@CandidateForRemoval
@Deprecated(MESSAGE_SHORTCUT_1_0, ReplaceWith("df().getRowOrNull(index)"), DeprecationLevel.ERROR)
public fun <T> DataRow<T>.getRowOrNull(index: Int): DataRow<T>? {
val df = df()
return if (index >= 0 && index < df.nrow) df[index] else null
}

/**
* Returns the previous [row][DataRow] in the [DataFrame] relative to the current row.
* If the current row is the first row in the [DataFrame], it returns `null`.
*
* @return The previous [DataRow] if it exists, or `null` if the current row is the first in the [DataFrame].
*/
public fun <T> DataRow<T>.prev(): DataRow<T>? {
val index = index()
return if (index > 0) df()[index - 1] else null
}

/**
* Returns the next [row][DataRow] in the [DataFrame] relative to the current row.
* If the current row is the last row in the [DataFrame], it returns `null`.
*
* @return The previous [DataRow] if it exists, or `null` if the current row is the last in the [DataFrame].
*/
public fun <T> DataRow<T>.next(): DataRow<T>? {
val index = index()
val df = df()
return if (index < df.nrow - 1) df[index + 1] else null
}

@Suppress("DEPRECATION_ERROR")
public fun <T> DataRow<T>.relative(relativeIndices: Iterable<Int>): DataFrame<T> =
getRows(relativeIndices.mapNotNull { (index + it).let { if (it >= 0 && it < df().rowsCount()) it else null } })

@Suppress("DEPRECATION_ERROR")
public fun <T> DataRow<T>.relative(relativeIndices: IntRange): DataFrame<T> =
getRows(
(relativeIndices.first + index).coerceIn(df().indices)..(relativeIndices.last + index).coerceIn(df().indices),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package org.jetbrains.kotlinx.dataframe.api

import org.jetbrains.kotlinx.dataframe.DataFrame
import org.jetbrains.kotlinx.dataframe.annotations.CandidateForRemoval
import org.jetbrains.kotlinx.dataframe.util.MESSAGE_SHORTCUT_1_0

// region DataFrame

@CandidateForRemoval
@Deprecated(MESSAGE_SHORTCUT_1_0, ReplaceWith("columns().toDataFrame().cast()"), DeprecationLevel.ERROR)
Copy link
Collaborator

Choose a reason for hiding this comment

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

we also usually put the replaceWith contents in the deprecations file. I'm impartial to it, as long as we have at least one constant String there to track the deprecations

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't like it, because it's hard to validate when it's remote, especially in singular cases + losing IDE code analysis.
And btw we have a lot of them in the project:
image

Copy link
Collaborator

Choose a reason for hiding this comment

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

makes sense :)

public fun <T> DataFrame<T>.copy(): DataFrame<T> = columns().toDataFrame().cast()

// endregion
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public fun <T, C, R> Merge<T, C, R>.intoList(): List<R> =
public fun <T, C, R> MergeWithTransform<T, C, R>.intoList(): List<R> =
df.select(selector).rows().map { transform(it, it.values() as List<C>) }

@Suppress("DEPRECATION_ERROR")
public fun <T, C, R> MergeWithTransform<T, C, R>.into(path: ColumnPath): DataFrame<T> {
// If target path exists, merge into temp path
val mergePath = if (df.getColumnOrNull(path) != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import org.jetbrains.kotlinx.dataframe.ColumnSelector
import org.jetbrains.kotlinx.dataframe.ColumnsSelector
import org.jetbrains.kotlinx.dataframe.DataFrame
import org.jetbrains.kotlinx.dataframe.annotations.AccessApiOverload
import org.jetbrains.kotlinx.dataframe.annotations.CandidateForRemoval
import org.jetbrains.kotlinx.dataframe.annotations.Interpretable
import org.jetbrains.kotlinx.dataframe.annotations.Refine
import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup
Expand All @@ -24,6 +23,7 @@ import org.jetbrains.kotlinx.dataframe.impl.api.moveImpl
import org.jetbrains.kotlinx.dataframe.impl.api.moveTo
import org.jetbrains.kotlinx.dataframe.ncol
import org.jetbrains.kotlinx.dataframe.util.DEPRECATED_ACCESS_API
import org.jetbrains.kotlinx.dataframe.util.MESSAGE_SHORTCUT_1_0
import org.jetbrains.kotlinx.dataframe.util.MOVE_TO_LEFT
import org.jetbrains.kotlinx.dataframe.util.MOVE_TO_LEFT_REPLACE
import org.jetbrains.kotlinx.dataframe.util.MOVE_TO_RIGHT
Expand Down Expand Up @@ -409,7 +409,7 @@ public fun <T, C> MoveClause<T, C>.into(
/**
* Move a single selected column to top level with a new name
*/
@CandidateForRemoval
@Deprecated(MESSAGE_SHORTCUT_1_0, ReplaceWith("into { pathOf(column) }"), DeprecationLevel.ERROR)
@Refine
@Interpretable("MoveInto0")
public fun <T, C> MoveClause<T, C>.into(column: String): DataFrame<T> = pathOf(column).let { path -> into { path } }
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you remember why we want to remove it? It's supported by compiler plugin, seems useful

Copy link
Collaborator

Choose a reason for hiding this comment

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

is it just rename {}.into {} maybe? or move {}.under("")?

Copy link
Collaborator

Choose a reason for hiding this comment

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

it's move { myCol }.toTop().rename { myCol }.into("newName")

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well, I really don't see a reason 😄 . Let's keep it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

move { myCol }.toTop().rename { myCol }.into("newName")

or, you know move { myCol }.into(pathOf("newName")) ;P

Copy link
Collaborator

Choose a reason for hiding this comment

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

but yes, let's keep it, as we treat column paths and the String API as the same thing :)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,15 @@ package org.jetbrains.kotlinx.dataframe.impl.aggregation.modes

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.RowExpression
import org.jetbrains.kotlinx.dataframe.annotations.CandidateForRemoval
import org.jetbrains.kotlinx.dataframe.api.GroupBy
import org.jetbrains.kotlinx.dataframe.api.Grouped
import org.jetbrains.kotlinx.dataframe.api.asSequence
import org.jetbrains.kotlinx.dataframe.api.cast
import org.jetbrains.kotlinx.dataframe.api.getOrNull
import org.jetbrains.kotlinx.dataframe.columns.ColumnReference
import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregateInternal
import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator
import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.indexOfAggregationResult
import org.jetbrains.kotlinx.dataframe.impl.namedValues
import kotlin.reflect.typeOf

@CandidateForRemoval
internal fun <T> Grouped<T>.aggregateByOrNull(body: DataFrameExpression<T, DataRow<T>?>): DataFrame<T> {
require(this is GroupBy<*, T>)
val keyColumns = keys.columnNames().toSet()
return aggregateInternal {
val row = body(df, df)
row?.namedValues()?.forEach {
if (!keyColumns.contains(it.name)) yield(it)
}
}.cast()
}

/**
* Selects the best matching value in the [sequence][values]
* using the provided [Aggregator] `by` the provided [selector].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ internal const val INSERT_AFTER_COL_PATH =
"This `after()` overload will be removed in favor of `after { }` with Column Selection DSL. $MESSAGE_1_0"
internal const val INSERT_AFTER_COL_PATH_REPLACE = "this.after { columnPath }"

internal const val MESSAGE_SHORTCUT_1_0 = "This shortcut is deprecated. $MESSAGE_1_0"

// endregion

// region WARNING in 1.0, ERROR in 1.1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ class ConstructorsTests {
col.type() shouldBe typeOf<AnyRow>()
col.kind() shouldBe ColumnKind.Group
col[0] shouldBe row
@Suppress("DEPRECATION_ERROR")
Copy link
Collaborator

Choose a reason for hiding this comment

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

If we deprecate them, we should probably remove any internal uses

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

for DataRow.isEmpty(), I'd make it internal after deprecation and public removal for such tests.

Copy link
Collaborator

@Jolanrensen Jolanrensen Oct 6, 2025

Choose a reason for hiding this comment

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

good idea! But we should put somewhere that we will make it internal maybe. Or should we have this deprecation suppression mechanism being seen as "we're planning not to remove it but to make it internal"?

col[1].isEmpty() shouldBe true
}

Expand All @@ -103,7 +104,9 @@ class ConstructorsTests {
col.type() shouldBe typeOf<AnyRow>()
col.kind() shouldBe ColumnKind.Group
col[0] shouldBe row
@Suppress("DEPRECATION_ERROR")
col[1]!!.isEmpty() shouldBe true
@Suppress("DEPRECATION_ERROR")
col[2]!!.isEmpty() shouldBe true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class SumTests {
}
}

@Suppress("DEPRECATION_ERROR")
@Test
fun `unknown number type`() {
columnOf(1.toBigDecimal(), 2.toBigDecimal()).toDataFrame()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2464,6 +2464,7 @@ class DataFrameTests : BaseTest() {
df.comparableNothing.valuesAreComparable() shouldBe false
}

@Suppress("DEPRECATION_ERROR")
// https://github.com/Kotlin/dataframe/pull/1077#discussion_r1981352374
@Test
fun `values are comparable difficult`() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ class DataFrameTreeTests : BaseTest() {

@Test
fun `move`() {
val actual = typed2.move { nameAndCity.name }.into("name")
val actual = typed2.move { nameAndCity.name }.into { pathOf("name") }
actual.columnNames() shouldBe listOf("nameAndCity", "name", "age", "weight")
actual.getColumnGroup("nameAndCity").columnNames() shouldBe listOf("city")
}
Expand Down Expand Up @@ -368,6 +368,7 @@ class DataFrameTreeTests : BaseTest() {
df2.pivot { it["nameAndCity"]["city"] }.groupBy { it["nameAndCity"]["name"] }.values("age").check()
}

@Suppress("DEPRECATION_ERROR")
@Test
fun `pivot grouped column`() {
val grouped = typed.group { age and weight }.into("info")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import org.jetbrains.kotlinx.dataframe.api.NullabilityOptions
import org.jetbrains.kotlinx.dataframe.api.add
import org.jetbrains.kotlinx.dataframe.api.columnOf
import org.jetbrains.kotlinx.dataframe.api.convertToBoolean
import org.jetbrains.kotlinx.dataframe.api.copy
import org.jetbrains.kotlinx.dataframe.api.dataFrameOf
import org.jetbrains.kotlinx.dataframe.api.map
import org.jetbrains.kotlinx.dataframe.api.pathOf
Expand Down Expand Up @@ -354,7 +353,7 @@ internal class ArrowKtTest {

@Test
fun testNarrowing() {
val frameWithoutRequiredField = citiesExampleFrame.copy().remove("settled")
val frameWithoutRequiredField = citiesExampleFrame.remove("settled")

frameWithoutRequiredField.arrowWriter(
targetSchema = Schema.fromJSON(citiesExampleSchema),
Expand All @@ -381,7 +380,7 @@ internal class ArrowKtTest {

@Test
fun testStrictType() {
val frameRenaming = citiesExampleFrame.copy().remove("settled")
val frameRenaming = citiesExampleFrame.remove("settled")
val frameWithIncompatibleField =
frameRenaming.add(
frameRenaming["is_capital"]
Expand Down Expand Up @@ -424,7 +423,7 @@ internal class ArrowKtTest {

@Test
fun testStrictNullable() {
val frameRenaming = citiesExampleFrame.copy().remove("settled")
val frameRenaming = citiesExampleFrame.remove("settled")
val frameWithNulls = frameRenaming.add(
DataColumn.createValueColumn(
"settled",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.jetbrains.kotlinx.dataframe.api.after
import org.jetbrains.kotlinx.dataframe.api.into
import org.jetbrains.kotlinx.dataframe.api.move
import org.jetbrains.kotlinx.dataframe.api.moveToStart
import org.jetbrains.kotlinx.dataframe.api.pathOf
import org.jetbrains.kotlinx.dataframe.api.to
import org.jetbrains.kotlinx.dataframe.api.toStart
import org.jetbrains.kotlinx.dataframe.api.toEnd
Expand Down Expand Up @@ -62,7 +63,7 @@ class MoveInto0 : AbstractSchemaModificationInterpreter() {

override fun Arguments.interpret(): PluginDataFrameSchema {
val columns = receiver.columns.resolve(receiver.df).map { it.path }
return receiver.df.asDataFrame().move { columns.toColumnSet() }.into(column).toPluginDataFrameSchema()
return receiver.df.asDataFrame().move { columns.toColumnSet() }.into{ pathOf(column) }.toPluginDataFrameSchema()
}
}

Expand Down
Loading