diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/Plugin.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/Plugin.kt index 1fbebc83b..0493f6254 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/Plugin.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/annotations/Plugin.kt @@ -8,12 +8,12 @@ public annotation class HasSchema(val schemaArg: Int) * Needed because some function calls only serve as a part of overall compile time DataSchema evaluation * There's no need to update return type of such calls */ -internal annotation class Interpretable(val interpreter: String) +public annotation class Interpretable(val interpreter: String) /** * Compiler plugin will replace return type of calls to the annotated function */ -internal annotation class Refine +public annotation class Refine internal annotation class OptInRefine diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt index 8d3c8cfa9..9f093ae24 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt @@ -69,6 +69,7 @@ private interface CommonFillNullsFunctionDoc * @include [SelectingColumns.Dsl.WithExample] {@include [SetFillNullsOperationArg]} * @include [Update.DslParam] */ +@Interpretable("FillNulls0") public fun DataFrame.fillNulls(columns: ColumnsSelector): Update = update(columns).where { it == null } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/constructors.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/constructors.kt index 497959e7c..ae1cc8e88 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/constructors.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/constructors.kt @@ -9,6 +9,8 @@ import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.RowExpression +import org.jetbrains.kotlinx.dataframe.annotations.Interpretable +import org.jetbrains.kotlinx.dataframe.annotations.Refine import org.jetbrains.kotlinx.dataframe.columns.ColumnAccessor import org.jetbrains.kotlinx.dataframe.columns.ColumnPath import org.jetbrains.kotlinx.dataframe.columns.ColumnReference @@ -18,6 +20,7 @@ import org.jetbrains.kotlinx.dataframe.exceptions.UnequalColumnSizesException import org.jetbrains.kotlinx.dataframe.impl.ColumnNameGenerator import org.jetbrains.kotlinx.dataframe.impl.DataFrameImpl import org.jetbrains.kotlinx.dataframe.impl.UNNAMED_COLUMN_PREFIX +import org.jetbrains.kotlinx.dataframe.impl.api.withValuesImpl import org.jetbrains.kotlinx.dataframe.impl.asList import org.jetbrains.kotlinx.dataframe.impl.columnName import org.jetbrains.kotlinx.dataframe.impl.columns.ColumnAccessorImpl @@ -268,6 +271,7 @@ public fun dataFrameOf(vararg header: ColumnReference<*>): DataFrameBuilder = Da public fun dataFrameOf(vararg columns: AnyBaseCol): AnyFrame = dataFrameOf(columns.asIterable()) +@Interpretable("DataFrameOf0") public fun dataFrameOf(vararg header: String): DataFrameBuilder = dataFrameOf(header.toList()) public inline fun dataFrameOf(vararg header: String, fill: (String) -> Iterable): AnyFrame = @@ -302,27 +306,15 @@ public class DataFrameBuilder(private val header: List) { }.toDataFrame() } + @Refine + @Interpretable("DataFrameBuilderInvoke0") public operator fun invoke(vararg values: Any?): AnyFrame = withValues(values.asIterable()) @JvmName("invoke1") - internal fun withValues(values: Iterable): AnyFrame { - val list = values.asList() - - val ncol = header.size - - require(header.isNotEmpty() && list.size.rem(ncol) == 0) { - "Number of values ${list.size} is not divisible by number of columns $ncol" - } - - val nrow = list.size / ncol - - return (0 until ncol).map { col -> - val colValues = (0 until nrow).map { row -> - list[row * ncol + col] - } - DataColumn.createWithTypeInference(header[col], colValues) + internal fun withValues(values: Iterable): AnyFrame = + withValuesImpl(header, values.asList()).map { (name, values) -> + DataColumn.createWithTypeInference(name, values) }.toDataFrame() - } public operator fun invoke(args: Sequence): AnyFrame = invoke(*args.toList().toTypedArray()) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/convert.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/convert.kt index 2ead3f759..7b6ff3f23 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/convert.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/convert.kt @@ -94,6 +94,7 @@ public inline fun Convert.notNull( public class Convert(internal val df: DataFrame, internal val columns: ColumnsSelector) { public fun cast(): Convert = Convert(df, columns as ColumnsSelector) + @Refine @Interpretable("To0") public inline fun to(): DataFrame = to(typeOf()) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/flatten.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/flatten.kt index b4dd6be35..07102bac1 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/flatten.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/flatten.kt @@ -2,6 +2,8 @@ package org.jetbrains.kotlinx.dataframe.api import org.jetbrains.kotlinx.dataframe.ColumnsSelector import org.jetbrains.kotlinx.dataframe.DataFrame +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.impl.api.flattenImpl @@ -9,9 +11,13 @@ import kotlin.reflect.KProperty // region DataFrame +@Refine +@Interpretable("FlattenDefault") public fun DataFrame.flatten(keepParentNameForColumns: Boolean = false, separator: String = "."): DataFrame = flatten(keepParentNameForColumns, separator) { all() } +@Refine +@Interpretable("Flatten0") public fun DataFrame.flatten( keepParentNameForColumns: Boolean = false, separator: String = ".", diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt index 31a6093ce..cdc56fccb 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt @@ -202,6 +202,13 @@ public abstract class CreateDataFrameDsl : TraversePropertiesDsl { public abstract operator fun String.invoke(builder: CreateDataFrameDsl.() -> Unit) } +@Refine +@Interpretable("ToDataFrameColumn") +public inline fun Iterable.toDataFrame(columnName: String): DataFrame<*> = + toDataFrame { + columnName from { it } + } + // endregion // region toDataFrame overloads for built-in types @@ -304,6 +311,8 @@ public interface ValueProperty { public val value: T } +// endregion + // region Create DataFrame from Map public fun Map>.toDataFrame(): AnyFrame = diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/update.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/update.kt index dde10ee9f..8c3f169e9 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/update.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/update.kt @@ -8,6 +8,8 @@ import org.jetbrains.kotlinx.dataframe.DataFrameExpression import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.RowColumnExpression import org.jetbrains.kotlinx.dataframe.RowValueFilter +import org.jetbrains.kotlinx.dataframe.annotations.Interpretable +import org.jetbrains.kotlinx.dataframe.annotations.Refine import org.jetbrains.kotlinx.dataframe.api.Update.Grammar import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.columns.ColumnReference @@ -273,7 +275,9 @@ public typealias UpdateExpression = AddDataRow.(C) -> R * - {@include [SeeAlsoPerRowCol]} * @param [expression] The {@include [ExpressionsGivenRow.RowValueExpressionLink]} to update the rows with. */ -public fun Update.with(expression: UpdateExpression): DataFrame = +@Refine +@Interpretable("UpdateWith0") +public fun Update.with(expression: UpdateExpression): DataFrame = updateImpl { row, _, value -> expression(row, value) } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt index 316473704..1ec8f6763 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt @@ -436,6 +436,8 @@ internal fun guessValueType(values: Sequence, upperBound: KType? = null, l collectionClasses.add(it.javaClass.kotlin) } + is Function<*> -> classes.add(Function::class) + else -> classes.add(it.javaClass.kotlin) } } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/constructors.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/constructors.kt new file mode 100644 index 000000000..ba166e3e2 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api/constructors.kt @@ -0,0 +1,18 @@ +package org.jetbrains.kotlinx.dataframe.impl.api + +internal fun withValuesImpl(header: List, values: List): List>> { + val ncol = header.size + + require(header.isNotEmpty() && values.size.rem(ncol) == 0) { + "Number of values ${values.size} is not divisible by number of columns $ncol" + } + + val nrow = values.size / ncol + + return (0 until ncol).map { col -> + val colValues = (0 until nrow).map { row -> + values[row * ncol + col] + } + header[col] to colValues + } +} diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt index 2f159e6fc..7a68f5d3f 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlinx.dataframe.kind import org.jetbrains.kotlinx.dataframe.type import org.junit.Ignore import org.junit.Test +import java.io.File import kotlin.reflect.KProperty import kotlin.reflect.typeOf @@ -452,4 +453,11 @@ class CreateDataFrameTests { df.participants[0].city } } + + @Test + fun toDataFrameColumn() { + val files = listOf(File("data.csv")) + val df = files.toDataFrame(columnName = "files") + df["files"][0] shouldBe File("data.csv") + } } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Create.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Create.kt index 6ed6986f8..b98992df6 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Create.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Create.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlinx.dataframe.explainer.TransformDataFrameExpressions import org.jetbrains.kotlinx.dataframe.kind import org.jetbrains.kotlinx.dataframe.type import org.junit.Test +import java.io.File import kotlin.reflect.typeOf class Create : TestBase() { @@ -456,4 +457,13 @@ class Create : TestBase() { peek(dataFrameOf(col), dataFrameOf(col)) // SampleEnd } + + @Test + @TransformDataFrameExpressions + fun toDataFrameColumn() { + // SampleStart + val files = listOf(File("data.csv"), File("data1.csv")) + val df = files.toDataFrame(columnName = "data") + // SampleEnd + } } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/person/DataFrameTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/person/DataFrameTests.kt index b1e738b4c..63ee6c5e0 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/person/DataFrameTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/person/DataFrameTests.kt @@ -217,6 +217,13 @@ class DataFrameTests : BaseTest() { dataFrameOf("name", "age", "city", "weight")(c1, c2, c3, c4) shouldBe df } + @Test + fun `guess column type for type without classifier`() { + val df = dataFrameOf("a", "b")({ 1 }, 2) + df["a"].type() shouldBe typeOf>() + (df["a"][0] as () -> Int).invoke() shouldBe 1 + } + @Test fun `create with columnOf`() { val col = columnOf("Alice", "Bob") diff --git a/dataframe-excel/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/xlsx.kt b/dataframe-excel/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/xlsx.kt index 315405e2f..a66f8abd1 100644 --- a/dataframe-excel/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/xlsx.kt +++ b/dataframe-excel/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/xlsx.kt @@ -24,6 +24,8 @@ import org.jetbrains.kotlinx.dataframe.AnyRow import org.jetbrains.kotlinx.dataframe.ColumnsSelector import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.annotations.Interpretable +import org.jetbrains.kotlinx.dataframe.annotations.Refine import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.forEach import org.jetbrains.kotlinx.dataframe.api.select @@ -143,6 +145,8 @@ public fun DataFrame.Companion.readExcel( * @param nameRepairStrategy handling of column names. * The default behavior is [NameRepairStrategy.CHECK_UNIQUE] */ +@Refine +@Interpretable("ReadExcel") public fun DataFrame.Companion.readExcel( fileOrUrl: String, sheetName: String? = null, @@ -209,7 +213,9 @@ public fun DataFrame.Companion.readExcel( * @param range comma separated list of Excel column letters and column ranges (e.g. “A:E” or “A,C,E:F”) */ @JvmInline -public value class StringColumns(public val range: String) +public value class StringColumns + @Interpretable("StringColumns") + constructor(public val range: String) public fun StringColumns.toFormattingOptions(formatter: DataFormatter = DataFormatter()): FormattingOptions = FormattingOptions(range, formatter) diff --git a/docs/StardustDocs/snippets/org.jetbrains.kotlinx.dataframe.samples.api.Create.toDataFrameColumn.html b/docs/StardustDocs/snippets/org.jetbrains.kotlinx.dataframe.samples.api.Create.toDataFrameColumn.html new file mode 100644 index 000000000..57c150c30 --- /dev/null +++ b/docs/StardustDocs/snippets/org.jetbrains.kotlinx.dataframe.samples.api.Create.toDataFrameColumn.html @@ -0,0 +1,466 @@ + + + + + +
+ +

