Skip to content

Commit d41aa53

Browse files
committed
Merge branch 'mean' into sum
2 parents f80bc97 + f17929b commit d41aa53

File tree

20 files changed

+89
-90
lines changed

20 files changed

+89
-90
lines changed

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.primitiveNumberColumns
2424
import org.jetbrains.kotlinx.dataframe.impl.columns.toNumberColumns
2525
import org.jetbrains.kotlinx.dataframe.impl.primitiveNumberTypes
2626
import kotlin.reflect.KProperty
27+
import kotlin.reflect.full.withNullability
2728
import kotlin.reflect.typeOf
2829

2930
/*
@@ -38,7 +39,7 @@ import kotlin.reflect.typeOf
3839
// region DataColumn
3940

4041
public fun <T : Number> DataColumn<T?>.mean(skipNA: Boolean = skipNA_default): Double =
41-
Aggregators.mean(skipNA).aggregate(this)!!
42+
Aggregators.mean(skipNA).aggregate(this)
4243

4344
public inline fun <T, reified R : Number> DataColumn<T>.meanOf(
4445
skipNA: Boolean = skipNA_default,
@@ -47,7 +48,6 @@ public inline fun <T, reified R : Number> DataColumn<T>.meanOf(
4748
Aggregators.mean(skipNA)
4849
.cast2<R?, Double>()
4950
.aggregateOf(this, expression)
50-
?: Double.NaN
5151

5252
// endregion
5353

@@ -56,15 +56,14 @@ public inline fun <T, reified R : Number> DataColumn<T>.meanOf(
5656
public fun AnyRow.rowMean(skipNA: Boolean = skipNA_default): Double =
5757
Aggregators.mean(skipNA).aggregateOfRow(this) {
5858
colsOf<Number?> { it.isPrimitiveNumber() }
59-
} ?: Double.NaN
59+
}
6060

61-
public inline fun <reified T : Number> AnyRow.rowMeanOf(skipNA: Boolean = skipNA_default): Double {
62-
require(typeOf<T>() in primitiveNumberTypes) {
61+
public inline fun <reified T : Number?> AnyRow.rowMeanOf(skipNA: Boolean = skipNA_default): Double {
62+
require(typeOf<T>().withNullability(false) in primitiveNumberTypes) {
6363
"Type ${T::class.simpleName} is not a primitive number type. Mean only supports primitive number types."
6464
}
6565
return Aggregators.mean(skipNA)
6666
.aggregateOfRow(this) { colsOf<T>() }
67-
?: Double.NaN
6867
}
6968

7069
// endregion
@@ -97,7 +96,7 @@ public fun <T, C : Number> DataFrame<T>.meanFor(
9796
public fun <T, C : Number> DataFrame<T>.mean(
9897
skipNA: Boolean = skipNA_default,
9998
columns: ColumnsSelector<T, C?>,
100-
): Double = Aggregators.mean(skipNA).aggregateAll(this, columns) ?: Double.NaN
99+
): Double = Aggregators.mean(skipNA).aggregateAll(this, columns)
101100

102101
public fun <T> DataFrame<T>.mean(vararg columns: String, skipNA: Boolean = skipNA_default): Double =
103102
mean(skipNA) { columns.toNumberColumns() }
@@ -115,7 +114,7 @@ public fun <T, C : Number> DataFrame<T>.mean(vararg columns: KProperty<C?>, skip
115114
public inline fun <T, reified D : Number> DataFrame<T>.meanOf(
116115
skipNA: Boolean = skipNA_default,
117116
noinline expression: RowExpression<T, D?>,
118-
): Double = Aggregators.mean(skipNA).of(this, expression) ?: Double.NaN
117+
): Double = Aggregators.mean(skipNA).of(this, expression)
119118

120119
// endregion
121120

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@ import kotlin.reflect.full.withNullability
1515
* @param Value The type of the values to be aggregated.
1616
* This can be nullable for [Iterables][Iterable] or not, depending on the use case.
1717
* For columns, [Value] will always be considered nullable; nulls are filtered out from columns anyway.
18-
* @param Return The type of the resulting value. It doesn't matter if this is nullable or not, as the aggregator
19-
* will always return a [Return]`?`.
18+
* @param Return The type of the resulting value. Can optionally be nullable.
2019
*/
2120
@PublishedApi
2221
internal interface Aggregator<in Value, out Return> {
@@ -33,20 +32,20 @@ internal interface Aggregator<in Value, out Return> {
3332
*
3433
* When the exact [type] is unknown, use [aggregateCalculatingType].
3534
*/
36-
fun aggregate(values: Iterable<Value>, type: KType): Return?
35+
fun aggregate(values: Iterable<Value>, type: KType): Return
3736

3837
/**
3938
* Aggregates the data in the given column and computes a single resulting value.
4039
* Nulls are filtered out by default, then [aggregate] (with [Iterable] and [KType]) is called.
4140
*
4241
* See [AggregatorBase.aggregate].
4342
*/
44-
fun aggregate(column: DataColumn<Value?>): Return?
43+
fun aggregate(column: DataColumn<Value?>): Return
4544

4645
/**
4746
* Aggregates the data in the multiple given columns and computes a single resulting value.
4847
*/
49-
fun aggregate(columns: Iterable<DataColumn<Value?>>): Return?
48+
fun aggregate(columns: Iterable<DataColumn<Value?>>): Return
5049

5150
/**
5251
* Special case of [aggregate] with [Iterable] that calculates the common type of the values at runtime.
@@ -58,7 +57,7 @@ internal interface Aggregator<in Value, out Return> {
5857
* It should contain all types of [values].
5958
* If `null`, the types of [values] will be calculated at runtime (heavy!).
6059
*/
61-
fun aggregateCalculatingType(values: Iterable<Value>, valueTypes: Set<KType>? = null): Return?
60+
fun aggregateCalculatingType(values: Iterable<Value>, valueTypes: Set<KType>? = null): Return
6261

6362
/**
6463
* Function that can give the return type of [aggregate] as [KType], given the type of the input.
@@ -82,17 +81,19 @@ internal interface Aggregator<in Value, out Return> {
8281
fun calculateReturnTypeOrNull(colTypes: Set<KType>, colsEmpty: Boolean): KType?
8382
}
8483

84+
@Suppress("UNCHECKED_CAST")
8585
@PublishedApi
8686
internal fun <Type> Aggregator<*, *>.cast(): Aggregator<Type, Type> = this as Aggregator<Type, Type>
8787

88+
@Suppress("UNCHECKED_CAST")
8889
@PublishedApi
8990
internal fun <Value, Return> Aggregator<*, *>.cast2(): Aggregator<Value, Return> = this as Aggregator<Value, Return>
9091

9192
/** Type alias for [Aggregator.calculateReturnTypeOrNull] */
9293
internal typealias CalculateReturnTypeOrNull = (type: KType, emptyInput: Boolean) -> KType?
9394

9495
/** Type alias for [Aggregator.aggregate]. */
95-
internal typealias Aggregate<Value, Return> = Iterable<Value>.(type: KType) -> Return?
96+
internal typealias Aggregate<Value, Return> = Iterable<Value>.(type: KType) -> Return
9697

9798
/** Common case for [CalculateReturnTypeOrNull], preserves return type, but makes it nullable for empty inputs. */
9899
internal val preserveReturnTypeNullIfEmpty: CalculateReturnTypeOrNull = { type, emptyInput ->

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorBase.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ internal abstract class AggregatorBase<in Value, out Return>(
3131
*
3232
* When the exact [type] is unknown, use [aggregateCalculatingType].
3333
*/
34-
override fun aggregate(values: Iterable<Value>, type: KType): Return? = aggregator(values, type)
34+
override fun aggregate(values: Iterable<Value>, type: KType): Return = aggregator(values, type)
3535

3636
/**
3737
* Function that can give the return type of [aggregate] as [KType], given the type of the input.
@@ -52,7 +52,7 @@ internal abstract class AggregatorBase<in Value, out Return>(
5252
* Nulls are filtered out by default, then [aggregate] (with [Iterable] and [KType]) is called.
5353
*/
5454
@Suppress("UNCHECKED_CAST")
55-
override fun aggregate(column: DataColumn<Value?>): Return? =
55+
override fun aggregate(column: DataColumn<Value?>): Return =
5656
aggregate(
5757
values =
5858
if (column.hasNulls()) {
@@ -71,7 +71,7 @@ internal abstract class AggregatorBase<in Value, out Return>(
7171
* If provided, this can be used to avoid calculating the types of [values][org.jetbrains.kotlinx.dataframe.values] at runtime with reflection.
7272
* It should contain all types of [values][org.jetbrains.kotlinx.dataframe.values].
7373
* If `null`, the types of [values][org.jetbrains.kotlinx.dataframe.values] will be calculated at runtime (heavy!). */
74-
override fun aggregateCalculatingType(values: Iterable<Value>, valueTypes: Set<KType>?): Return? {
74+
override fun aggregateCalculatingType(values: Iterable<Value>, valueTypes: Set<KType>?): Return {
7575
val commonType = if (valueTypes != null) {
7676
valueTypes.commonType(false)
7777
} else {
@@ -93,7 +93,7 @@ internal abstract class AggregatorBase<in Value, out Return>(
9393
* Aggregates the data in the multiple given columns and computes a single resulting value.
9494
* Must be overridden to use.
9595
*/
96-
abstract override fun aggregate(columns: Iterable<DataColumn<Value?>>): Return?
96+
abstract override fun aggregate(columns: Iterable<DataColumn<Value?>>): Return
9797

9898
/**
9999
* Function that can give the return type of [aggregate] with columns as [KType],

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ internal object Aggregators {
3030
* -> stepOneAggregator(Iterable<Value>, colType) // called on each iterable
3131
* -> Iterable<Return> // nulls filtered out
3232
* -> stepTwoAggregator(Iterable<Return>, common valueType)
33-
* -> Return?
33+
* -> Return
3434
* ```
3535
*
3636
* It can also be used as a "simple" aggregator by providing the same function for both steps.
@@ -43,7 +43,7 @@ internal object Aggregators {
4343
* @param stepTwoAggregator Functional argument for the aggregation function used between different columns.
4444
* It is run on the results of [stepOneAggregator].
4545
*/
46-
private fun <Type> twoStepPreservingType(aggregator: Aggregate<Type, Type>) =
46+
private fun <Type> twoStepPreservingType(aggregator: Aggregate<Type, Type?>) =
4747
TwoStepAggregator.Factory(
4848
getReturnTypeOrNull = preserveReturnTypeNullIfEmpty,
4949
stepOneAggregator = aggregator,
@@ -68,7 +68,7 @@ internal object Aggregators {
6868
* -> stepOneAggregator(Iterable<Value>, colType) // called on each iterable
6969
* -> Iterable<Return> // nulls filtered out
7070
* -> stepTwoAggregator(Iterable<Return>, common valueType)
71-
* -> Return?
71+
* -> Return
7272
* ```
7373
*
7474
* It can also be used as a "simple" aggregator by providing the same function for both steps.
@@ -106,7 +106,7 @@ internal object Aggregators {
106106
* Iterable<Column<Value?>>
107107
* -> Iterable<Value> // flattened without nulls
108108
* -> aggregator(Iterable<Value>, common colType)
109-
* -> Return?
109+
* -> Return
110110
* ```
111111
*
112112
* This is essential for aggregators that depend on the distribution of all values across the dataframe, like
@@ -119,7 +119,7 @@ internal object Aggregators {
119119
* @param aggregator Functional argument for the [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.FlatteningAggregator.aggregate] function.
120120
* Note that it must be able to handle `null` values for the [Iterable] overload of [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.FlatteningAggregator.aggregate].
121121
*/
122-
private fun <Type> flatteningPreservingTypes(aggregate: Aggregate<Type, Type>) =
122+
private fun <Type> flatteningPreservingTypes(aggregate: Aggregate<Type, Type?>) =
123123
FlatteningAggregator.Factory(
124124
getReturnTypeOrNull = preserveReturnTypeNullIfEmpty,
125125
aggregator = aggregate,
@@ -140,7 +140,7 @@ internal object Aggregators {
140140
* Iterable<Column<Value?>>
141141
* -> Iterable<Value> // flattened without nulls
142142
* -> aggregator(Iterable<Value>, common colType)
143-
* -> Return?
143+
* -> Return
144144
* ```
145145
*
146146
* This is essential for aggregators that depend on the distribution of all values across the dataframe, like
@@ -182,7 +182,7 @@ internal object Aggregators {
182182
* -> aggregator(Iterable<specific Number>, unified number type of common colType) // called on each iterable
183183
* -> Iterable<Return> // nulls filtered out
184184
* -> aggregator(Iterable<specific Return>, unified number type of common valueType)
185-
* -> Return?
185+
* -> Return
186186
* ```
187187
*
188188
* @param name The name of this aggregator.
@@ -191,7 +191,7 @@ internal object Aggregators {
191191
* While it takes a [Number] argument, you can assume that all values are of the same specific type, however,
192192
* this type can be different for different calls to [aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorBase.aggregator].
193193
*/
194-
private fun <Return : Number> twoStepForNumbers(
194+
private fun <Return : Number?> twoStepForNumbers(
195195
getReturnTypeOrNull: CalculateReturnTypeOrNull,
196196
aggregate: Aggregate<Number, Return>,
197197
) = TwoStepNumbersAggregator.Factory(

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/FlatteningAggregator.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import kotlin.reflect.full.withNullability
1818
* Iterable<Column<Value?>>
1919
* -> Iterable<Value> // flattened without nulls
2020
* -> aggregator(Iterable<Value>, common colType)
21-
* -> Return?
21+
* -> Return
2222
* ```
2323
*
2424
* This is essential for aggregators that depend on the distribution of all values across the dataframe, like
@@ -42,7 +42,7 @@ internal class FlatteningAggregator<in Value, out Return>(
4242
* The columns are flattened into a single list of values, filtering nulls as usual;
4343
* then the aggregation function is with the common type of the columns.
4444
*/
45-
override fun aggregate(columns: Iterable<DataColumn<Value?>>): Return? {
45+
override fun aggregate(columns: Iterable<DataColumn<Value?>>): Return {
4646
val commonType = columns.map { it.type() }.commonType().withNullability(false)
4747
val allValues = columns.asSequence().flatMap { it.values() }.filterNotNull()
4848
return aggregate(allValues.asIterable(), commonType)

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import kotlin.reflect.full.withNullability
2323
* -> stepOneAggregator(Iterable<Value>, colType) // called on each iterable
2424
* -> Iterable<Return> // nulls filtered out
2525
* -> stepTwoAggregator(Iterable<Return>, common valueType)
26-
* -> Return?
26+
* -> Return
2727
* ```
2828
*
2929
* It can also be used as a "simple" aggregator by providing the same function for both steps.
@@ -40,7 +40,7 @@ internal class TwoStepAggregator<in Value, out Return>(
4040
name: String,
4141
getReturnTypeOrNull: CalculateReturnTypeOrNull,
4242
stepOneAggregator: Aggregate<Value, Return>,
43-
private val stepTwoAggregator: Aggregate<Return, Return>,
43+
private val stepTwoAggregator: Aggregate<Return & Any, Return>,
4444
) : AggregatorBase<Value, Return>(name, getReturnTypeOrNull, stepOneAggregator) {
4545

4646
/**
@@ -50,7 +50,7 @@ internal class TwoStepAggregator<in Value, out Return>(
5050
*
5151
* Post-step-one types are calculated by [calculateReturnTypeOrNull].
5252
*/
53-
override fun aggregate(columns: Iterable<DataColumn<Value?>>): Return? {
53+
override fun aggregate(columns: Iterable<DataColumn<Value?>>): Return {
5454
val (values, types) = columns.mapNotNull { col ->
5555
// uses stepOneAggregator
5656
val value = aggregate(col) ?: return@mapNotNull null
@@ -93,7 +93,7 @@ internal class TwoStepAggregator<in Value, out Return>(
9393
class Factory<in Value, out Return>(
9494
private val getReturnTypeOrNull: CalculateReturnTypeOrNull,
9595
private val stepOneAggregator: Aggregate<Value, Return>,
96-
private val stepTwoAggregator: Aggregate<Return, Return>,
96+
private val stepTwoAggregator: Aggregate<Return & Any, Return>,
9797
) : AggregatorProvider<TwoStepAggregator<Value, Return>> by AggregatorProvider({ name ->
9898
TwoStepAggregator(
9999
name = name,

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepNumbersAggregator.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ private val logger = KotlinLogging.logger { }
3939
* -> aggregator(Iterable<specific Number>, unified number type of common colType) // called on each iterable
4040
* -> Iterable<Return> // nulls filtered out
4141
* -> aggregator(Iterable<specific Return>, unified number type of common valueType)
42-
* -> Return?
42+
* -> Return
4343
* ```
4444
*
4545
* @param name The name of this aggregator.
@@ -48,7 +48,7 @@ private val logger = KotlinLogging.logger { }
4848
* While it takes a [Number] argument, you can assume that all values are of the same specific type, however,
4949
* this type can be different for different calls to [aggregator].
5050
*/
51-
internal class TwoStepNumbersAggregator<out Return : Number>(
51+
internal class TwoStepNumbersAggregator<out Return : Number?>(
5252
name: String,
5353
getReturnTypeOrNull: CalculateReturnTypeOrNull,
5454
aggregator: Aggregate<Number, Return>,
@@ -62,7 +62,7 @@ internal class TwoStepNumbersAggregator<out Return : Number>(
6262
* After the first aggregation, the number types are found by [calculateReturnTypeOrNull] and then
6363
* unified using [aggregateCalculatingType].
6464
*/
65-
override fun aggregate(columns: Iterable<DataColumn<Number?>>): Return? {
65+
override fun aggregate(columns: Iterable<DataColumn<Number?>>): Return {
6666
val (values, types) = columns.mapNotNull { col ->
6767
val value = aggregate(col) ?: return@mapNotNull null
6868
val type = calculateReturnTypeOrNull(
@@ -113,7 +113,7 @@ internal class TwoStepNumbersAggregator<out Return : Number>(
113113
*
114114
* When the exact [type] is unknown, use [aggregateCalculatingType].
115115
*/
116-
override fun aggregate(values: Iterable<Number>, type: KType): Return? {
116+
override fun aggregate(values: Iterable<Number>, type: KType): Return {
117117
require(type.isSubtypeOf(typeOf<Number?>())) {
118118
"${TwoStepNumbersAggregator::class.simpleName}: Type $type is not a subtype of Number?"
119119
}
@@ -147,7 +147,7 @@ internal class TwoStepNumbersAggregator<out Return : Number>(
147147
* If `null`, the types of [values] will be calculated at runtime (heavy!).
148148
*/
149149
@Suppress("UNCHECKED_CAST")
150-
override fun aggregateCalculatingType(values: Iterable<Number>, valueTypes: Set<KType>?): Return? {
150+
override fun aggregateCalculatingType(values: Iterable<Number>, valueTypes: Set<KType>?): Return {
151151
val valueTypes = valueTypes ?: values.types()
152152
val commonType = valueTypes
153153
.unifiedNumberType(PRIMITIVES_ONLY)
@@ -176,7 +176,7 @@ internal class TwoStepNumbersAggregator<out Return : Number>(
176176
* @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function.
177177
* @param aggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable].
178178
*/
179-
class Factory<out Return : Number>(
179+
class Factory<out Return : Number?>(
180180
private val getReturnTypeOrNull: CalculateReturnTypeOrNull,
181181
private val aggregate: Aggregate<Number, Return>,
182182
) : AggregatorProvider<TwoStepNumbersAggregator<Return>> by AggregatorProvider({ name ->

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,19 @@ import kotlin.reflect.typeOf
1919
internal inline fun <C, reified V, R> Aggregator<V, R>.aggregateOf(
2020
values: Iterable<C>,
2121
noinline transform: (C) -> V,
22-
): R? = aggregate(values.asSequence().map(transform).asIterable(), typeOf<V>())
22+
): R = aggregate(values.asSequence().map(transform).asIterable(), typeOf<V>())
2323

2424
@PublishedApi
2525
internal inline fun <C, reified V, R> Aggregator<V, R>.aggregateOf(
2626
column: DataColumn<C>,
2727
noinline transform: (C) -> V,
28-
): R? = aggregateOf(column.values(), transform)
28+
): R = aggregateOf(column.values(), transform)
2929

3030
@PublishedApi
3131
internal inline fun <T, reified C, R> Aggregator<*, R>.aggregateOf(
3232
frame: DataFrame<T>,
3333
crossinline expression: RowExpression<T, C>,
34-
): R? = (this as Aggregator<C, R>).aggregateOf(frame.rows()) { expression(it, it) }
34+
): R = (this as Aggregator<C, R>).aggregateOf(frame.rows()) { expression(it, it) }
3535

3636
@PublishedApi
3737
internal fun <T, C, R> Aggregator<*, R>.aggregateOfDelegated(
@@ -47,10 +47,10 @@ internal fun <T, C, R> Aggregator<*, R>.aggregateOfDelegated(
4747
internal inline fun <T, reified C, R> Aggregator<*, R>.of(
4848
data: DataFrame<T>,
4949
crossinline expression: RowExpression<T, C>,
50-
): R? = aggregateOf(data as DataFrame<T>, expression)
50+
): R = aggregateOf(data as DataFrame<T>, expression)
5151

5252
@PublishedApi
53-
internal inline fun <C, reified V, R> Aggregator<V, R>.of(data: DataColumn<C>, crossinline expression: (C) -> V): R? =
53+
internal inline fun <C, reified V, R> Aggregator<V, R>.of(data: DataColumn<C>, crossinline expression: (C) -> V): R =
5454
aggregateOf(data.values()) { expression(it) }
5555

5656
@PublishedApi

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator
1414
* @param columns selector of which columns inside the [row] to aggregate
1515
*/
1616
@PublishedApi
17-
internal fun <V, R> Aggregator<V, R>.aggregateOfRow(row: AnyRow, columns: ColumnsSelector<*, V?>): R? {
17+
internal fun <V, R> Aggregator<V, R>.aggregateOfRow(row: AnyRow, columns: ColumnsSelector<*, V?>): R {
1818
val filteredColumns = row.df().getColumns(columns)
1919
return aggregateCalculatingType(
2020
values = filteredColumns.mapNotNull { row[it] },

0 commit comments

Comments
 (0)