Skip to content

Commit d9af0b9

Browse files
committed
Merge branch 'master' into kproperties-columnsSelectionDsl
# Conflicts: # core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/ColumnsSelectionDsl.kt # core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/ColumnsSelectionDsl.kt
2 parents 2ee6a63 + 6c6a26c commit d9af0b9

File tree

152 files changed

+20528
-524
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+20528
-524
lines changed

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ indent_size=2
1111

1212
[*.yaml]
1313
indent_size=2
14+
15+
[*.ipynb]
16+
insert_final_newline=false

core/build.gradle.kts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,12 @@ val addGeneratedSourcesToGit by tasks.creating(GitTask::class) {
6969

7070
// Backup the kotlin source files location
7171
val kotlinMainSources = kotlin.sourceSets.main.get().kotlin.sourceDirectories
72+
val kotlinTestSources = kotlin.sourceSets.test.get().kotlin.sourceDirectories
7273

7374
// Task to generate the processed documentation
7475
val processKDocsMain by creatingProcessDocTask(
75-
sources = kotlinMainSources.filterNot { "build/generated" in it.path }, // Exclude generated sources
76+
sources = (kotlinMainSources + kotlinTestSources) // Include both test and main sources for cross-referencing
77+
.filterNot { "build/generated" in it.path }, // Exclude generated sources
7678
) {
7779
target = file(generatedSourcesFolderName)
7880
processors = listOf(
@@ -107,8 +109,9 @@ tasks.withType<Jar> {
107109
doFirst {
108110
kotlin.sourceSets.main {
109111
kotlin.setSrcDirs(
110-
processKDocsMain.targets +
111-
kotlinMainSources.filter { "build/generated" in it.path } // Include generated sources (which were excluded above)
112+
processKDocsMain.targets
113+
.filterNot { "src/test/kotlin" in it.path || "src/test/java" in it.path } // filter out test sources again
114+
.plus(kotlinMainSources.filter { "build/generated" in it.path }) // Include generated sources (which were excluded above)
112115
)
113116
}
114117
}

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/aliases.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,17 @@ public typealias RowValueExpression<T, C, R> = DataRow<T>.(it: C) -> R
7474
*/
7575
public typealias RowColumnExpression<T, C, R> = (row: DataRow<T>, col: DataColumn<C>) -> R
7676

77+
/**
78+
* [ColumnExpression] is used to express or select any instance of `R` using the given instance of [DataColumn]`<C>` as
79+
* `this` and `it`.
80+
*
81+
* Shorthand for:
82+
* ```kotlin
83+
* DataColumn<C>.(it: DataColumn<C>) -> R
84+
* ```
85+
*/
86+
public typealias ColumnExpression<C, R> = Selector<DataColumn<C>, R>
87+
7788
/**
7889
* [ColumnSelector] is used to express or select a single column, represented by [SingleColumn]`<C>`, using the
7990
* context of [ColumnsSelectionDsl]`<T>` as `this` and `it`.

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/ColumnsSelectionDsl.kt

Lines changed: 64 additions & 168 deletions
Large diffs are not rendered by default.

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt

Lines changed: 1056 additions & 69 deletions
Large diffs are not rendered by default.

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/add.kt

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ public fun <T> DataFrame<T>.add(vararg columns: AnyBaseCol): DataFrame<T> = addA
5050
* @throws [UnequalColumnSizesException] if columns in expected result have different sizes
5151
* @return new [DataFrame] with added columns
5252
*/
53-
public fun <T> DataFrame<T>.addAll(columns: Iterable<AnyBaseCol>): DataFrame<T> = dataFrameOf(columns() + columns).cast()
53+
public fun <T> DataFrame<T>.addAll(columns: Iterable<AnyBaseCol>): DataFrame<T> =
54+
dataFrameOf(columns() + columns).cast()
5455

5556
/**
5657
* Creates new [DataFrame] with all columns from given [dataFrames] added to the end of original [DataFrame.columns] list.
@@ -75,7 +76,8 @@ public fun <T> DataFrame<T>.add(vararg dataFrames: AnyFrame): DataFrame<T> = add
7576
* @return new [DataFrame] with added columns
7677
*/
7778
@JvmName("addAllFrames")
78-
public fun <T> DataFrame<T>.addAll(dataFrames: Iterable<AnyFrame>): DataFrame<T> = addAll(dataFrames.flatMap { it.columns() })
79+
public fun <T> DataFrame<T>.addAll(dataFrames: Iterable<AnyFrame>): DataFrame<T> =
80+
addAll(dataFrames.flatMap { it.columns() })
7981

8082
// endregion
8183

@@ -96,7 +98,16 @@ public interface AddDataRow<out T> : DataRow<T> {
9698
public fun <C> AnyRow.newValue(): C
9799
}
98100

99-
public typealias AddExpression<T, C> = Selector<AddDataRow<T>, C>
101+
/**
102+
* [AddExpression] is used to express or select any instance of `R` using the given instance of [AddDataRow]`<T>` as
103+
* `this` and `it`.
104+
*
105+
* Shorthand for:
106+
* ```kotlin
107+
* AddDataRow<T>.(it: AddDataRow<T>) -> R
108+
* ```
109+
*/
110+
public typealias AddExpression<T, R> = Selector<AddDataRow<T>, R>
100111

101112
/**
102113
* Creates new column using row [expression] and adds it to the end of [DataFrame]
@@ -166,11 +177,15 @@ public class AddDsl<T>(@PublishedApi internal val df: DataFrame<T>) : ColumnsCon
166177
return df.mapToColumn("", Infer.Nulls, expression)
167178
}
168179

169-
public inline infix fun <reified R> String.from(noinline expression: RowExpression<T, R>): Boolean = add(this, Infer.Nulls, expression)
180+
public inline infix fun <reified R> String.from(noinline expression: RowExpression<T, R>): Boolean =
181+
add(this, Infer.Nulls, expression)
170182

171183
// TODO: use path instead of name
172-
public inline infix fun <reified R> ColumnAccessor<R>.from(noinline expression: RowExpression<T, R>): Boolean = name().from(expression)
173-
public inline infix fun <reified R> KProperty<R>.from(noinline expression: RowExpression<T, R>): Boolean = add(name, Infer.Nulls, expression)
184+
public inline infix fun <reified R> ColumnAccessor<R>.from(noinline expression: RowExpression<T, R>): Boolean =
185+
name().from(expression)
186+
187+
public inline infix fun <reified R> KProperty<R>.from(noinline expression: RowExpression<T, R>): Boolean =
188+
add(name, Infer.Nulls, expression)
174189

175190
public infix fun String.from(column: AnyColumnReference): Boolean = add(column.rename(this))
176191
public inline infix fun <reified R> ColumnAccessor<R>.from(column: ColumnReference<R>): Boolean = name() from column

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/gather.kt

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,43 @@ package org.jetbrains.kotlinx.dataframe.api
22

33
import org.jetbrains.kotlinx.dataframe.ColumnsSelector
44
import org.jetbrains.kotlinx.dataframe.DataFrame
5-
import org.jetbrains.kotlinx.dataframe.Predicate
5+
import org.jetbrains.kotlinx.dataframe.RowValueFilter
66
import org.jetbrains.kotlinx.dataframe.columns.ColumnAccessor
77
import org.jetbrains.kotlinx.dataframe.columns.ColumnReference
8-
import org.jetbrains.kotlinx.dataframe.impl.and
98
import org.jetbrains.kotlinx.dataframe.impl.api.gatherImpl
109
import org.jetbrains.kotlinx.dataframe.impl.columnName
1110
import org.jetbrains.kotlinx.dataframe.impl.columns.toColumns
1211
import kotlin.reflect.KProperty
1312
import kotlin.reflect.KType
1413
import kotlin.reflect.typeOf
1514

16-
public fun <T, C> DataFrame<T>.gather(selector: ColumnsSelector<T, C>): Gather<T, C, String, C> = Gather(
17-
this, selector, null, typeOf<String>(),
18-
{ it }, null
19-
)
20-
public fun <T> DataFrame<T>.gather(vararg columns: String): Gather<T, Any?, String, Any?> = gather { columns.toColumns() }
21-
public fun <T, C> DataFrame<T>.gather(vararg columns: ColumnReference<C>): Gather<T, C, String, C> = gather { columns.toColumns() }
22-
public fun <T, C> DataFrame<T>.gather(vararg columns: KProperty<C>): Gather<T, C, String, C> = gather { columns.toColumns() }
15+
public fun <T, C> DataFrame<T>.gather(selector: ColumnsSelector<T, C>): Gather<T, C, String, C> =
16+
Gather(
17+
df = this,
18+
columns = selector,
19+
filter = null,
20+
keyType = typeOf<String>(),
21+
keyTransform = { it },
22+
valueTransform = null,
23+
)
2324

24-
public fun <T, C, K, R> Gather<T, C, K, R>.where(filter: Predicate<C>): Gather<T, C, K, R> = copy(filter = this.filter and filter)
25-
public fun <T, C, K, R> Gather<T, C?, K, R>.notNull(): Gather<T, C, K, R> = where { it != null } as Gather<T, C, K, R>
25+
public fun <T> DataFrame<T>.gather(vararg columns: String): Gather<T, Any?, String, Any?> =
26+
gather { columns.toColumns() }
2627

27-
public fun <T, C, K, R> Gather<T, C, K, R>.explodeLists(): Gather<T, C, K, R> = copy(explode = true)
28+
public fun <T, C> DataFrame<T>.gather(vararg columns: ColumnReference<C>): Gather<T, C, String, C> =
29+
gather { columns.toColumns() }
30+
31+
public fun <T, C> DataFrame<T>.gather(vararg columns: KProperty<C>): Gather<T, C, String, C> =
32+
gather { columns.toColumns() }
33+
34+
public fun <T, C, K, R> Gather<T, C, K, R>.where(filter: RowValueFilter<T, C>): Gather<T, C, K, R> =
35+
copy(filter = this.filter and filter)
36+
37+
public fun <T, C, K, R> Gather<T, C?, K, R>.notNull(): Gather<T, C, K, R> =
38+
where { it != null } as Gather<T, C, K, R>
39+
40+
public fun <T, C, K, R> Gather<T, C, K, R>.explodeLists(): Gather<T, C, K, R> =
41+
copy(explode = true)
2842

2943
public inline fun <T, C, reified K, R> Gather<T, C, *, R>.mapKeys(noinline transform: (String) -> K): Gather<T, C, K, R> =
3044
copy(keyTransform = transform as ((String) -> Nothing), keyType = typeOf<K>()) as Gather<T, C, K, R>
@@ -35,7 +49,7 @@ public fun <T, C, K, R> Gather<T, C, K, *>.mapValues(transform: (C) -> R): Gathe
3549
public data class Gather<T, C, K, R>(
3650
internal val df: DataFrame<T>,
3751
internal val columns: ColumnsSelector<T, C>,
38-
internal val filter: ((C) -> Boolean)? = null,
52+
internal val filter: RowValueFilter<T, C>? = null,
3953
internal val keyType: KType? = null,
4054
internal val keyTransform: ((String) -> K),
4155
internal val valueTransform: ((C) -> R)? = null,

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/reorder.kt

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package org.jetbrains.kotlinx.dataframe.api
22

33
import org.jetbrains.kotlinx.dataframe.AnyCol
4+
import org.jetbrains.kotlinx.dataframe.ColumnExpression
45
import org.jetbrains.kotlinx.dataframe.ColumnsSelector
5-
import org.jetbrains.kotlinx.dataframe.DataColumn
66
import org.jetbrains.kotlinx.dataframe.DataFrame
77
import org.jetbrains.kotlinx.dataframe.Selector
88
import org.jetbrains.kotlinx.dataframe.columns.ColumnReference
@@ -21,22 +21,28 @@ public data class Reorder<T, C>(
2121
}
2222

2323
public fun <T, C> DataFrame<T>.reorder(selector: ColumnsSelector<T, C>): Reorder<T, C> = Reorder(this, selector, false)
24-
public fun <T, C> DataFrame<T>.reorder(vararg columns: ColumnReference<C>): Reorder<T, C> = reorder { columns.toColumns() }
24+
public fun <T, C> DataFrame<T>.reorder(vararg columns: ColumnReference<C>): Reorder<T, C> =
25+
reorder { columns.toColumns() }
26+
2527
public fun <T, C> DataFrame<T>.reorder(vararg columns: KProperty<C>): Reorder<T, C> = reorder { columns.toColumns() }
2628
public fun <T> DataFrame<T>.reorder(vararg columns: String): Reorder<T, *> = reorder { columns.toColumns() }
2729

28-
public fun <T, C, V : Comparable<V>> Reorder<T, C>.by(expression: Selector<DataColumn<C>, V>): DataFrame<T> = reorderImpl(false, expression)
30+
public fun <T, C, V : Comparable<V>> Reorder<T, C>.by(expression: ColumnExpression<C, V>): DataFrame<T> =
31+
reorderImpl(false, expression)
2932

30-
public fun <T, C> Reorder<T, C>.byName(desc: Boolean = false): DataFrame<T> = if (desc) byDesc { it.name } else by { it.name }
33+
public fun <T, C> Reorder<T, C>.byName(desc: Boolean = false): DataFrame<T> =
34+
if (desc) byDesc { it.name } else by { it.name }
3135

32-
public fun <T, C, V : Comparable<V>> Reorder<T, C>.byDesc(expression: Selector<DataColumn<C>, V>): DataFrame<T> = reorderImpl(true, expression)
36+
public fun <T, C, V : Comparable<V>> Reorder<T, C>.byDesc(expression: ColumnExpression<C, V>): DataFrame<T> =
37+
reorderImpl(true, expression)
3338

3439
public fun <T, V : Comparable<V>> DataFrame<T>.reorderColumnsBy(
3540
dfs: Boolean = true,
3641
desc: Boolean = false,
3742
expression: Selector<AnyCol, V>
3843
): DataFrame<T> = Reorder(this, { if (dfs) allDfs(true) else all() }, dfs).reorderImpl(desc, expression)
3944

40-
public fun <T> DataFrame<T>.reorderColumnsByName(dfs: Boolean = true, desc: Boolean = false): DataFrame<T> = reorderColumnsBy(dfs, desc) { name() }
45+
public fun <T> DataFrame<T>.reorderColumnsByName(dfs: Boolean = true, desc: Boolean = false): DataFrame<T> =
46+
reorderColumnsBy(dfs, desc) { name() }
4147

4248
// endregion

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/select.kt

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,28 @@ import kotlin.reflect.KProperty
1010

1111
// region DataFrame
1212

13-
public fun <T> DataFrame<T>.select(columns: ColumnsSelector<T, *>): DataFrame<T> = get(columns).toDataFrame().cast()
14-
public fun <T> DataFrame<T>.select(vararg columns: KProperty<*>): DataFrame<T> = select(columns.map { it.columnName })
15-
public fun <T> DataFrame<T>.select(vararg columns: String): DataFrame<T> = select(columns.asIterable())
16-
public fun <T> DataFrame<T>.select(vararg columns: AnyColumnReference): DataFrame<T> = select { columns.toColumns() }
17-
@JvmName("selectT")
18-
public fun <T> DataFrame<T>.select(columns: Iterable<String>): DataFrame<T> = columns.map { get(it) }.toDataFrame().cast()
19-
public fun <T> DataFrame<T>.select(columns: Iterable<AnyColumnReference>): DataFrame<T> = select { columns.toColumnSet() }
13+
public fun <T> DataFrame<T>.select(columns: ColumnsSelector<T, *>): DataFrame<T> =
14+
get(columns).toDataFrame().cast()
15+
16+
public fun <T> DataFrame<T>.select(vararg columns: KProperty<*>): DataFrame<T> =
17+
select(columns.asIterable())
18+
19+
@JvmName("selectKPropertyIterable")
20+
public fun <T> DataFrame<T>.select(columns: Iterable<KProperty<*>>): DataFrame<T> =
21+
select(columns.map { it.columnName })
22+
23+
public fun <T> DataFrame<T>.select(vararg columns: String): DataFrame<T> =
24+
select(columns.asIterable())
25+
26+
@JvmName("selectStringIterable")
27+
public fun <T> DataFrame<T>.select(columns: Iterable<String>): DataFrame<T> =
28+
columns.map { get(it) }.toDataFrame().cast()
29+
30+
public fun <T> DataFrame<T>.select(vararg columns: AnyColumnReference): DataFrame<T> =
31+
select { columns.toColumns() }
32+
33+
@JvmName("selectAnyColumnReferenceIterable")
34+
public fun <T> DataFrame<T>.select(columns: Iterable<AnyColumnReference>): DataFrame<T> =
35+
select { columns.toColumnSet() }
2036

2137
// endregion

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/toDataFrame.kt

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import org.jetbrains.kotlinx.dataframe.ColumnsSelector
77
import org.jetbrains.kotlinx.dataframe.DataColumn
88
import org.jetbrains.kotlinx.dataframe.DataFrame
99
import org.jetbrains.kotlinx.dataframe.DataRow
10+
import org.jetbrains.kotlinx.dataframe.annotations.DataSchema
1011
import org.jetbrains.kotlinx.dataframe.columns.ColumnPath
1112
import org.jetbrains.kotlinx.dataframe.impl.ColumnNameGenerator
1213
import org.jetbrains.kotlinx.dataframe.impl.api.createDataFrameImpl
@@ -23,7 +24,8 @@ public inline fun <reified T> Iterable<T>.toDataFrame(): DataFrame<T> = toDataFr
2324
properties()
2425
}
2526

26-
public inline fun <reified T> Iterable<T>.toDataFrame(noinline body: CreateDataFrameDsl<T>.() -> Unit): DataFrame<T> = createDataFrameImpl(T::class, body)
27+
public inline fun <reified T> Iterable<T>.toDataFrame(noinline body: CreateDataFrameDsl<T>.() -> Unit): DataFrame<T> =
28+
createDataFrameImpl(T::class, body)
2729

2830
public inline fun <reified T> Iterable<T>.toDataFrame(vararg props: KProperty<*>, maxDepth: Int = 0): DataFrame<T> =
2931
toDataFrame {
@@ -76,6 +78,7 @@ public fun <T> Iterable<Pair<ColumnPath, AnyBaseCol>>.toDataFrameFromPairs(): Da
7678
when (path.size) {
7779
0 -> {
7880
}
81+
7982
1 -> {
8083
val name = path[0]
8184
val uniqueName = nameGenerator.addUnique(name)
@@ -85,6 +88,7 @@ public fun <T> Iterable<Pair<ColumnPath, AnyBaseCol>>.toDataFrameFromPairs(): Da
8588
columns.add(col.rename(uniqueName))
8689
columnIndices[uniqueName] = index
8790
}
91+
8892
else -> {
8993
val name = path[0]
9094
val uniqueName = columnGroupName.getOrPut(name) {
@@ -187,6 +191,83 @@ public abstract class CreateDataFrameDsl<T> : TraversePropertiesDsl {
187191

188192
// endregion
189193

194+
// region toDataFrame overloads for built-in types
195+
196+
/*
197+
Without overloads Iterable<String>.toDataFrame produces unexpected result
198+
199+
200+
```
201+
val string = listOf("aaa", "aa", null)
202+
string.toDataFrame()
203+
```
204+
=>
205+
length
206+
0 3
207+
1 2
208+
2 null
209+
*/
210+
211+
@JvmName("toDataFrameByte")
212+
public inline fun <reified B : Byte?> Iterable<B>.toDataFrame(): DataFrame<ValueProperty<B>> = toDataFrame {
213+
ValueProperty<B>::value from { it }
214+
}.cast()
215+
216+
@JvmName("toDataFrameShort")
217+
public inline fun <reified S : Short?> Iterable<S>.toDataFrame(): DataFrame<ValueProperty<S>> = toDataFrame {
218+
ValueProperty<S>::value from { it }
219+
}.cast()
220+
221+
@JvmName("toDataFrameInt")
222+
public inline fun <reified I : Int?> Iterable<I>.toDataFrame(): DataFrame<ValueProperty<I>> = toDataFrame {
223+
ValueProperty<I>::value from { it }
224+
}.cast()
225+
226+
@JvmName("toDataFrameLong")
227+
public inline fun <reified L : Long?> Iterable<L>.toDataFrame(): DataFrame<ValueProperty<L>> = toDataFrame {
228+
ValueProperty<L>::value from { it }
229+
}.cast()
230+
231+
@JvmName("toDataFrameString")
232+
public inline fun <reified S : String?> Iterable<S>.toDataFrame(): DataFrame<ValueProperty<S>> = toDataFrame {
233+
ValueProperty<S>::value from { it }
234+
}.cast()
235+
236+
@JvmName("toDataFrameChar")
237+
public inline fun <reified C : Char?> Iterable<C>.toDataFrame(): DataFrame<ValueProperty<C>> = toDataFrame {
238+
ValueProperty<C>::value from { it }
239+
}.cast()
240+
241+
@JvmName("toDataFrameBoolean")
242+
public inline fun <reified B : Boolean?> Iterable<B>.toDataFrame(): DataFrame<ValueProperty<B>> = toDataFrame {
243+
ValueProperty<B>::value from { it }
244+
}.cast()
245+
246+
@JvmName("toDataFrameUByte")
247+
public inline fun <reified U : UByte?> Iterable<U>.toDataFrame(): DataFrame<ValueProperty<U>> = toDataFrame {
248+
ValueProperty<U>::value from { it }
249+
}.cast()
250+
251+
@JvmName("toDataFrameUShort")
252+
public inline fun <reified U : UShort?> Iterable<U>.toDataFrame(): DataFrame<ValueProperty<U>> = toDataFrame {
253+
ValueProperty<U>::value from { it }
254+
}.cast()
255+
256+
@JvmName("toDataFrameUInt")
257+
public inline fun <reified U : UInt?> Iterable<U>.toDataFrame(): DataFrame<ValueProperty<U>> = toDataFrame {
258+
ValueProperty<U>::value from { it }
259+
}.cast()
260+
261+
@JvmName("toDataFrameULong")
262+
public inline fun <reified U : ULong?> Iterable<U>.toDataFrame(): DataFrame<ValueProperty<U>> = toDataFrame {
263+
ValueProperty<U>::value from { it }
264+
}.cast()
265+
266+
@DataSchema
267+
public interface ValueProperty<T> {
268+
public val value: T
269+
}
270+
190271
// region Create DataFrame from Map
191272

192273
public fun Map<String, Iterable<Any?>>.toDataFrame(): AnyFrame {
@@ -195,7 +276,12 @@ public fun Map<String, Iterable<Any?>>.toDataFrame(): AnyFrame {
195276

196277
@JvmName("toDataFrameColumnPathAnyNullable")
197278
public fun Map<ColumnPath, Iterable<Any?>>.toDataFrame(): AnyFrame {
198-
return map { it.key to DataColumn.createWithTypeInference(it.key.last(), it.value.asList()) }.toDataFrameFromPairs<Unit>()
279+
return map {
280+
it.key to DataColumn.createWithTypeInference(
281+
it.key.last(),
282+
it.value.asList()
283+
)
284+
}.toDataFrameFromPairs<Unit>()
199285
}
200286

201287
// endregion

0 commit comments

Comments
 (0)