+ + + diff --git a/docs/StardustDocs/topics/createDataFrame.md b/docs/StardustDocs/topics/createDataFrame.md index 023d76012..65c78324e 100644 --- a/docs/StardustDocs/topics/createDataFrame.md +++ b/docs/StardustDocs/topics/createDataFrame.md @@ -151,6 +151,19 @@ df.add("length") { value.length } +Creates a [`DataFrame`](DataFrame.md) from [`Iterable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-iterable/) with one column: +"columnName: `DataColumn`". + + + +```kotlin +val files = listOf(File("data.csv"), File("data1.csv")) +val df = files.toDataFrame(columnName = "data") +``` + + + + Creates a [`DataFrame`](DataFrame.md) from an [`Iterable`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-iterable/) of objects: diff --git a/plugins/kotlin-dataframe/build.gradle.kts b/plugins/kotlin-dataframe/build.gradle.kts index a28ebc9fd..6c21ce80a 100644 --- a/plugins/kotlin-dataframe/build.gradle.kts +++ b/plugins/kotlin-dataframe/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { testRuntimeOnly("org.jetbrains.kotlin:kotlin-annotations-jvm:$kotlinVersion") implementation(project(":core")) + implementation(project(":dataframe-excel")) api(libs.kotlinLogging) api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.4.0-RC") diff --git a/plugins/kotlin-dataframe/gradle.properties b/plugins/kotlin-dataframe/gradle.properties index c97a3b48c..5bcaad8f1 100644 --- a/plugins/kotlin-dataframe/gradle.properties +++ b/plugins/kotlin-dataframe/gradle.properties @@ -1,2 +1,2 @@ kotlin.code.style=official -kotlinVersion=2.0.20-Beta2-78 +kotlinVersion=2.0.20-RC2 diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/FunctionCallTransformer.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/FunctionCallTransformer.kt index 3e2715c91..6b4fe2be1 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/FunctionCallTransformer.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/extensions/FunctionCallTransformer.kt @@ -364,8 +364,13 @@ class FunctionCallTransformer( resolvedSymbol = parameterSymbol } } + if (callDispatchReceiver != null) { + call.replaceDispatchReceiver(itPropertyAccess) + } call.replaceExplicitReceiver(itPropertyAccess) - call.replaceExtensionReceiver(itPropertyAccess) + if (callExtensionReceiver != null) { + call.replaceExtensionReceiver(itPropertyAccess) + } result = call this.target = target } @@ -403,9 +408,9 @@ class FunctionCallTransformer( } variance = Variance.INVARIANT } - dispatchReceiver = callDispatchReceiver + dispatchReceiver = null this.explicitReceiver = callExplicitReceiver - extensionReceiver = callExtensionReceiver + extensionReceiver = callExtensionReceiver ?: callDispatchReceiver argumentList = buildResolvedArgumentList(original = null, linkedMapOf(argument to parameter.fir)) calleeReference = buildResolvedNamedReference { source = call.calleeReference.source diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/DataFrameAdapter.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/DataFrameAdapter.kt new file mode 100644 index 000000000..185578aa5 --- /dev/null +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/DataFrameAdapter.kt @@ -0,0 +1,38 @@ +package org.jetbrains.kotlinx.dataframe.plugin.impl + +import org.jetbrains.kotlinx.dataframe.AnyCol +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.api.cast +import org.jetbrains.kotlinx.dataframe.api.dataFrameOf +import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup +import org.jetbrains.kotlinx.dataframe.columns.FrameColumn +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.TypeApproximation + +fun PluginDataFrameSchema.asDataFrame(): DataFrame = columns().map() + +fun DataFrame.toPluginDataFrameSchema() = PluginDataFrameSchema(columns().mapBack()) + +interface ConeTypesAdapter + +private fun List.map(): DataFrame = map { + when (it) { + is SimpleDataColumn -> DataColumn.create(it.name, listOf(it.type)) + is SimpleColumnGroup -> DataColumn.createColumnGroup(it.name, it.columns().map()) + is SimpleFrameColumn -> DataColumn.createFrameColumn(it.name, listOf(it.columns().map())) + } +}.let { dataFrameOf(it).cast() } + +private fun List.mapBack(): List = map { + when (it) { + is ColumnGroup<*> -> { + SimpleColumnGroup(it.name(), it.columns().mapBack()) + } + is FrameColumn<*> -> { + SimpleFrameColumn(it.name(), it[0].columns().mapBack()) + } + else -> { + SimpleDataColumn(it.name(), it[0] as TypeApproximation) + } + } +} diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/dataFrameOf.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/dataFrameOf.kt new file mode 100644 index 000000000..bae8d7b6a --- /dev/null +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/dataFrameOf.kt @@ -0,0 +1,38 @@ +@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") +package org.jetbrains.kotlinx.dataframe.plugin.impl.api + +import org.jetbrains.kotlin.fir.expressions.FirVarargArgumentsExpression +import org.jetbrains.kotlin.fir.types.commonSuperTypeOrNull +import org.jetbrains.kotlin.fir.types.resolvedType +import org.jetbrains.kotlin.fir.types.typeContext +import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractInterpreter +import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractSchemaModificationInterpreter +import org.jetbrains.kotlinx.dataframe.plugin.impl.Arguments +import org.jetbrains.kotlinx.dataframe.plugin.impl.Interpreter +import org.jetbrains.kotlinx.dataframe.plugin.impl.PluginDataFrameSchema +import org.jetbrains.kotlinx.dataframe.plugin.impl.simpleColumnOf +import org.jetbrains.kotlinx.dataframe.plugin.impl.varargString +import org.jetbrains.kotlinx.dataframe.impl.api.withValuesImpl + +class DataFrameOf0 : AbstractInterpreter() { + val Arguments.header: List by varargString() + + override fun Arguments.interpret(): DataFrameBuilderApproximation { + return DataFrameBuilderApproximation(header) + } +} + +class DataFrameBuilderApproximation(val header: List) + +class DataFrameBuilderInvoke0 : AbstractSchemaModificationInterpreter() { + val Arguments.receiver: DataFrameBuilderApproximation by arg() + val Arguments.values: FirVarargArgumentsExpression by arg(lens = Interpreter.Id) + + override fun Arguments.interpret(): PluginDataFrameSchema { + val columns = withValuesImpl(receiver.header, values.arguments).map { (name, values) -> + val type = session.typeContext.commonSuperTypeOrNull(values.map { it.resolvedType }) ?: error("$name $values") + simpleColumnOf(name, type) + } + return PluginDataFrameSchema(columns) + } +} diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/fillNulls.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/fillNulls.kt new file mode 100644 index 000000000..7474230fe --- /dev/null +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/fillNulls.kt @@ -0,0 +1,28 @@ +package org.jetbrains.kotlinx.dataframe.plugin.impl.api + +import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractInterpreter +import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractSchemaModificationInterpreter +import org.jetbrains.kotlinx.dataframe.plugin.impl.Arguments +import org.jetbrains.kotlinx.dataframe.plugin.impl.PluginDataFrameSchema +import org.jetbrains.kotlinx.dataframe.plugin.impl.dataFrame +import org.jetbrains.kotlinx.dataframe.plugin.impl.type + +class FillNulls0 : AbstractInterpreter() { + val Arguments.receiver: PluginDataFrameSchema by dataFrame() + val Arguments.columns: ColumnsResolver by arg() + + override fun Arguments.interpret(): FillNullsApproximation { + return FillNullsApproximation(receiver, columns) + } +} + +class FillNullsApproximation(val schema: PluginDataFrameSchema, val columns: ColumnsResolver) + +class UpdateWith0 : AbstractSchemaModificationInterpreter() { + val Arguments.receiver: FillNullsApproximation by arg() + val Arguments.expression: TypeApproximation by type() + + override fun Arguments.interpret(): PluginDataFrameSchema { + return convertImpl(receiver.schema, receiver.columns.resolve(receiver.schema).map { it.path.path }, expression) + } +} diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/flatten.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/flatten.kt new file mode 100644 index 000000000..6677a0f74 --- /dev/null +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/flatten.kt @@ -0,0 +1,38 @@ +package org.jetbrains.kotlinx.dataframe.plugin.impl.api + +import org.jetbrains.kotlinx.dataframe.api.flatten +import org.jetbrains.kotlinx.dataframe.api.pathOf +import org.jetbrains.kotlinx.dataframe.columns.toColumnSet +import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractSchemaModificationInterpreter +import org.jetbrains.kotlinx.dataframe.plugin.impl.Arguments +import org.jetbrains.kotlinx.dataframe.plugin.impl.PluginDataFrameSchema +import org.jetbrains.kotlinx.dataframe.plugin.impl.Present +import org.jetbrains.kotlinx.dataframe.plugin.impl.asDataFrame +import org.jetbrains.kotlinx.dataframe.plugin.impl.dataFrame +import org.jetbrains.kotlinx.dataframe.plugin.impl.toPluginDataFrameSchema + +class FlattenDefault : AbstractSchemaModificationInterpreter() { + val Arguments.receiver by dataFrame() + val Arguments.keepParentNameForColumns: Boolean by arg(defaultValue = Present(false)) + val Arguments.separator: String by arg(defaultValue = Present(".")) + + override fun Arguments.interpret(): PluginDataFrameSchema { + return receiver.asDataFrame().flatten(keepParentNameForColumns, separator).toPluginDataFrameSchema() + } +} + +class Flatten0 : AbstractSchemaModificationInterpreter() { + val Arguments.receiver by dataFrame() + val Arguments.keepParentNameForColumns: Boolean by arg(defaultValue = Present(false)) + val Arguments.separator: String by arg(defaultValue = Present(".")) + val Arguments.columns: ColumnsResolver by arg() + + override fun Arguments.interpret(): PluginDataFrameSchema { + val columns = columns.resolve(receiver).map { pathOf(*it.path.path.toTypedArray()) } + return receiver + .asDataFrame() + .flatten(keepParentNameForColumns, separator) { columns.toColumnSet() } + .toPluginDataFrameSchema() + } +} + diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/read.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/read.kt index 2191b790e..282fe2a5f 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/read.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/read.kt @@ -7,11 +7,17 @@ import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractInterpreter import org.jetbrains.kotlinx.dataframe.plugin.impl.Arguments import org.jetbrains.kotlinx.dataframe.plugin.impl.Present import org.jetbrains.kotlinx.dataframe.api.schema +import org.jetbrains.kotlinx.dataframe.io.JSON +import org.jetbrains.kotlinx.dataframe.io.JSON.TypeClashTactic.ARRAY_AND_VALUE_COLUMNS +import org.jetbrains.kotlinx.dataframe.io.NameRepairStrategy +import org.jetbrains.kotlinx.dataframe.io.StringColumns import org.jetbrains.kotlinx.dataframe.io.read import org.jetbrains.kotlinx.dataframe.io.readCSV import org.jetbrains.kotlinx.dataframe.io.readDelimStr +import org.jetbrains.kotlinx.dataframe.io.readExcel import org.jetbrains.kotlinx.dataframe.io.readJson import org.jetbrains.kotlinx.dataframe.io.readJsonStr +import org.jetbrains.kotlinx.dataframe.plugin.impl.AbstractSchemaModificationInterpreter import org.jetbrains.kotlinx.dataframe.plugin.impl.PluginDataFrameSchema import org.jetbrains.kotlinx.dataframe.plugin.impl.data.IoSchema import org.jetbrains.kotlinx.dataframe.plugin.impl.data.deserializeToPluginDataFrameSchema @@ -30,13 +36,17 @@ internal class Read0 : AbstractInterpreter() { internal class ReadCSV0 : AbstractInterpreter() { val Arguments.fileOrUrl: String by arg() + val Arguments.delimiter: Char by arg(defaultValue = Present(',')) + val Arguments.skipLines: Int by arg(defaultValue = Present(0)) + val Arguments.readLines: Int? by arg(defaultValue = Present(null)) + val Arguments.duplicate: Boolean by arg(defaultValue = Present(true)) override fun Arguments.interpret(): PluginDataFrameSchema { val file = resolveFile(resolutionPath, fileOrUrl) val df = if (file != null && file.exists()) { - DataFrame.readCSV(file) + DataFrame.readCSV(file, delimiter, skipLines = skipLines, readLines = readLines, duplicate = duplicate) } else { - DataFrame.readCSV(fileOrUrl) + DataFrame.readCSV(fileOrUrl, delimiter, skipLines = skipLines, readLines = readLines, duplicate = duplicate) } return df.schema().toPluginDataFrameSchema() } @@ -91,17 +101,42 @@ private fun resolveFile(resolutionPath: String?, path: String): File? { internal class ReadDelimStr : AbstractInterpreter() { val Arguments.text: String by arg() val Arguments.delimiter: Char by arg(defaultValue = Present(',')) + val Arguments.skipLines: Int by arg(defaultValue = Present(0)) + val Arguments.readLines: Int? by arg(defaultValue = Present(null)) override fun Arguments.interpret(): PluginDataFrameSchema { - return DataFrame.readDelimStr(text, delimiter).schema().toPluginDataFrameSchema() + return DataFrame.readDelimStr(text, delimiter, skipLines = skipLines, readLines = readLines).schema().toPluginDataFrameSchema() } } internal class ReadJsonStr : AbstractInterpreter() { val Arguments.text: String by arg() + val Arguments.typeClashTactic: JSON.TypeClashTactic by arg(defaultValue = Present(ARRAY_AND_VALUE_COLUMNS)) override fun Arguments.interpret(): PluginDataFrameSchema { - return DataFrame.readJsonStr(text).schema().toPluginDataFrameSchema() + return DataFrame.readJsonStr(text, typeClashTactic = typeClashTactic).schema().toPluginDataFrameSchema() } } +internal class ReadExcel : AbstractSchemaModificationInterpreter() { + val Arguments.fileOrUrl: String by arg() + val Arguments.sheetName: String? by arg(defaultValue = Present(null)) + val Arguments.skipRows: Int by arg(defaultValue = Present(0)) + val Arguments.columns: String? by arg(defaultValue = Present(null)) + val Arguments.stringColumns: StringColumns? by arg(defaultValue = Present(null)) + val Arguments.rowsCount: Int? by arg(defaultValue = Present(null)) + val Arguments.nameRepairStrategy: NameRepairStrategy by arg(defaultValue = Present(NameRepairStrategy.CHECK_UNIQUE)) + + override fun Arguments.interpret(): PluginDataFrameSchema { + val df = DataFrame.readExcel(fileOrUrl, sheetName, skipRows, columns, stringColumns, rowsCount, nameRepairStrategy) + return df.schema().toPluginDataFrameSchema() + } +} + +internal class StringColumnsConstructor : AbstractInterpreter() { + val Arguments.range: String by arg() + + override fun Arguments.interpret(): StringColumns { + return StringColumns(range) + } +} diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/toDataFrame.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/toDataFrame.kt index 29d76d533..91d075cd5 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/toDataFrame.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/toDataFrame.kt @@ -87,6 +87,16 @@ class ToDataFrameDefault : AbstractSchemaModificationInterpreter() { } } +class ToDataFrameColumn : AbstractSchemaModificationInterpreter() { + val Arguments.receiver: FirExpression? by arg(lens = Interpreter.Id) + val Arguments.typeArg0 by type() + val Arguments.columnName: String by arg() + + override fun Arguments.interpret(): PluginDataFrameSchema { + return PluginDataFrameSchema(listOf(simpleColumnOf(columnName, typeArg0.type))) + } +} + private const val DEFAULT_MAX_DEPTH = 0 class Properties0 : AbstractInterpreter() { diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/interpret.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/interpret.kt index d69f0ef02..a03804d14 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/interpret.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/interpret.kt @@ -78,6 +78,7 @@ import org.jetbrains.kotlinx.dataframe.plugin.impl.SimpleColumnGroup import org.jetbrains.kotlinx.dataframe.plugin.impl.SimpleFrameColumn import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ColumnsResolver import org.jetbrains.kotlinx.dataframe.plugin.impl.api.SingleColumnApproximation +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.TypeApproximation fun KotlinTypeFacade.interpret( functionCall: FirFunctionCall, @@ -374,19 +375,23 @@ private fun KotlinTypeFacade.columnWithPathApproximations(result: FirPropertyAcc } } -private fun KotlinTypeFacade.columnOf(it: FirPropertySymbol, mapping: Map): SimpleCol? = - when { +private fun KotlinTypeFacade.columnOf(it: FirPropertySymbol, mapping: Map): SimpleCol? { + val annotation = it.getAnnotationByClassId(Names.COLUMN_NAME_ANNOTATION, session) + val columnName = (annotation?.argumentMapping?.mapping?.get(Names.COLUMN_NAME_ARGUMENT) as? FirLiteralExpression)?.value as? String + val name = columnName ?: it.name.identifier + return when { shouldBeConvertedToFrameColumn(it) -> { - val nestedColumns = it.resolvedReturnType.typeArguments[0].type - ?.toRegularClassSymbol(session) - ?.declaredMemberScope(session, FirResolvePhase.DECLARATIONS) - ?.collectAllProperties() - ?.filterIsInstance() - ?.mapNotNull { columnOf(it, mapping) } - ?: emptyList() - - SimpleFrameColumn(it.name.identifier, nestedColumns) - } + val nestedColumns = it.resolvedReturnType.typeArguments[0].type + ?.toRegularClassSymbol(session) + ?.declaredMemberScope(session, FirResolvePhase.DECLARATIONS) + ?.collectAllProperties() + ?.filterIsInstance() + ?.mapNotNull { columnOf(it, mapping) } + ?: emptyList() + + SimpleFrameColumn(name, nestedColumns) + } + shouldBeConvertedToColumnGroup(it) -> { val type = if (isDataRow(it)) it.resolvedReturnType.typeArguments[0].type!! else it.resolvedReturnType val nestedColumns = type @@ -396,8 +401,9 @@ private fun KotlinTypeFacade.columnOf(it: FirPropertySymbol, mapping: Map() ?.mapNotNull { columnOf(it, mapping) } ?: emptyList() - SimpleColumnGroup(it.name.identifier, nestedColumns) + SimpleColumnGroup(name, nestedColumns) } + else -> { val type = when (val type = it.resolvedReturnType) { is ConeTypeParameterType -> { @@ -408,13 +414,15 @@ private fun KotlinTypeFacade.columnOf(it: FirPropertySymbol, mapping: Map type } - type?.let { type -> SimpleDataColumn(it.name.identifier, - org.jetbrains.kotlinx.dataframe.plugin.impl.api.TypeApproximation(type) - ) } + type?.let { type -> + SimpleDataColumn(name, TypeApproximation(type)) + } } } +} private fun KotlinTypeFacade.shouldBeConvertedToColumnGroup(it: FirPropertySymbol) = isDataRow(it) || diff --git a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/loadInterpreter.kt b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/loadInterpreter.kt index 2be2faeda..ffc938c17 100644 --- a/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/loadInterpreter.kt +++ b/plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/loadInterpreter.kt @@ -71,11 +71,19 @@ import org.jetbrains.kotlinx.dataframe.plugin.impl.api.All0 import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ColsAtAnyDepth0 import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ColsOf0 import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ColsOf1 +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.DataFrameBuilderInvoke0 +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.DataFrameOf0 +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.FillNulls0 +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.Flatten0 +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.FlattenDefault import org.jetbrains.kotlinx.dataframe.plugin.impl.api.FrameCols0 +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ReadExcel import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ToDataFrame +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ToDataFrameColumn import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ToDataFrameDefault import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ToDataFrameDsl import org.jetbrains.kotlinx.dataframe.plugin.impl.api.ToDataFrameFrom +import org.jetbrains.kotlinx.dataframe.plugin.impl.api.UpdateWith0 internal fun FirFunctionCall.loadInterpreter(session: FirSession): Interpreter<*>? { val symbol = @@ -177,6 +185,15 @@ internal inline fun String.load(): T { "toDataFrameDsl" -> ToDataFrameDsl() "toDataFrame" -> ToDataFrame() "toDataFrameDefault" -> ToDataFrameDefault() + "DataFrameOf0" -> DataFrameOf0() + "DataFrameBuilderInvoke0" -> DataFrameBuilderInvoke0() + "ToDataFrameColumn" -> ToDataFrameColumn() + "StringColumns" -> ToDataFrameColumn() + "ReadExcel" -> ReadExcel() + "FillNulls0" -> FillNulls0() + "UpdateWith0" -> UpdateWith0() + "Flatten0" -> Flatten0() + "FlattenDefault" -> FlattenDefault() else -> error("$this") } as T } diff --git a/plugins/kotlin-dataframe/testData/box/columnName.kt b/plugins/kotlin-dataframe/testData/box/columnName.kt index 1f16d7470..23b14f0a9 100644 --- a/plugins/kotlin-dataframe/testData/box/columnName.kt +++ b/plugins/kotlin-dataframe/testData/box/columnName.kt @@ -10,7 +10,10 @@ data class Record( ) fun box(): String { - val df = dataFrameOf("a")(1).cast() + val df = dataFrameOf("a")("1").cast() df.abc + + val df1 = df.add("b") { 1 } + df1.a return "OK" } diff --git a/plugins/kotlin-dataframe/testData/box/convert_to.kt b/plugins/kotlin-dataframe/testData/box/convert_to.kt new file mode 100644 index 000000000..10331382a --- /dev/null +++ b/plugins/kotlin-dataframe/testData/box/convert_to.kt @@ -0,0 +1,10 @@ +import org.jetbrains.kotlinx.dataframe.* +import org.jetbrains.kotlinx.dataframe.annotations.* +import org.jetbrains.kotlinx.dataframe.api.* +import org.jetbrains.kotlinx.dataframe.io.* + +fun box(): String { + val df = dataFrameOf("col")("1", "2").convert { col }.to() + val i: Int = df.col[0] + return "OK" +} diff --git a/plugins/kotlin-dataframe/testData/box/dataFrameOf_vararg.kt b/plugins/kotlin-dataframe/testData/box/dataFrameOf_vararg.kt new file mode 100644 index 000000000..19f6b2228 --- /dev/null +++ b/plugins/kotlin-dataframe/testData/box/dataFrameOf_vararg.kt @@ -0,0 +1,13 @@ +import org.jetbrains.kotlinx.dataframe.* +import org.jetbrains.kotlinx.dataframe.annotations.* +import org.jetbrains.kotlinx.dataframe.api.* +import org.jetbrains.kotlinx.dataframe.io.* + +fun box(): String { + val df = dataFrameOf("a")(1, 2, 3) + val i: Int = df.a[0] + + val df1 = dataFrameOf("a", "b")({ 1 }, 2) + val i1: Int = df1.a[0].invoke() + return "OK" +} diff --git a/plugins/kotlin-dataframe/testData/box/dfIde.kt b/plugins/kotlin-dataframe/testData/box/dfIde.kt index acac15b56..744f0aa93 100644 --- a/plugins/kotlin-dataframe/testData/box/dfIde.kt +++ b/plugins/kotlin-dataframe/testData/box/dfIde.kt @@ -10,7 +10,7 @@ interface Schema { } fun main(args: Array) { - val df = dataFrameOf("i")(1, 2, 3).cast() + val df = dataFrameOf("i", "fff")(1, "321").cast() println(df.i) val df1 = df.add("ca") { 423 } diff --git a/plugins/kotlin-dataframe/testData/box/fillNulls.kt b/plugins/kotlin-dataframe/testData/box/fillNulls.kt new file mode 100644 index 000000000..a9910aa7e --- /dev/null +++ b/plugins/kotlin-dataframe/testData/box/fillNulls.kt @@ -0,0 +1,11 @@ +import org.jetbrains.kotlinx.dataframe.* +import org.jetbrains.kotlinx.dataframe.annotations.* +import org.jetbrains.kotlinx.dataframe.api.* +import org.jetbrains.kotlinx.dataframe.io.* + +fun box(): String { + val df = dataFrameOf("a", "b")(1, null, null, "") + val df1 = df.fillNulls { b }.with { "empty" } + val b: DataColumn = df1.b + return "OK" +} diff --git a/plugins/kotlin-dataframe/testData/box/flatten.kt b/plugins/kotlin-dataframe/testData/box/flatten.kt new file mode 100644 index 000000000..f6eaf17ea --- /dev/null +++ b/plugins/kotlin-dataframe/testData/box/flatten.kt @@ -0,0 +1,23 @@ +import org.jetbrains.kotlinx.dataframe.* +import org.jetbrains.kotlinx.dataframe.annotations.* +import org.jetbrains.kotlinx.dataframe.api.* +import org.jetbrains.kotlinx.dataframe.io.* + +fun box(): String { + val df = dataFrameOf("a", "b", "c", "d")(1, 2, 3, 4) + val grouped = df + .group { a and b }.into("e") + .group { e and c }.into("f") + + grouped.flatten().compareSchemas(strict = true) + val flattened = grouped.flatten { f.e } + flattened.compareSchemas(strict = true) + flattened.ungroup { f }.compareSchemas(strict = true) + + grouped.flatten { f.e and f }.compareSchemas(strict = true) + return "OK" +} + + + + diff --git a/plugins/kotlin-dataframe/testData/box/toDataFrame_column.kt b/plugins/kotlin-dataframe/testData/box/toDataFrame_column.kt new file mode 100644 index 000000000..133bab194 --- /dev/null +++ b/plugins/kotlin-dataframe/testData/box/toDataFrame_column.kt @@ -0,0 +1,11 @@ +import org.jetbrains.kotlinx.dataframe.* +import org.jetbrains.kotlinx.dataframe.annotations.* +import org.jetbrains.kotlinx.dataframe.api.* +import org.jetbrains.kotlinx.dataframe.io.* +import java.io.File + +fun box(): String { + val df = listOf(File("abc.csv")).toDataFrame(columnName = "data") + val res: DataColumn = df.data + return "OK" +} diff --git a/plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameBlackBoxCodegenTestGenerated.java b/plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameBlackBoxCodegenTestGenerated.java index 3e73f4e5a..c803cbde7 100644 --- a/plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameBlackBoxCodegenTestGenerated.java +++ b/plugins/kotlin-dataframe/tests-gen/org/jetbrains/kotlin/fir/dataframe/DataFrameBlackBoxCodegenTestGenerated.java @@ -58,12 +58,24 @@ public void testConvertToDataFrame() { runTest("testData/box/convertToDataFrame.kt"); } + @Test + @TestMetadata("convert_to.kt") + public void testConvert_to() { + runTest("testData/box/convert_to.kt"); + } + @Test @TestMetadata("dataFrameOf.kt") public void testDataFrameOf() { runTest("testData/box/dataFrameOf.kt"); } + @Test + @TestMetadata("dataFrameOf_vararg.kt") + public void testDataFrameOf_vararg() { + runTest("testData/box/dataFrameOf_vararg.kt"); + } + @Test @TestMetadata("dataRowSchemaApi.kt") public void testDataRowSchemaApi() { @@ -130,6 +142,18 @@ public void testExtractPluginSchemaWithUnfold() { runTest("testData/box/extractPluginSchemaWithUnfold.kt"); } + @Test + @TestMetadata("fillNulls.kt") + public void testFillNulls() { + runTest("testData/box/fillNulls.kt"); + } + + @Test + @TestMetadata("flatten.kt") + public void testFlatten() { + runTest("testData/box/flatten.kt"); + } + @Test @TestMetadata("flexibleReturnType.kt") public void testFlexibleReturnType() { @@ -328,6 +352,12 @@ public void testToDataFrame() { runTest("testData/box/toDataFrame.kt"); } + @Test + @TestMetadata("toDataFrame_column.kt") + public void testToDataFrame_column() { + runTest("testData/box/toDataFrame_column.kt"); + } + @Test @TestMetadata("toDataFrame_dsl.kt") public void testToDataFrame_dsl() {