diff --git a/core/api/core.api b/core/api/core.api index f03122f4c3..de0f34c2da 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -1894,7 +1894,7 @@ public abstract interface class org/jetbrains/kotlinx/dataframe/api/DataSchemaEn public final class org/jetbrains/kotlinx/dataframe/api/DefaultsKt { public static final fun getDdof_default ()I - public static final fun getSkipNA_default ()Z + public static final fun getSkipNaN_default ()Z } public final class org/jetbrains/kotlinx/dataframe/api/DescribeKt { @@ -2386,6 +2386,7 @@ public final class org/jetbrains/kotlinx/dataframe/api/GroupByKt { public static synthetic fun groupBy$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/GroupBy; public static synthetic fun groupBy$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy; public static final fun groupByOther (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;)Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy; + public static final fun reduce (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; } public final class org/jetbrains/kotlinx/dataframe/api/GroupClause { @@ -2685,114 +2686,200 @@ public final class org/jetbrains/kotlinx/dataframe/api/MatchesKt { } public final class org/jetbrains/kotlinx/dataframe/api/MaxKt { - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Comparable; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Comparable; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Ljava/lang/Comparable; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Ljava/lang/Comparable; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Comparable; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Z)Ljava/lang/Comparable; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Comparable; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Ljava/lang/Comparable; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Ljava/lang/Comparable; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)Ljava/lang/Comparable; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Ljava/lang/Comparable; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Ljava/lang/Comparable; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun max (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/DataColumn;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Ljava/lang/Comparable; public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; - public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; - public static final fun maxByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun maxByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun max$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; + public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; + public static final synthetic fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; + public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; + public static final synthetic fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; + public static final fun maxBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; + public static synthetic fun maxBy$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxBy$default (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; + public static synthetic fun maxBy$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; + public static synthetic fun maxBy$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; + public static final synthetic fun maxByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxByOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun maxFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxOf (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)Ljava/lang/Comparable; - public static final fun maxOf (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; - public static final fun maxOf (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxOf (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun maxOf (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun maxOf$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun maxOfOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)Ljava/lang/Comparable; - public static final fun maxOfOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; - public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Comparable; - public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; - public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Comparable; - public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Ljava/lang/Comparable; - public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Ljava/lang/Comparable; + public static synthetic fun maxFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Comparable; + public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Z)Ljava/lang/Comparable; + public static final synthetic fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; + public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; + public static final synthetic fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Comparable; + public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Ljava/lang/Comparable; + public static final synthetic fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Ljava/lang/Comparable; + public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)Ljava/lang/Comparable; + public static final synthetic fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Ljava/lang/Comparable; + public static final fun maxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Ljava/lang/Comparable; + public static synthetic fun maxOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataColumn;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun maxOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun maxOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun maxOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun maxOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Ljava/lang/Comparable; public static final fun rowMax (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; public static final fun rowMaxOrNull (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; } public final class org/jetbrains/kotlinx/dataframe/api/MeanKt { + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)D public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Z)D + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)D public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)D + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)D public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)D + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)D public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)D + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)D public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)D + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun mean (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/DataColumn;ZILjava/lang/Object;)D public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; @@ -2800,33 +2887,55 @@ public final class org/jetbrains/kotlinx/dataframe/api/MeanKt { public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)D public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)D public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)D + public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun mean$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun meanFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; @@ -2836,14 +2945,23 @@ public final class org/jetbrains/kotlinx/dataframe/api/MeanKt { public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun meanFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun rowMean (Lorg/jetbrains/kotlinx/dataframe/DataRow;)D public static final fun rowMean (Lorg/jetbrains/kotlinx/dataframe/DataRow;Z)D public static synthetic fun rowMean$default (Lorg/jetbrains/kotlinx/dataframe/DataRow;ZILjava/lang/Object;)D } @@ -2945,92 +3063,160 @@ public final class org/jetbrains/kotlinx/dataframe/api/MergeWithTransform { } public final class org/jetbrains/kotlinx/dataframe/api/MinKt { - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Comparable; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Comparable; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Ljava/lang/Comparable; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Ljava/lang/Comparable; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Comparable; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Z)Ljava/lang/Comparable; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Comparable; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Ljava/lang/Comparable; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Ljava/lang/Comparable; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)Ljava/lang/Comparable; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Ljava/lang/Comparable; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Ljava/lang/Comparable; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun min (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/DataColumn;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Ljava/lang/Comparable; public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; - public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; - public static final fun minByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun minByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun min$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; + public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; + public static final synthetic fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; + public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; + public static final synthetic fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; + public static final fun minBy (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; + public static synthetic fun minBy$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minBy$default (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedGroupBy; + public static synthetic fun minBy$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; + public static synthetic fun minBy$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; + public static final synthetic fun minByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minByOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minByOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun minFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minOf (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)Ljava/lang/Comparable; - public static final fun minOf (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; - public static final fun minOf (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minOf (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun minOf (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static synthetic fun minOf$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun minOfOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)Ljava/lang/Comparable; - public static final fun minOfOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; - public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Comparable; - public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; - public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Comparable; - public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Ljava/lang/Comparable; - public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Ljava/lang/Comparable; + public static synthetic fun minFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Comparable; + public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Z)Ljava/lang/Comparable; + public static final synthetic fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; + public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Ljava/lang/Comparable; + public static final synthetic fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Comparable; + public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Ljava/lang/Comparable; + public static final synthetic fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Ljava/lang/Comparable; + public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)Ljava/lang/Comparable; + public static final synthetic fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Ljava/lang/Comparable; + public static final fun minOrNull (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Ljava/lang/Comparable; + public static synthetic fun minOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataColumn;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun minOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun minOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun minOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Ljava/lang/Comparable; + public static synthetic fun minOrNull$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Ljava/lang/Comparable; public static final fun rowMin (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; public static final fun rowMinOrNull (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Object; } @@ -3376,6 +3562,7 @@ public final class org/jetbrains/kotlinx/dataframe/api/PivotKt { public static synthetic fun pivotMatches$default (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun pivotMatches$default (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun pivotMatches$default (Lorg/jetbrains/kotlinx/dataframe/api/GroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun reduce (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivot; public static final fun reduce (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/api/ReducedPivotGroupBy; } @@ -3817,60 +4004,132 @@ public final class org/jetbrains/kotlinx/dataframe/api/StdKt { } public final class org/jetbrains/kotlinx/dataframe/api/SumKt { - public static final fun rowSum (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Number; - public static final fun rowSumOf (Lorg/jetbrains/kotlinx/dataframe/DataRow;Lkotlin/reflect/KType;)Ljava/lang/Number; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Number; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun rowSum (Lorg/jetbrains/kotlinx/dataframe/DataRow;)Ljava/lang/Number; + public static final fun rowSum (Lorg/jetbrains/kotlinx/dataframe/DataRow;Z)Ljava/lang/Number; + public static synthetic fun rowSum$default (Lorg/jetbrains/kotlinx/dataframe/DataRow;ZILjava/lang/Object;)Ljava/lang/Number; + public static final synthetic fun rowSumOf (Lorg/jetbrains/kotlinx/dataframe/DataRow;Lkotlin/reflect/KType;)Ljava/lang/Number; + public static final fun rowSumOf (Lorg/jetbrains/kotlinx/dataframe/DataRow;Lkotlin/reflect/KType;Z)Ljava/lang/Number; + public static synthetic fun rowSumOf$default (Lorg/jetbrains/kotlinx/dataframe/DataRow;Lkotlin/reflect/KType;ZILjava/lang/Object;)Ljava/lang/Number; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/DataFrame;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Ljava/lang/Number; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Ljava/lang/Number; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sum (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Ljava/lang/Number; public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sum$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static final fun sumByte (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)I public static final fun sumByte (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)I public static final fun sumByte (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)I public static final fun sumByte (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)I - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZLkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;Z)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final fun sumFor (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZ)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/DataFrame;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Grouped;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Ljava/lang/String;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lkotlin/reflect/KProperty;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/Pivot;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataRow; public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;ZZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Ljava/lang/String;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lkotlin/reflect/KProperty;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; - public static final fun sumNumber (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Number; + public static synthetic fun sumFor$default (Lorg/jetbrains/kotlinx/dataframe/api/PivotGroupBy;[Lorg/jetbrains/kotlinx/dataframe/columns/ColumnReference;ZZILjava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/DataFrame; + public static final synthetic fun sumNumber (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Number; + public static final fun sumNumber (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Z)Ljava/lang/Number; + public static synthetic fun sumNumber$default (Lorg/jetbrains/kotlinx/dataframe/DataColumn;ZILjava/lang/Object;)Ljava/lang/Number; public static final fun sumOfByte (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)I public static final fun sumOfByte (Lorg/jetbrains/kotlinx/dataframe/DataFrame;Lkotlin/jvm/functions/Function2;)I public static final fun sumOfShort (Lorg/jetbrains/kotlinx/dataframe/DataColumn;Lkotlin/jvm/functions/Function1;)I @@ -5167,59 +5426,76 @@ public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/Aggregations public static synthetic fun yieldOneOrMany$default (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/receivers/AggregateInternalDsl;Lorg/jetbrains/kotlinx/dataframe/columns/ColumnPath;Ljava/util/List;Lkotlin/reflect/KType;Ljava/lang/Object;ILjava/lang/Object;)V } -public abstract interface class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator { - public abstract fun aggregate (Ljava/lang/Iterable;)Ljava/lang/Object; - public abstract fun aggregate (Ljava/lang/Iterable;Lkotlin/reflect/KType;)Ljava/lang/Object; - public abstract fun aggregate (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Object; - public abstract fun aggregateCalculatingType (Ljava/lang/Iterable;Ljava/util/Set;)Ljava/lang/Object; - public static synthetic fun aggregateCalculatingType$default (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;Ljava/lang/Iterable;Ljava/util/Set;ILjava/lang/Object;)Ljava/lang/Object; - public abstract fun calculateReturnTypeOrNull (Ljava/util/Set;Z)Lkotlin/reflect/KType; - public abstract fun calculateReturnTypeOrNull (Lkotlin/reflect/KType;Z)Lkotlin/reflect/KType; - public abstract fun getName ()Ljava/lang/String; +public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator : org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorAggregationHandler, org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler, org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorMultipleColumnsHandler { + public fun (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorAggregationHandler;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorMultipleColumnsHandler;Ljava/lang/String;)V + public fun aggregateMultipleColumns (Lkotlin/sequences/Sequence;)Ljava/lang/Object; + public fun aggregateSequence (Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)Ljava/lang/Object; + public fun aggregateSingleColumn (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Object; + public fun calculateReturnType (Lkotlin/reflect/KType;Z)Lkotlin/reflect/KType; + public fun calculateReturnTypeMultipleColumns (Ljava/util/Set;Z)Lkotlin/reflect/KType; + public fun calculateValueType (Ljava/util/Set;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType; + public fun calculateValueType (Lkotlin/sequences/Sequence;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType; + public final fun getAggregationHandler ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorAggregationHandler; + public fun getAggregator ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; + public final fun getInputHandler ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler; + public final fun getMultipleColumnsHandler ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorMultipleColumnsHandler; + public final fun getName ()Ljava/lang/String; + public fun indexOfAggregationResultSingleSequence (Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)I + public fun init (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;)V + public fun preprocessAggregation (Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)Lkotlin/Pair; + public fun setAggregator (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;)V + public fun toString ()Ljava/lang/String; +} + +public abstract interface class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorAggregationHandler : org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorHandler { + public abstract fun aggregateSequence (Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)Ljava/lang/Object; + public abstract fun aggregateSingleColumn (Lorg/jetbrains/kotlinx/dataframe/DataColumn;)Ljava/lang/Object; + public abstract fun calculateReturnType (Lkotlin/reflect/KType;Z)Lkotlin/reflect/KType; + public abstract fun indexOfAggregationResultSingleSequence (Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)I } public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorKt { + public static final fun aggregate (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;Lkotlin/sequences/Sequence;Lkotlin/reflect/KType;)Ljava/lang/Object; + public static final fun aggregate (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)Ljava/lang/Object; public static final fun cast (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; public static final fun cast2 (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; + public static final fun indexOfAggregationResult (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;Lkotlin/sequences/Sequence;Lkotlin/reflect/KType;)I + public static final fun indexOfAggregationResult (Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator;Lkotlin/sequences/Sequence;Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType;)I } public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1 { + public static final field Companion Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1$Companion; public fun (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V public final fun getGetAggregator ()Lkotlin/jvm/functions/Function1; public final fun getName ()Ljava/lang/String; public final fun invoke (Ljava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; } -public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1$Factory : org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Provider { - public fun (Lkotlin/jvm/functions/Function1;)V - public synthetic fun create (Ljava/lang/String;)Ljava/lang/Object; - public fun create (Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1; - public final fun getGetAggregator ()Lkotlin/jvm/functions/Function1; +public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1$Companion { + public final fun Factory (Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Provider; } public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2 { + public static final field Companion Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2$Companion; public fun (Ljava/lang/String;Lkotlin/jvm/functions/Function2;)V public final fun getGetAggregator ()Lkotlin/jvm/functions/Function2; public final fun getName ()Ljava/lang/String; public final fun invoke (Ljava/lang/Object;Ljava/lang/Object;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; } -public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2$Factory : org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Provider { - public fun (Lkotlin/jvm/functions/Function2;)V - public synthetic fun create (Ljava/lang/String;)Ljava/lang/Object; - public fun create (Ljava/lang/String;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2; - public final fun getGetAggregator ()Lkotlin/jvm/functions/Function2; +public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2$Companion { + public final fun Factory (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Provider; } public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators { public static final field INSTANCE Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators; - public final fun getMax ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator; public final fun getMean ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1; - public final fun getMedian ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/FlatteningAggregator; - public final fun getMin ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator; + public final fun getMedian ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; public final fun getPercentile ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1; public final fun getStd ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch2; - public final fun getSum ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepNumbersAggregator; + public final fun getSum ()Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch1; + public final fun max (Z)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; + public final fun min (Z)Lorg/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator; } public final class org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/NoAggregationKt { @@ -6155,9 +6431,9 @@ public final class org/jetbrains/kotlinx/dataframe/keywords/SoftKeywords$Compani public final fun getVALUES ()Ljava/util/List; } -public final class org/jetbrains/kotlinx/dataframe/math/MeanKt { - public static final fun mean (Ljava/lang/Iterable;Lkotlin/reflect/KType;Z)D - public static synthetic fun mean$default (Ljava/lang/Iterable;Lkotlin/reflect/KType;ZILjava/lang/Object;)D +public final class org/jetbrains/kotlinx/dataframe/math/MinMaxKt { + public static final fun maxOrNull (Lkotlin/sequences/Sequence;Lkotlin/reflect/KType;Z)Ljava/lang/Comparable; + public static final fun minOrNull (Lkotlin/sequences/Sequence;Lkotlin/reflect/KType;Z)Ljava/lang/Comparable; } public final class org/jetbrains/kotlinx/dataframe/math/PercentileKt { @@ -6170,7 +6446,7 @@ public final class org/jetbrains/kotlinx/dataframe/math/StdKt { } public final class org/jetbrains/kotlinx/dataframe/math/SumKt { - public static final fun sumNullableT (Lkotlin/sequences/Sequence;Lkotlin/reflect/KType;)Ljava/lang/Number; + public static final fun sumNullableT (Lkotlin/sequences/Sequence;Lkotlin/reflect/KType;Z)Ljava/lang/Number; } public abstract class org/jetbrains/kotlinx/dataframe/schema/ColumnSchema { diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataColumnType.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataColumnType.kt index 50ef9500b7..a6105f8dd7 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataColumnType.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataColumnType.kt @@ -7,6 +7,7 @@ import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.columns.ColumnKind import org.jetbrains.kotlinx.dataframe.columns.FrameColumn import org.jetbrains.kotlinx.dataframe.columns.ValueColumn +import org.jetbrains.kotlinx.dataframe.impl.isIntraComparable import org.jetbrains.kotlinx.dataframe.impl.isMixedNumber import org.jetbrains.kotlinx.dataframe.impl.isPrimitiveNumber import org.jetbrains.kotlinx.dataframe.impl.isPrimitiveOrMixedNumber @@ -18,11 +19,7 @@ import org.jetbrains.kotlinx.dataframe.util.IS_INTER_COMPARABLE_IMPORT import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.reflect.KType -import kotlin.reflect.KTypeProjection -import kotlin.reflect.KVariance -import kotlin.reflect.full.createType import kotlin.reflect.full.isSubtypeOf -import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf public fun AnyCol.isColumnGroup(): Boolean { @@ -93,13 +90,4 @@ public fun AnyCol.isComparable(): Boolean = valuesAreComparable() * * Technically, this means the values' common type `T(?)` is a subtype of [Comparable]`(?)` */ -public fun AnyCol.valuesAreComparable(): Boolean = - isValueColumn() && - isSubtypeOf( - Comparable::class.createType( - arguments = listOf( - KTypeProjection(KVariance.IN, type().withNullability(false)), - ), - nullable = hasNulls(), - ), - ) +public fun AnyCol.valuesAreComparable(): Boolean = isValueColumn() && type().isIntraComparable() diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Defaults.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Defaults.kt index 646954aa45..c7778320be 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Defaults.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Defaults.kt @@ -1,7 +1,7 @@ package org.jetbrains.kotlinx.dataframe.api @PublishedApi -internal val skipNA_default: Boolean = false +internal val skipNaN_default: Boolean = false @PublishedApi internal val ddof_default: Int = 1 diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt index 669265adc6..d7d81f701f 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Nulls.kt @@ -18,6 +18,8 @@ import org.jetbrains.kotlinx.dataframe.documentation.NaN import org.jetbrains.kotlinx.dataframe.documentation.SelectingColumns import org.jetbrains.kotlinx.dataframe.get import org.jetbrains.kotlinx.dataframe.typeClass +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract import kotlin.reflect.KProperty // region fillNulls @@ -300,6 +302,14 @@ public fun DataFrame.fillNulls(vararg columns: ColumnReference): Up internal inline val Any?.isNaN: Boolean get() = (this is Double && isNaN()) || (this is Float && isNaN()) +@JvmName("isNaWithContract") +@Suppress("NOTHING_TO_INLINE") +@OptIn(ExperimentalContracts::class) +internal inline fun T.isNA(): Boolean { + contract { returns(false) implies (this@isNA != null) } + return isNA +} + internal inline val Any?.isNA: Boolean get() = when (this) { null -> true diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt index eb5be20565..3debb714e4 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt @@ -109,4 +109,5 @@ public class ReducedGroupBy( override fun toString(): String = "ReducedGroupBy(groupBy=$groupBy, reducer=$reducer)" } +@PublishedApi internal fun GroupBy.reduce(reducer: Selector, DataRow?>) = ReducedGroupBy(this, reducer) diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt index 6de276a7e4..9356ce052c 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt @@ -12,295 +12,423 @@ 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.columns.values import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregators import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateByOrNull import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor -import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfDelegated +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfRow import org.jetbrains.kotlinx.dataframe.impl.columns.toComparableColumns -import org.jetbrains.kotlinx.dataframe.impl.indexOfMax import org.jetbrains.kotlinx.dataframe.impl.suggestIfNull +import org.jetbrains.kotlinx.dataframe.util.ROW_MAX +import org.jetbrains.kotlinx.dataframe.util.ROW_MAX_OR_NULL import kotlin.reflect.KProperty // region DataColumn -public fun > DataColumn.max(): T = maxOrNull().suggestIfNull("max") +public fun > DataColumn.max(skipNaN: Boolean = skipNaN_default): T = + maxOrNull(skipNaN).suggestIfNull("max") -public fun > DataColumn.maxOrNull(): T? = asSequence().filterNotNull().maxOrNull() +public fun > DataColumn.maxOrNull(skipNaN: Boolean = skipNaN_default): T? = + Aggregators.max(skipNaN).aggregateSingleColumn(this) -public fun > DataColumn.maxBy(selector: (T) -> R): T = - maxByOrNull(selector).suggestIfNull("maxBy") +public inline fun ?> DataColumn.maxBy( + skipNaN: Boolean = skipNaN_default, + noinline selector: (T) -> R, +): T & Any = maxByOrNull(skipNaN, selector).suggestIfNull("maxBy") -public fun > DataColumn.maxByOrNull(selector: (T) -> R): T? = values.maxByOrNull(selector) +public inline fun ?> DataColumn.maxByOrNull( + skipNaN: Boolean = skipNaN_default, + noinline selector: (T) -> R, +): T? = Aggregators.max(skipNaN).aggregateByOrNull(this, selector) -public fun > DataColumn.maxOf(selector: (T) -> R): R = - maxOfOrNull(selector).suggestIfNull("maxOf") +public inline fun ?> DataColumn.maxOf( + skipNaN: Boolean = skipNaN_default, + crossinline selector: (T) -> R, +): R & Any = maxOfOrNull(skipNaN, selector).suggestIfNull("maxOf") -public fun > DataColumn.maxOfOrNull(selector: (T) -> R): R? = values.maxOfOrNull(selector) +public inline fun ?> DataColumn.maxOfOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline selector: (T) -> R, +): R? = Aggregators.max(skipNaN).aggregateOf(this, selector) // endregion // region DataRow -public fun AnyRow.rowMaxOrNull(): Any? = values().filterIsInstance>().maxWithOrNull(compareBy { it }) +@Deprecated(ROW_MAX_OR_NULL, level = DeprecationLevel.ERROR) +public fun AnyRow.rowMaxOrNull(): Any? = error(ROW_MAX_OR_NULL) -public fun AnyRow.rowMax(): Any = rowMaxOrNull().suggestIfNull("rowMax") +@Deprecated(ROW_MAX, level = DeprecationLevel.ERROR) +public fun AnyRow.rowMax(): Any = error(ROW_MAX) -public inline fun > AnyRow.rowMaxOfOrNull(): T? = values().filterIsInstance().maxOrNull() +public inline fun ?> AnyRow.rowMaxOfOrNull(skipNaN: Boolean = skipNaN_default): T? = + Aggregators.max(skipNaN).aggregateOfRow(this) { colsOf() } -public inline fun > AnyRow.rowMaxOf(): T = rowMaxOfOrNull().suggestIfNull("rowMaxOf") +public inline fun ?> AnyRow.rowMaxOf(skipNaN: Boolean = skipNaN_default): T & Any = + rowMaxOfOrNull(skipNaN).suggestIfNull("rowMaxOf") // endregion // region DataFrame -public fun DataFrame.max(): DataRow = maxFor(intraComparableColumns()) +public fun DataFrame.max(skipNaN: Boolean = skipNaN_default): DataRow = + maxFor(skipNaN, intraComparableColumns()) -public fun > DataFrame.maxFor(columns: ColumnsForAggregateSelector): DataRow = - Aggregators.max.aggregateFor(this, columns) +public fun ?> DataFrame.maxFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = Aggregators.max(skipNaN).aggregateFor(this, columns) -public fun DataFrame.maxFor(vararg columns: String): DataRow = maxFor { columns.toComparableColumns() } +public fun DataFrame.maxFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + maxFor(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > DataFrame.maxFor(vararg columns: ColumnReference): DataRow = - maxFor { columns.toColumnSet() } +public fun ?> DataFrame.maxFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > DataFrame.maxFor(vararg columns: KProperty): DataRow = - maxFor { columns.toColumnSet() } +public fun ?> DataFrame.maxFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(skipNaN) { columns.toColumnSet() } -public fun > DataFrame.max(columns: ColumnsSelector): C = - maxOrNull(columns).suggestIfNull("max") +public fun ?> DataFrame.max( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): C & Any = maxOrNull(skipNaN, columns).suggestIfNull("max") -public fun DataFrame.max(vararg columns: String): Comparable = maxOrNull(*columns).suggestIfNull("max") +public fun DataFrame.max(vararg columns: String, skipNaN: Boolean = skipNaN_default): Comparable = + maxOrNull(*columns, skipNaN = skipNaN).suggestIfNull("max") @AccessApiOverload -public fun > DataFrame.max(vararg columns: ColumnReference): C = - maxOrNull(*columns).suggestIfNull("max") +public fun ?> DataFrame.max( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C & Any = maxOrNull(*columns, skipNaN = skipNaN).suggestIfNull("max") @AccessApiOverload -public fun > DataFrame.max(vararg columns: KProperty): C = - maxOrNull(*columns).suggestIfNull("max") +public fun ?> DataFrame.max( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): C & Any = maxOrNull(*columns, skipNaN = skipNaN).suggestIfNull("max") -public fun > DataFrame.maxOrNull(columns: ColumnsSelector): C? = - Aggregators.max.aggregateAll(this, columns) as C? +public fun ?> DataFrame.maxOrNull( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): C? = Aggregators.max(skipNaN).aggregateAll(this, columns) -public fun DataFrame.maxOrNull(vararg columns: String): Comparable? = - maxOrNull { columns.toComparableColumns() } +public fun DataFrame.maxOrNull(vararg columns: String, skipNaN: Boolean = skipNaN_default): Comparable? = + maxOrNull(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > DataFrame.maxOrNull(vararg columns: ColumnReference): C? = - maxOrNull { columns.toColumnSet() } +public fun ?> DataFrame.maxOrNull( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C? = maxOrNull(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > DataFrame.maxOrNull(vararg columns: KProperty): C? = - maxOrNull { columns.toColumnSet() } +public fun ?> DataFrame.maxOrNull( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): C? = maxOrNull(skipNaN) { columns.toColumnSet() } -public fun > DataFrame.maxOf(expression: RowExpression): C = - maxOfOrNull(expression).suggestIfNull("maxOf") +public inline fun ?> DataFrame.maxOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C & Any = maxOfOrNull(skipNaN, expression).suggestIfNull("maxOf") -public fun > DataFrame.maxOfOrNull(expression: RowExpression): C? = - rows().maxOfOrNull { expression(it, it) } +public inline fun ?> DataFrame.maxOfOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C? = Aggregators.max(skipNaN).aggregateOf(this, expression) -public fun > DataFrame.maxBy(expression: RowExpression): DataRow = - maxByOrNull(expression).suggestIfNull("maxBy") +public inline fun ?> DataFrame.maxBy( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow = maxByOrNull(skipNaN, expression).suggestIfNull("maxBy") -public fun DataFrame.maxBy(column: String): DataRow = maxByOrNull(column).suggestIfNull("maxBy") +public fun DataFrame.maxBy(column: String, skipNaN: Boolean = skipNaN_default): DataRow = + maxByOrNull(column, skipNaN).suggestIfNull("maxBy") @AccessApiOverload -public fun > DataFrame.maxBy(column: ColumnReference): DataRow = - maxByOrNull(column).suggestIfNull("maxBy") +public inline fun ?> DataFrame.maxBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxByOrNull(column, skipNaN).suggestIfNull("maxBy") @AccessApiOverload -public fun > DataFrame.maxBy(column: KProperty): DataRow = - maxByOrNull(column).suggestIfNull("maxBy") +public inline fun ?> DataFrame.maxBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxByOrNull(column, skipNaN).suggestIfNull("maxBy") -public fun > DataFrame.maxByOrNull(expression: RowExpression): DataRow? = - getOrNull(rows().asSequence().map { expression(it, it) }.indexOfMax()) +public inline fun ?> DataFrame.maxByOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow? = Aggregators.max(skipNaN).aggregateByOrNull(this, expression) -public fun DataFrame.maxByOrNull(column: String): DataRow? = - maxByOrNull(column.toColumnOf?>()) +public fun DataFrame.maxByOrNull(column: String, skipNaN: Boolean = skipNaN_default): DataRow? = + maxByOrNull(column.toColumnOf?>(), skipNaN) @AccessApiOverload -public fun > DataFrame.maxByOrNull(column: ColumnReference): DataRow? = - getOrNull(get(column).asSequence().indexOfMax()) +public inline fun ?> DataFrame.maxByOrNull( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow? = Aggregators.max(skipNaN).aggregateByOrNull(this, column) @AccessApiOverload -public fun > DataFrame.maxByOrNull(column: KProperty): DataRow? = - maxByOrNull(column.toColumnAccessor()) +public inline fun ?> DataFrame.maxByOrNull( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow? = maxByOrNull(column.toColumnAccessor(), skipNaN) // endregion // region GroupBy + @Refine @Interpretable("GroupByMax1") -public fun Grouped.max(): DataFrame = maxFor(intraComparableColumns()) +public fun Grouped.max(skipNaN: Boolean = skipNaN_default): DataFrame = + maxFor(skipNaN, intraComparableColumns()) @Refine @Interpretable("GroupByMax0") -public fun > Grouped.maxFor(columns: ColumnsForAggregateSelector): DataFrame = - Aggregators.max.aggregateFor(this, columns) +public fun ?> Grouped.maxFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.max(skipNaN).aggregateFor(this, columns) -public fun Grouped.maxFor(vararg columns: String): DataFrame = maxFor { columns.toComparableColumns() } +public fun Grouped.maxFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + maxFor(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Grouped.maxFor(vararg columns: ColumnReference): DataFrame = - maxFor { columns.toColumnSet() } +public fun ?> Grouped.maxFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Grouped.maxFor(vararg columns: KProperty): DataFrame = - maxFor { columns.toColumnSet() } +public fun ?> Grouped.maxFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMax0") -public fun > Grouped.max(name: String? = null, columns: ColumnsSelector): DataFrame = - Aggregators.max.aggregateAll(this, name, columns) +public fun ?> Grouped.max( + name: String? = null, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.max(skipNaN).aggregateAll(this, name, columns) -public fun Grouped.max(vararg columns: String, name: String? = null): DataFrame = - max(name) { columns.toComparableColumns() } +public fun Grouped.max( + vararg columns: String, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(name, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Grouped.max( - vararg columns: ColumnReference, +public fun ?> Grouped.max( + vararg columns: ColumnReference, name: String? = null, -): DataFrame = max(name) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(name, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Grouped.max(vararg columns: KProperty, name: String? = null): DataFrame = - max(name) { columns.toColumnSet() } +public fun ?> Grouped.max( + vararg columns: KProperty, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(name, skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMaxOf") -public fun > Grouped.maxOf( +public inline fun ?> Grouped.maxOf( name: String? = null, - expression: RowExpression, -): DataFrame = Aggregators.max.aggregateOfDelegated(this, name) { maxOfOrNull(expression) } + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataFrame = Aggregators.max(skipNaN).aggregateOf(this, name, expression) @Interpretable("GroupByReduceExpression") -public fun > GroupBy.maxBy(rowExpression: RowExpression): ReducedGroupBy = - reduce { maxByOrNull(rowExpression) } +public inline fun ?> GroupBy.maxBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedGroupBy = reduce { maxByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > GroupBy.maxBy(column: ColumnReference): ReducedGroupBy = - reduce { maxByOrNull(column) } +public inline fun ?> GroupBy.maxBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedGroupBy = reduce { maxByOrNull(column, skipNaN) } -public fun GroupBy.maxBy(column: String): ReducedGroupBy = - maxBy(column.toColumnAccessor().cast>()) +public fun GroupBy.maxBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedGroupBy = + maxBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > GroupBy.maxBy(column: KProperty): ReducedGroupBy = - maxBy(column.toColumnAccessor()) +public inline fun ?> GroupBy.maxBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedGroupBy = maxBy(column.toColumnAccessor(), skipNaN) // endregion // region Pivot -public fun Pivot.max(separate: Boolean = false): DataRow = delegate { max(separate) } +public fun Pivot.max(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataRow = + delegate { max(separate, skipNaN) } -public fun > Pivot.maxFor( +public fun ?> Pivot.maxFor( separate: Boolean = false, - columns: ColumnsForAggregateSelector, -): DataRow = delegate { maxFor(separate, columns) } + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = delegate { maxFor(separate, skipNaN, columns) } -public fun Pivot.maxFor(vararg columns: String, separate: Boolean = false): DataRow = - maxFor(separate) { columns.toComparableColumns() } +public fun Pivot.maxFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(separate, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Pivot.maxFor( - vararg columns: ColumnReference, +public fun ?> Pivot.maxFor( + vararg columns: ColumnReference, separate: Boolean = false, -): DataRow = maxFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(separate, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Pivot.maxFor( - vararg columns: KProperty, +public fun ?> Pivot.maxFor( + vararg columns: KProperty, separate: Boolean = false, -): DataRow = maxFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(separate, skipNaN) { columns.toColumnSet() } -public fun > Pivot.max(columns: ColumnsSelector): DataRow = delegate { max(columns) } +public fun ?> Pivot.max( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataRow = delegate { max(skipNaN, columns) } -public fun Pivot.max(vararg columns: String): DataRow = max { columns.toComparableColumns() } +public fun ?> Pivot.max( + vararg columns: String, + skipNaN: Boolean = skipNaN_default, +): DataRow = max(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Pivot.max(vararg columns: ColumnReference): DataRow = - max { columns.toColumnSet() } +public fun ?> Pivot.max( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = max(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Pivot.max(vararg columns: KProperty): DataRow = - max { columns.toColumnSet() } +public fun ?> Pivot.max( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = max(skipNaN) { columns.toColumnSet() } -public fun > Pivot.maxOf(rowExpression: RowExpression): DataRow = - delegate { maxOf(rowExpression) } +public inline fun ?> Pivot.maxOf( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): DataRow = delegate { maxOf(skipNaN, rowExpression) } -public fun > Pivot.maxBy(rowExpression: RowExpression): ReducedPivot = - reduce { maxByOrNull(rowExpression) } +public inline fun ?> Pivot.maxBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedPivot = reduce { maxByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > Pivot.maxBy(column: ColumnReference): ReducedPivot = - reduce { maxByOrNull(column) } +public inline fun ?> Pivot.maxBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedPivot = reduce { maxByOrNull(column, skipNaN) } -public fun Pivot.maxBy(column: String): ReducedPivot = - maxBy(column.toColumnAccessor().cast>()) +public fun Pivot.maxBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedPivot = + maxBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > Pivot.maxBy(column: KProperty): ReducedPivot = - maxBy(column.toColumnAccessor()) +public inline fun ?> Pivot.maxBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedPivot = maxBy(column.toColumnAccessor(), skipNaN) // endregion // region PivotGroupBy -public fun PivotGroupBy.max(separate: Boolean = false): DataFrame = maxFor(separate, intraComparableColumns()) +public fun PivotGroupBy.max(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataFrame = + maxFor(separate, skipNaN, intraComparableColumns()) -public fun > PivotGroupBy.maxFor( +public fun ?> PivotGroupBy.maxFor( separate: Boolean = false, - columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.max.aggregateFor(this, separate, columns) + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.max(skipNaN).aggregateFor(this, separate, columns) -public fun PivotGroupBy.maxFor(vararg columns: String, separate: Boolean = false): DataFrame = - maxFor(separate) { columns.toComparableColumns() } +public fun PivotGroupBy.maxFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(separate, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > PivotGroupBy.maxFor( - vararg columns: ColumnReference, +public fun ?> PivotGroupBy.maxFor( + vararg columns: ColumnReference, separate: Boolean = false, -): DataFrame = maxFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(separate, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > PivotGroupBy.maxFor( - vararg columns: KProperty, +public fun ?> PivotGroupBy.maxFor( + vararg columns: KProperty, separate: Boolean = false, -): DataFrame = maxFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(separate, skipNaN) { columns.toColumnSet() } -public fun > PivotGroupBy.max(columns: ColumnsSelector): DataFrame = - Aggregators.max.aggregateAll(this, columns) +public fun ?> PivotGroupBy.max( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.max(skipNaN).aggregateAll(this, columns) -public fun PivotGroupBy.max(vararg columns: String): DataFrame = max { columns.toComparableColumns() } +public fun PivotGroupBy.max(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + max(skipNaN) { columns.toComparableColumns() } -@AccessApiOverload -public fun > PivotGroupBy.max(vararg columns: ColumnReference): DataFrame = - max { columns.toColumnSet() } +public fun ?> PivotGroupBy.max( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > PivotGroupBy.max(vararg columns: KProperty): DataFrame = - max { columns.toColumnSet() } +public fun ?> PivotGroupBy.max( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(skipNaN) { columns.toColumnSet() } -public fun > PivotGroupBy.maxOf(rowExpression: RowExpression): DataFrame = - aggregate { maxOf(rowExpression) } +public inline fun ?> PivotGroupBy.maxOf( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): DataFrame = aggregate { maxOf(skipNaN, rowExpression) } -public fun > PivotGroupBy.maxBy(rowExpression: RowExpression): ReducedPivotGroupBy = - reduce { maxByOrNull(rowExpression) } +public inline fun ?> PivotGroupBy.maxBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedPivotGroupBy = reduce { maxByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > PivotGroupBy.maxBy(column: ColumnReference): ReducedPivotGroupBy = - reduce { maxByOrNull(column) } +public inline fun ?> PivotGroupBy.maxBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedPivotGroupBy = reduce { maxByOrNull(column, skipNaN) } -public fun PivotGroupBy.maxBy(column: String): ReducedPivotGroupBy = - maxBy(column.toColumnAccessor().cast>()) +public fun PivotGroupBy.maxBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedPivotGroupBy = + maxBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > PivotGroupBy.maxBy(column: KProperty): ReducedPivotGroupBy = - maxBy(column.toColumnAccessor()) +public inline fun ?> PivotGroupBy.maxBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedPivotGroupBy = maxBy(column.toColumnAccessor(), skipNaN) // endregion diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt index 3ebb607306..537a6dc338 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt @@ -34,242 +34,245 @@ import kotlin.reflect.typeOf // region DataColumn -public fun DataColumn.mean(skipNA: Boolean = skipNA_default): Double = Aggregators.mean(skipNA).aggregate(this) +public fun DataColumn.mean(skipNaN: Boolean = skipNaN_default): Double = + Aggregators.mean(skipNaN).aggregateSingleColumn(this) public inline fun DataColumn.meanOf( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: (T) -> R?, -): Double = Aggregators.mean(skipNA).aggregateOf(this, expression) +): Double = Aggregators.mean(skipNaN).aggregateOf(this, expression) // endregion // region DataRow -public fun AnyRow.rowMean(skipNA: Boolean = skipNA_default): Double = - Aggregators.mean(skipNA).aggregateOfRow(this, primitiveOrMixedNumberColumns()) +public fun AnyRow.rowMean(skipNaN: Boolean = skipNaN_default): Double = + Aggregators.mean(skipNaN).aggregateOfRow(this, primitiveOrMixedNumberColumns()) -public inline fun AnyRow.rowMeanOf(skipNA: Boolean = skipNA_default): Double { +public inline fun AnyRow.rowMeanOf(skipNaN: Boolean = skipNaN_default): Double { require(typeOf().isPrimitiveOrMixedNumber()) { "Type ${T::class.simpleName} is not a primitive number type. Mean only supports primitive number types." } - return Aggregators.mean(skipNA).aggregateOfRow(this) { colsOf() } + return Aggregators.mean(skipNaN).aggregateOfRow(this) { colsOf() } } // endregion // region DataFrame -public fun DataFrame.mean(skipNA: Boolean = skipNA_default): DataRow = - meanFor(skipNA, primitiveOrMixedNumberColumns()) +public fun DataFrame.mean(skipNaN: Boolean = skipNaN_default): DataRow = + meanFor(skipNaN, primitiveOrMixedNumberColumns()) public fun DataFrame.meanFor( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsForAggregateSelector, -): DataRow = Aggregators.mean(skipNA).aggregateFor(this, columns) +): DataRow = Aggregators.mean(skipNaN).aggregateFor(this, columns) -public fun DataFrame.meanFor(vararg columns: String, skipNA: Boolean = skipNA_default): DataRow = - meanFor(skipNA) { columns.toNumberColumns() } +public fun DataFrame.meanFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + meanFor(skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun DataFrame.meanFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, -): DataRow = meanFor(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = meanFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun DataFrame.meanFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, -): DataRow = meanFor(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = meanFor(skipNaN) { columns.toColumnSet() } public fun DataFrame.mean( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsSelector, -): Double = Aggregators.mean(skipNA).aggregateAll(this, columns) +): Double = Aggregators.mean(skipNaN).aggregateAll(this, columns) -public fun DataFrame.mean(vararg columns: String, skipNA: Boolean = skipNA_default): Double = - mean(skipNA) { columns.toNumberColumns() } +public fun DataFrame.mean(vararg columns: String, skipNaN: Boolean = skipNaN_default): Double = + mean(skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun DataFrame.mean( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, -): Double = mean(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): Double = mean(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun DataFrame.mean(vararg columns: KProperty, skipNA: Boolean = skipNA_default): Double = - mean(skipNA) { columns.toColumnSet() } +public fun DataFrame.mean( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): Double = mean(skipNaN) { columns.toColumnSet() } public inline fun DataFrame.meanOf( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): Double = Aggregators.mean(skipNA).aggregateOf(this, expression) +): Double = Aggregators.mean(skipNaN).aggregateOf(this, expression) // endregion // region GroupBy @Refine @Interpretable("GroupByMean1") -public fun Grouped.mean(skipNA: Boolean = skipNA_default): DataFrame = - meanFor(skipNA, primitiveOrMixedNumberColumns()) +public fun Grouped.mean(skipNaN: Boolean = skipNaN_default): DataFrame = + meanFor(skipNaN, primitiveOrMixedNumberColumns()) @Refine @Interpretable("GroupByMean0") public fun Grouped.meanFor( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.mean(skipNA).aggregateFor(this, columns) +): DataFrame = Aggregators.mean(skipNaN).aggregateFor(this, columns) -public fun Grouped.meanFor(vararg columns: String, skipNA: Boolean = skipNA_default): DataFrame = - meanFor(skipNA) { columns.toNumberColumns() } +public fun Grouped.meanFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + meanFor(skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun Grouped.meanFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun Grouped.meanFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMean0") public fun Grouped.mean( name: String? = null, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsSelector, -): DataFrame = Aggregators.mean(skipNA).aggregateAll(this, name, columns) +): DataFrame = Aggregators.mean(skipNaN).aggregateAll(this, name, columns) public fun Grouped.mean( vararg columns: String, name: String? = null, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(name, skipNA) { columns.toNumberColumns() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(name, skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun Grouped.mean( vararg columns: ColumnReference, name: String? = null, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(name, skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(name, skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun Grouped.mean( vararg columns: KProperty, name: String? = null, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(name, skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(name, skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMeanOf") public inline fun Grouped.meanOf( name: String? = null, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): DataFrame = Aggregators.mean(skipNA).aggregateOf(this, name, expression) +): DataFrame = Aggregators.mean(skipNaN).aggregateOf(this, name, expression) // endregion // region Pivot -public fun Pivot.mean(skipNA: Boolean = skipNA_default, separate: Boolean = false): DataRow = - meanFor(skipNA, separate, primitiveOrMixedNumberColumns()) +public fun Pivot.mean(skipNaN: Boolean = skipNaN_default, separate: Boolean = false): DataRow = + meanFor(skipNaN, separate, primitiveOrMixedNumberColumns()) public fun Pivot.meanFor( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, columns: ColumnsForAggregateSelector, -): DataRow = delegate { meanFor(skipNA, separate, columns) } +): DataRow = delegate { meanFor(skipNaN, separate, columns) } public fun Pivot.meanFor( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, -): DataRow = meanFor(skipNA, separate) { columns.toNumberColumns() } +): DataRow = meanFor(skipNaN, separate) { columns.toNumberColumns() } @AccessApiOverload public fun Pivot.meanFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, -): DataRow = meanFor(skipNA, separate) { columns.toColumnSet() } +): DataRow = meanFor(skipNaN, separate) { columns.toColumnSet() } @AccessApiOverload public fun Pivot.meanFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, -): DataRow = meanFor(skipNA, separate) { columns.toColumnSet() } +): DataRow = meanFor(skipNaN, separate) { columns.toColumnSet() } public fun Pivot.mean( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsSelector, -): DataRow = delegate { mean(skipNA, columns) } +): DataRow = delegate { mean(skipNaN, columns) } public inline fun Pivot.meanOf( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): DataRow = delegate { meanOf(skipNA, expression) } +): DataRow = delegate { meanOf(skipNaN, expression) } // endregion // region PivotGroupBy -public fun PivotGroupBy.mean(separate: Boolean = false, skipNA: Boolean = skipNA_default): DataFrame = - meanFor(skipNA, separate, primitiveOrMixedNumberColumns()) +public fun PivotGroupBy.mean(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataFrame = + meanFor(skipNaN, separate, primitiveOrMixedNumberColumns()) public fun PivotGroupBy.meanFor( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.mean(skipNA).aggregateFor(this, separate, columns) +): DataFrame = Aggregators.mean(skipNaN).aggregateFor(this, separate, columns) public fun PivotGroupBy.meanFor( vararg columns: String, separate: Boolean = false, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA, separate) { columns.toNumberColumns() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN, separate) { columns.toNumberColumns() } @AccessApiOverload public fun PivotGroupBy.meanFor( vararg columns: ColumnReference, separate: Boolean = false, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA, separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN, separate) { columns.toColumnSet() } @AccessApiOverload public fun PivotGroupBy.meanFor( vararg columns: KProperty, separate: Boolean = false, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA, separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN, separate) { columns.toColumnSet() } public fun PivotGroupBy.mean( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsSelector, -): DataFrame = Aggregators.mean(skipNA).aggregateAll(this, columns) +): DataFrame = Aggregators.mean(skipNaN).aggregateAll(this, columns) -public fun PivotGroupBy.mean(vararg columns: String, skipNA: Boolean = skipNA_default): DataFrame = - mean(skipNA) { columns.toColumnsSetOf() } +public fun PivotGroupBy.mean(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + mean(skipNaN) { columns.toColumnsSetOf() } @AccessApiOverload public fun PivotGroupBy.mean( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun PivotGroupBy.mean( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(skipNaN) { columns.toColumnSet() } public inline fun PivotGroupBy.meanOf( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): DataFrame = Aggregators.mean(skipNA).aggregateOf(this, expression) +): DataFrame = Aggregators.mean(skipNaN).aggregateOf(this, expression) // endregion diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt index 0dfd662d1e..bad4fa12da 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt @@ -13,6 +13,7 @@ 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.aggregation.aggregators.Aggregators +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregateCalculatingValueType import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.cast import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll @@ -27,7 +28,8 @@ import kotlin.reflect.KProperty public fun > DataColumn.median(): T = medianOrNull().suggestIfNull("median") -public fun > DataColumn.medianOrNull(): T? = Aggregators.median.cast().aggregate(this) +public fun > DataColumn.medianOrNull(): T? = + Aggregators.median.cast().aggregateSingleColumn(this) public inline fun > DataColumn.medianOfOrNull(noinline expression: (T) -> R?): R? = Aggregators.median.cast().aggregateOf(this, expression) @@ -40,8 +42,8 @@ public inline fun > DataColumn.medianOf(noinline // region DataRow public fun AnyRow.rowMedianOrNull(): Any? = - Aggregators.median.aggregateCalculatingType( - values = values().filterIsInstance>().asIterable(), + Aggregators.median.aggregateCalculatingValueType( + values = values().asSequence().filterIsInstance>(), valueTypes = df().columns().filter { it.valuesAreComparable() }.map { it.type() }.toSet(), ) diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt index c843cc871f..b737ceaa7c 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt @@ -12,295 +12,423 @@ 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.columns.values import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregators import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateByOrNull import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor -import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfDelegated +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfRow import org.jetbrains.kotlinx.dataframe.impl.columns.toComparableColumns -import org.jetbrains.kotlinx.dataframe.impl.indexOfMin import org.jetbrains.kotlinx.dataframe.impl.suggestIfNull +import org.jetbrains.kotlinx.dataframe.util.ROW_MIN +import org.jetbrains.kotlinx.dataframe.util.ROW_MIN_OR_NULL import kotlin.reflect.KProperty // region DataColumn -public fun > DataColumn.min(): T = minOrNull().suggestIfNull("min") +public fun > DataColumn.min(skipNaN: Boolean = skipNaN_default): T = + minOrNull(skipNaN).suggestIfNull("min") -public fun > DataColumn.minOrNull(): T? = asSequence().filterNotNull().minOrNull() +public fun > DataColumn.minOrNull(skipNaN: Boolean = skipNaN_default): T? = + Aggregators.min(skipNaN).aggregateSingleColumn(this) -public fun > DataColumn.minBy(selector: (T) -> R): T = - minByOrNull(selector).suggestIfNull("minBy") +public inline fun ?> DataColumn.minBy( + skipNaN: Boolean = skipNaN_default, + noinline selector: (T) -> R, +): T & Any = minByOrNull(skipNaN, selector).suggestIfNull("minBy") -public fun > DataColumn.minByOrNull(selector: (T) -> R): T? = values.minByOrNull(selector) +public inline fun ?> DataColumn.minByOrNull( + skipNaN: Boolean = skipNaN_default, + noinline selector: (T) -> R, +): T? = Aggregators.min(skipNaN).aggregateByOrNull(this, selector) -public fun > DataColumn.minOf(selector: (T) -> R): R = - minOfOrNull(selector).suggestIfNull("minOf") +public inline fun ?> DataColumn.minOf( + skipNaN: Boolean = skipNaN_default, + crossinline selector: (T) -> R, +): R & Any = minOfOrNull(skipNaN, selector).suggestIfNull("minOf") -public fun > DataColumn.minOfOrNull(selector: (T) -> R): R? = values.minOfOrNull(selector) +public inline fun ?> DataColumn.minOfOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline selector: (T) -> R, +): R? = Aggregators.min(skipNaN).aggregateOf(this, selector) // endregion // region DataRow -public fun AnyRow.rowMinOrNull(): Any? = values().filterIsInstance>().minWithOrNull(compareBy { it }) +@Deprecated(ROW_MIN_OR_NULL, level = DeprecationLevel.ERROR) +public fun AnyRow.rowMinOrNull(): Any? = error(ROW_MIN_OR_NULL) -public fun AnyRow.rowMin(): Any = rowMinOrNull().suggestIfNull("rowMin") +@Deprecated(ROW_MIN, level = DeprecationLevel.ERROR) +public fun AnyRow.rowMin(): Any = error(ROW_MIN) -public inline fun > AnyRow.rowMinOfOrNull(): T? = values().filterIsInstance().minOrNull() +public inline fun ?> AnyRow.rowMinOfOrNull(skipNaN: Boolean = skipNaN_default): T? = + Aggregators.min(skipNaN).aggregateOfRow(this) { colsOf() } -public inline fun > AnyRow.rowMinOf(): T = rowMinOfOrNull().suggestIfNull("rowMinOf") +public inline fun ?> AnyRow.rowMinOf(skipNaN: Boolean = skipNaN_default): T & Any = + rowMinOfOrNull(skipNaN).suggestIfNull("rowMinOf") // endregion // region DataFrame -public fun DataFrame.min(): DataRow = minFor(intraComparableColumns()) +public fun DataFrame.min(skipNaN: Boolean = skipNaN_default): DataRow = + minFor(skipNaN, intraComparableColumns()) -public fun > DataFrame.minFor(columns: ColumnsForAggregateSelector): DataRow = - Aggregators.min.aggregateFor(this, columns) +public fun ?> DataFrame.minFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = Aggregators.min(skipNaN).aggregateFor(this, columns) -public fun DataFrame.minFor(vararg columns: String): DataRow = minFor { columns.toComparableColumns() } +public fun DataFrame.minFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + minFor(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > DataFrame.minFor(vararg columns: ColumnReference): DataRow = - minFor { columns.toColumnSet() } +public fun ?> DataFrame.minFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > DataFrame.minFor(vararg columns: KProperty): DataRow = - minFor { columns.toColumnSet() } +public fun ?> DataFrame.minFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(skipNaN) { columns.toColumnSet() } -public fun > DataFrame.min(columns: ColumnsSelector): C = - minOrNull(columns).suggestIfNull("min") +public fun ?> DataFrame.min( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): C & Any = minOrNull(skipNaN, columns).suggestIfNull("min") -public fun DataFrame.min(vararg columns: String): Comparable = minOrNull(*columns).suggestIfNull("min") +public fun DataFrame.min(vararg columns: String, skipNaN: Boolean = skipNaN_default): Comparable = + minOrNull(*columns, skipNaN = skipNaN).suggestIfNull("min") @AccessApiOverload -public fun > DataFrame.min(vararg columns: ColumnReference): C = - minOrNull(*columns).suggestIfNull("min") +public fun ?> DataFrame.min( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C & Any = minOrNull(*columns, skipNaN = skipNaN).suggestIfNull("min") @AccessApiOverload -public fun > DataFrame.min(vararg columns: KProperty): C = - minOrNull(*columns).suggestIfNull("min") +public fun ?> DataFrame.min( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): C & Any = minOrNull(*columns, skipNaN = skipNaN).suggestIfNull("min") -public fun > DataFrame.minOrNull(columns: ColumnsSelector): C? = - Aggregators.min.aggregateAll(this, columns) as C? +public fun ?> DataFrame.minOrNull( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): C? = Aggregators.min(skipNaN).aggregateAll(this, columns) -public fun DataFrame.minOrNull(vararg columns: String): Comparable? = - minOrNull { columns.toComparableColumns() } +public fun DataFrame.minOrNull(vararg columns: String, skipNaN: Boolean = skipNaN_default): Comparable? = + minOrNull(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > DataFrame.minOrNull(vararg columns: ColumnReference): C? = - minOrNull { columns.toColumnSet() } +public fun ?> DataFrame.minOrNull( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C? = minOrNull(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > DataFrame.minOrNull(vararg columns: KProperty): C? = - minOrNull { columns.toColumnSet() } +public fun ?> DataFrame.minOrNull( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): C? = minOrNull(skipNaN) { columns.toColumnSet() } -public fun > DataFrame.minOf(expression: RowExpression): C = - minOfOrNull(expression).suggestIfNull("minOf") +public inline fun ?> DataFrame.minOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C & Any = minOfOrNull(skipNaN, expression).suggestIfNull("minOf") -public fun > DataFrame.minOfOrNull(expression: RowExpression): C? = - rows().minOfOrNull { expression(it, it) } +public inline fun ?> DataFrame.minOfOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C? = Aggregators.min(skipNaN).aggregateOf(this, expression) -public fun > DataFrame.minBy(expression: RowExpression): DataRow = - minByOrNull(expression).suggestIfNull("minBy") +public inline fun ?> DataFrame.minBy( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow = minByOrNull(skipNaN, expression).suggestIfNull("minBy") -public fun DataFrame.minBy(column: String): DataRow = minByOrNull(column).suggestIfNull("minBy") +public fun DataFrame.minBy(column: String, skipNaN: Boolean = skipNaN_default): DataRow = + minByOrNull(column, skipNaN).suggestIfNull("minBy") @AccessApiOverload -public fun > DataFrame.minBy(column: ColumnReference): DataRow = - minByOrNull(column).suggestIfNull("minBy") +public inline fun ?> DataFrame.minBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = minByOrNull(column, skipNaN).suggestIfNull("minBy") @AccessApiOverload -public fun > DataFrame.minBy(column: KProperty): DataRow = - minByOrNull(column).suggestIfNull("minBy") +public inline fun ?> DataFrame.minBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = minByOrNull(column, skipNaN).suggestIfNull("minBy") -public fun > DataFrame.minByOrNull(expression: RowExpression): DataRow? = - getOrNull(rows().asSequence().map { expression(it, it) }.indexOfMin()) +public inline fun ?> DataFrame.minByOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow? = Aggregators.min(skipNaN).aggregateByOrNull(this, expression) -public fun DataFrame.minByOrNull(column: String): DataRow? = - minByOrNull(column.toColumnOf?>()) +public fun DataFrame.minByOrNull(column: String, skipNaN: Boolean = skipNaN_default): DataRow? = + minByOrNull(column.toColumnOf?>(), skipNaN) @AccessApiOverload -public fun > DataFrame.minByOrNull(column: ColumnReference): DataRow? = - getOrNull(get(column).asSequence().indexOfMin()) +public inline fun ?> DataFrame.minByOrNull( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow? = Aggregators.min(skipNaN).aggregateByOrNull(this, column) @AccessApiOverload -public fun > DataFrame.minByOrNull(column: KProperty): DataRow? = - minByOrNull(column.toColumnAccessor()) +public inline fun ?> DataFrame.minByOrNull( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow? = minByOrNull(column.toColumnAccessor(), skipNaN) // endregion // region GroupBy + @Refine @Interpretable("GroupByMin1") -public fun Grouped.min(): DataFrame = minFor(intraComparableColumns()) +public fun Grouped.min(skipNaN: Boolean = skipNaN_default): DataFrame = + minFor(skipNaN, intraComparableColumns()) @Refine @Interpretable("GroupByMin0") -public fun > Grouped.minFor(columns: ColumnsForAggregateSelector): DataFrame = - Aggregators.min.aggregateFor(this, columns) +public fun ?> Grouped.minFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.min(skipNaN).aggregateFor(this, columns) -public fun Grouped.minFor(vararg columns: String): DataFrame = minFor { columns.toComparableColumns() } +public fun Grouped.minFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + minFor(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Grouped.minFor(vararg columns: ColumnReference): DataFrame = - minFor { columns.toColumnSet() } +public fun ?> Grouped.minFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Grouped.minFor(vararg columns: KProperty): DataFrame = - minFor { columns.toColumnSet() } +public fun ?> Grouped.minFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMin0") -public fun > Grouped.min(name: String? = null, columns: ColumnsSelector): DataFrame = - Aggregators.min.aggregateAll(this, name, columns) +public fun ?> Grouped.min( + name: String? = null, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.min(skipNaN).aggregateAll(this, name, columns) -public fun Grouped.min(vararg columns: String, name: String? = null): DataFrame = - min(name) { columns.toComparableColumns() } +public fun Grouped.min( + vararg columns: String, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(name, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Grouped.min( - vararg columns: ColumnReference, +public fun ?> Grouped.min( + vararg columns: ColumnReference, name: String? = null, -): DataFrame = min(name) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(name, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Grouped.min(vararg columns: KProperty, name: String? = null): DataFrame = - min(name) { columns.toColumnSet() } +public fun ?> Grouped.min( + vararg columns: KProperty, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(name, skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMinOf") -public fun > Grouped.minOf( +public inline fun ?> Grouped.minOf( name: String? = null, - expression: RowExpression, -): DataFrame = Aggregators.min.aggregateOfDelegated(this, name) { minOfOrNull(expression) } + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataFrame = Aggregators.min(skipNaN).aggregateOf(this, name, expression) @Interpretable("GroupByReduceExpression") -public fun > GroupBy.minBy(rowExpression: RowExpression): ReducedGroupBy = - reduce { minByOrNull(rowExpression) } +public inline fun ?> GroupBy.minBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedGroupBy = reduce { minByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > GroupBy.minBy(column: ColumnReference): ReducedGroupBy = - reduce { minByOrNull(column) } +public inline fun ?> GroupBy.minBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedGroupBy = reduce { minByOrNull(column, skipNaN) } -public fun GroupBy.minBy(column: String): ReducedGroupBy = - minBy(column.toColumnAccessor().cast>()) +public fun GroupBy.minBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedGroupBy = + minBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > GroupBy.minBy(column: KProperty): ReducedGroupBy = - minBy(column.toColumnAccessor()) +public inline fun ?> GroupBy.minBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedGroupBy = minBy(column.toColumnAccessor(), skipNaN) // endregion // region Pivot -public fun Pivot.min(separate: Boolean = false): DataRow = delegate { min(separate) } +public fun Pivot.min(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataRow = + delegate { min(separate, skipNaN) } -public fun > Pivot.minFor( +public fun ?> Pivot.minFor( separate: Boolean = false, - columns: ColumnsForAggregateSelector, -): DataRow = delegate { minFor(separate, columns) } + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = delegate { minFor(separate, skipNaN, columns) } -public fun Pivot.minFor(vararg columns: String, separate: Boolean = false): DataRow = - minFor(separate) { columns.toComparableColumns() } +public fun Pivot.minFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(separate, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Pivot.minFor( - vararg columns: ColumnReference, +public fun ?> Pivot.minFor( + vararg columns: ColumnReference, separate: Boolean = false, -): DataRow = minFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(separate, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Pivot.minFor( - vararg columns: KProperty, +public fun ?> Pivot.minFor( + vararg columns: KProperty, separate: Boolean = false, -): DataRow = minFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(separate, skipNaN) { columns.toColumnSet() } -public fun > Pivot.min(columns: ColumnsSelector): DataRow = delegate { min(columns) } +public fun ?> Pivot.min( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataRow = delegate { min(skipNaN, columns) } -public fun > Pivot.min(vararg columns: String): DataRow = - min { columns.toComparableColumns() } +public fun ?> Pivot.min( + vararg columns: String, + skipNaN: Boolean = skipNaN_default, +): DataRow = min(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Pivot.min(vararg columns: ColumnReference): DataRow = - min { columns.toColumnSet() } +public fun ?> Pivot.min( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = min(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Pivot.min(vararg columns: KProperty): DataRow = - min { columns.toColumnSet() } +public fun ?> Pivot.min( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = min(skipNaN) { columns.toColumnSet() } -public fun > Pivot.minOf(rowExpression: RowExpression): DataRow = - delegate { minOf(rowExpression) } +public inline fun ?> Pivot.minOf( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): DataRow = delegate { minOf(skipNaN, rowExpression) } -public fun > Pivot.minBy(rowExpression: RowExpression): ReducedPivot = - reduce { minByOrNull(rowExpression) } +public inline fun ?> Pivot.minBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedPivot = reduce { minByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > Pivot.minBy(column: ColumnReference): ReducedPivot = - reduce { minByOrNull(column) } +public inline fun ?> Pivot.minBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedPivot = reduce { minByOrNull(column, skipNaN) } -public fun Pivot.minBy(column: String): ReducedPivot = - minBy(column.toColumnAccessor().cast>()) +public fun Pivot.minBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedPivot = + minBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > Pivot.minBy(column: KProperty): ReducedPivot = - minBy(column.toColumnAccessor()) +public inline fun ?> Pivot.minBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedPivot = minBy(column.toColumnAccessor(), skipNaN) // endregion // region PivotGroupBy -public fun PivotGroupBy.min(separate: Boolean = false): DataFrame = minFor(separate, intraComparableColumns()) +public fun PivotGroupBy.min(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataFrame = + minFor(separate, skipNaN, intraComparableColumns()) -public fun > PivotGroupBy.minFor( +public fun ?> PivotGroupBy.minFor( separate: Boolean = false, - columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.min.aggregateFor(this, separate, columns) + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.min(skipNaN).aggregateFor(this, separate, columns) -public fun PivotGroupBy.minFor(vararg columns: String, separate: Boolean = false): DataFrame = - minFor(separate) { columns.toComparableColumns() } +public fun PivotGroupBy.minFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(separate, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > PivotGroupBy.minFor( - vararg columns: ColumnReference, +public fun ?> PivotGroupBy.minFor( + vararg columns: ColumnReference, separate: Boolean = false, -): DataFrame = minFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(separate, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > PivotGroupBy.minFor( - vararg columns: KProperty, +public fun ?> PivotGroupBy.minFor( + vararg columns: KProperty, separate: Boolean = false, -): DataFrame = minFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(separate, skipNaN) { columns.toColumnSet() } -public fun > PivotGroupBy.min(columns: ColumnsSelector): DataFrame = - Aggregators.min.aggregateAll(this, columns) +public fun ?> PivotGroupBy.min( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.min(skipNaN).aggregateAll(this, columns) -public fun PivotGroupBy.min(vararg columns: String): DataFrame = min { columns.toComparableColumns() } +public fun PivotGroupBy.min(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + min(skipNaN) { columns.toComparableColumns() } -public fun > PivotGroupBy.min(vararg columns: ColumnReference): DataFrame = - min { columns.toColumnSet() } +public fun ?> PivotGroupBy.min( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > PivotGroupBy.min(vararg columns: KProperty): DataFrame = - min { columns.toColumnSet() } +public fun ?> PivotGroupBy.min( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(skipNaN) { columns.toColumnSet() } -public fun > PivotGroupBy.minOf(rowExpression: RowExpression): DataFrame = - aggregate { minOf(rowExpression) } +public inline fun ?> PivotGroupBy.minOf( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): DataFrame = aggregate { minOf(skipNaN, rowExpression) } -public fun > PivotGroupBy.minBy(rowExpression: RowExpression): ReducedPivotGroupBy = - reduce { minByOrNull(rowExpression) } +public inline fun ?> PivotGroupBy.minBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedPivotGroupBy = reduce { minByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > PivotGroupBy.minBy(column: ColumnReference): ReducedPivotGroupBy = - reduce { minByOrNull(column) } +public inline fun ?> PivotGroupBy.minBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedPivotGroupBy = reduce { minByOrNull(column, skipNaN) } -public fun PivotGroupBy.minBy(column: String): ReducedPivotGroupBy = - minBy(column.toColumnAccessor().cast>()) +public fun PivotGroupBy.minBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedPivotGroupBy = + minBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > PivotGroupBy.minBy(column: KProperty): ReducedPivotGroupBy = - minBy(column.toColumnAccessor()) +public inline fun ?> PivotGroupBy.minBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedPivotGroupBy = minBy(column.toColumnAccessor(), skipNaN) // endregion diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt index 421817eeb7..7a78adb04a 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt @@ -27,7 +27,7 @@ public fun > DataColumn.percentile(percentile: Double): T percentileOrNull(percentile).suggestIfNull("percentile") public fun > DataColumn.percentileOrNull(percentile: Double): T? = - Aggregators.percentile(percentile).cast().aggregate(this) + Aggregators.percentile(percentile).cast().aggregateSingleColumn(this) public inline fun > DataColumn.percentileOfOrNull( percentile: Double, @@ -44,7 +44,7 @@ public inline fun > DataColumn.percentileOf( // region DataRow public fun AnyRow.rowPercentileOrNull(percentile: Double): Any? = - Aggregators.percentile(percentile).aggregate( + Aggregators.percentile(percentile).aggregateSingleColumn( values().filterIsInstance>().toValueColumn(), ) diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/pivot.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/pivot.kt index 03dfaa0610..383be1bbb5 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/pivot.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/pivot.kt @@ -243,6 +243,7 @@ public class ReducedPivot( override fun toString(): String = "ReducedPivot(pivot=$pivot, reducer=$reducer)" } +@PublishedApi internal fun Pivot.reduce(reducer: Selector, DataRow?>) = ReducedPivot(this, reducer) @PublishedApi diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt index 6ff20f4795..a28f781a90 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt @@ -25,20 +25,20 @@ import kotlin.reflect.typeOf // region DataColumn -public fun DataColumn.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): Double = - Aggregators.std(skipNA, ddof).aggregate(this) ?: .0 +public fun DataColumn.std(skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default): Double = + Aggregators.std(skipNA, ddof).aggregateSingleColumn(this) public inline fun DataColumn.stdOf( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, noinline expression: (T) -> R?, -): Double = Aggregators.std(skipNA, ddof).cast2().aggregateOf(this, expression) ?: .0 +): Double = Aggregators.std(skipNA, ddof).cast2().aggregateOf(this, expression) // endregion // region DataRow -public fun AnyRow.rowStd(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): Double = +public fun AnyRow.rowStd(skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default): Double = values().filterIsInstance().map { it.toDouble() }.std(skipNA, ddof) public inline fun AnyRow.rowStdOf(ddof: Int = ddof_default): Double = @@ -53,39 +53,39 @@ public inline fun AnyRow.rowStdOf(ddof: Int = ddof_default) // region DataFrame -public fun DataFrame.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): DataRow = +public fun DataFrame.std(skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default): DataRow = stdFor(skipNA, ddof, numberColumns()) public fun DataFrame.stdFor( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsForAggregateSelector, ): DataRow = Aggregators.std(skipNA, ddof).aggregateFor(this, columns) public fun DataFrame.stdFor( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(skipNA, ddof) { columns.toColumnsSetOf() } public fun DataFrame.stdFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(skipNA, ddof) { columns.toColumnSet() } @AccessApiOverload public fun DataFrame.stdFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(skipNA, ddof) { columns.toColumnSet() } public fun DataFrame.std( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsSelector, -): Double = Aggregators.std(skipNA, ddof).aggregateAll(this, columns) ?: .0 +): Double = Aggregators.std(skipNA, ddof).aggregateAll(this, columns) public fun DataFrame.std(vararg columns: ColumnReference): Double = std { columns.toColumnSet() } @@ -95,44 +95,44 @@ public fun DataFrame.std(vararg columns: String): Double = std { columns. public fun DataFrame.std(vararg columns: KProperty): Double = std { columns.toColumnSet() } public inline fun DataFrame.stdOf( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, crossinline expression: RowExpression, -): Double = Aggregators.std(skipNA, ddof).aggregateOf(this, expression) ?: .0 +): Double = Aggregators.std(skipNA, ddof).aggregateOf(this, expression) // endregion // region GroupBy @Refine @Interpretable("GroupByStd1") -public fun Grouped.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): DataFrame = +public fun Grouped.std(skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default): DataFrame = stdFor(skipNA, ddof, numberColumns()) @Refine @Interpretable("GroupByStd0") public fun Grouped.stdFor( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateFor(this, columns) public fun Grouped.stdFor( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(skipNA, ddof) { columns.toColumnsSetOf() } @AccessApiOverload public fun Grouped.stdFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(skipNA, ddof) { columns.toColumnSet() } @AccessApiOverload public fun Grouped.stdFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(skipNA, ddof) { columns.toColumnSet() } @@ -140,7 +140,7 @@ public fun Grouped.stdFor( @Interpretable("GroupByStd0") public fun Grouped.std( name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsSelector, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateAll(this, name, columns) @@ -149,14 +149,14 @@ public fun Grouped.std( public fun Grouped.std( vararg columns: ColumnReference, name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(name, skipNA, ddof) { columns.toColumnSet() } public fun Grouped.std( vararg columns: String, name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(name, skipNA, ddof) { columns.toColumnsSetOf() } @@ -164,7 +164,7 @@ public fun Grouped.std( public fun Grouped.std( vararg columns: KProperty, name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(name, skipNA, ddof) { columns.toColumnSet() } @@ -172,7 +172,7 @@ public fun Grouped.std( @Interpretable("GroupByStdOf") public inline fun Grouped.stdOf( name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, crossinline expression: RowExpression, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateOf(this, name, expression) @@ -183,13 +183,13 @@ public inline fun Grouped.stdOf( public fun Pivot.std( separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(separate, skipNA, ddof, numberColumns()) public fun Pivot.stdFor( separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsForAggregateSelector, ): DataRow = delegate { stdFor(separate, skipNA, ddof, columns) } @@ -197,14 +197,14 @@ public fun Pivot.stdFor( public fun Pivot.stdFor( vararg columns: String, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(separate, skipNA, ddof) { columns.toColumnsSetOf() } public fun Pivot.stdFor( vararg columns: ColumnReference, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(separate, skipNA, ddof) { columns.toColumnSet() } @@ -212,37 +212,37 @@ public fun Pivot.stdFor( public fun Pivot.stdFor( vararg columns: KProperty, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(separate, skipNA, ddof) { columns.toColumnSet() } public fun Pivot.std( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsSelector, ): DataRow = delegate { std(skipNA, ddof, columns) } public fun Pivot.std( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = std(skipNA, ddof) { columns.toColumnSet() } public fun Pivot.std( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = std(skipNA, ddof) { columns.toColumnsSetOf() } @AccessApiOverload public fun Pivot.std( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = std(skipNA, ddof) { columns.toColumnSet() } public inline fun Pivot.stdOf( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, crossinline expression: RowExpression, ): DataRow = delegate { stdOf(skipNA, ddof, expression) } @@ -253,13 +253,13 @@ public inline fun Pivot.stdOf( public fun PivotGroupBy.std( separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(separate, skipNA, ddof, numberColumns()) public fun PivotGroupBy.stdFor( separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateFor(this, separate, columns) @@ -267,7 +267,7 @@ public fun PivotGroupBy.stdFor( public fun PivotGroupBy.stdFor( vararg columns: String, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(separate, skipNA, ddof) { columns.toColumnsSetOf() } @@ -275,7 +275,7 @@ public fun PivotGroupBy.stdFor( public fun PivotGroupBy.stdFor( vararg columns: ColumnReference, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(separate, skipNA, ddof) { columns.toColumnSet() } @@ -283,12 +283,12 @@ public fun PivotGroupBy.stdFor( public fun PivotGroupBy.stdFor( vararg columns: KProperty, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(separate, skipNA, ddof) { columns.toColumnSet() } public fun PivotGroupBy.std( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsSelector, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateAll(this, columns) @@ -296,25 +296,25 @@ public fun PivotGroupBy.std( @AccessApiOverload public fun PivotGroupBy.std( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(skipNA, ddof) { columns.toColumnSet() } public fun PivotGroupBy.std( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(skipNA, ddof) { columns.toColumnsSetOf() } @AccessApiOverload public fun PivotGroupBy.std( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(skipNA, ddof) { columns.toColumnSet() } public inline fun PivotGroupBy.stdOf( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, crossinline expression: RowExpression, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateOf(this, expression) diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index c786320ac8..1023a4edcc 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlinx.dataframe.aggregation.ColumnsForAggregateSelector import org.jetbrains.kotlinx.dataframe.annotations.AccessApiOverload import org.jetbrains.kotlinx.dataframe.annotations.Interpretable import org.jetbrains.kotlinx.dataframe.annotations.Refine +import org.jetbrains.kotlinx.dataframe.api.skipNaN_default import org.jetbrains.kotlinx.dataframe.columns.ColumnReference import org.jetbrains.kotlinx.dataframe.columns.toColumnSet import org.jetbrains.kotlinx.dataframe.columns.toColumnsSetOf @@ -42,99 +43,118 @@ import kotlin.reflect.typeOf // region DataColumn @JvmName("sumShort") -public fun DataColumn.sum(): Int = Aggregators.sum.aggregate(this) as Int +public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingleColumn(this) as Int @JvmName("sumByte") -public fun DataColumn.sum(): Int = Aggregators.sum.aggregate(this) as Int +public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingleColumn(this) as Int @Suppress("UNCHECKED_CAST") @JvmName("sumNumber") -public fun DataColumn.sum(): T = Aggregators.sum.aggregate(this) as T +public fun DataColumn.sum(skipNaN: Boolean = skipNaN_default): T = + Aggregators.sum(skipNaN).aggregateSingleColumn(this) as T @JvmName("sumOfShort") @OverloadResolutionByLambdaReturnType public fun DataColumn.sumOf(expression: (C) -> Short?): Int = - Aggregators.sum.aggregateOf(this, expression) as Int + Aggregators.sum(false).aggregateOf(this, expression) as Int @JvmName("sumOfByte") @OverloadResolutionByLambdaReturnType -public fun DataColumn.sumOf(expression: (C) -> Byte?): Int = Aggregators.sum.aggregateOf(this, expression) as Int +public fun DataColumn.sumOf(expression: (C) -> Byte?): Int = + Aggregators.sum(false).aggregateOf(this, expression) as Int @JvmName("sumOfNumber") @OverloadResolutionByLambdaReturnType -public inline fun DataColumn.sumOf(crossinline expression: (C) -> V?): V = - Aggregators.sum.aggregateOf(this, expression) as V +public inline fun DataColumn.sumOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: (C) -> V?, +): V = Aggregators.sum(skipNaN).aggregateOf(this, expression) as V // endregion // region DataRow -public fun AnyRow.rowSum(): Number = Aggregators.sum.aggregateOfRow(this, primitiveOrMixedNumberColumns()) +public fun AnyRow.rowSum(skipNaN: Boolean = skipNaN_default): Number = + Aggregators.sum(skipNaN).aggregateOfRow(this, primitiveOrMixedNumberColumns()) @JvmName("rowSumOfShort") public inline fun AnyRow.rowSumOf(_kClass: KClass = Short::class): Int = - rowSumOf(typeOf()) as Int + rowSumOf(typeOf(), false) as Int @JvmName("rowSumOfByte") public inline fun AnyRow.rowSumOf(_kClass: KClass = Byte::class): Int = - rowSumOf(typeOf()) as Int + rowSumOf(typeOf(), false) as Int @JvmName("rowSumOfInt") public inline fun AnyRow.rowSumOf(_kClass: KClass = Int::class): Int = - rowSumOf(typeOf()) as Int + rowSumOf(typeOf(), false) as Int @JvmName("rowSumOfLong") public inline fun AnyRow.rowSumOf(_kClass: KClass = Long::class): Long = - rowSumOf(typeOf()) as Long + rowSumOf(typeOf(), false) as Long @JvmName("rowSumOfFloat") -public inline fun AnyRow.rowSumOf(_kClass: KClass = Float::class): Float = - rowSumOf(typeOf()) as Float +public inline fun AnyRow.rowSumOf( + skipNaN: Boolean = skipNaN_default, + _kClass: KClass = Float::class, +): Float = rowSumOf(typeOf(), skipNaN) as Float @JvmName("rowSumOfDouble") -public inline fun AnyRow.rowSumOf(_kClass: KClass = Double::class): Double = - rowSumOf(typeOf()) as Double +public inline fun AnyRow.rowSumOf( + skipNaN: Boolean = skipNaN_default, + _kClass: KClass = Double::class, +): Double = rowSumOf(typeOf(), skipNaN) as Double // unfortunately, we cannot make a `reified T : Number?` due to clashes -public fun AnyRow.rowSumOf(type: KType): Number { +public fun AnyRow.rowSumOf(type: KType, skipNaN: Boolean = skipNaN_default): Number { require(type.isPrimitiveOrMixedNumber()) { "Type $type is not a primitive number type. Mean only supports primitive number types." } - return Aggregators.sum.aggregateOfRow(this) { colsOf(type) } + return Aggregators.sum(skipNaN).aggregateOfRow(this) { colsOf(type) } } // endregion // region DataFrame -public fun DataFrame.sum(): DataRow = sumFor(primitiveOrMixedNumberColumns()) +public fun DataFrame.sum(skipNaN: Boolean = skipNaN_default): DataRow = + sumFor(skipNaN, primitiveOrMixedNumberColumns()) -public fun DataFrame.sumFor(columns: ColumnsForAggregateSelector): DataRow = - Aggregators.sum.aggregateFor(this, columns) +public fun DataFrame.sumFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = Aggregators.sum(skipNaN).aggregateFor(this, columns) -public fun DataFrame.sumFor(vararg columns: String): DataRow = sumFor { columns.toColumnsSetOf() } +public fun DataFrame.sumFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + sumFor(skipNaN) { columns.toColumnsSetOf() } @AccessApiOverload -public fun DataFrame.sumFor(vararg columns: ColumnReference): DataRow = - sumFor { columns.toColumnSet() } +public fun DataFrame.sumFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun DataFrame.sumFor(vararg columns: KProperty): DataRow = - sumFor { columns.toColumnSet() } +public fun DataFrame.sumFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(skipNaN) { columns.toColumnSet() } @JvmName("sumShort") @OverloadResolutionByLambdaReturnType public fun DataFrame.sum(columns: ColumnsSelector): Int = - Aggregators.sum.aggregateAll(this, columns) as Int + Aggregators.sum(false).aggregateAll(this, columns) as Int @JvmName("sumByte") @OverloadResolutionByLambdaReturnType public fun DataFrame.sum(columns: ColumnsSelector): Int = - Aggregators.sum.aggregateAll(this, columns) as Int + Aggregators.sum(false).aggregateAll(this, columns) as Int @JvmName("sumNumber") @OverloadResolutionByLambdaReturnType -public inline fun DataFrame.sum(noinline columns: ColumnsSelector): C = - Aggregators.sum.aggregateAll(this, columns) as C +public inline fun DataFrame.sum( + skipNaN: Boolean = skipNaN_default, + noinline columns: ColumnsSelector, +): C = Aggregators.sum(skipNaN).aggregateAll(this, columns) as C @JvmName("sumShort") @AccessApiOverload @@ -146,10 +166,13 @@ public fun DataFrame.sum(vararg columns: ColumnReference): Int = s @JvmName("sumNumber") @AccessApiOverload -public inline fun DataFrame.sum(vararg columns: ColumnReference): C = - sum { columns.toColumnSet() } +public inline fun DataFrame.sum( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C = sum(skipNaN) { columns.toColumnSet() } -public fun DataFrame.sum(vararg columns: String): Number = sum { columns.toColumnsSetOf() } +public fun DataFrame.sum(vararg columns: String, skipNaN: Boolean = skipNaN_default): Number = + sum(skipNaN) { columns.toColumnsSetOf() } @JvmName("sumShort") @AccessApiOverload @@ -161,148 +184,206 @@ public fun DataFrame.sum(vararg columns: KProperty): Int = sum { c @JvmName("sumNumber") @AccessApiOverload -public inline fun DataFrame.sum(vararg columns: KProperty): C = - sum { columns.toColumnSet() } +public inline fun DataFrame.sum( + skipNaN: Boolean = skipNaN_default, + vararg columns: KProperty, +): C = sum(skipNaN) { columns.toColumnSet() } @JvmName("sumOfShort") @OverloadResolutionByLambdaReturnType public fun DataFrame.sumOf(expression: RowExpression): Int = - Aggregators.sum.aggregateOf(this, expression) as Int + Aggregators.sum(false).aggregateOf(this, expression) as Int @JvmName("sumOfByte") @OverloadResolutionByLambdaReturnType public fun DataFrame.sumOf(expression: RowExpression): Int = - Aggregators.sum.aggregateOf(this, expression) as Int + Aggregators.sum(false).aggregateOf(this, expression) as Int @JvmName("sumOfNumber") @OverloadResolutionByLambdaReturnType -public inline fun DataFrame.sumOf(crossinline expression: RowExpression): C = - Aggregators.sum.aggregateOf(this, expression) as C +public inline fun DataFrame.sumOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C = Aggregators.sum(skipNaN).aggregateOf(this, expression) as C // endregion // region GroupBy @Refine @Interpretable("GroupBySum1") -public fun Grouped.sum(): DataFrame = sumFor(primitiveOrMixedNumberColumns()) +public fun Grouped.sum(skipNaN: Boolean = skipNaN_default): DataFrame = + sumFor(skipNaN, primitiveOrMixedNumberColumns()) @Refine @Interpretable("GroupBySum0") -public fun Grouped.sumFor(columns: ColumnsForAggregateSelector): DataFrame = - Aggregators.sum.aggregateFor(this, columns) +public fun Grouped.sumFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, columns) -public fun Grouped.sumFor(vararg columns: String): DataFrame = sumFor { columns.toNumberColumns() } +public fun Grouped.sumFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + sumFor(skipNaN) { columns.toNumberColumns() } @AccessApiOverload -public fun Grouped.sumFor(vararg columns: ColumnReference): DataFrame = - sumFor { columns.toColumnSet() } +public fun Grouped.sumFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun Grouped.sumFor(vararg columns: KProperty): DataFrame = - sumFor { columns.toColumnSet() } +public fun Grouped.sumFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupBySum0") -public fun Grouped.sum(name: String? = null, columns: ColumnsSelector): DataFrame = - Aggregators.sum.aggregateAll(this, name, columns) - -public fun Grouped.sum(vararg columns: String, name: String? = null): DataFrame = - sum(name) { columns.toNumberColumns() } +public fun Grouped.sum( + name: String? = null, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, name, columns) + +public fun Grouped.sum( + vararg columns: String, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(name, skipNaN) { columns.toNumberColumns() } @AccessApiOverload -public fun Grouped.sum(vararg columns: ColumnReference, name: String? = null): DataFrame = - sum(name) { columns.toColumnSet() } +public fun Grouped.sum( + vararg columns: ColumnReference, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(name, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun Grouped.sum(vararg columns: KProperty, name: String? = null): DataFrame = - sum(name) { columns.toColumnSet() } +public fun Grouped.sum( + vararg columns: KProperty, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(name, skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupBySumOf") public inline fun Grouped.sumOf( resultName: String? = null, + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): DataFrame = Aggregators.sum.aggregateOf(this, resultName, expression) +): DataFrame = Aggregators.sum(skipNaN).aggregateOf(this, resultName, expression) // endregion // region Pivot -public fun Pivot.sum(separate: Boolean = false): DataRow = sumFor(separate, primitiveOrMixedNumberColumns()) +public fun Pivot.sum(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataRow = + sumFor(separate, skipNaN, primitiveOrMixedNumberColumns()) public fun Pivot.sumFor( separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, columns: ColumnsForAggregateSelector, -): DataRow = delegate { sumFor(separate, columns) } +): DataRow = delegate { sumFor(separate, skipNaN, columns) } -public fun Pivot.sumFor(vararg columns: String, separate: Boolean = false): DataRow = - sumFor(separate) { columns.toNumberColumns() } +public fun Pivot.sumFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(separate, skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun Pivot.sumFor( vararg columns: ColumnReference, separate: Boolean = false, -): DataRow = sumFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(separate, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun Pivot.sumFor(vararg columns: KProperty, separate: Boolean = false): DataRow = - sumFor(separate) { columns.toColumnSet() } +public fun Pivot.sumFor( + vararg columns: KProperty, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(separate, skipNaN) { columns.toColumnSet() } -public fun Pivot.sum(columns: ColumnsSelector): DataRow = delegate { sum(columns) } +public fun Pivot.sum( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataRow = delegate { sum(skipNaN, columns) } -public fun Pivot.sum(vararg columns: String): DataRow = sum { columns.toNumberColumns() } +public fun Pivot.sum(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + sum(skipNaN) { columns.toNumberColumns() } @AccessApiOverload -public fun Pivot.sum(vararg columns: ColumnReference): DataRow = sum { columns.toColumnSet() } +public fun Pivot.sum( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = sum(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun Pivot.sum(vararg columns: KProperty): DataRow = sum { columns.toColumnSet() } +public fun Pivot.sum(vararg columns: KProperty, skipNaN: Boolean = skipNaN_default): DataRow = + sum(skipNaN) { columns.toColumnSet() } -public inline fun Pivot.sumOf(crossinline expression: RowExpression): DataRow = - delegate { sumOf(expression) } +public inline fun Pivot.sumOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow = delegate { sumOf(skipNaN, expression) } // endregion // region PivotGroupBy -public fun PivotGroupBy.sum(separate: Boolean = false): DataFrame = - sumFor(separate, primitiveOrMixedNumberColumns()) +public fun PivotGroupBy.sum(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataFrame = + sumFor(separate, skipNaN, primitiveOrMixedNumberColumns()) public fun PivotGroupBy.sumFor( separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.sum.aggregateFor(this, separate, columns) +): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, separate, columns) -public fun PivotGroupBy.sumFor(vararg columns: String, separate: Boolean = false): DataFrame = - sumFor(separate) { columns.toNumberColumns() } +public fun PivotGroupBy.sumFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(separate, skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun PivotGroupBy.sumFor( vararg columns: ColumnReference, separate: Boolean = false, -): DataFrame = sumFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(separate, skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun PivotGroupBy.sumFor( vararg columns: KProperty, separate: Boolean = false, -): DataFrame = sumFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(separate, skipNaN) { columns.toColumnSet() } -public fun PivotGroupBy.sum(columns: ColumnsSelector): DataFrame = - Aggregators.sum.aggregateAll(this, columns) +public fun PivotGroupBy.sum( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, columns) -public fun PivotGroupBy.sum(vararg columns: String): DataFrame = sum { columns.toNumberColumns() } +public fun PivotGroupBy.sum(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + sum(skipNaN) { columns.toNumberColumns() } @AccessApiOverload -public fun PivotGroupBy.sum(vararg columns: ColumnReference): DataFrame = - sum { columns.toColumnSet() } +public fun PivotGroupBy.sum( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun PivotGroupBy.sum(vararg columns: KProperty): DataFrame = - sum { columns.toColumnSet() } +public fun PivotGroupBy.sum( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(skipNaN) { columns.toColumnSet() } public inline fun PivotGroupBy.sumOf( + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): DataFrame = Aggregators.sum.aggregateOf(this, expression) +): DataFrame = Aggregators.sum(skipNaN).aggregateOf(this, expression) // endregion diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt index d8e24f6d02..581fa737e2 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/TypeUtils.kt @@ -9,6 +9,7 @@ import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.api.Infer +import org.jetbrains.kotlinx.dataframe.api.isSubtypeOf import org.jetbrains.kotlinx.dataframe.impl.columns.createColumnGuessingType import org.jetbrains.kotlinx.dataframe.util.GUESS_VALUE_TYPE import java.math.BigDecimal @@ -564,6 +565,9 @@ internal val nullableNothingType: KType = typeOf>().arguments.fir internal fun nothingType(nullable: Boolean): KType = if (nullable) nullableNothingType else nothingType +internal val KType.canBeNaN: Boolean + get() = isSubtypeOf(typeOf()) || isSubtypeOf(typeOf()) + @OptIn(ExperimentalUnsignedTypes::class) private val primitiveArrayClasses = setOf( BooleanArray::class, @@ -690,3 +694,16 @@ internal fun Iterable.types(): Set = mapTo(mutableSetOf()) { if (it == null) nullableNothingType else it::class.createStarProjectedType(false) } + +/** + * Checks whether this KType adheres to `T : Comparable?`, aka, it is comparable with itself. + */ +internal fun KType.isIntraComparable(): Boolean = + this.isSubtypeOf( + Comparable::class.createType( + arguments = listOf( + KTypeProjection(IN, this.withNullability(false)), + ), + nullable = this.isMarkedNullable, + ), + ) diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt index 002b720d80..48cde41f76 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt @@ -222,54 +222,6 @@ internal fun DataFrame.getColumnPaths( selector: ColumnsSelector, ): List = getColumnsWithPaths(unresolvedColumnsPolicy, selector).map { it.path } -internal fun > Sequence.indexOfMin(): Int { - val iterator = iterator() - if (!iterator.hasNext()) return -1 - var value = iterator.next() - var index = 0 - while (value == null) { - if (!iterator.hasNext()) return -1 - value = iterator.next() - index++ - } - var min: C = value - var minIndex = index - if (!iterator.hasNext()) return minIndex - do { - val v = iterator.next() - index++ - if (v != null && min > v) { - min = v - minIndex = index - } - } while (iterator.hasNext()) - return minIndex -} - -internal fun > Sequence.indexOfMax(): Int { - val iterator = iterator() - if (!iterator.hasNext()) return -1 - var value = iterator.next() - var index = 0 - while (value == null) { - if (!iterator.hasNext()) return -1 - value = iterator.next() - index++ - } - var max: C = value - var maxIndex = index - if (!iterator.hasNext()) return maxIndex - do { - val v = iterator.next() - index++ - if (v != null && max < v) { - max = v - maxIndex = index - } - } while (iterator.hasNext()) - return maxIndex -} - internal fun createStarProjectedType(klass: KClass<*>, nullable: Boolean): KType = if (klass == Nothing::class) { nothingType(nullable) // would be Void otherwise diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt index 74bbc1a6e9..7fb85489a5 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt @@ -1,105 +1,240 @@ package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.ReducingAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.SelectingAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers.AnyInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers.NumberInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.FlatteningMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.NoMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.TwoStepMultipleColumnsHandler import kotlin.reflect.KType import kotlin.reflect.full.withNullability /** - * Base interface for all aggregators. + * This class is the main entry-point for creating an aggregator. * - * Aggregators are used to compute a single value from an [Iterable] of values, a single [DataColumn], - * or multiple [DataColumns][DataColumn]. + * Aggregators are used to compute a single value from a [Sequence] of values, + * a single [DataColumn], or multiple [DataColumns][DataColumn]. * - * The [AggregatorBase] class is a base implementation of this interface. + * [Aggregator] follows a dependency injection pattern: * - * @param Value The type of the values to be aggregated. + * Using the constructor or [Aggregator.invoke] function, you can create an [Aggregator] instance with a choice of: + * - [AggregatorInputHandler] - The input handler of the aggregator, + * which handles type checks, conversions, and preprocessing of a single sequence of input values. + * It can also calculate a specific [value type][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.ValueType] from the input values or input types + * if the (specific) type is not known. + * + * Options: [NumberInputHandler], [AnyInputHandler] + * + * - [AggregatorAggregationHandler] - The base functionality of the aggregator, + * which defines how the aggregation of a single [Sequence] or [column][org.jetbrains.kotlinx.dataframe.DataColumn] is done. + * It also provides information on which return type will be given, as [KType], given a [value type][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.ValueType]. + * It can also provide the index of the result in the input values if it is a selecting aggregator. + * + * Options: [ReducingAggregationHandler], [SelectingAggregationHandler] + * + * - [AggregatorMultipleColumnsHandler] - The multiple columns handler, + * which specifies how to aggregate multiple columns into a single value by using the supplied + * [AggregatorAggregationHandler][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorAggregationHandler]. + * It can also calculate the return type of the aggregation given all input column types. + * + * Options: [FlatteningMultipleColumnsHandler], [TwoStepMultipleColumnsHandler], [NoMultipleColumnsHandler] + * + * @param Value The non-null type of the values to be aggregated. * The input can always have nulls, they are filtered out. * @param Return The type of the resulting value. Can optionally be nullable. + * @see [invoke] + */ +@PublishedApi +internal class Aggregator( + val aggregationHandler: AggregatorAggregationHandler, + val inputHandler: AggregatorInputHandler, + val multipleColumnsHandler: AggregatorMultipleColumnsHandler, + val name: String, +) : AggregatorInputHandler by inputHandler, + AggregatorMultipleColumnsHandler by multipleColumnsHandler, + AggregatorAggregationHandler by aggregationHandler { + + // Set the aggregator reference in all handlers to this instance + init { + aggregationHandler.init(this) + inputHandler.init(this) + multipleColumnsHandler.init(this) + init(this) + } + + override fun init(aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>) { + this.aggregator = aggregator + } + + override var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? = null + + override fun toString(): String = + "Aggregator(name='$name', aggregationHandler=$aggregationHandler, inputHandler=$inputHandler, multipleColumnsHandler=$multipleColumnsHandler)" + + internal companion object { + + /** + * Factory function for creating an [Aggregator] instance given a name. + * + * @see AggregatorProvider + * @see Aggregator + */ + internal operator fun invoke( + aggregationHandler: AggregatorAggregationHandler, + inputHandler: AggregatorInputHandler, + multipleColumnsHandler: AggregatorMultipleColumnsHandler, + ): AggregatorProvider = + AggregatorProvider { name -> + Aggregator( + aggregationHandler = aggregationHandler, + inputHandler = inputHandler, + multipleColumnsHandler = multipleColumnsHandler, + name = name, + ) + } + } +} + +/** + * Performs aggregation on the given [values], taking [valueType] into account. + * If [valueType] is unknown, see [calculateValueType] or [aggregateCalculatingValueType]. + */ +@PublishedApi +internal fun Aggregator.aggregate( + values: Sequence, + valueType: ValueType, +) = aggregateSequence(values, valueType) + +/** + * Performs aggregation on the given [values], taking [valueType] into account. + * If [valueType] is unknown, see [calculateValueType] or [aggregateCalculatingValueType]. */ @PublishedApi -internal interface Aggregator { - - /** The name of this aggregator. */ - val name: String - - /** - * Base function of [Aggregator]. - * - * Aggregates the given values, taking [type] into account, - * filtering nulls (only if [type.isMarkedNullable][KType.isMarkedNullable]), - * and computes a single resulting value. - * - * When using [AggregatorBase], this can be supplied by the [AggregatorBase.aggregator] argument. - * - * When the exact [type] is unknown, use [aggregateCalculatingType]. - */ - fun aggregate(values: Iterable, type: KType): Return - - /** - * Aggregates the data in the given column and computes a single resulting value. - * Calls [aggregate] (with [Iterable] and [KType]). - * - * See [AggregatorBase.aggregate]. - */ - fun aggregate(column: DataColumn): Return - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - */ - fun aggregate(columns: Iterable>): Return - - /** - * Special case of [aggregate] with [Iterable] that calculates the common type of the values at runtime. - * Without [valueTypes], this is a heavy operation and should be avoided when possible. - * - * @param values The values to be aggregated. - * @param valueTypes The types of the values. - * If provided, this can be used to avoid calculating the types of [values] at runtime with reflection. - * It should contain all types of [values]. - * If `null` or empty, the types of [values] will be calculated at runtime (heavy!). - */ - fun aggregateCalculatingType(values: Iterable, valueTypes: Set? = null): Return - - /** - * Function that can give the return type of [aggregate] as [KType], given the type of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param type The type of the input values. - * @param emptyInput If `true`, the input values are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - fun calculateReturnTypeOrNull(type: KType, emptyInput: Boolean): KType? - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? +internal fun Aggregator.aggregate( + values: Sequence, + valueType: KType, +) = aggregate(values, valueType.toValueType(needsFullConversion = false)) + +/** + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it by combining the set of known [valueTypes] or + * by gathering the types from [values]. + * + * This is a helper function that calls the correct + * [AggregatorInputHandler.calculateValueType] based on the given input. + * + * Giving [valueTypes] is preferred because of efficiency, as it allows for avoiding runtime type checks. + */ +internal fun Aggregator.calculateValueType( + values: Sequence, + valueTypes: Set? = null, +) = if (valueTypes != null && valueTypes.isNotEmpty()) { + calculateValueType(valueTypes) +} else { + calculateValueType(values) } +/** + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it by combining the set of known [valueTypes] or + * by gathering the types from [values] and then aggregating them. + * + * Giving [valueTypes] is preferred because of efficiency, as it allows for avoiding runtime type checks. + */ +internal fun Aggregator.aggregateCalculatingValueType( + values: Sequence, + valueTypes: Set? = null, +) = aggregateSequence( + values = values, + valueType = calculateValueType(values, valueTypes), +) + +/** + * Aggregates the data in the given column and computes a single resulting value. + */ +internal fun Aggregator.aggregate(column: DataColumn) = + aggregateSingleColumn(column) + +/** + * Aggregates the data in the given columns and computes a single resulting value. + */ +internal fun Aggregator.aggregate(columns: Sequence>) = + aggregateMultipleColumns(columns) + +/** + * Gives the index of the aggregation result in the input [values], if it applies. + * This is used for aggregators with an [AggregatorAggregationHandler] where + * [Value][Value]` == `[Return][Return], and where the result exists in the input. + * + * Like for [SelectingAggregationHandler]. + * + * Defaults to `-1`. + * + * If [valueType] is unknown, see [calculateValueType] + */ +@PublishedApi +internal fun Aggregator.indexOfAggregationResult( + values: Sequence, + valueType: ValueType, +): Int = indexOfAggregationResultSingleSequence(values, valueType) + +/** + * Gives the index of the aggregation result in the input [values], if it applies. + * This is used for aggregators with an [AggregatorAggregationHandler] where + * [Value][Value]` == `[Return][Return], and where the result exists in the input. + * + * Like for [SelectingAggregationHandler]. + * + * Defaults to `-1`. + * + * If [valueType] is unknown, see [calculateValueType] + */ +@PublishedApi +internal fun Aggregator.indexOfAggregationResult( + values: Sequence, + valueType: KType, +): Int = indexOfAggregationResultSingleSequence(values, valueType.toValueType(needsFullConversion = false)) + @Suppress("UNCHECKED_CAST") @PublishedApi -internal fun Aggregator<*, *>.cast(): Aggregator = this as Aggregator +internal fun Aggregator<*, *>.cast(): Aggregator = this as Aggregator @Suppress("UNCHECKED_CAST") @PublishedApi -internal fun Aggregator<*, *>.cast2(): Aggregator = this as Aggregator +internal fun Aggregator<*, *>.cast2(): Aggregator = + this as Aggregator + +/** + * Type alias for a function that gives the return type of a [Reducer] or [Selector] + * given some input type and whether the input is empty. + */ +internal typealias CalculateReturnType = (type: KType, emptyInput: Boolean) -> KType -/** Type alias for [Aggregator.calculateReturnTypeOrNull] */ -internal typealias CalculateReturnTypeOrNull = (type: KType, emptyInput: Boolean) -> KType? +/** + * Type alias for a reducer function where the type of the values is provided as [KType]. + * Nulls have already been filtered out when this function is called. + */ +internal typealias Reducer = Sequence.(valueType: KType) -> Return + +/** + * Type alias for a selector function where the type of the values is provided as [KType]. + * + * It is expected that [Value][Value]` : `[Return][Return]` & `[Any][Any], and [Return][Return]` : `[Any?][Any]. + * + * Nulls have already been filtered out when this function is called. + */ +internal typealias Selector = Sequence.(type: KType) -> Return /** - * Type alias for the argument for [Aggregator.aggregate]. - * Nulls have already been filtered out when this argument is called. + * Type alias for a function that returns the index of the result of [Selector] in this sequence. + * If the result is not in the sequence, it returns -1. + * The type of the values is provided as [KType] and the sequence can contain nulls. */ -internal typealias Aggregate = Iterable.(type: KType) -> Return +internal typealias IndexOfResult = Sequence.(type: KType) -> Int -/** Common case for [CalculateReturnTypeOrNull], preserves return type, but makes it nullable for empty inputs. */ -internal val preserveReturnTypeNullIfEmpty: CalculateReturnTypeOrNull = { type, emptyInput -> +/** Common case for [CalculateReturnType], preserves return type, but makes it nullable for empty inputs. */ +internal val preserveReturnTypeNullIfEmpty: CalculateReturnType = { type, emptyInput -> type.withNullability(emptyInput) } diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorBase.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorBase.kt deleted file mode 100644 index 89bb2a276b..0000000000 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorBase.kt +++ /dev/null @@ -1,121 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators - -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.api.asIterable -import org.jetbrains.kotlinx.dataframe.api.asSequence -import org.jetbrains.kotlinx.dataframe.impl.commonType -import org.jetbrains.kotlinx.dataframe.impl.nothingType -import kotlin.reflect.KType -import kotlin.reflect.full.withNullability - -/** - * Abstract base class for [aggregators][Aggregator]. - * - * Aggregators are used to compute a single value from an [Iterable] of values, a single [DataColumn], - * or multiple [DataColumns][DataColumn]. - * - * @param name The name of this aggregator. - * @param aggregator Functional argument for the [aggregate] function. Nulls are filtered out before this is called. - */ -internal abstract class AggregatorBase( - override val name: String, - protected val getReturnTypeOrNull: CalculateReturnTypeOrNull, - protected val aggregator: Aggregate, -) : Aggregator { - - /** - * Base function of [Aggregator]. - * - * Aggregates the given values, taking [type] into account, - * filtering nulls (only if [type.isMarkedNullable][KType.isMarkedNullable]), - * and computes a single resulting value. - * - * When using [AggregatorBase], this can be supplied by the [AggregatorBase.aggregator] argument. - * - * When the exact [type] is unknown, use [aggregateCalculatingType]. - */ - @Suppress("UNCHECKED_CAST") - override fun aggregate(values: Iterable, type: KType): Return = - aggregator( - // values = - if (type.isMarkedNullable) { - values.asSequence().filterNotNull().asIterable() - } else { - values as Iterable - }, - // type = - type.withNullability(false), - ) - - /** - * Function that can give the return type of [aggregate] as [KType], given the type of the input. - * This allows aggregators to avoid runtime type calculations. - * - * Uses [getReturnTypeOrNull] to calculate the return type. - * - * @param type The type of the input values. - * @param emptyInput If `true`, the input values are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - override fun calculateReturnTypeOrNull(type: KType, emptyInput: Boolean): KType? = - getReturnTypeOrNull(type.withNullability(false), emptyInput) - - /** - * Aggregates the data in the given column and computes a single resulting value. - * - * Nulls are filtered out by default, then [aggregate] (with [Iterable] and [KType]) is called. - */ - @Suppress("UNCHECKED_CAST") - override fun aggregate(column: DataColumn): Return = - aggregate( - values = column.asIterable(), - type = column.type(), - ) - - /** Special case of [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator.aggregate] with [Iterable] that calculates the common type of the values at runtime. - * Without [valueTypes], this is a heavy operation and should be avoided when possible. - * - * @param values The values to be aggregated. - * @param valueTypes The types of the values. - * If provided, this can be used to avoid calculating the types of [values][org.jetbrains.kotlinx.dataframe.values] at runtime with reflection. - * It should contain all types of [values][org.jetbrains.kotlinx.dataframe.values]. - * If `null` or empty, the types of [values][org.jetbrains.kotlinx.dataframe.values] will be calculated at runtime (heavy!). */ - override fun aggregateCalculatingType(values: Iterable, valueTypes: Set?): Return { - val commonType = if (valueTypes != null && valueTypes.isNotEmpty()) { - valueTypes.commonType(false) - } else { - var hasNulls = false - val classes = values.mapNotNull { - if (it == null) { - hasNulls = true - null - } else { - it.javaClass.kotlin - } - } - if (classes.isEmpty()) { - nothingType(hasNulls) - } else { - classes.commonType(hasNulls) - } - } - return aggregate(values, commonType) - } - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - * Must be overridden to use. - */ - abstract override fun aggregate(columns: Iterable>): Return - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - abstract override fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? -} diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch.kt index a21b06c401..987771547a 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch.kt @@ -7,31 +7,34 @@ package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators * @see AggregatorOptionSwitch2 */ @PublishedApi -internal class AggregatorOptionSwitch1>( +internal class AggregatorOptionSwitch1( val name: String, - val getAggregator: (param1: Param1) -> AggregatorProvider, + val getAggregator: (param1: Param1) -> AggregatorProvider, ) { - private val cache: MutableMap = mutableMapOf() + private val cache: MutableMap> = mutableMapOf() - operator fun invoke(param1: Param1): AggregatorType = + operator fun invoke(param1: Param1): Aggregator = cache.getOrPut(param1) { getAggregator(param1).create(name) } - /** - * Creates [AggregatorOptionSwitch1]. - * - * Used like: - * ```kt - * val myAggregator by AggregatorOptionSwitch1.Factory { param1: Param1 -> - * MyAggregator.Factory(param1) - * } - */ - class Factory>( - val getAggregator: (param1: Param1) -> AggregatorProvider, - ) : Provider> by - Provider({ name -> AggregatorOptionSwitch1(name, getAggregator) }) + @Suppress("FunctionName") + companion object { + + /** + * Creates [AggregatorOptionSwitch1]. + * + * Used like: + * ```kt + * val myAggregator by AggregatorOptionSwitch1.Factory { param1: Param1 -> + * MyAggregator.Factory(param1) + * } + */ + fun Factory( + getAggregator: (param1: Param1) -> AggregatorProvider, + ) = Provider { name -> AggregatorOptionSwitch1(name, getAggregator) } + } } /** @@ -41,30 +44,32 @@ internal class AggregatorOptionSwitch1>( +internal class AggregatorOptionSwitch2( val name: String, - val getAggregator: (param1: Param1, param2: Param2) -> AggregatorProvider, + val getAggregator: (param1: Param1, param2: Param2) -> AggregatorProvider, ) { - private val cache: MutableMap, AggregatorType> = mutableMapOf() + private val cache: MutableMap, Aggregator> = mutableMapOf() - operator fun invoke(param1: Param1, param2: Param2): AggregatorType = + operator fun invoke(param1: Param1, param2: Param2): Aggregator = cache.getOrPut(param1 to param2) { getAggregator(param1, param2).create(name) } - /** - * Creates [AggregatorOptionSwitch2]. - * - * Used like: - * ```kt - * val myAggregator by AggregatorOptionSwitch2.Factory { param1: Param1, param2: Param2 -> - * MyAggregator.Factory(param1, param2) - * } - * ``` - */ - class Factory>( - val getAggregator: (param1: Param1, param2: Param2) -> AggregatorProvider, - ) : Provider> by - Provider({ name -> AggregatorOptionSwitch2(name, getAggregator) }) + @Suppress("FunctionName") + companion object { + + /** + * Creates [AggregatorOptionSwitch2]. + * + * Used like: + * ```kt + * val myAggregator by AggregatorOptionSwitch2.Factory { param1: Param1, param2: Param2 -> + * MyAggregator.Factory(param1, param2) + * } + */ + fun Factory( + getAggregator: (param1: Param1, param2: Param2) -> AggregatorProvider, + ) = Provider { name -> AggregatorOptionSwitch2(name, getAggregator) } + } } diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorProvider.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorProvider.kt index 9c16fcdb59..fd1ef8db35 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorProvider.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorProvider.kt @@ -25,4 +25,4 @@ internal operator fun Provider.getValue(obj: Any?, property: KProperty<*> * val myAggregator by MyAggregator.Factory * ``` */ -internal fun interface AggregatorProvider> : Provider +internal fun interface AggregatorProvider : Provider> diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt index c876054fa1..f6e2422c1b 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt @@ -1,8 +1,20 @@ package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.ReducingAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.SelectingAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers.AnyInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers.NumberInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.FlatteningMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.TwoStepMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.math.indexOfMax +import org.jetbrains.kotlinx.dataframe.math.indexOfMin +import org.jetbrains.kotlinx.dataframe.math.maxOrNull +import org.jetbrains.kotlinx.dataframe.math.maxTypeConversion import org.jetbrains.kotlinx.dataframe.math.mean import org.jetbrains.kotlinx.dataframe.math.meanTypeConversion import org.jetbrains.kotlinx.dataframe.math.median +import org.jetbrains.kotlinx.dataframe.math.minOrNull +import org.jetbrains.kotlinx.dataframe.math.minTypeConversion import org.jetbrains.kotlinx.dataframe.math.percentile import org.jetbrains.kotlinx.dataframe.math.std import org.jetbrains.kotlinx.dataframe.math.stdTypeConversion @@ -12,248 +24,128 @@ import org.jetbrains.kotlinx.dataframe.math.sumTypeConversion @PublishedApi internal object Aggregators { - /** - * Factory for a simple aggregator that preserves the type of the input values. - * - * A slightly more advanced [Aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator] implementation. - * - * Nulls are filtered out. - * - * When called on multiple columns, this [Aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator] works in two steps: - * First, it aggregates within a [DataColumn][org.jetbrains.kotlinx.dataframe.DataColumn]/[Iterable] ([stepOneAggregator]) with their (given) type, - * and then in between different columns ([stepTwoAggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepAggregator.stepTwoAggregator]) using the results of the first and the newly - * calculated common type of those results. - * - * ``` - * Iterable> - * -> Iterable> // nulls filtered out - * -> stepOneAggregator(Iterable, colType) // called on each iterable - * -> Iterable // nulls filtered out - * -> stepTwoAggregator(Iterable, common valueType) - * -> Return - * ``` - * - * It can also be used as a "simple" aggregator by providing the same function for both steps. - * - * See [FlatteningAggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.FlatteningAggregator] for different behavior for multiple columns. - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepAggregator.calculateReturnTypeOrNull] function. - * @param stepOneAggregator Functional argument for the [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepAggregator.aggregate] function, used within a [DataColumn][org.jetbrains.kotlinx.dataframe.DataColumn] or [Iterable]. - * @param stepTwoAggregator Functional argument for the aggregation function used between different columns. - * It is run on the results of [stepOneAggregator]. - */ - private fun twoStepPreservingType(aggregator: Aggregate) = - TwoStepAggregator.Factory( - getReturnTypeOrNull = preserveReturnTypeNullIfEmpty, - stepOneAggregator = aggregator, - stepTwoAggregator = aggregator, - ) + // TODO these might need some small refactoring - /** - * Factory for a simple aggregator that changes the type of the input values. - * - * A slightly more advanced [Aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator] implementation. - * - * Nulls are filtered out. - * - * When called on multiple columns, this [Aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator] works in two steps: - * First, it aggregates within a [DataColumn][org.jetbrains.kotlinx.dataframe.DataColumn]/[Iterable] ([stepOneAggregator]) with their (given) type, - * and then in between different columns ([stepTwoAggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepAggregator.stepTwoAggregator]) using the results of the first and the newly - * calculated common type of those results. - * - * ``` - * Iterable> - * -> Iterable> // nulls filtered out - * -> stepOneAggregator(Iterable, colType) // called on each iterable - * -> Iterable // nulls filtered out - * -> stepTwoAggregator(Iterable, common valueType) - * -> Return - * ``` - * - * It can also be used as a "simple" aggregator by providing the same function for both steps. - * - * See [FlatteningAggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.FlatteningAggregator] for different behavior for multiple columns. - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepAggregator.calculateReturnTypeOrNull] function. - * @param stepOneAggregator Functional argument for the [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepAggregator.aggregate] function, used within a [DataColumn][org.jetbrains.kotlinx.dataframe.DataColumn] or [Iterable]. - * @param stepTwoAggregator Functional argument for the aggregation function used between different columns. - * It is run on the results of [stepOneAggregator]. - */ - private fun twoStepChangingType( - getReturnTypeOrNull: CalculateReturnTypeOrNull, - stepOneAggregator: Aggregate, - stepTwoAggregator: Aggregate, - ) = TwoStepAggregator.Factory( - getReturnTypeOrNull = getReturnTypeOrNull, - stepOneAggregator = stepOneAggregator, - stepTwoAggregator = stepTwoAggregator, + private fun twoStepSelectingForAny( + getReturnType: CalculateReturnType, + indexOfResult: IndexOfResult, + stepOneReducer: Reducer, + ) = Aggregator( + aggregationHandler = SelectingAggregationHandler(stepOneReducer, indexOfResult, getReturnType), + inputHandler = AnyInputHandler(), + multipleColumnsHandler = TwoStepMultipleColumnsHandler(), ) - /** - * Factory for a flattening aggregator that preserves the type of the input values. - * - * Simple [Aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator] implementation with flattening behavior for multiple columns. - * - * Nulls are filtered out. - * - * When called on multiple columns, - * the columns are flattened into a single list of values, filtering nulls as usual; - * then the aggregation function is called with their common type. - * - * ``` - * Iterable> - * -> Iterable // flattened without nulls - * -> aggregator(Iterable, common colType) - * -> Return - * ``` - * - * This is essential for aggregators that depend on the distribution of all values across the dataframe, like - * the median, percentile, and standard deviation. - * - * See [TwoStepAggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepAggregator] for different behavior for multiple columns. - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.FlatteningAggregator.calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.FlatteningAggregator.aggregate] function. - * 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]. - */ - private fun flatteningPreservingTypes(aggregate: Aggregate) = - FlatteningAggregator.Factory( - getReturnTypeOrNull = preserveReturnTypeNullIfEmpty, - aggregator = aggregate, + private fun twoStepReducingForAny( + getReturnType: CalculateReturnType, + stepOneReducer: Reducer, + stepTwoReducer: Reducer? = null, + ) = Aggregator( + aggregationHandler = ReducingAggregationHandler(stepOneReducer, getReturnType), + inputHandler = AnyInputHandler(), + multipleColumnsHandler = TwoStepMultipleColumnsHandler( + stepTwoAggregationHandler = stepTwoReducer?.let { + ReducingAggregationHandler(stepTwoReducer, getReturnType) + }, + ), + ) + + private fun flattenReducingForAny(reducer: Reducer) = + Aggregator( + aggregationHandler = ReducingAggregationHandler(reducer, preserveReturnTypeNullIfEmpty), + inputHandler = AnyInputHandler(), + multipleColumnsHandler = FlatteningMultipleColumnsHandler(), ) - /** - * Factory for a flattening aggregator that changes the type of the input values. - * - * Simple [Aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator] implementation with flattening behavior for multiple columns. - * - * Nulls are filtered out. - * - * When called on multiple columns, - * the columns are flattened into a single list of values, filtering nulls as usual; - * then the aggregation function is called with their common type. - * - * ``` - * Iterable> - * -> Iterable // flattened without nulls - * -> aggregator(Iterable, common colType) - * -> Return - * ``` - * - * This is essential for aggregators that depend on the distribution of all values across the dataframe, like - * the median, percentile, and standard deviation. - * - * See [TwoStepAggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepAggregator] for different behavior for multiple columns. - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.FlatteningAggregator.calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.FlatteningAggregator.aggregate] function. - * 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]. - */ - private fun flatteningChangingTypes( - getReturnTypeOrNull: CalculateReturnTypeOrNull, - aggregate: Aggregate, - ) = FlatteningAggregator.Factory( - getReturnTypeOrNull = getReturnTypeOrNull, - aggregator = aggregate, + private fun flattenReducingForAny( + getReturnType: CalculateReturnType, + reducer: Reducer, + ) = Aggregator( + aggregationHandler = ReducingAggregationHandler(reducer, getReturnType), + inputHandler = AnyInputHandler(), + multipleColumnsHandler = FlatteningMultipleColumnsHandler(), ) - /** - * Factory for a two-step aggregator that works only with numbers. - * - * [Aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator] made specifically for number calculations. - * Mixed number types are [unified][org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers] to [primitives][org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions.Companion.PRIMITIVES_ONLY]. - * - * Nulls are filtered out. - * - * When called on multiple columns (with potentially mixed [Number] types), - * this [Aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator] works in two steps: - * - * First, it aggregates within a [DataColumn][org.jetbrains.kotlinx.dataframe.DataColumn]/[Iterable] with their (given) [Number] type - * (potentially unifying the types), and then between different columns - * using the results of the first and the newly calculated [unified number][org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers] type of those results. - * - * ``` - * Iterable> - * -> Iterable> // nulls filtered out - * -> aggregator(Iterable, unified number type of common colType) // called on each iterable - * -> Iterable // nulls filtered out - * -> aggregator(Iterable, unified number type of common valueType) - * -> Return - * ``` - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepNumbersAggregator.calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.TwoStepNumbersAggregator.aggregate] function, used within a [DataColumn][org.jetbrains.kotlinx.dataframe.DataColumn] or [Iterable]. - * While it takes a [Number] argument, you can assume that all values are of the same specific type, however, - * this type can be different for different calls to [aggregator][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorBase.aggregator]. - */ - private fun twoStepForNumbers( - getReturnTypeOrNull: CalculateReturnTypeOrNull, - aggregate: Aggregate, - ) = TwoStepNumbersAggregator.Factory( - getReturnTypeOrNull = getReturnTypeOrNull, - aggregate = aggregate, + private fun twoStepReducingForNumbers( + getReturnType: CalculateReturnType, + reducer: Reducer, + ) = Aggregator( + aggregationHandler = ReducingAggregationHandler(reducer, getReturnType), + inputHandler = NumberInputHandler(), + multipleColumnsHandler = TwoStepMultipleColumnsHandler(), ) /** Wrapper around an [aggregator factory][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorProvider] for aggregators that require a single parameter. * * Aggregators are cached by their parameter value. * @see AggregatorOptionSwitch2 */ - private fun > withOneOption( - getAggregator: (Param1) -> AggregatorProvider, + private fun withOneOption( + getAggregator: (Param1) -> AggregatorProvider, ) = AggregatorOptionSwitch1.Factory(getAggregator) /** Wrapper around an [aggregator factory][org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorProvider] for aggregators that require two parameters. * * Aggregators are cached by their parameter values. * @see AggregatorOptionSwitch1 */ - private fun > withTwoOptions( - getAggregator: (Param1, Param2) -> AggregatorProvider, + private fun withTwoOptions( + getAggregator: (Param1, Param2) -> AggregatorProvider, ) = AggregatorOptionSwitch2.Factory(getAggregator) // T: Comparable -> T? - val min by twoStepPreservingType> { - minOrNull() + // T : Comparable? -> T? + fun ?> min(skipNaN: Boolean): Aggregator = min.invoke(skipNaN).cast2() + + private val min by withOneOption { skipNaN: Boolean -> + twoStepSelectingForAny, Comparable?>( + getReturnType = minTypeConversion, + stepOneReducer = { type -> minOrNull(type, skipNaN) }, + indexOfResult = { type -> indexOfMin(type, skipNaN) }, + ) } // T: Comparable -> T? - val max by twoStepPreservingType> { - maxOrNull() + // T : Comparable? -> T? + fun ?> max(skipNaN: Boolean): Aggregator = max.invoke(skipNaN).cast2() + + private val max by withOneOption { skipNaN: Boolean -> + twoStepSelectingForAny, Comparable?>( + getReturnType = maxTypeConversion, + stepOneReducer = { type -> maxOrNull(type, skipNaN) }, + indexOfResult = { type -> indexOfMax(type, skipNaN) }, + ) } // T: Number? -> Double val std by withTwoOptions { skipNA: Boolean, ddof: Int -> - flatteningChangingTypes(stdTypeConversion) { type -> - std(type, skipNA, ddof) + flattenReducingForAny(stdTypeConversion) { type -> + asIterable().std(type, skipNA, ddof) } } // step one: T: Number? -> Double // step two: Double -> Double - val mean by withOneOption { skipNA: Boolean -> - twoStepForNumbers(meanTypeConversion) { type -> - mean(type, skipNA) + val mean by withOneOption { skipNaN: Boolean -> + twoStepReducingForNumbers(meanTypeConversion) { type -> + mean(type, skipNaN) } } // T: Comparable? -> T val percentile by withOneOption { percentile: Double -> - flatteningPreservingTypes> { type -> - percentile(percentile, type) + flattenReducingForAny> { type -> + asIterable().percentile(percentile, type) } } // T: Comparable? -> T - val median by flatteningPreservingTypes> { type -> - median(type) + val median by flattenReducingForAny> { type -> + asIterable().median(type) } // T: Number -> T - val sum by twoStepForNumbers(sumTypeConversion) { type -> - sum(type) + val sum by withOneOption { skipNaN: Boolean -> + twoStepReducingForNumbers(sumTypeConversion) { type -> + sum(type, skipNaN) + } } } diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/FlatteningAggregator.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/FlatteningAggregator.kt deleted file mode 100644 index 1ba0c41eae..0000000000 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/FlatteningAggregator.kt +++ /dev/null @@ -1,81 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators - -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.impl.commonType -import kotlin.reflect.KType -import kotlin.reflect.full.withNullability - -/** - * Simple [Aggregator] implementation with flattening behavior for multiple columns. - * - * Nulls are filtered out. - * - * When called on multiple columns, - * the columns are flattened into a single list of values, filtering nulls as usual; - * then the aggregation function is called with their common type. - * - * ``` - * Iterable> - * -> Iterable // flattened without nulls - * -> aggregator(Iterable, common colType) - * -> Return - * ``` - * - * This is essential for aggregators that depend on the distribution of all values across the dataframe, like - * the median, percentile, and standard deviation. - * - * See [TwoStepAggregator] for different behavior for multiple columns. - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate] function. - * Note that it must be able to handle `null` values for the [Iterable] overload of [aggregate]. - */ -internal class FlatteningAggregator( - name: String, - getReturnTypeOrNull: CalculateReturnTypeOrNull, - aggregator: Aggregate, -) : AggregatorBase(name, getReturnTypeOrNull, aggregator) { - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - * The columns are flattened into a single list of values, filtering nulls as usual; - * then the aggregation function is with the common type of the columns. - */ - override fun aggregate(columns: Iterable>): Return { - val commonType = columns.map { it.type() }.commonType().withNullability(false) - val allValues = columns.asSequence().flatMap { it.values() }.filterNotNull() - return aggregate(allValues.asIterable(), commonType) - } - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - override fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? { - val commonType = colTypes.commonType().withNullability(false) - return calculateReturnTypeOrNull(commonType, colsEmpty) - } - - /** - * Creates [FlatteningAggregator]. - * - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate] function. - */ - class Factory( - private val getReturnTypeOrNull: CalculateReturnTypeOrNull, - private val aggregator: Aggregate, - ) : AggregatorProvider> by AggregatorProvider({ name -> - FlatteningAggregator( - name = name, - getReturnTypeOrNull = getReturnTypeOrNull, - aggregator = aggregator, - ) - }) -} diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator.kt deleted file mode 100644 index b593f4f261..0000000000 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator.kt +++ /dev/null @@ -1,105 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators - -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.columns.isEmpty -import org.jetbrains.kotlinx.dataframe.impl.commonType -import kotlin.reflect.KType -import kotlin.reflect.full.starProjectedType -import kotlin.reflect.full.withNullability - -/** - * A slightly more advanced [Aggregator] implementation. - * - * Nulls are filtered out. - * - * When called on multiple columns, this [Aggregator] works in two steps: - * First, it aggregates within a [DataColumn]/[Iterable] ([stepOneAggregator]) with their (given) type, - * and then in between different columns ([stepTwoAggregator]) using the results of the first and the newly - * calculated common type of those results. - * - * ``` - * Iterable> - * -> Iterable> // nulls filtered out - * -> stepOneAggregator(Iterable, colType) // called on each iterable - * -> Iterable // nulls filtered out - * -> stepTwoAggregator(Iterable, common valueType) - * -> Return - * ``` - * - * It can also be used as a "simple" aggregator by providing the same function for both steps. - * - * See [FlatteningAggregator] for different behavior for multiple columns. - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param stepOneAggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable]. - * @param stepTwoAggregator Functional argument for the aggregation function used between different columns. - * It is run on the results of [stepOneAggregator]. - */ -internal class TwoStepAggregator( - name: String, - getReturnTypeOrNull: CalculateReturnTypeOrNull, - stepOneAggregator: Aggregate, - private val stepTwoAggregator: Aggregate, -) : AggregatorBase(name, getReturnTypeOrNull, stepOneAggregator) { - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - * - * This function calls [stepOneAggregator] on each column and then [stepTwoAggregator] on the results. - * - * Post-step-one types are calculated by [calculateReturnTypeOrNull]. - */ - override fun aggregate(columns: Iterable>): Return { - val (values, types) = columns.mapNotNull { col -> - // uses stepOneAggregator - val value = aggregate(col) ?: return@mapNotNull null - val type = calculateReturnTypeOrNull( - type = col.type().withNullability(false), - emptyInput = col.isEmpty, - ) ?: value::class.starProjectedType // heavy fallback type calculation - - value to type - }.unzip() - val commonType = types.commonType() - return stepTwoAggregator(values, commonType) - } - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - override fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? { - val typesAfterStepOne = colTypes.map { type -> - calculateReturnTypeOrNull(type = type.withNullability(false), emptyInput = colsEmpty) - } - if (typesAfterStepOne.any { it == null }) return null - return typesAfterStepOne.commonType() - } - - /** - * Creates [TwoStepAggregator]. - * - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param stepOneAggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable]. - * @param stepTwoAggregator Functional argument for the aggregation function used between different columns. - * It is run on the results of [stepOneAggregator]. - */ - class Factory( - private val getReturnTypeOrNull: CalculateReturnTypeOrNull, - private val stepOneAggregator: Aggregate, - private val stepTwoAggregator: Aggregate, - ) : AggregatorProvider> by AggregatorProvider({ name -> - TwoStepAggregator( - name = name, - getReturnTypeOrNull = getReturnTypeOrNull, - stepOneAggregator = stepOneAggregator, - stepTwoAggregator = stepTwoAggregator, - ) - }) -} diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepNumbersAggregator.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepNumbersAggregator.kt deleted file mode 100644 index 8cfc4e92a7..0000000000 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepNumbersAggregator.kt +++ /dev/null @@ -1,199 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators - -import io.github.oshai.kotlinlogging.KotlinLogging -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.columns.isEmpty -import org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers -import org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions.Companion.PRIMITIVES_ONLY -import org.jetbrains.kotlinx.dataframe.impl.anyNull -import org.jetbrains.kotlinx.dataframe.impl.convertToUnifiedNumberType -import org.jetbrains.kotlinx.dataframe.impl.isNothing -import org.jetbrains.kotlinx.dataframe.impl.nothingType -import org.jetbrains.kotlinx.dataframe.impl.primitiveNumberTypes -import org.jetbrains.kotlinx.dataframe.impl.renderType -import org.jetbrains.kotlinx.dataframe.impl.types -import org.jetbrains.kotlinx.dataframe.impl.unifiedNumberTypeOrNull -import kotlin.reflect.KType -import kotlin.reflect.full.isSubtypeOf -import kotlin.reflect.full.starProjectedType -import kotlin.reflect.full.withNullability -import kotlin.reflect.typeOf - -private val logger = KotlinLogging.logger { } - -/** - * [Aggregator] made specifically for number calculations. - * Mixed number types are [unified][UnifyingNumbers] to [primitives][PRIMITIVES_ONLY]. - * - * Nulls are filtered out. - * - * When called on multiple columns (with potentially mixed [Number] types), - * this [Aggregator] works in two steps: - * - * First, it aggregates within a [DataColumn]/[Iterable] with their (given) [Number] type - * (potentially unifying the types), and then between different columns - * using the results of the first and the newly calculated [unified number][UnifyingNumbers] type of those results. - * - * ``` - * Iterable> - * -> Iterable> // nulls filtered out - * -> aggregator(Iterable, unified number type of common colType) // called on each iterable - * -> Iterable // nulls filtered out - * -> aggregator(Iterable, unified number type of common valueType) - * -> Return - * ``` - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable]. - * While it takes a [Number] argument, you can assume that all values are of the same specific type, however, - * this type can be different for different calls to [aggregator]. - */ -internal class TwoStepNumbersAggregator( - name: String, - getReturnTypeOrNull: CalculateReturnTypeOrNull, - aggregator: Aggregate, -) : AggregatorBase(name, getReturnTypeOrNull, aggregator) { - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - * - * This function calls [aggregator] on each column and then again on the results. - * - * After the first aggregation, the number types are found by [calculateReturnTypeOrNull] and then - * unified using [aggregateCalculatingType]. - */ - override fun aggregate(columns: Iterable>): Return { - val (values, types) = columns.mapNotNull { col -> - val value = aggregate(col) ?: return@mapNotNull null - val type = calculateReturnTypeOrNull( - type = col.type().withNullability(false), - emptyInput = col.isEmpty, - ) ?: value::class.starProjectedType // heavy fallback type calculation - - value to type - }.unzip() - - return aggregateCalculatingType( - values = values, - valueTypes = types.toSet(), - ) - } - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - @Suppress("UNCHECKED_CAST") - override fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? { - val typesAfterStepOne = colTypes.map { type -> - calculateReturnTypeOrNull(type = type.withNullability(false), emptyInput = colsEmpty) - } - if (typesAfterStepOne.anyNull()) return null - val typeSet = (typesAfterStepOne as List).toSet() - val unifiedType = typeSet.unifiedNumberTypeOrNull(PRIMITIVES_ONLY) - ?.withNullability(false) - ?: throw IllegalArgumentException( - "Cannot calculate the $name of the number types: ${typeSet.joinToString { renderType(it) }}. " + - "Note, only primitive number types are supported in statistics.", - ) - - return unifiedType - } - - /** - * Base function of [Aggregator]. - * - * Aggregates the given values, taking [type] into account, and computes a single resulting value. - * - * Nulls are filtered out (only if [type.isMarkedNullable][KType.isMarkedNullable]). - * - * Uses [aggregator] to compute the result. - * - * This function is modified to call [aggregateCalculatingType] when it encounters mixed number types. - * This is not optimal and should be avoided by calling [aggregateCalculatingType] with known number types directly. - * - * When the exact [type] is unknown, use [aggregateCalculatingType]. - */ - override fun aggregate(values: Iterable, type: KType): Return { - require(type.isSubtypeOf(typeOf())) { - "${TwoStepNumbersAggregator::class.simpleName}: Type $type is not a subtype of Number?" - } - return when (type.withNullability(false)) { - // If the type is not a specific number, but rather a mixed Number, we unify the types first. - // This is heavy and could be avoided by calling aggregate with a specific number type - // or calling aggregateCalculatingType with all known number types - typeOf() -> aggregateCalculatingType(values) - - // Nothing can occur when values are empty - nothingType -> super.aggregate(values, type) - - !in primitiveNumberTypes -> throw IllegalArgumentException( - "Cannot calculate $name of ${renderType(type)}, only primitive numbers are supported.", - ) - - else -> super.aggregate(values, type) - } - } - - /** - * Special case of [aggregate] with [Iterable] that calculates the [unified number type][UnifyingNumbers] - * of the values at runtime and converts all numbers to this type before aggregating. - * Without [valueTypes], this is a heavy operation and should be avoided when possible. - * - * @param values The numbers to be aggregated. - * @param valueTypes The types of the numbers. - * If provided, this can be used to avoid calculating the types of [values] at runtime with reflection. - * It should contain all types of [values]. - * If `null` or empty, the types of [values] will be calculated at runtime (heavy!). - */ - @Suppress("UNCHECKED_CAST") - override fun aggregateCalculatingType(values: Iterable, valueTypes: Set?): Return { - val valueTypes = valueTypes?.takeUnless { it.isEmpty() } ?: values.types() - val unifiedType = valueTypes.unifiedNumberTypeOrNull(PRIMITIVES_ONLY) - ?: throw IllegalArgumentException( - "Cannot calculate the $name of the number types: ${valueTypes.joinToString { renderType(it) }}. " + - "Note, only primitive number types are supported in statistics.", - ) - - if (unifiedType.isSubtypeOf(typeOf()) && - (typeOf() in valueTypes || typeOf() in valueTypes) - ) { - logger.warn { - "Number unification of Long -> Double happened during aggregation. Loss of precision may have occurred." - } - } - if (unifiedType.withNullability(false) !in primitiveNumberTypes && !unifiedType.isNothing) { - throw IllegalArgumentException( - "Cannot calculate $name of ${renderType(unifiedType)}, only primitive numbers are supported.", - ) - } - - return super.aggregate( - values = values.convertToUnifiedNumberType(commonNumberType = unifiedType), - type = unifiedType, - ) - } - - /** - * Creates [TwoStepNumbersAggregator]. - * - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable]. - */ - class Factory( - private val getReturnTypeOrNull: CalculateReturnTypeOrNull, - private val aggregate: Aggregate, - ) : AggregatorProvider> by AggregatorProvider({ name -> - TwoStepNumbersAggregator( - name = name, - getReturnTypeOrNull = getReturnTypeOrNull, - aggregator = aggregate, - ) - }) -} diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/aggregateBy.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/aggregateBy.kt index 659180a3aa..ebf10a5fd8 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/aggregateBy.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/aggregateBy.kt @@ -1,17 +1,25 @@ 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 Grouped.aggregateBy(body: DataFrameExpression?>): DataFrame { +internal fun Grouped.aggregateByOrNull(body: DataFrameExpression?>): DataFrame { require(this is GroupBy<*, T>) val keyColumns = keys.columnNames().toSet() return aggregateInternal { @@ -21,3 +29,90 @@ internal fun Grouped.aggregateBy(body: DataFrameExpression? } }.cast() } + +/** + * Selects the best matching value in the [sequence][values] + * using the provided [Aggregator] `by` the provided [selector]. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + values: Sequence, + crossinline selector: (T) -> V, +): T? = + values.elementAtOrNull( + indexOfAggregationResult( + values = values.map { selector(it) }, + valueType = typeOf(), + ), + ) + +/** + * Selects the best matching value in the [iterable][values] + * using the provided [Aggregator] `by` the provided [selector]. + * + * Faster implementation than for sequences. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + values: Iterable, + crossinline selector: (T) -> V, +): T? = + values.elementAtOrNull( + indexOfAggregationResult( + values = values.asSequence().map { selector(it) }, + valueType = typeOf(), + ), + ) + +/** + * Selects the best matching value in the [column] using the provided [Aggregator] `by` the provided [selector]. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + column: DataColumn, + crossinline selector: (T) -> V, +): T? = aggregateByOrNull(column.values(), selector) + +/** + * Selects the best matching value in the [dataframe][data] + * using the provided [Aggregator] `by` the provided [rowExpression]. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + data: DataFrame, + crossinline rowExpression: RowExpression, +): DataRow? = + data.getOrNull( + indexOfAggregationResult( + values = data.asSequence().map { rowExpression(it, it) }, + valueType = typeOf(), + ), + ) + +/** + * Selects the best matching value in the [dataframe][data] + * using the provided [Aggregator] `by` the provided [column]. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + data: DataFrame, + column: ColumnReference, +): DataRow? = + data.getOrNull( + indexOfAggregationResult( + values = data.asSequence().map { it[column] }, + valueType = typeOf(), + ), + ) diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/forEveryColumn.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/forEveryColumn.kt index 70e55e2f8b..8650779aa0 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/forEveryColumn.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/forEveryColumn.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.internal import org.jetbrains.kotlinx.dataframe.impl.aggregation.receivers.AggregateInternalDsl import org.jetbrains.kotlinx.dataframe.type -internal fun Aggregator<*, R>.aggregateFor( +internal fun Aggregator<*, R>.aggregateFor( data: Grouped, columns: ColumnsForAggregateSelector, ): DataFrame = @@ -23,7 +23,7 @@ internal fun Aggregator<*, R>.aggregateFor( aggregateFor(columns, cast()) } -internal fun Aggregator<*, R>.aggregateFor( +internal fun Aggregator<*, R>.aggregateFor( data: PivotGroupBy, separate: Boolean, columns: ColumnsForAggregateSelector, @@ -32,7 +32,7 @@ internal fun Aggregator<*, R>.aggregateFor( internal().aggregateFor(columns, cast()) } -internal fun Aggregator<*, R>.aggregateFor( +internal fun Aggregator<*, R>.aggregateFor( data: DataFrame, columns: ColumnsForAggregateSelector, ): DataRow = @@ -40,7 +40,7 @@ internal fun Aggregator<*, R>.aggregateFor( internal().aggregateFor(columns, cast()) } -internal fun AggregateInternalDsl.aggregateFor( +internal fun AggregateInternalDsl.aggregateFor( columns: ColumnsForAggregateSelector, aggregator: Aggregator, ) { @@ -48,14 +48,14 @@ internal fun AggregateInternalDsl.aggregateFor( val isSingle = cols.size == 1 cols.forEach { col -> val path = getPath(col, isSingle) - val value = aggregator.aggregate(col.data) - val returnType = aggregator.calculateReturnTypeOrNull(col.data.type, col.data.isEmpty) + val value = aggregator.aggregateSingleColumn(col.data) + val returnType = aggregator.calculateReturnType(col.data.type, col.data.isEmpty) yield( path = path, value = value, type = returnType, default = col.default, - guessType = returnType == null, + guessType = false, ) } } diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt index c2ca6a2483..0dd71e7e2d 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt @@ -6,40 +6,56 @@ import org.jetbrains.kotlinx.dataframe.RowExpression import org.jetbrains.kotlinx.dataframe.aggregation.AggregateBody import org.jetbrains.kotlinx.dataframe.api.Grouped import org.jetbrains.kotlinx.dataframe.api.PivotGroupBy +import org.jetbrains.kotlinx.dataframe.api.asSequence import org.jetbrains.kotlinx.dataframe.api.isEmpty import org.jetbrains.kotlinx.dataframe.api.pathOf import org.jetbrains.kotlinx.dataframe.api.rows 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.aggregate import org.jetbrains.kotlinx.dataframe.impl.aggregation.internal import org.jetbrains.kotlinx.dataframe.impl.emptyPath -import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf +/** + * Aggregates [values] by first applying [transform] to each element of the sequence and then + * applying the [Aggregator] ([this]) to the resulting sequence. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ @PublishedApi -internal inline fun Aggregator.aggregateOf( - values: Iterable, - crossinline transform: (C) -> V?, -): R = - aggregate( - values = values.asSequence().mapNotNull { transform(it) }.asIterable(), - type = typeOf().withNullability(false), - ) +internal inline fun Aggregator.aggregateOf( + values: Sequence, + crossinline transform: (C) -> V, +): R = aggregate(values = values.map { transform(it) }, valueType = typeOf()) +/** + * Aggregates [column] by first applying [transform] to each element of the column and then + * applying the [Aggregator] ([this]) to the resulting sequence. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ @PublishedApi -internal inline fun Aggregator.aggregateOf( +internal inline fun Aggregator.aggregateOf( column: DataColumn, - crossinline transform: (C) -> V?, -): R = aggregateOf(column.values(), transform) + crossinline transform: (C) -> V, +): R = aggregateOf(column.asSequence(), transform) +/** + * Aggregates [frame] by first applying [expression] to each row of the frame and then + * applying the [Aggregator] ([this]) to the resulting sequence. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") @PublishedApi -internal inline fun Aggregator<*, R>.aggregateOf( +internal inline fun Aggregator<*, R>.aggregateOf( frame: DataFrame, - crossinline expression: RowExpression, -): R = (this as Aggregator).aggregateOf(frame.rows()) { expression(it, it) } + crossinline expression: RowExpression, +): R = (this as Aggregator).aggregateOf(frame.rows().asSequence()) { expression(it, it) } @PublishedApi -internal fun Aggregator<*, R>.aggregateOfDelegated( +internal fun Aggregator<*, R>.aggregateOfDelegated( frame: Grouped, name: String?, body: AggregateBody, @@ -48,31 +64,44 @@ internal fun Aggregator<*, R>.aggregateOfDelegated( body(this, this) } +/** + * Aggregates [data] by first applying [expression] to each row of the frame and then + * + * @param C is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") @PublishedApi -internal inline fun Aggregator<*, R>.aggregateOf( +internal inline fun Aggregator<*, R>.aggregateOf( data: Grouped, resultName: String? = null, - crossinline expression: RowExpression, + crossinline expression: RowExpression, ): DataFrame = data.aggregateOf(resultName, expression, this as Aggregator) +/** + * @param C is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") @PublishedApi -internal inline fun Aggregator<*, R>.aggregateOf( +internal inline fun Aggregator<*, R>.aggregateOf( data: PivotGroupBy, - crossinline expression: RowExpression, + crossinline expression: RowExpression, ): DataFrame = data.aggregateOf(expression, this as Aggregator) +/** + * @param C is used to infer whether there are nulls in the values fed to the aggregator! + */ @PublishedApi -internal inline fun Grouped.aggregateOf( +internal inline fun Grouped.aggregateOf( resultName: String?, - crossinline expression: RowExpression, - aggregator: Aggregator, + crossinline expression: RowExpression, + aggregator: Aggregator, ): DataFrame { val path = pathOf(resultName ?: aggregator.name) val expressionResultType = typeOf() return aggregateInternal { val value = aggregator.aggregateOf(df, expression) - val returnType = aggregator.calculateReturnTypeOrNull( - type = expressionResultType, + val returnType = aggregator.calculateReturnType( + valueType = expressionResultType, emptyInput = df.isEmpty(), ) yield( @@ -80,15 +109,18 @@ internal inline fun Grouped.aggregateOf( value = value, type = returnType, default = null, - guessType = returnType == null, + guessType = false, ) } } +/** + * @param C is used to infer whether there are nulls in the values fed to the aggregator! + */ @PublishedApi -internal inline fun PivotGroupBy.aggregateOf( - crossinline expression: RowExpression, - aggregator: Aggregator, +internal inline fun PivotGroupBy.aggregateOf( + crossinline expression: RowExpression, + aggregator: Aggregator, ): DataFrame = aggregate { internal().yield(emptyPath(), aggregator.aggregateOf(this, expression)) diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt index d6adab9304..a91b2c26d7 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt @@ -4,20 +4,24 @@ import org.jetbrains.kotlinx.dataframe.ColumnsSelector import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.api.getColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregateCalculatingValueType /** * Generic function to apply an [Aggregator] ([this]) to aggregate values of a row. * - * [Aggregator.aggregateCalculatingType] is used to deal with mixed types. + * [Aggregator.aggregateCalculatingValueType] is used to deal with mixed types. * * @param row a row to aggregate * @param columns selector of which columns inside the [row] to aggregate */ @PublishedApi -internal fun Aggregator.aggregateOfRow(row: DataRow, columns: ColumnsSelector): R { - val filteredColumns = row.df().getColumns(columns) - return aggregateCalculatingType( - values = filteredColumns.mapNotNull { row[it] }, +internal fun Aggregator.aggregateOfRow( + row: DataRow, + columns: ColumnsSelector, +): R { + val filteredColumns = row.df().getColumns(columns).asSequence() + return aggregateCalculatingValueType( + values = filteredColumns.map { row[it] }, valueTypes = filteredColumns.map { it.type() }.toSet(), ) } diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/withinAllColumns.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/withinAllColumns.kt index 7467f2da3f..593db8f3c6 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/withinAllColumns.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/withinAllColumns.kt @@ -15,66 +15,70 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.internal import org.jetbrains.kotlinx.dataframe.impl.emptyPath @PublishedApi -internal fun Aggregator<*, R>.aggregateAll(data: DataFrame, columns: ColumnsSelector): R = - data.aggregateAll(cast2(), columns) +internal fun Aggregator<*, R>.aggregateAll( + data: DataFrame, + columns: ColumnsSelector, +): R = data.aggregateAll(cast2(), columns) -internal fun Aggregator<*, R>.aggregateAll( +internal fun Aggregator<*, R>.aggregateAll( data: Grouped, name: String?, - columns: ColumnsSelector, + columns: ColumnsSelector, ): DataFrame = data.aggregateAll(cast(), columns, name) -internal fun Aggregator<*, R>.aggregateAll( +internal fun Aggregator<*, R>.aggregateAll( data: PivotGroupBy, - columns: ColumnsSelector, + columns: ColumnsSelector, ): DataFrame = data.aggregateAll(cast(), columns) -internal fun DataFrame.aggregateAll(aggregator: Aggregator, columns: ColumnsSelector): R = - aggregator.aggregate(get(columns)) +internal fun DataFrame.aggregateAll( + aggregator: Aggregator, + columns: ColumnsSelector, +): R = aggregator.aggregateMultipleColumns(get(columns).asSequence()) -internal fun Grouped.aggregateAll( - aggregator: Aggregator, - columns: ColumnsSelector, +internal fun Grouped.aggregateAll( + aggregator: Aggregator, + columns: ColumnsSelector, name: String?, ): DataFrame = aggregateInternal { val cols = df[columns] if (cols.size == 1) { - yield(pathOf(name ?: cols[0].name()), aggregator.aggregate(cols[0])) + yield(pathOf(name ?: cols[0].name()), aggregator.aggregateSingleColumn(cols[0])) } else { - yield(pathOf(name ?: aggregator.name), aggregator.aggregate(cols)) + yield(pathOf(name ?: aggregator.name), aggregator.aggregateMultipleColumns(cols.asSequence())) } } -internal fun PivotGroupBy.aggregateAll( - aggregator: Aggregator, - columns: ColumnsSelector, +internal fun PivotGroupBy.aggregateAll( + aggregator: Aggregator, + columns: ColumnsSelector, ): DataFrame = aggregate { val cols = get(columns) if (cols.size == 1) { - val returnType = aggregator.calculateReturnTypeOrNull( - type = cols[0].type(), + val returnType = aggregator.calculateReturnType( + valueType = cols[0].type(), emptyInput = cols[0].isEmpty, ) internal().yield( path = emptyPath(), - value = aggregator.aggregate(cols[0]), + value = aggregator.aggregateSingleColumn(cols[0]), type = returnType, default = null, - guessType = returnType == null, + guessType = false, ) } else { - val returnType = aggregator.calculateReturnTypeOrNull( + val returnType = aggregator.calculateReturnTypeMultipleColumns( colTypes = cols.map { it.type() }.toSet(), colsEmpty = cols.any { it.isEmpty }, ) internal().yield( path = emptyPath(), - value = aggregator.aggregate(cols), + value = aggregator.aggregateMultipleColumns(cols.asSequence()), type = returnType, default = null, - guessType = returnType == null, + guessType = false, ) } } diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/mean.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/mean.kt index f94c274a04..ef71fabbbc 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/mean.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/mean.kt @@ -1,31 +1,26 @@ package org.jetbrains.kotlinx.dataframe.math import io.github.oshai.kotlinlogging.KotlinLogging -import org.jetbrains.kotlinx.dataframe.api.skipNA_default -import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnTypeOrNull +import org.jetbrains.kotlinx.dataframe.api.skipNaN_default +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnType import org.jetbrains.kotlinx.dataframe.impl.nothingType import org.jetbrains.kotlinx.dataframe.impl.renderType import java.math.BigDecimal import java.math.BigInteger import kotlin.reflect.KType -import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf private val logger = KotlinLogging.logger { } -@PublishedApi -internal fun Iterable.mean(type: KType, skipNA: Boolean = skipNA_default): Double = - asSequence().mean(type, skipNA) - @Suppress("UNCHECKED_CAST") -internal fun Sequence.mean(type: KType, skipNA: Boolean = skipNA_default): Double { +internal fun Sequence.mean(type: KType, skipNaN: Boolean): Double { if (type.isMarkedNullable) { - return filterNotNull().mean(type.withNullability(false), skipNA) + error("Encountered nullable type ${renderType(type)} in mean function. This should not occur.") } - return when (type.withNullability(false)) { - typeOf() -> (this as Sequence).mean(skipNA) + return when (type) { + typeOf() -> (this as Sequence).mean(skipNaN) - typeOf() -> (this as Sequence).map { it.toDouble() }.mean(skipNA) + typeOf() -> (this as Sequence).map { it.toDouble() }.mean(skipNaN) typeOf() -> (this as Sequence).map { it.toDouble() }.mean(false) @@ -56,16 +51,16 @@ internal fun Sequence.mean(type: KType, skipNA: Boolean = skipN } /** T: Number? -> Double */ -internal val meanTypeConversion: CalculateReturnTypeOrNull = { _, _ -> +internal val meanTypeConversion: CalculateReturnType = { _, _ -> typeOf() } -internal fun Sequence.mean(skipNA: Boolean = skipNA_default): Double { +internal fun Sequence.mean(skipNaN: Boolean = skipNaN_default): Double { var count = 0 var sum: Double = 0.toDouble() for (element in this) { if (element.isNaN()) { - if (skipNA) { + if (skipNaN) { continue } else { return Double.NaN diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/std.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/std.kt index a91184985c..af8d7ee936 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/std.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/std.kt @@ -1,8 +1,8 @@ package org.jetbrains.kotlinx.dataframe.math import org.jetbrains.kotlinx.dataframe.api.ddof_default -import org.jetbrains.kotlinx.dataframe.api.skipNA_default -import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnTypeOrNull +import org.jetbrains.kotlinx.dataframe.api.skipNaN_default +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnType import org.jetbrains.kotlinx.dataframe.impl.renderType import java.math.BigDecimal import java.math.BigInteger @@ -14,41 +14,41 @@ import kotlin.reflect.typeOf @PublishedApi internal fun Iterable.std( type: KType, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, ddof: Int = ddof_default, ): Double { if (type.isMarkedNullable) { return when { - skipNA -> filterNotNull().std(type = type.withNullability(false), skipNA = true, ddof = ddof) + skipNaN -> filterNotNull().std(type = type.withNullability(false), skipNaN = true, ddof = ddof) contains(null) -> Double.NaN - else -> std(type = type.withNullability(false), skipNA = false, ddof = ddof) + else -> std(type = type.withNullability(false), skipNaN = false, ddof = ddof) } } return when (type.classifier) { - Double::class -> (this as Iterable).std(skipNA, ddof) - Float::class -> (this as Iterable).std(skipNA, ddof) + Double::class -> (this as Iterable).std(skipNaN, ddof) + Float::class -> (this as Iterable).std(skipNaN, ddof) Int::class, Short::class, Byte::class -> (this as Iterable).std(ddof) Long::class -> (this as Iterable).std(ddof) BigDecimal::class -> (this as Iterable).std(ddof) BigInteger::class -> (this as Iterable).std(ddof) - Number::class -> (this as Iterable).map { it.toDouble() }.std(skipNA, ddof) + Number::class -> (this as Iterable).map { it.toDouble() }.std(skipNaN, ddof) Nothing::class -> Double.NaN else -> throw IllegalArgumentException("Unable to compute the std for type ${renderType(type)}") } } /** T: Number? -> Double */ -internal val stdTypeConversion: CalculateReturnTypeOrNull = { _, _ -> +internal val stdTypeConversion: CalculateReturnType = { _, _ -> typeOf() } @JvmName("doubleStd") -internal fun Iterable.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): Double = - varianceAndMean(skipNA)?.std(ddof) ?: Double.NaN +internal fun Iterable.std(skipNaN: Boolean = skipNaN_default, ddof: Int = ddof_default): Double = + varianceAndMean(skipNaN)?.std(ddof) ?: Double.NaN @JvmName("floatStd") -internal fun Iterable.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): Double = - varianceAndMean(skipNA)?.std(ddof) ?: Double.NaN +internal fun Iterable.std(skipNaN: Boolean = skipNaN_default, ddof: Int = ddof_default): Double = + varianceAndMean(skipNaN)?.std(ddof) ?: Double.NaN @JvmName("intStd") internal fun Iterable.std(ddof: Int = ddof_default): Double = varianceAndMean().std(ddof) diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/stdMean.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/stdMean.kt index b9276c62a4..c3c0a413ce 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/stdMean.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/stdMean.kt @@ -2,7 +2,7 @@ package org.jetbrains.kotlinx.dataframe.math -import org.jetbrains.kotlinx.dataframe.api.skipNA_default +import org.jetbrains.kotlinx.dataframe.api.skipNaN_default import java.math.BigDecimal import java.math.BigInteger import kotlin.math.sqrt @@ -16,12 +16,12 @@ internal data class BasicStats(val count: Int, val mean: Double, val variance: D } @JvmName("doubleVarianceAndMean") -internal fun Iterable.varianceAndMean(skipNA: Boolean = skipNA_default): BasicStats? { +internal fun Iterable.varianceAndMean(skipNaN: Boolean = skipNaN_default): BasicStats? { var count = 0 var sum = .0 for (element in this) { if (element.isNaN()) { - if (skipNA) { + if (skipNaN) { continue } else { return null @@ -41,12 +41,12 @@ internal fun Iterable.varianceAndMean(skipNA: Boolean = skipNA_default): } @JvmName("floatVarianceAndMean") -internal fun Iterable.varianceAndMean(skipNA: Boolean = skipNA_default): BasicStats? { +internal fun Iterable.varianceAndMean(skipNaN: Boolean = skipNaN_default): BasicStats? { var count = 0 var sum = .0 for (element in this) { if (element.isNaN()) { - if (skipNA) { + if (skipNaN) { continue } else { return null diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/sum.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/sum.kt index 7ef56e1147..e845bb49a6 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/sum.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/sum.kt @@ -1,26 +1,23 @@ package org.jetbrains.kotlinx.dataframe.math -import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnTypeOrNull +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnType import org.jetbrains.kotlinx.dataframe.impl.nothingType import org.jetbrains.kotlinx.dataframe.impl.renderType import kotlin.reflect.KType import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf -import kotlin.sequences.filterNotNull - -internal fun Iterable.sum(type: KType): Number = asSequence().sum(type) @Suppress("UNCHECKED_CAST") @JvmName("sumNullableT") @PublishedApi -internal fun Sequence.sum(type: KType): Number { +internal fun Sequence.sum(type: KType, skipNaN: Boolean): Number { if (type.isMarkedNullable) { - return filterNotNull().sum(type.withNullability(false)) + error("Encountered nullable type ${renderType(type)} in sum function. This should not occur.") } - return when (type.withNullability(false)) { - typeOf() -> (this as Sequence).sum() + return when (type) { + typeOf() -> (this as Sequence).filterNot { skipNaN && it.isNaN() }.sum() - typeOf() -> (this as Sequence).sum() + typeOf() -> (this as Sequence).filterNot { skipNaN && it.isNaN() }.sum() typeOf() -> (this as Sequence).sum() @@ -44,7 +41,7 @@ internal fun Sequence.sum(type: KType): Number { } /** T: Number? -> T */ -internal val sumTypeConversion: CalculateReturnTypeOrNull = { type, _ -> +internal val sumTypeConversion: CalculateReturnType = { type, _ -> when (val type = type.withNullability(false)) { // type changes to Int typeOf(), typeOf() -> typeOf() diff --git a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt index 11ab7599e5..ead3b1060a 100644 --- a/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt +++ b/core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt @@ -74,6 +74,12 @@ internal const val TO_LEFT_REPLACE = "this.toStart()" internal const val TO_RIGHT = "This `toRight` overload will be removed in favor of `toEnd`. $MESSAGE_0_16" internal const val TO_RIGHT_REPLACE = "this.toEnd()" +internal const val ROW_MIN = "`rowMin` is deprecated in favor of `rowMinOf`. $MESSAGE_0_16" +internal const val ROW_MIN_OR_NULL = "`rowMinOrNull` is deprecated in favor of `rowMinOfOrNull`. $MESSAGE_0_16" + +internal const val ROW_MAX = "`rowMax` is deprecated in favor of `rowMaxOf`. $MESSAGE_0_16" +internal const val ROW_MAX_OR_NULL = "`rowMaxOrNull` is deprecated in favor of `rowMaxOfOrNull`. $MESSAGE_0_16" + // endregion // region WARNING in 0.16, ERROR in 0.17 diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/describe.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/describe.kt index 3161e3bc7b..d161b82ae5 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/describe.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/describe.kt @@ -62,9 +62,9 @@ class DescribeTests { nulls shouldBe 0 top shouldBe 1 freq shouldBe 1 - this.mean.shouldBeNaN() + mean.shouldBeNaN() std.shouldBeNaN() - min shouldBe 1.0 // TODO should be NaN too? + min.isNaN shouldBe true p25 shouldBe 1.75 median shouldBe 3.0 p75.isNaN shouldBe true diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/puzzles/BasicTests.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/puzzles/BasicTests.kt index 4241f7570a..d49928a42a 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/puzzles/BasicTests.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/puzzles/BasicTests.kt @@ -216,8 +216,8 @@ class BasicTests { "dog", 3.0, Double.NaN, 6.0, ) - val actualDfAcc = df.pivot(inward = false) { visits }.groupBy { animal }.mean(skipNA = true) { age } - val actualDfStr = df.pivot("visits", inward = false).groupBy("animal").mean("age", skipNA = true) + val actualDfAcc = df.pivot(inward = false) { visits }.groupBy { animal }.mean(skipNaN = true) { age } + val actualDfStr = df.pivot("visits", inward = false).groupBy("animal").mean("age", skipNaN = true) actualDfAcc shouldBe expected actualDfStr shouldBe expected diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt index 79f5ef4327..fa4a77415b 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt @@ -54,7 +54,6 @@ import org.jetbrains.kotlinx.dataframe.api.stdOf import org.jetbrains.kotlinx.dataframe.api.sum import org.jetbrains.kotlinx.dataframe.api.sumFor import org.jetbrains.kotlinx.dataframe.api.sumOf -import org.jetbrains.kotlinx.dataframe.api.toDataFrame import org.jetbrains.kotlinx.dataframe.api.valueCounts import org.jetbrains.kotlinx.dataframe.api.values import org.jetbrains.kotlinx.dataframe.explainer.TransformDataFrameExpressions @@ -259,8 +258,8 @@ class Analyze : TestBase() { fun meanModes() { // SampleStart df.mean() // mean of values per every numeric column - df.mean(skipNA = true) { age and weight } // mean of all values in `age` and `weight`, skips NA - df.meanFor(skipNA = true) { age and weight } // mean of values per `age` and `weight` separately, skips NA + df.mean(skipNaN = true) { age and weight } // mean of all values in `age` and `weight`, skips NA + df.meanFor(skipNaN = true) { age and weight } // mean of values per `age` and `weight` separately, skips NA df.meanOf { (weight ?: 0) / age } // median of expression evaluated for every row // SampleEnd } @@ -304,7 +303,7 @@ class Analyze : TestBase() { @TransformDataFrameExpressions fun meanAggregationsSkipNA() { // SampleStart - df.mean(skipNA = true) + df.mean(skipNaN = true) // SampleEnd } diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Modify.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Modify.kt index 296dacb8bf..503fde4164 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Modify.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Modify.kt @@ -160,12 +160,12 @@ class Modify : TestBase() { fun updatePerColumn() { val updated = // SampleStart - df.update { colsOf() }.perCol { mean(skipNA = true) } + df.update { colsOf() }.perCol { mean(skipNaN = true) } // SampleEnd updated.age.countDistinct() shouldBe 1 updated.weight.countDistinct() shouldBe 1 - val means = df.meanFor(skipNA = true) { colsOf() } + val means = df.meanFor(skipNaN = true) { colsOf() } df.update { colsOf() }.perCol(means) shouldBe updated df.update { colsOf() }.perCol(means.toMap() as Map) shouldBe updated } diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/mean.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/mean.kt index 16ad780fac..15b867e2bf 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/mean.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/mean.kt @@ -4,7 +4,11 @@ import io.kotest.matchers.doubles.shouldBeNaN import io.kotest.matchers.shouldBe import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.api.columnOf +import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.mean +import org.jetbrains.kotlinx.dataframe.api.meanFor +import org.jetbrains.kotlinx.dataframe.api.meanOf +import org.jetbrains.kotlinx.dataframe.api.rowMean import org.jetbrains.kotlinx.dataframe.impl.nothingType import org.junit.Test import kotlin.reflect.typeOf @@ -20,9 +24,228 @@ class MeanTests { @Test fun `mean with nans and nulls`() { columnOf(10, 20, Double.NaN, null).mean().shouldBeNaN() - columnOf(10, 20, Double.NaN, null).mean(skipNA = true) shouldBe 15 + columnOf(10, 20, Double.NaN, null).mean(skipNaN = true) shouldBe 15 DataColumn.createValueColumn("", emptyList(), nothingType(false)).mean().shouldBeNaN() DataColumn.createValueColumn("", listOf(null), nothingType(true)).mean().shouldBeNaN() } + + @Test + fun `mean with int values`() { + val col = columnOf(1, 2, 3, 4, 5) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1, 2, 3, 4, 5, null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with long values`() { + val col = columnOf(1L, 2L, 3L, 4L, 5L) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1L, 2L, 3L, 4L, 5L, null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with float values`() { + val col = columnOf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with double values`() { + val col = columnOf(1.0, 2.0, 3.0, 4.0, 5.0) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1.0, 2.0, 3.0, 4.0, 5.0, null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with short values`() { + val col = columnOf(1.toShort(), 2.toShort(), 3.toShort(), 4.toShort(), 5.toShort()) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1.toShort(), 2.toShort(), 3.toShort(), 4.toShort(), 5.toShort(), null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with byte values`() { + val col = columnOf(1.toByte(), 2.toByte(), 3.toByte(), 4.toByte(), 5.toByte()) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1.toByte(), 2.toByte(), 3.toByte(), 4.toByte(), 5.toByte(), null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with mixed number types`() { + val col = columnOf(1, 2L, 3.0f, 4.0, 5.toShort()) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1, 2L, 3.0f, 4.0, 5.toShort(), null) + colWithNull.mean() shouldBe 3.0 + + // Mix of different integer types + val intMix = columnOf(1, 2L, 3.toShort(), 4.toByte()) + intMix.mean() shouldBe 2.5 + + // Mix of different floating point types + val floatMix = columnOf(1.0f, 2.0, 3.0f, 4.0) + floatMix.mean() shouldBe 2.5 + + // Mix of integer and floating point types + val mixedTypes = columnOf(1, 2.0f, 3L, 4.0) + mixedTypes.mean() shouldBe 2.5 + } + + @Test + fun `meanOf with transformation`() { + val col = columnOf("1", "2", "3", "4", "5") + col.meanOf { it.toInt() } shouldBe 3.0 + + val colWithNull = columnOf("1", "2", "3", null, "5") + colWithNull.meanOf { it?.toInt() } shouldBe 2.75 + } + + @Suppress("ktlint:standard:argument-list-wrapping") + @Test + fun `rowMean with dataframe`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + ) + + df[0].rowMean() shouldBe 2.0 + df[1].rowMean() shouldBe 5.0 + df[2].rowMean() shouldBe 8.0 + } + + @Suppress("ktlint:standard:argument-list-wrapping") + @Test + fun `dataframe mean`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2.0, 3f, + 4, 5.0, 6f, + 7, 8.0, 9f, + ) + + val means = df.mean() + means["a"] shouldBe 4.0 + means["b"] shouldBe 5.0 + means["c"] shouldBe 6.0 + + // Test mean for specific columns + val meanFor = df.meanFor("a", "c") + meanFor["a"] shouldBe 4.0 + meanFor["c"] shouldBe 6.0 + + // Test mean of all columns as a single value + df.mean("a", "b", "c") shouldBe 5.0 + } + + @Suppress("ktlint:standard:argument-list-wrapping") + @Test + fun `dataframe meanOf with transformation`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + ) + + df.meanOf { "a"() + "c"() } shouldBe 10.0 + } + + @Suppress("ktlint:standard:argument-list-wrapping") + @Test + fun `mean with skipNaN for floating point numbers`() { + // Test with Float.NaN values + val floatWithNaN = columnOf(1.0f, 2.0f, Float.NaN, 4.0f, 5.0f) + floatWithNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + floatWithNaN.mean(skipNaN = true) shouldBe 3.0 // Skip NaN values + + // Test with Double.NaN values + val doubleWithNaN = columnOf(1.0, 2.0, Double.NaN, 4.0, 5.0) + doubleWithNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + doubleWithNaN.mean(skipNaN = true) shouldBe 3.0 // Skip NaN values + + // Test with multiple NaN values in different positions + val multipleNaN = columnOf(Float.NaN, 2.0f, Float.NaN, 4.0f, Float.NaN) + multipleNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + multipleNaN.mean(skipNaN = true) shouldBe 3.0 // Skip NaN values + + // Test with all NaN values + val allNaN = columnOf(Float.NaN, Float.NaN, Float.NaN) + allNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + allNaN.mean(skipNaN = true).shouldBeNaN() // No valid values, result is NaN + + // Test with mixed number types including NaN + val mixedWithNaN = columnOf(1, 2.0f, Double.NaN, 4L, 5.0) + mixedWithNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + mixedWithNaN.mean(skipNaN = true) shouldBe 3.0 // Skip NaN values + + // Test with DataFrame containing NaN values + val dfWithNaN = dataFrameOf( + "a", "b", "c", + )( + 1.0, Double.NaN, 3.0, + 4.0, 5.0, Float.NaN, + Double.NaN, 8.0, 9.0, + ) + + // Test DataFrame mean with skipNaN + val meansWithNaN = dfWithNaN.mean() // Default behavior + (meansWithNaN["a"] as Double).shouldBeNaN() // Contains NaN + (meansWithNaN["b"] as Double).shouldBeNaN() // Contains NaN + (meansWithNaN["c"] as Double).shouldBeNaN() // Contains NaN + + val meansSkipNaN = dfWithNaN.mean(skipNaN = true) // Skip NaN values + meansSkipNaN["a"] shouldBe 2.5 // (1.0 + 4.0) / 2 + meansSkipNaN["b"] shouldBe 6.5 // (5.0 + 8.0) / 2 + meansSkipNaN["c"] shouldBe 6.0 // (3.0 + 9.0) / 2 + + // Test meanFor with skipNaN + val meanForWithNaN = dfWithNaN.meanFor("a", "c") // Default behavior + (meanForWithNaN["a"] as Double).shouldBeNaN() // Contains NaN + (meanForWithNaN["c"] as Double).shouldBeNaN() // Contains NaN + + val meanForSkipNaN = dfWithNaN.meanFor("a", "c", skipNaN = true) // Skip NaN values + meanForSkipNaN["a"] shouldBe 2.5 // (1.0 + 4.0) / 2 + meanForSkipNaN["c"] shouldBe 6.0 // (3.0 + 9.0) / 2 + + // Test mean of all columns as a single value with skipNaN + dfWithNaN.mean("a", "b", "c").shouldBeNaN() // Default behavior: NaN propagates + dfWithNaN.mean("a", "b", "c", skipNaN = true) shouldBe 5.0 // Skip NaN values + + // Test meanOf with transformation that might produce NaN values + val dfForTransform = dataFrameOf( + "a", "b", + )( + 1.0, 0.0, + 4.0, 2.0, + 0.0, 0.0, + ) + + // Division by zero produces NaN + dfForTransform.meanOf { "a"() / "b"() }.shouldBeNaN() // Default behavior: NaN propagates + + // Skip NaN values from division by zero + dfForTransform.meanOf(skipNaN = true) { + val b = "b"() + if (b == 0.0) Double.NaN else "a"() / b + } shouldBe 2.0 // Only 4.0/2.0 = 2.0 is valid + } } diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt index 0e158e73d4..6079fa5799 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt @@ -1,13 +1,17 @@ package org.jetbrains.kotlinx.dataframe.statistics import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.doubles.shouldBeNaN +import io.kotest.matchers.floats.shouldBeNaN import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain import org.jetbrains.kotlinx.dataframe.api.columnOf import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.isEmpty import org.jetbrains.kotlinx.dataframe.api.rowSum +import org.jetbrains.kotlinx.dataframe.api.rowSumOf import org.jetbrains.kotlinx.dataframe.api.sum +import org.jetbrains.kotlinx.dataframe.api.sumFor import org.jetbrains.kotlinx.dataframe.api.sumOf import org.jetbrains.kotlinx.dataframe.api.toDataFrame import org.junit.Test @@ -60,10 +64,10 @@ class SumTests { df.sumOf { value3() } shouldBe expected3 df.sum(value1) shouldBe expected1 df.sum(value2) shouldBe expected2 - // TODO sum rework, has Number in results df.sum(value3) shouldBe expected3 + df.sum(value3) shouldBe expected3 df.sum { value1 } shouldBe expected1 df.sum { value2 } shouldBe expected2 - // TODO sum rework, has Number in results df.sum { value3 } shouldBe expected3 + df.sum { value3 } shouldBe expected3 } /** [Issue #1068](https://github.com/Kotlin/dataframe/issues/1068) */ @@ -106,4 +110,75 @@ class SumTests { columnOf(1.0, 2, 3.0.toBigDecimal()).toDataFrame().sum()[0] }.message?.lowercase() shouldContain "primitive" } + + @Test + fun `test skipNaN with float column`() { + val value by columnOf(1.0f, 2.0f, Float.NaN, 3.0f) + val df = dataFrameOf(value) + + // With skipNaN = true (default is false) + value.sum(skipNaN = true) shouldBe 6.0f + df[value].sum(skipNaN = true) shouldBe 6.0f + df.sum(skipNaN = true)[value] shouldBe 6.0f + df.sumOf(skipNaN = true) { value().toInt() } shouldBe 6 + + // With skipNaN = false (default) + value.sum().shouldBeNaN() + df[value].sum().shouldBeNaN() + df.sum()[value].shouldBeNaN() + df.sumOf { value().toDouble() }.shouldBeNaN() + } + + @Test + fun `test skipNaN with double column`() { + val value by columnOf(1.0, 2.0, Double.NaN, 3.0) + val df = dataFrameOf(value) + + // With skipNaN = true (default is false) + value.sum(skipNaN = true) shouldBe 6.0 + df[value].sum(skipNaN = true) shouldBe 6.0 + df.sum(skipNaN = true)[value] shouldBe 6.0 + df.sumOf(skipNaN = true) { value().toLong() } shouldBe 6L + + // With skipNaN = false (default) + value.sum().shouldBeNaN() + df[value].sum().shouldBeNaN() + df.sum()[value].shouldBeNaN() + df.sumOf { value().toFloat() }.shouldBeNaN() + } + + @Test + fun `test rowSum with skipNaN`() { + val row1 = dataFrameOf("a", "b", "c")(1.0, 2.0, 3.0)[0] + val row2 = dataFrameOf("a", "b", "c")(1.0, Double.NaN, 3)[0] + + // With skipNaN = true + row1.rowSum(skipNaN = true) shouldBe 6.0 + row2.rowSum(skipNaN = true) shouldBe 4.0 + + // With skipNaN = false (default) + row1.rowSum() shouldBe 6.0 + (row2.rowSum() as Double).shouldBeNaN() + + // Test rowSumOf + row1.rowSumOf(skipNaN = true) shouldBe 6.0 + row2.rowSumOf(skipNaN = true) shouldBe 1.0 + row1.rowSumOf() shouldBe 6.0 + row2.rowSumOf().shouldBeNaN() + } + + @Test + fun `test sumFor with skipNaN`() { + val value1 by columnOf(1.0, 2.0, 3.0) + val value2 by columnOf(4.0, Float.NaN, 6) + val df = dataFrameOf(value1, value2) + + // With skipNaN = true + df.sumFor(skipNaN = true) { value1 and value2 }[value1] shouldBe 6.0 + df.sumFor(skipNaN = true) { value1 and value2 }[value2] shouldBe 10.0 + + // With skipNaN = false (default) + df.sumFor { value1 and value2 }[value1] shouldBe 6.0 + (df.sumFor { value1 and value2 }[value2] as Double).shouldBeNaN() + } } diff --git a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/animals/AnimalsTests.kt b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/animals/AnimalsTests.kt index 2bc8b69b37..70e70d1702 100644 --- a/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/animals/AnimalsTests.kt +++ b/core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/animals/AnimalsTests.kt @@ -25,7 +25,7 @@ class AnimalsTests { @Test fun `ignore nans`() { - df.mean("age", skipNA = true) shouldBe 3.4375 + df.mean("age", skipNaN = true) shouldBe 3.4375 } @Test diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataColumnType.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataColumnType.kt index a69d8db723..21dc50ec8d 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataColumnType.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/DataColumnType.kt @@ -7,6 +7,7 @@ import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.dataframe.columns.ColumnKind import org.jetbrains.kotlinx.dataframe.columns.FrameColumn import org.jetbrains.kotlinx.dataframe.columns.ValueColumn +import org.jetbrains.kotlinx.dataframe.impl.isIntraComparable import org.jetbrains.kotlinx.dataframe.impl.isMixedNumber import org.jetbrains.kotlinx.dataframe.impl.isPrimitiveNumber import org.jetbrains.kotlinx.dataframe.impl.isPrimitiveOrMixedNumber @@ -18,11 +19,7 @@ import org.jetbrains.kotlinx.dataframe.util.IS_INTER_COMPARABLE_IMPORT import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.reflect.KType -import kotlin.reflect.KTypeProjection -import kotlin.reflect.KVariance -import kotlin.reflect.full.createType import kotlin.reflect.full.isSubtypeOf -import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf public fun AnyCol.isColumnGroup(): Boolean { @@ -87,13 +84,4 @@ public fun AnyCol.isComparable(): Boolean = valuesAreComparable() * * Technically, this means the values' common type `T(?)` is a subtype of [Comparable]`(?)` */ -public fun AnyCol.valuesAreComparable(): Boolean = - isValueColumn() && - isSubtypeOf( - Comparable::class.createType( - arguments = listOf( - KTypeProjection(KVariance.IN, type().withNullability(false)), - ), - nullable = hasNulls(), - ), - ) +public fun AnyCol.valuesAreComparable(): Boolean = isValueColumn() && type().isIntraComparable() diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Defaults.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Defaults.kt index 646954aa45..c7778320be 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Defaults.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/Defaults.kt @@ -1,7 +1,7 @@ package org.jetbrains.kotlinx.dataframe.api @PublishedApi -internal val skipNA_default: Boolean = false +internal val skipNaN_default: Boolean = false @PublishedApi internal val ddof_default: Int = 1 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 76aaefe695..096e53198d 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 @@ -22,6 +22,8 @@ import org.jetbrains.kotlinx.dataframe.documentation.NaN import org.jetbrains.kotlinx.dataframe.documentation.SelectingColumns import org.jetbrains.kotlinx.dataframe.get import org.jetbrains.kotlinx.dataframe.typeClass +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract import kotlin.reflect.KProperty // region fillNulls @@ -98,8 +100,30 @@ public fun DataFrame.fillNulls(vararg columns: ColumnReference): Up // endregion +/** Is only `true` if [this] is [Double.NaN] or [Float.NaN]. */ internal inline val Any?.isNaN: Boolean get() = (this is Double && isNaN()) || (this is Float && isNaN()) +/** + * Returns `true` if [this] is considered NA. + * "NA", in DataFrame, roughly means `null` or `NaN`. + * + * Overload of `isNA` with contract support. + * + * @see NA + */ +@JvmName("isNaWithContract") +@Suppress("NOTHING_TO_INLINE") +@OptIn(ExperimentalContracts::class) +internal inline fun T.isNA(): Boolean { + contract { returns(false) implies (this@isNA != null) } + return isNA +} + +/** + * Is `true` if [this] is considered NA. + * "NA", in DataFrame, roughly means `null` or `NaN`. + * @see NA + */ internal inline val Any?.isNA: Boolean get() = when (this) { null -> true @@ -112,10 +136,22 @@ internal inline val Any?.isNA: Boolean internal inline val AnyCol.canHaveNaN: Boolean get() = typeClass.let { it == Double::class || it == Float::class } +/** + * Is `true` when [this] column can have [NA] values. + * @see NA + */ internal inline val AnyCol.canHaveNA: Boolean get() = hasNulls() || canHaveNaN || kind() != ColumnKind.Value +/** + * Is `true` when [this] is `null` or [Double.NaN]. + * @see NA + */ internal inline val Double?.isNA: Boolean get() = this == null || this.isNaN() +/** + * Is `true` when [this] is `null` or [Float.NaN]. + * @see NA + */ internal inline val Float?.isNA: Boolean get() = this == null || this.isNaN() // region fillNaNs diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt index eb5be20565..3debb714e4 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/groupBy.kt @@ -109,4 +109,5 @@ public class ReducedGroupBy( override fun toString(): String = "ReducedGroupBy(groupBy=$groupBy, reducer=$reducer)" } +@PublishedApi internal fun GroupBy.reduce(reducer: Selector, DataRow?>) = ReducedGroupBy(this, reducer) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt index 6de276a7e4..644076199d 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/max.kt @@ -12,295 +12,775 @@ 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.columns.values import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregators import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateByOrNull import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor -import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfDelegated +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfRow import org.jetbrains.kotlinx.dataframe.impl.columns.toComparableColumns -import org.jetbrains.kotlinx.dataframe.impl.indexOfMax import org.jetbrains.kotlinx.dataframe.impl.suggestIfNull +import org.jetbrains.kotlinx.dataframe.util.MAX_NO_SKIPNAN +import org.jetbrains.kotlinx.dataframe.util.ROW_MAX +import org.jetbrains.kotlinx.dataframe.util.ROW_MAX_OR_NULL import kotlin.reflect.KProperty // region DataColumn -public fun > DataColumn.max(): T = maxOrNull().suggestIfNull("max") +public fun > DataColumn.max(skipNaN: Boolean = skipNaN_default): T = + maxOrNull(skipNaN).suggestIfNull("max") -public fun > DataColumn.maxOrNull(): T? = asSequence().filterNotNull().maxOrNull() +public fun > DataColumn.maxOrNull(skipNaN: Boolean = skipNaN_default): T? = + Aggregators.max(skipNaN).aggregateSingleColumn(this) -public fun > DataColumn.maxBy(selector: (T) -> R): T = - maxByOrNull(selector).suggestIfNull("maxBy") +public inline fun ?> DataColumn.maxBy( + skipNaN: Boolean = skipNaN_default, + noinline selector: (T) -> R, +): T & Any = maxByOrNull(skipNaN, selector).suggestIfNull("maxBy") -public fun > DataColumn.maxByOrNull(selector: (T) -> R): T? = values.maxByOrNull(selector) +public inline fun ?> DataColumn.maxByOrNull( + skipNaN: Boolean = skipNaN_default, + noinline selector: (T) -> R, +): T? = Aggregators.max(skipNaN).aggregateByOrNull(this, selector) -public fun > DataColumn.maxOf(selector: (T) -> R): R = - maxOfOrNull(selector).suggestIfNull("maxOf") +public inline fun ?> DataColumn.maxOf( + skipNaN: Boolean = skipNaN_default, + crossinline selector: (T) -> R, +): R & Any = maxOfOrNull(skipNaN, selector).suggestIfNull("maxOf") -public fun > DataColumn.maxOfOrNull(selector: (T) -> R): R? = values.maxOfOrNull(selector) +public inline fun ?> DataColumn.maxOfOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline selector: (T) -> R, +): R? = Aggregators.max(skipNaN).aggregateOf(this, selector) // endregion // region DataRow -public fun AnyRow.rowMaxOrNull(): Any? = values().filterIsInstance>().maxWithOrNull(compareBy { it }) +@Deprecated(ROW_MAX_OR_NULL, level = DeprecationLevel.ERROR) +public fun AnyRow.rowMaxOrNull(): Any? = error(ROW_MAX_OR_NULL) -public fun AnyRow.rowMax(): Any = rowMaxOrNull().suggestIfNull("rowMax") +@Deprecated(ROW_MAX, level = DeprecationLevel.ERROR) +public fun AnyRow.rowMax(): Any = error(ROW_MAX) -public inline fun > AnyRow.rowMaxOfOrNull(): T? = values().filterIsInstance().maxOrNull() +public inline fun ?> AnyRow.rowMaxOfOrNull(skipNaN: Boolean = skipNaN_default): T? = + Aggregators.max(skipNaN).aggregateOfRow(this) { colsOf() } -public inline fun > AnyRow.rowMaxOf(): T = rowMaxOfOrNull().suggestIfNull("rowMaxOf") +public inline fun ?> AnyRow.rowMaxOf(skipNaN: Boolean = skipNaN_default): T & Any = + rowMaxOfOrNull(skipNaN).suggestIfNull("rowMaxOf") // endregion // region DataFrame -public fun DataFrame.max(): DataRow = maxFor(intraComparableColumns()) +public fun DataFrame.max(skipNaN: Boolean = skipNaN_default): DataRow = + maxFor(skipNaN, intraComparableColumns()) -public fun > DataFrame.maxFor(columns: ColumnsForAggregateSelector): DataRow = - Aggregators.max.aggregateFor(this, columns) +public fun ?> DataFrame.maxFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = Aggregators.max(skipNaN).aggregateFor(this, columns) -public fun DataFrame.maxFor(vararg columns: String): DataRow = maxFor { columns.toComparableColumns() } +public fun DataFrame.maxFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + maxFor(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > DataFrame.maxFor(vararg columns: ColumnReference): DataRow = - maxFor { columns.toColumnSet() } +public fun ?> DataFrame.maxFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > DataFrame.maxFor(vararg columns: KProperty): DataRow = - maxFor { columns.toColumnSet() } +public fun ?> DataFrame.maxFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(skipNaN) { columns.toColumnSet() } -public fun > DataFrame.max(columns: ColumnsSelector): C = - maxOrNull(columns).suggestIfNull("max") +public fun ?> DataFrame.max( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): C & Any = maxOrNull(skipNaN, columns).suggestIfNull("max") -public fun DataFrame.max(vararg columns: String): Comparable = maxOrNull(*columns).suggestIfNull("max") +public fun DataFrame.max(vararg columns: String, skipNaN: Boolean = skipNaN_default): Comparable = + maxOrNull(*columns, skipNaN = skipNaN).suggestIfNull("max") @AccessApiOverload -public fun > DataFrame.max(vararg columns: ColumnReference): C = - maxOrNull(*columns).suggestIfNull("max") +public fun ?> DataFrame.max( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C & Any = maxOrNull(*columns, skipNaN = skipNaN).suggestIfNull("max") @AccessApiOverload -public fun > DataFrame.max(vararg columns: KProperty): C = - maxOrNull(*columns).suggestIfNull("max") +public fun ?> DataFrame.max( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): C & Any = maxOrNull(*columns, skipNaN = skipNaN).suggestIfNull("max") -public fun > DataFrame.maxOrNull(columns: ColumnsSelector): C? = - Aggregators.max.aggregateAll(this, columns) as C? +public fun ?> DataFrame.maxOrNull( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): C? = Aggregators.max(skipNaN).aggregateAll(this, columns) -public fun DataFrame.maxOrNull(vararg columns: String): Comparable? = - maxOrNull { columns.toComparableColumns() } +public fun DataFrame.maxOrNull(vararg columns: String, skipNaN: Boolean = skipNaN_default): Comparable? = + maxOrNull(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > DataFrame.maxOrNull(vararg columns: ColumnReference): C? = - maxOrNull { columns.toColumnSet() } +public fun ?> DataFrame.maxOrNull( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C? = maxOrNull(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > DataFrame.maxOrNull(vararg columns: KProperty): C? = - maxOrNull { columns.toColumnSet() } +public fun ?> DataFrame.maxOrNull( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): C? = maxOrNull(skipNaN) { columns.toColumnSet() } -public fun > DataFrame.maxOf(expression: RowExpression): C = - maxOfOrNull(expression).suggestIfNull("maxOf") +public inline fun ?> DataFrame.maxOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C & Any = maxOfOrNull(skipNaN, expression).suggestIfNull("maxOf") -public fun > DataFrame.maxOfOrNull(expression: RowExpression): C? = - rows().maxOfOrNull { expression(it, it) } +public inline fun ?> DataFrame.maxOfOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C? = Aggregators.max(skipNaN).aggregateOf(this, expression) -public fun > DataFrame.maxBy(expression: RowExpression): DataRow = - maxByOrNull(expression).suggestIfNull("maxBy") +public inline fun ?> DataFrame.maxBy( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow = maxByOrNull(skipNaN, expression).suggestIfNull("maxBy") -public fun DataFrame.maxBy(column: String): DataRow = maxByOrNull(column).suggestIfNull("maxBy") +public fun DataFrame.maxBy(column: String, skipNaN: Boolean = skipNaN_default): DataRow = + maxByOrNull(column, skipNaN).suggestIfNull("maxBy") @AccessApiOverload -public fun > DataFrame.maxBy(column: ColumnReference): DataRow = - maxByOrNull(column).suggestIfNull("maxBy") +public inline fun ?> DataFrame.maxBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxByOrNull(column, skipNaN).suggestIfNull("maxBy") @AccessApiOverload -public fun > DataFrame.maxBy(column: KProperty): DataRow = - maxByOrNull(column).suggestIfNull("maxBy") +public inline fun ?> DataFrame.maxBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxByOrNull(column, skipNaN).suggestIfNull("maxBy") -public fun > DataFrame.maxByOrNull(expression: RowExpression): DataRow? = - getOrNull(rows().asSequence().map { expression(it, it) }.indexOfMax()) +public inline fun ?> DataFrame.maxByOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow? = Aggregators.max(skipNaN).aggregateByOrNull(this, expression) -public fun DataFrame.maxByOrNull(column: String): DataRow? = - maxByOrNull(column.toColumnOf?>()) +public fun DataFrame.maxByOrNull(column: String, skipNaN: Boolean = skipNaN_default): DataRow? = + maxByOrNull(column.toColumnOf?>(), skipNaN) @AccessApiOverload -public fun > DataFrame.maxByOrNull(column: ColumnReference): DataRow? = - getOrNull(get(column).asSequence().indexOfMax()) +public inline fun ?> DataFrame.maxByOrNull( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow? = Aggregators.max(skipNaN).aggregateByOrNull(this, column) @AccessApiOverload -public fun > DataFrame.maxByOrNull(column: KProperty): DataRow? = - maxByOrNull(column.toColumnAccessor()) +public inline fun ?> DataFrame.maxByOrNull( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow? = maxByOrNull(column.toColumnAccessor(), skipNaN) // endregion // region GroupBy + @Refine @Interpretable("GroupByMax1") -public fun Grouped.max(): DataFrame = maxFor(intraComparableColumns()) +public fun Grouped.max(skipNaN: Boolean = skipNaN_default): DataFrame = + maxFor(skipNaN, intraComparableColumns()) @Refine @Interpretable("GroupByMax0") -public fun > Grouped.maxFor(columns: ColumnsForAggregateSelector): DataFrame = - Aggregators.max.aggregateFor(this, columns) +public fun ?> Grouped.maxFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.max(skipNaN).aggregateFor(this, columns) -public fun Grouped.maxFor(vararg columns: String): DataFrame = maxFor { columns.toComparableColumns() } +public fun Grouped.maxFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + maxFor(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Grouped.maxFor(vararg columns: ColumnReference): DataFrame = - maxFor { columns.toColumnSet() } +public fun ?> Grouped.maxFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Grouped.maxFor(vararg columns: KProperty): DataFrame = - maxFor { columns.toColumnSet() } +public fun ?> Grouped.maxFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMax0") -public fun > Grouped.max(name: String? = null, columns: ColumnsSelector): DataFrame = - Aggregators.max.aggregateAll(this, name, columns) +public fun ?> Grouped.max( + name: String? = null, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.max(skipNaN).aggregateAll(this, name, columns) -public fun Grouped.max(vararg columns: String, name: String? = null): DataFrame = - max(name) { columns.toComparableColumns() } +public fun Grouped.max( + vararg columns: String, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(name, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Grouped.max( - vararg columns: ColumnReference, +public fun ?> Grouped.max( + vararg columns: ColumnReference, name: String? = null, -): DataFrame = max(name) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(name, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Grouped.max(vararg columns: KProperty, name: String? = null): DataFrame = - max(name) { columns.toColumnSet() } +public fun ?> Grouped.max( + vararg columns: KProperty, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(name, skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMaxOf") -public fun > Grouped.maxOf( +public inline fun ?> Grouped.maxOf( name: String? = null, - expression: RowExpression, -): DataFrame = Aggregators.max.aggregateOfDelegated(this, name) { maxOfOrNull(expression) } + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataFrame = Aggregators.max(skipNaN).aggregateOf(this, name, expression) @Interpretable("GroupByReduceExpression") -public fun > GroupBy.maxBy(rowExpression: RowExpression): ReducedGroupBy = - reduce { maxByOrNull(rowExpression) } +public inline fun ?> GroupBy.maxBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedGroupBy = reduce { maxByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > GroupBy.maxBy(column: ColumnReference): ReducedGroupBy = - reduce { maxByOrNull(column) } +public inline fun ?> GroupBy.maxBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedGroupBy = reduce { maxByOrNull(column, skipNaN) } -public fun GroupBy.maxBy(column: String): ReducedGroupBy = - maxBy(column.toColumnAccessor().cast>()) +public fun GroupBy.maxBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedGroupBy = + maxBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > GroupBy.maxBy(column: KProperty): ReducedGroupBy = - maxBy(column.toColumnAccessor()) +public inline fun ?> GroupBy.maxBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedGroupBy = maxBy(column.toColumnAccessor(), skipNaN) // endregion // region Pivot -public fun Pivot.max(separate: Boolean = false): DataRow = delegate { max(separate) } +public fun Pivot.max(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataRow = + delegate { max(separate, skipNaN) } -public fun > Pivot.maxFor( +public fun ?> Pivot.maxFor( separate: Boolean = false, - columns: ColumnsForAggregateSelector, -): DataRow = delegate { maxFor(separate, columns) } + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = delegate { maxFor(separate, skipNaN, columns) } -public fun Pivot.maxFor(vararg columns: String, separate: Boolean = false): DataRow = - maxFor(separate) { columns.toComparableColumns() } +public fun Pivot.maxFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(separate, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Pivot.maxFor( - vararg columns: ColumnReference, +public fun ?> Pivot.maxFor( + vararg columns: ColumnReference, separate: Boolean = false, -): DataRow = maxFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(separate, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Pivot.maxFor( - vararg columns: KProperty, +public fun ?> Pivot.maxFor( + vararg columns: KProperty, separate: Boolean = false, -): DataRow = maxFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = maxFor(separate, skipNaN) { columns.toColumnSet() } -public fun > Pivot.max(columns: ColumnsSelector): DataRow = delegate { max(columns) } +public fun ?> Pivot.max( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataRow = delegate { max(skipNaN, columns) } -public fun Pivot.max(vararg columns: String): DataRow = max { columns.toComparableColumns() } +public fun ?> Pivot.max( + vararg columns: String, + skipNaN: Boolean = skipNaN_default, +): DataRow = max(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Pivot.max(vararg columns: ColumnReference): DataRow = - max { columns.toColumnSet() } +public fun ?> Pivot.max( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = max(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Pivot.max(vararg columns: KProperty): DataRow = - max { columns.toColumnSet() } +public fun ?> Pivot.max( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = max(skipNaN) { columns.toColumnSet() } -public fun > Pivot.maxOf(rowExpression: RowExpression): DataRow = - delegate { maxOf(rowExpression) } +public inline fun ?> Pivot.maxOf( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): DataRow = delegate { maxOf(skipNaN, rowExpression) } -public fun > Pivot.maxBy(rowExpression: RowExpression): ReducedPivot = - reduce { maxByOrNull(rowExpression) } +public inline fun ?> Pivot.maxBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedPivot = reduce { maxByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > Pivot.maxBy(column: ColumnReference): ReducedPivot = - reduce { maxByOrNull(column) } +public inline fun ?> Pivot.maxBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedPivot = reduce { maxByOrNull(column, skipNaN) } -public fun Pivot.maxBy(column: String): ReducedPivot = - maxBy(column.toColumnAccessor().cast>()) +public fun Pivot.maxBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedPivot = + maxBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > Pivot.maxBy(column: KProperty): ReducedPivot = - maxBy(column.toColumnAccessor()) +public inline fun ?> Pivot.maxBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedPivot = maxBy(column.toColumnAccessor(), skipNaN) // endregion // region PivotGroupBy -public fun PivotGroupBy.max(separate: Boolean = false): DataFrame = maxFor(separate, intraComparableColumns()) +public fun PivotGroupBy.max(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataFrame = + maxFor(separate, skipNaN, intraComparableColumns()) -public fun > PivotGroupBy.maxFor( +public fun ?> PivotGroupBy.maxFor( separate: Boolean = false, - columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.max.aggregateFor(this, separate, columns) + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.max(skipNaN).aggregateFor(this, separate, columns) -public fun PivotGroupBy.maxFor(vararg columns: String, separate: Boolean = false): DataFrame = - maxFor(separate) { columns.toComparableColumns() } +public fun PivotGroupBy.maxFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(separate, skipNaN) { columns.toComparableColumns() } + +@AccessApiOverload +public fun ?> PivotGroupBy.maxFor( + vararg columns: ColumnReference, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(separate, skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun ?> PivotGroupBy.maxFor( + vararg columns: KProperty, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = maxFor(separate, skipNaN) { columns.toColumnSet() } + +public fun ?> PivotGroupBy.max( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.max(skipNaN).aggregateAll(this, columns) + +public fun PivotGroupBy.max(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + max(skipNaN) { columns.toComparableColumns() } + +public fun ?> PivotGroupBy.max( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun ?> PivotGroupBy.max( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = max(skipNaN) { columns.toColumnSet() } + +public inline fun ?> PivotGroupBy.maxOf( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): DataFrame = aggregate { maxOf(skipNaN, rowExpression) } + +public inline fun ?> PivotGroupBy.maxBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedPivotGroupBy = reduce { maxByOrNull(skipNaN, rowExpression) } + +@AccessApiOverload +public inline fun ?> PivotGroupBy.maxBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedPivotGroupBy = reduce { maxByOrNull(column, skipNaN) } + +public fun PivotGroupBy.maxBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedPivotGroupBy = + maxBy(column.toColumnAccessor().cast?>(), skipNaN) + +@AccessApiOverload +public inline fun ?> PivotGroupBy.maxBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedPivotGroupBy = maxBy(column.toColumnAccessor(), skipNaN) + +// endregion + +// region binary compatibility + +@Suppress("UNCHECKED_CAST") +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun > DataColumn.max(): T = max(skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun > DataColumn.maxOrNull(): T? = maxOrNull(skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataColumn.maxBy(noinline selector: (T) -> R): T & Any = + maxBy(skipNaN = skipNaN_default, selector = selector) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataColumn.maxByOrNull(noinline selector: (T) -> R): T? = + maxByOrNull(skipNaN = skipNaN_default, selector = selector) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataColumn.maxOf(crossinline selector: (T) -> R): R & Any = + maxOf(skipNaN = skipNaN_default, selector = selector) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataColumn.maxOfOrNull(crossinline selector: (T) -> R): R? = + maxOfOrNull(skipNaN = skipNaN_default, selector = selector) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> AnyRow.rowMaxOfOrNull(): T? = + rowMaxOfOrNull(skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> AnyRow.rowMaxOf(): T & Any = rowMaxOf(skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.max(): DataRow = max(skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.maxFor(columns: ColumnsForAggregateSelector): DataRow = + maxFor(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.maxFor(vararg columns: String): DataRow = + maxFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.maxFor(vararg columns: ColumnReference): DataRow = + maxFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.maxFor(vararg columns: KProperty): DataRow = + maxFor(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.max(columns: ColumnsSelector): C & Any = + max(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.max(vararg columns: String): Comparable = + max(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.max(vararg columns: ColumnReference): C & Any = + max(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.max(vararg columns: KProperty): C & Any = + max(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.maxOrNull(columns: ColumnsSelector): C? = + maxOrNull(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.maxOrNull(vararg columns: String): Comparable? = + maxOrNull(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.maxOrNull(vararg columns: ColumnReference): C? = + maxOrNull(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.maxOrNull(vararg columns: KProperty): C? = + maxOrNull(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.maxOf( + crossinline expression: RowExpression, +): C & Any = maxOf(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.maxOfOrNull( + crossinline expression: RowExpression, +): C? = maxOfOrNull(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.maxBy( + crossinline expression: RowExpression, +): DataRow = maxBy(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.maxBy(column: String): DataRow = maxBy(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.maxBy(column: ColumnReference): DataRow = + maxBy(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.maxBy(column: KProperty): DataRow = + maxBy(column, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.maxByOrNull( + crossinline expression: RowExpression, +): DataRow? = maxByOrNull(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.maxByOrNull(column: String): DataRow? = maxByOrNull(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.maxByOrNull( + column: ColumnReference, +): DataRow? = maxByOrNull(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.maxByOrNull(column: KProperty): DataRow? = + maxByOrNull(column, skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMax1") +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.max(): DataFrame = max(skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMax0") +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.maxFor(columns: ColumnsForAggregateSelector): DataFrame = + maxFor(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.maxFor(vararg columns: String): DataFrame = + maxFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.maxFor(vararg columns: ColumnReference): DataFrame = + maxFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.maxFor(vararg columns: KProperty): DataFrame = + maxFor(columns = columns, skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMax0") +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.max( + name: String? = null, + columns: ColumnsSelector, +): DataFrame = max(name, skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.max(vararg columns: String, name: String? = null): DataFrame = + max(columns = columns, name = name, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.max( + vararg columns: ColumnReference, + name: String? = null, +): DataFrame = max(columns = columns, name = name, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.max( + vararg columns: KProperty, + name: String? = null, +): DataFrame = max(columns = columns, name = name, skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMaxOf") +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Grouped.maxOf( + name: String? = null, + crossinline expression: RowExpression, +): DataFrame = maxOf(name, skipNaN = skipNaN_default, expression = expression) + +@Interpretable("GroupByReduceExpression") +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> GroupBy.maxBy( + crossinline rowExpression: RowExpression, +): ReducedGroupBy = maxBy(skipNaN = skipNaN_default, rowExpression = rowExpression) @AccessApiOverload -public fun > PivotGroupBy.maxFor( - vararg columns: ColumnReference, +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> GroupBy.maxBy( + column: ColumnReference, +): ReducedGroupBy = maxBy(column, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun GroupBy.maxBy(column: String): ReducedGroupBy = maxBy(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> GroupBy.maxBy( + column: KProperty, +): ReducedGroupBy = maxBy(column, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.max(separate: Boolean = false): DataRow = max(separate, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.maxFor( separate: Boolean = false, -): DataFrame = maxFor(separate) { columns.toColumnSet() } + columns: ColumnsForAggregateSelector, +): DataRow = maxFor(separate, skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.maxFor(vararg columns: String, separate: Boolean = false): DataRow = + maxFor(columns = columns, separate = separate, skipNaN = skipNaN_default) @AccessApiOverload -public fun > PivotGroupBy.maxFor( - vararg columns: KProperty, +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.maxFor( + vararg columns: ColumnReference, separate: Boolean = false, -): DataFrame = maxFor(separate) { columns.toColumnSet() } +): DataRow = maxFor(columns = columns, separate = separate, skipNaN = skipNaN_default) -public fun > PivotGroupBy.max(columns: ColumnsSelector): DataFrame = - Aggregators.max.aggregateAll(this, columns) +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.maxFor( + vararg columns: KProperty, + separate: Boolean = false, +): DataRow = maxFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.max(columns: ColumnsSelector): DataRow = + max(skipNaN = skipNaN_default, columns = columns) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.max(vararg columns: ColumnReference): DataRow = + max(columns = columns, skipNaN = skipNaN_default) -public fun PivotGroupBy.max(vararg columns: String): DataFrame = max { columns.toComparableColumns() } +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.max(vararg columns: KProperty): DataRow = + max(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Pivot.maxOf( + crossinline rowExpression: RowExpression, +): DataRow = maxOf(skipNaN = skipNaN_default, rowExpression = rowExpression) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Pivot.maxBy( + crossinline rowExpression: RowExpression, +): ReducedPivot = maxBy(skipNaN = skipNaN_default, rowExpression = rowExpression) @AccessApiOverload -public fun > PivotGroupBy.max(vararg columns: ColumnReference): DataFrame = - max { columns.toColumnSet() } +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Pivot.maxBy(column: ColumnReference): ReducedPivot = + maxBy(column, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.maxBy(column: String): ReducedPivot = maxBy(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Pivot.maxBy(column: KProperty): ReducedPivot = + maxBy(column, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.max(separate: Boolean = false): DataFrame = max(separate, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.maxFor( + separate: Boolean = false, + columns: ColumnsForAggregateSelector, +): DataFrame = maxFor(separate, skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.maxFor(vararg columns: String, separate: Boolean = false): DataFrame = + maxFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.maxFor( + vararg columns: ColumnReference, + separate: Boolean = false, +): DataFrame = maxFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.maxFor( + vararg columns: KProperty, + separate: Boolean = false, +): DataFrame = maxFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.max(columns: ColumnsSelector): DataFrame = + max(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.max(vararg columns: String): DataFrame = + max(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.max(vararg columns: ColumnReference): DataFrame = + max(columns = columns, skipNaN = skipNaN_default) @AccessApiOverload -public fun > PivotGroupBy.max(vararg columns: KProperty): DataFrame = - max { columns.toColumnSet() } +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.max(vararg columns: KProperty): DataFrame = + max(columns = columns, skipNaN = skipNaN_default) -public fun > PivotGroupBy.maxOf(rowExpression: RowExpression): DataFrame = - aggregate { maxOf(rowExpression) } +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> PivotGroupBy.maxOf( + crossinline rowExpression: RowExpression, +): DataFrame = maxOf(skipNaN = skipNaN_default, rowExpression = rowExpression) -public fun > PivotGroupBy.maxBy(rowExpression: RowExpression): ReducedPivotGroupBy = - reduce { maxByOrNull(rowExpression) } +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> PivotGroupBy.maxBy( + crossinline rowExpression: RowExpression, +): ReducedPivotGroupBy = maxBy(skipNaN = skipNaN_default, rowExpression = rowExpression) @AccessApiOverload -public fun > PivotGroupBy.maxBy(column: ColumnReference): ReducedPivotGroupBy = - reduce { maxByOrNull(column) } +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> PivotGroupBy.maxBy( + column: ColumnReference, +): ReducedPivotGroupBy = maxBy(column, skipNaN = skipNaN_default) -public fun PivotGroupBy.maxBy(column: String): ReducedPivotGroupBy = - maxBy(column.toColumnAccessor().cast>()) +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.maxBy(column: String): ReducedPivotGroupBy = maxBy(column, skipNaN = skipNaN_default) @AccessApiOverload -public fun > PivotGroupBy.maxBy(column: KProperty): ReducedPivotGroupBy = - maxBy(column.toColumnAccessor()) +@Deprecated(MAX_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> PivotGroupBy.maxBy( + column: KProperty, +): ReducedPivotGroupBy = maxBy(column, skipNaN = skipNaN_default) // endregion diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt index 3ebb607306..accd7a1145 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/mean.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfRow import org.jetbrains.kotlinx.dataframe.impl.aggregation.primitiveOrMixedNumberColumns import org.jetbrains.kotlinx.dataframe.impl.columns.toNumberColumns import org.jetbrains.kotlinx.dataframe.impl.isPrimitiveOrMixedNumber +import org.jetbrains.kotlinx.dataframe.util.MEAN_NO_SKIPNAN import kotlin.reflect.KProperty import kotlin.reflect.typeOf @@ -34,242 +35,441 @@ import kotlin.reflect.typeOf // region DataColumn -public fun DataColumn.mean(skipNA: Boolean = skipNA_default): Double = Aggregators.mean(skipNA).aggregate(this) +public fun DataColumn.mean(skipNaN: Boolean = skipNaN_default): Double = + Aggregators.mean(skipNaN).aggregateSingleColumn(this) public inline fun DataColumn.meanOf( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: (T) -> R?, -): Double = Aggregators.mean(skipNA).aggregateOf(this, expression) +): Double = Aggregators.mean(skipNaN).aggregateOf(this, expression) // endregion // region DataRow -public fun AnyRow.rowMean(skipNA: Boolean = skipNA_default): Double = - Aggregators.mean(skipNA).aggregateOfRow(this, primitiveOrMixedNumberColumns()) +public fun AnyRow.rowMean(skipNaN: Boolean = skipNaN_default): Double = + Aggregators.mean(skipNaN).aggregateOfRow(this, primitiveOrMixedNumberColumns()) -public inline fun AnyRow.rowMeanOf(skipNA: Boolean = skipNA_default): Double { +public inline fun AnyRow.rowMeanOf(skipNaN: Boolean = skipNaN_default): Double { require(typeOf().isPrimitiveOrMixedNumber()) { "Type ${T::class.simpleName} is not a primitive number type. Mean only supports primitive number types." } - return Aggregators.mean(skipNA).aggregateOfRow(this) { colsOf() } + return Aggregators.mean(skipNaN).aggregateOfRow(this) { colsOf() } } // endregion // region DataFrame -public fun DataFrame.mean(skipNA: Boolean = skipNA_default): DataRow = - meanFor(skipNA, primitiveOrMixedNumberColumns()) +public fun DataFrame.mean(skipNaN: Boolean = skipNaN_default): DataRow = + meanFor(skipNaN, primitiveOrMixedNumberColumns()) public fun DataFrame.meanFor( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsForAggregateSelector, -): DataRow = Aggregators.mean(skipNA).aggregateFor(this, columns) +): DataRow = Aggregators.mean(skipNaN).aggregateFor(this, columns) -public fun DataFrame.meanFor(vararg columns: String, skipNA: Boolean = skipNA_default): DataRow = - meanFor(skipNA) { columns.toNumberColumns() } +public fun DataFrame.meanFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + meanFor(skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun DataFrame.meanFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, -): DataRow = meanFor(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = meanFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun DataFrame.meanFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, -): DataRow = meanFor(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = meanFor(skipNaN) { columns.toColumnSet() } public fun DataFrame.mean( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsSelector, -): Double = Aggregators.mean(skipNA).aggregateAll(this, columns) +): Double = Aggregators.mean(skipNaN).aggregateAll(this, columns) -public fun DataFrame.mean(vararg columns: String, skipNA: Boolean = skipNA_default): Double = - mean(skipNA) { columns.toNumberColumns() } +public fun DataFrame.mean(vararg columns: String, skipNaN: Boolean = skipNaN_default): Double = + mean(skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun DataFrame.mean( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, -): Double = mean(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): Double = mean(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun DataFrame.mean(vararg columns: KProperty, skipNA: Boolean = skipNA_default): Double = - mean(skipNA) { columns.toColumnSet() } +public fun DataFrame.mean( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): Double = mean(skipNaN) { columns.toColumnSet() } public inline fun DataFrame.meanOf( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): Double = Aggregators.mean(skipNA).aggregateOf(this, expression) +): Double = Aggregators.mean(skipNaN).aggregateOf(this, expression) // endregion // region GroupBy @Refine @Interpretable("GroupByMean1") -public fun Grouped.mean(skipNA: Boolean = skipNA_default): DataFrame = - meanFor(skipNA, primitiveOrMixedNumberColumns()) +public fun Grouped.mean(skipNaN: Boolean = skipNaN_default): DataFrame = + meanFor(skipNaN, primitiveOrMixedNumberColumns()) @Refine @Interpretable("GroupByMean0") public fun Grouped.meanFor( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.mean(skipNA).aggregateFor(this, columns) +): DataFrame = Aggregators.mean(skipNaN).aggregateFor(this, columns) -public fun Grouped.meanFor(vararg columns: String, skipNA: Boolean = skipNA_default): DataFrame = - meanFor(skipNA) { columns.toNumberColumns() } +public fun Grouped.meanFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + meanFor(skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun Grouped.meanFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun Grouped.meanFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMean0") public fun Grouped.mean( name: String? = null, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsSelector, -): DataFrame = Aggregators.mean(skipNA).aggregateAll(this, name, columns) +): DataFrame = Aggregators.mean(skipNaN).aggregateAll(this, name, columns) public fun Grouped.mean( vararg columns: String, name: String? = null, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(name, skipNA) { columns.toNumberColumns() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(name, skipNaN) { columns.toNumberColumns() } @AccessApiOverload public fun Grouped.mean( vararg columns: ColumnReference, name: String? = null, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(name, skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(name, skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun Grouped.mean( vararg columns: KProperty, name: String? = null, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(name, skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(name, skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMeanOf") public inline fun Grouped.meanOf( name: String? = null, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): DataFrame = Aggregators.mean(skipNA).aggregateOf(this, name, expression) +): DataFrame = Aggregators.mean(skipNaN).aggregateOf(this, name, expression) // endregion // region Pivot -public fun Pivot.mean(skipNA: Boolean = skipNA_default, separate: Boolean = false): DataRow = - meanFor(skipNA, separate, primitiveOrMixedNumberColumns()) +public fun Pivot.mean(skipNaN: Boolean = skipNaN_default, separate: Boolean = false): DataRow = + meanFor(skipNaN, separate, primitiveOrMixedNumberColumns()) public fun Pivot.meanFor( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, columns: ColumnsForAggregateSelector, -): DataRow = delegate { meanFor(skipNA, separate, columns) } +): DataRow = delegate { meanFor(skipNaN, separate, columns) } public fun Pivot.meanFor( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, -): DataRow = meanFor(skipNA, separate) { columns.toNumberColumns() } +): DataRow = meanFor(skipNaN, separate) { columns.toNumberColumns() } @AccessApiOverload public fun Pivot.meanFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, -): DataRow = meanFor(skipNA, separate) { columns.toColumnSet() } +): DataRow = meanFor(skipNaN, separate) { columns.toColumnSet() } @AccessApiOverload public fun Pivot.meanFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, -): DataRow = meanFor(skipNA, separate) { columns.toColumnSet() } +): DataRow = meanFor(skipNaN, separate) { columns.toColumnSet() } public fun Pivot.mean( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsSelector, -): DataRow = delegate { mean(skipNA, columns) } +): DataRow = delegate { mean(skipNaN, columns) } public inline fun Pivot.meanOf( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, crossinline expression: RowExpression, -): DataRow = delegate { meanOf(skipNA, expression) } +): DataRow = delegate { meanOf(skipNaN, expression) } // endregion // region PivotGroupBy -public fun PivotGroupBy.mean(separate: Boolean = false, skipNA: Boolean = skipNA_default): DataFrame = - meanFor(skipNA, separate, primitiveOrMixedNumberColumns()) +public fun PivotGroupBy.mean(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataFrame = + meanFor(skipNaN, separate, primitiveOrMixedNumberColumns()) public fun PivotGroupBy.meanFor( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, separate: Boolean = false, columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.mean(skipNA).aggregateFor(this, separate, columns) +): DataFrame = Aggregators.mean(skipNaN).aggregateFor(this, separate, columns) public fun PivotGroupBy.meanFor( vararg columns: String, separate: Boolean = false, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA, separate) { columns.toNumberColumns() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN, separate) { columns.toNumberColumns() } @AccessApiOverload public fun PivotGroupBy.meanFor( vararg columns: ColumnReference, separate: Boolean = false, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA, separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN, separate) { columns.toColumnSet() } @AccessApiOverload public fun PivotGroupBy.meanFor( vararg columns: KProperty, separate: Boolean = false, - skipNA: Boolean = skipNA_default, -): DataFrame = meanFor(skipNA, separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = meanFor(skipNaN, separate) { columns.toColumnSet() } public fun PivotGroupBy.mean( - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, columns: ColumnsSelector, -): DataFrame = Aggregators.mean(skipNA).aggregateAll(this, columns) +): DataFrame = Aggregators.mean(skipNaN).aggregateAll(this, columns) -public fun PivotGroupBy.mean(vararg columns: String, skipNA: Boolean = skipNA_default): DataFrame = - mean(skipNA) { columns.toColumnsSetOf() } +public fun PivotGroupBy.mean(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + mean(skipNaN) { columns.toColumnsSetOf() } @AccessApiOverload public fun PivotGroupBy.mean( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(skipNaN) { columns.toColumnSet() } @AccessApiOverload public fun PivotGroupBy.mean( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, -): DataFrame = mean(skipNA) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = mean(skipNaN) { columns.toColumnSet() } + +public inline fun PivotGroupBy.meanOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataFrame = Aggregators.mean(skipNaN).aggregateOf(this, expression) + +// endregion + +// region binary compatibility + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataColumn.mean(): Double = mean(skipNaN = skipNaN_default) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun DataColumn.meanOf(crossinline expression: (T) -> R?): Double = + meanOf(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun AnyRow.rowMean(): Double = rowMean(skipNaN = skipNaN_default) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun AnyRow.rowMeanOf(): Double = rowMeanOf(skipNaN = skipNaN_default) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.mean(): DataRow = mean(skipNaN = skipNaN_default) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.meanFor(columns: ColumnsForAggregateSelector): DataRow = + meanFor(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.meanFor(vararg columns: String): DataRow = + meanFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.meanFor(vararg columns: ColumnReference): DataRow = + meanFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.meanFor(vararg columns: KProperty): DataRow = + meanFor(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.mean(columns: ColumnsSelector): Double = + mean(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.mean(vararg columns: String): Double = mean(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.mean(vararg columns: ColumnReference): Double = + mean(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.mean(vararg columns: KProperty): Double = + mean(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun DataFrame.meanOf(crossinline expression: RowExpression): Double = + meanOf(skipNaN = skipNaN_default, expression = expression) + +@Refine +@Interpretable("GroupByMean1") +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.mean(): DataFrame = mean(skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMean0") +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.meanFor(columns: ColumnsForAggregateSelector): DataFrame = + meanFor(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.meanFor(vararg columns: String): DataFrame = + meanFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.meanFor(vararg columns: ColumnReference): DataFrame = + meanFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.meanFor(vararg columns: KProperty): DataFrame = + meanFor(columns = columns, skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMean0") +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.mean(name: String? = null, columns: ColumnsSelector): DataFrame = + mean(name, skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.mean(vararg columns: String, name: String? = null): DataFrame = + mean(columns = columns, name = name, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.mean(vararg columns: ColumnReference, name: String? = null): DataFrame = + mean(columns = columns, name = name, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.mean(vararg columns: KProperty, name: String? = null): DataFrame = + mean(columns = columns, name = name, skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMeanOf") +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun Grouped.meanOf( + name: String? = null, + crossinline expression: RowExpression, +): DataFrame = meanOf(name, skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.mean(separate: Boolean = false): DataRow = + mean(skipNaN = skipNaN_default, separate = separate) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.meanFor( + separate: Boolean = false, + columns: ColumnsForAggregateSelector, +): DataRow = meanFor(skipNaN = skipNaN_default, separate = separate, columns = columns) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.meanFor(vararg columns: String, separate: Boolean = false): DataRow = + meanFor(columns = columns, skipNaN = skipNaN_default, separate = separate) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.meanFor( + vararg columns: ColumnReference, + separate: Boolean = false, +): DataRow = meanFor(columns = columns, skipNaN = skipNaN_default, separate = separate) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.meanFor(vararg columns: KProperty, separate: Boolean = false): DataRow = + meanFor(columns = columns, skipNaN = skipNaN_default, separate = separate) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.mean(columns: ColumnsSelector): DataRow = + mean(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun Pivot.meanOf(crossinline expression: RowExpression): DataRow = + meanOf(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.mean(separate: Boolean = false): DataFrame = mean(separate, skipNaN = skipNaN_default) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.meanFor( + separate: Boolean = false, + columns: ColumnsForAggregateSelector, +): DataFrame = meanFor(skipNaN = skipNaN_default, separate = separate, columns = columns) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.meanFor(vararg columns: String, separate: Boolean = false): DataFrame = + meanFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.meanFor( + vararg columns: ColumnReference, + separate: Boolean = false, +): DataFrame = meanFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.meanFor( + vararg columns: KProperty, + separate: Boolean = false, +): DataFrame = meanFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.mean(columns: ColumnsSelector): DataFrame = + mean(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.mean(vararg columns: String): DataFrame = + mean(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.mean(vararg columns: ColumnReference): DataFrame = + mean(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.mean(vararg columns: KProperty): DataFrame = + mean(columns = columns, skipNaN = skipNaN_default) +@Deprecated(MEAN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public inline fun PivotGroupBy.meanOf( - skipNA: Boolean = skipNA_default, crossinline expression: RowExpression, -): DataFrame = Aggregators.mean(skipNA).aggregateOf(this, expression) +): DataFrame = meanOf(skipNaN = skipNaN_default, expression = expression) // endregion diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt index 0dfd662d1e..bad4fa12da 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/median.kt @@ -13,6 +13,7 @@ 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.aggregation.aggregators.Aggregators +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregateCalculatingValueType import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.cast import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll @@ -27,7 +28,8 @@ import kotlin.reflect.KProperty public fun > DataColumn.median(): T = medianOrNull().suggestIfNull("median") -public fun > DataColumn.medianOrNull(): T? = Aggregators.median.cast().aggregate(this) +public fun > DataColumn.medianOrNull(): T? = + Aggregators.median.cast().aggregateSingleColumn(this) public inline fun > DataColumn.medianOfOrNull(noinline expression: (T) -> R?): R? = Aggregators.median.cast().aggregateOf(this, expression) @@ -40,8 +42,8 @@ public inline fun > DataColumn.medianOf(noinline // region DataRow public fun AnyRow.rowMedianOrNull(): Any? = - Aggregators.median.aggregateCalculatingType( - values = values().filterIsInstance>().asIterable(), + Aggregators.median.aggregateCalculatingValueType( + values = values().asSequence().filterIsInstance>(), valueTypes = df().columns().filter { it.valuesAreComparable() }.map { it.type() }.toSet(), ) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt index c843cc871f..de91140951 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/min.kt @@ -12,295 +12,775 @@ 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.columns.values import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregators import org.jetbrains.kotlinx.dataframe.impl.aggregation.intraComparableColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateAll +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateByOrNull import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateFor -import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfDelegated +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOf +import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfRow import org.jetbrains.kotlinx.dataframe.impl.columns.toComparableColumns -import org.jetbrains.kotlinx.dataframe.impl.indexOfMin import org.jetbrains.kotlinx.dataframe.impl.suggestIfNull +import org.jetbrains.kotlinx.dataframe.util.MIN_NO_SKIPNAN +import org.jetbrains.kotlinx.dataframe.util.ROW_MIN +import org.jetbrains.kotlinx.dataframe.util.ROW_MIN_OR_NULL import kotlin.reflect.KProperty // region DataColumn -public fun > DataColumn.min(): T = minOrNull().suggestIfNull("min") +public fun > DataColumn.min(skipNaN: Boolean = skipNaN_default): T = + minOrNull(skipNaN).suggestIfNull("min") -public fun > DataColumn.minOrNull(): T? = asSequence().filterNotNull().minOrNull() +public fun > DataColumn.minOrNull(skipNaN: Boolean = skipNaN_default): T? = + Aggregators.min(skipNaN).aggregateSingleColumn(this) -public fun > DataColumn.minBy(selector: (T) -> R): T = - minByOrNull(selector).suggestIfNull("minBy") +public inline fun ?> DataColumn.minBy( + skipNaN: Boolean = skipNaN_default, + noinline selector: (T) -> R, +): T & Any = minByOrNull(skipNaN, selector).suggestIfNull("minBy") -public fun > DataColumn.minByOrNull(selector: (T) -> R): T? = values.minByOrNull(selector) +public inline fun ?> DataColumn.minByOrNull( + skipNaN: Boolean = skipNaN_default, + noinline selector: (T) -> R, +): T? = Aggregators.min(skipNaN).aggregateByOrNull(this, selector) -public fun > DataColumn.minOf(selector: (T) -> R): R = - minOfOrNull(selector).suggestIfNull("minOf") +public inline fun ?> DataColumn.minOf( + skipNaN: Boolean = skipNaN_default, + crossinline selector: (T) -> R, +): R & Any = minOfOrNull(skipNaN, selector).suggestIfNull("minOf") -public fun > DataColumn.minOfOrNull(selector: (T) -> R): R? = values.minOfOrNull(selector) +public inline fun ?> DataColumn.minOfOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline selector: (T) -> R, +): R? = Aggregators.min(skipNaN).aggregateOf(this, selector) // endregion // region DataRow -public fun AnyRow.rowMinOrNull(): Any? = values().filterIsInstance>().minWithOrNull(compareBy { it }) +@Deprecated(ROW_MIN_OR_NULL, level = DeprecationLevel.ERROR) +public fun AnyRow.rowMinOrNull(): Any? = error(ROW_MIN_OR_NULL) -public fun AnyRow.rowMin(): Any = rowMinOrNull().suggestIfNull("rowMin") +@Deprecated(ROW_MIN, level = DeprecationLevel.ERROR) +public fun AnyRow.rowMin(): Any = error(ROW_MIN) -public inline fun > AnyRow.rowMinOfOrNull(): T? = values().filterIsInstance().minOrNull() +public inline fun ?> AnyRow.rowMinOfOrNull(skipNaN: Boolean = skipNaN_default): T? = + Aggregators.min(skipNaN).aggregateOfRow(this) { colsOf() } -public inline fun > AnyRow.rowMinOf(): T = rowMinOfOrNull().suggestIfNull("rowMinOf") +public inline fun ?> AnyRow.rowMinOf(skipNaN: Boolean = skipNaN_default): T & Any = + rowMinOfOrNull(skipNaN).suggestIfNull("rowMinOf") // endregion // region DataFrame -public fun DataFrame.min(): DataRow = minFor(intraComparableColumns()) +public fun DataFrame.min(skipNaN: Boolean = skipNaN_default): DataRow = + minFor(skipNaN, intraComparableColumns()) -public fun > DataFrame.minFor(columns: ColumnsForAggregateSelector): DataRow = - Aggregators.min.aggregateFor(this, columns) +public fun ?> DataFrame.minFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = Aggregators.min(skipNaN).aggregateFor(this, columns) -public fun DataFrame.minFor(vararg columns: String): DataRow = minFor { columns.toComparableColumns() } +public fun DataFrame.minFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + minFor(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > DataFrame.minFor(vararg columns: ColumnReference): DataRow = - minFor { columns.toColumnSet() } +public fun ?> DataFrame.minFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > DataFrame.minFor(vararg columns: KProperty): DataRow = - minFor { columns.toColumnSet() } +public fun ?> DataFrame.minFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(skipNaN) { columns.toColumnSet() } -public fun > DataFrame.min(columns: ColumnsSelector): C = - minOrNull(columns).suggestIfNull("min") +public fun ?> DataFrame.min( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): C & Any = minOrNull(skipNaN, columns).suggestIfNull("min") -public fun DataFrame.min(vararg columns: String): Comparable = minOrNull(*columns).suggestIfNull("min") +public fun DataFrame.min(vararg columns: String, skipNaN: Boolean = skipNaN_default): Comparable = + minOrNull(*columns, skipNaN = skipNaN).suggestIfNull("min") @AccessApiOverload -public fun > DataFrame.min(vararg columns: ColumnReference): C = - minOrNull(*columns).suggestIfNull("min") +public fun ?> DataFrame.min( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C & Any = minOrNull(*columns, skipNaN = skipNaN).suggestIfNull("min") @AccessApiOverload -public fun > DataFrame.min(vararg columns: KProperty): C = - minOrNull(*columns).suggestIfNull("min") +public fun ?> DataFrame.min( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): C & Any = minOrNull(*columns, skipNaN = skipNaN).suggestIfNull("min") -public fun > DataFrame.minOrNull(columns: ColumnsSelector): C? = - Aggregators.min.aggregateAll(this, columns) as C? +public fun ?> DataFrame.minOrNull( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): C? = Aggregators.min(skipNaN).aggregateAll(this, columns) -public fun DataFrame.minOrNull(vararg columns: String): Comparable? = - minOrNull { columns.toComparableColumns() } +public fun DataFrame.minOrNull(vararg columns: String, skipNaN: Boolean = skipNaN_default): Comparable? = + minOrNull(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > DataFrame.minOrNull(vararg columns: ColumnReference): C? = - minOrNull { columns.toColumnSet() } +public fun ?> DataFrame.minOrNull( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C? = minOrNull(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > DataFrame.minOrNull(vararg columns: KProperty): C? = - minOrNull { columns.toColumnSet() } +public fun ?> DataFrame.minOrNull( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): C? = minOrNull(skipNaN) { columns.toColumnSet() } -public fun > DataFrame.minOf(expression: RowExpression): C = - minOfOrNull(expression).suggestIfNull("minOf") +public inline fun ?> DataFrame.minOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C & Any = minOfOrNull(skipNaN, expression).suggestIfNull("minOf") -public fun > DataFrame.minOfOrNull(expression: RowExpression): C? = - rows().minOfOrNull { expression(it, it) } +public inline fun ?> DataFrame.minOfOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C? = Aggregators.min(skipNaN).aggregateOf(this, expression) -public fun > DataFrame.minBy(expression: RowExpression): DataRow = - minByOrNull(expression).suggestIfNull("minBy") +public inline fun ?> DataFrame.minBy( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow = minByOrNull(skipNaN, expression).suggestIfNull("minBy") -public fun DataFrame.minBy(column: String): DataRow = minByOrNull(column).suggestIfNull("minBy") +public fun DataFrame.minBy(column: String, skipNaN: Boolean = skipNaN_default): DataRow = + minByOrNull(column, skipNaN).suggestIfNull("minBy") @AccessApiOverload -public fun > DataFrame.minBy(column: ColumnReference): DataRow = - minByOrNull(column).suggestIfNull("minBy") +public inline fun ?> DataFrame.minBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = minByOrNull(column, skipNaN).suggestIfNull("minBy") @AccessApiOverload -public fun > DataFrame.minBy(column: KProperty): DataRow = - minByOrNull(column).suggestIfNull("minBy") +public inline fun ?> DataFrame.minBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = minByOrNull(column, skipNaN).suggestIfNull("minBy") -public fun > DataFrame.minByOrNull(expression: RowExpression): DataRow? = - getOrNull(rows().asSequence().map { expression(it, it) }.indexOfMin()) +public inline fun ?> DataFrame.minByOrNull( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow? = Aggregators.min(skipNaN).aggregateByOrNull(this, expression) -public fun DataFrame.minByOrNull(column: String): DataRow? = - minByOrNull(column.toColumnOf?>()) +public fun DataFrame.minByOrNull(column: String, skipNaN: Boolean = skipNaN_default): DataRow? = + minByOrNull(column.toColumnOf?>(), skipNaN) @AccessApiOverload -public fun > DataFrame.minByOrNull(column: ColumnReference): DataRow? = - getOrNull(get(column).asSequence().indexOfMin()) +public inline fun ?> DataFrame.minByOrNull( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow? = Aggregators.min(skipNaN).aggregateByOrNull(this, column) @AccessApiOverload -public fun > DataFrame.minByOrNull(column: KProperty): DataRow? = - minByOrNull(column.toColumnAccessor()) +public inline fun ?> DataFrame.minByOrNull( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow? = minByOrNull(column.toColumnAccessor(), skipNaN) // endregion // region GroupBy + @Refine @Interpretable("GroupByMin1") -public fun Grouped.min(): DataFrame = minFor(intraComparableColumns()) +public fun Grouped.min(skipNaN: Boolean = skipNaN_default): DataFrame = + minFor(skipNaN, intraComparableColumns()) @Refine @Interpretable("GroupByMin0") -public fun > Grouped.minFor(columns: ColumnsForAggregateSelector): DataFrame = - Aggregators.min.aggregateFor(this, columns) +public fun ?> Grouped.minFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.min(skipNaN).aggregateFor(this, columns) -public fun Grouped.minFor(vararg columns: String): DataFrame = minFor { columns.toComparableColumns() } +public fun Grouped.minFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + minFor(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Grouped.minFor(vararg columns: ColumnReference): DataFrame = - minFor { columns.toColumnSet() } +public fun ?> Grouped.minFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Grouped.minFor(vararg columns: KProperty): DataFrame = - minFor { columns.toColumnSet() } +public fun ?> Grouped.minFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMin0") -public fun > Grouped.min(name: String? = null, columns: ColumnsSelector): DataFrame = - Aggregators.min.aggregateAll(this, name, columns) +public fun ?> Grouped.min( + name: String? = null, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.min(skipNaN).aggregateAll(this, name, columns) -public fun Grouped.min(vararg columns: String, name: String? = null): DataFrame = - min(name) { columns.toComparableColumns() } +public fun Grouped.min( + vararg columns: String, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(name, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Grouped.min( - vararg columns: ColumnReference, +public fun ?> Grouped.min( + vararg columns: ColumnReference, name: String? = null, -): DataFrame = min(name) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(name, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Grouped.min(vararg columns: KProperty, name: String? = null): DataFrame = - min(name) { columns.toColumnSet() } +public fun ?> Grouped.min( + vararg columns: KProperty, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(name, skipNaN) { columns.toColumnSet() } @Refine @Interpretable("GroupByMinOf") -public fun > Grouped.minOf( +public inline fun ?> Grouped.minOf( name: String? = null, - expression: RowExpression, -): DataFrame = Aggregators.min.aggregateOfDelegated(this, name) { minOfOrNull(expression) } + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataFrame = Aggregators.min(skipNaN).aggregateOf(this, name, expression) @Interpretable("GroupByReduceExpression") -public fun > GroupBy.minBy(rowExpression: RowExpression): ReducedGroupBy = - reduce { minByOrNull(rowExpression) } +public inline fun ?> GroupBy.minBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedGroupBy = reduce { minByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > GroupBy.minBy(column: ColumnReference): ReducedGroupBy = - reduce { minByOrNull(column) } +public inline fun ?> GroupBy.minBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedGroupBy = reduce { minByOrNull(column, skipNaN) } -public fun GroupBy.minBy(column: String): ReducedGroupBy = - minBy(column.toColumnAccessor().cast>()) +public fun GroupBy.minBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedGroupBy = + minBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > GroupBy.minBy(column: KProperty): ReducedGroupBy = - minBy(column.toColumnAccessor()) +public inline fun ?> GroupBy.minBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedGroupBy = minBy(column.toColumnAccessor(), skipNaN) // endregion // region Pivot -public fun Pivot.min(separate: Boolean = false): DataRow = delegate { min(separate) } +public fun Pivot.min(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataRow = + delegate { min(separate, skipNaN) } -public fun > Pivot.minFor( +public fun ?> Pivot.minFor( separate: Boolean = false, - columns: ColumnsForAggregateSelector, -): DataRow = delegate { minFor(separate, columns) } + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = delegate { minFor(separate, skipNaN, columns) } -public fun Pivot.minFor(vararg columns: String, separate: Boolean = false): DataRow = - minFor(separate) { columns.toComparableColumns() } +public fun Pivot.minFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(separate, skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Pivot.minFor( - vararg columns: ColumnReference, +public fun ?> Pivot.minFor( + vararg columns: ColumnReference, separate: Boolean = false, -): DataRow = minFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(separate, skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Pivot.minFor( - vararg columns: KProperty, +public fun ?> Pivot.minFor( + vararg columns: KProperty, separate: Boolean = false, -): DataRow = minFor(separate) { columns.toColumnSet() } + skipNaN: Boolean = skipNaN_default, +): DataRow = minFor(separate, skipNaN) { columns.toColumnSet() } -public fun > Pivot.min(columns: ColumnsSelector): DataRow = delegate { min(columns) } +public fun ?> Pivot.min( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataRow = delegate { min(skipNaN, columns) } -public fun > Pivot.min(vararg columns: String): DataRow = - min { columns.toComparableColumns() } +public fun ?> Pivot.min( + vararg columns: String, + skipNaN: Boolean = skipNaN_default, +): DataRow = min(skipNaN) { columns.toComparableColumns() } @AccessApiOverload -public fun > Pivot.min(vararg columns: ColumnReference): DataRow = - min { columns.toColumnSet() } +public fun ?> Pivot.min( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = min(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun > Pivot.min(vararg columns: KProperty): DataRow = - min { columns.toColumnSet() } +public fun ?> Pivot.min( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = min(skipNaN) { columns.toColumnSet() } -public fun > Pivot.minOf(rowExpression: RowExpression): DataRow = - delegate { minOf(rowExpression) } +public inline fun ?> Pivot.minOf( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): DataRow = delegate { minOf(skipNaN, rowExpression) } -public fun > Pivot.minBy(rowExpression: RowExpression): ReducedPivot = - reduce { minByOrNull(rowExpression) } +public inline fun ?> Pivot.minBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedPivot = reduce { minByOrNull(skipNaN, rowExpression) } @AccessApiOverload -public fun > Pivot.minBy(column: ColumnReference): ReducedPivot = - reduce { minByOrNull(column) } +public inline fun ?> Pivot.minBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedPivot = reduce { minByOrNull(column, skipNaN) } -public fun Pivot.minBy(column: String): ReducedPivot = - minBy(column.toColumnAccessor().cast>()) +public fun Pivot.minBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedPivot = + minBy(column.toColumnAccessor().cast?>(), skipNaN) @AccessApiOverload -public fun > Pivot.minBy(column: KProperty): ReducedPivot = - minBy(column.toColumnAccessor()) +public inline fun ?> Pivot.minBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedPivot = minBy(column.toColumnAccessor(), skipNaN) // endregion // region PivotGroupBy -public fun PivotGroupBy.min(separate: Boolean = false): DataFrame = minFor(separate, intraComparableColumns()) +public fun PivotGroupBy.min(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataFrame = + minFor(separate, skipNaN, intraComparableColumns()) + +public fun ?> PivotGroupBy.minFor( + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.min(skipNaN).aggregateFor(this, separate, columns) + +public fun PivotGroupBy.minFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(separate, skipNaN) { columns.toComparableColumns() } + +@AccessApiOverload +public fun ?> PivotGroupBy.minFor( + vararg columns: ColumnReference, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(separate, skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun ?> PivotGroupBy.minFor( + vararg columns: KProperty, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = minFor(separate, skipNaN) { columns.toColumnSet() } + +public fun ?> PivotGroupBy.min( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.min(skipNaN).aggregateAll(this, columns) + +public fun PivotGroupBy.min(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + min(skipNaN) { columns.toComparableColumns() } + +public fun ?> PivotGroupBy.min( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun ?> PivotGroupBy.min( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = min(skipNaN) { columns.toColumnSet() } + +public inline fun ?> PivotGroupBy.minOf( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): DataFrame = aggregate { minOf(skipNaN, rowExpression) } + +public inline fun ?> PivotGroupBy.minBy( + skipNaN: Boolean = skipNaN_default, + crossinline rowExpression: RowExpression, +): ReducedPivotGroupBy = reduce { minByOrNull(skipNaN, rowExpression) } + +@AccessApiOverload +public inline fun ?> PivotGroupBy.minBy( + column: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): ReducedPivotGroupBy = reduce { minByOrNull(column, skipNaN) } + +public fun PivotGroupBy.minBy(column: String, skipNaN: Boolean = skipNaN_default): ReducedPivotGroupBy = + minBy(column.toColumnAccessor().cast?>(), skipNaN) + +@AccessApiOverload +public inline fun ?> PivotGroupBy.minBy( + column: KProperty, + skipNaN: Boolean = skipNaN_default, +): ReducedPivotGroupBy = minBy(column.toColumnAccessor(), skipNaN) + +// endregion + +// region binary compatibility + +@Suppress("UNCHECKED_CAST") +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun > DataColumn.min(): T = min(skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun > DataColumn.minOrNull(): T? = minOrNull(skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataColumn.minBy(noinline selector: (T) -> R): T & Any = + minBy(skipNaN = skipNaN_default, selector = selector) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataColumn.minByOrNull(noinline selector: (T) -> R): T? = + minByOrNull(skipNaN = skipNaN_default, selector = selector) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataColumn.minOf(crossinline selector: (T) -> R): R & Any = + minOf(skipNaN = skipNaN_default, selector = selector) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataColumn.minOfOrNull(crossinline selector: (T) -> R): R? = + minOfOrNull(skipNaN = skipNaN_default, selector = selector) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> AnyRow.rowMinOfOrNull(): T? = + rowMinOfOrNull(skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> AnyRow.rowMinOf(): T & Any = rowMinOf(skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.min(): DataRow = min(skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.minFor(columns: ColumnsForAggregateSelector): DataRow = + minFor(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.minFor(vararg columns: String): DataRow = + minFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.minFor(vararg columns: ColumnReference): DataRow = + minFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.minFor(vararg columns: KProperty): DataRow = + minFor(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.min(columns: ColumnsSelector): C & Any = + min(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.min(vararg columns: String): Comparable = + min(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.min(vararg columns: ColumnReference): C & Any = + min(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.min(vararg columns: KProperty): C & Any = + min(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.minOrNull(columns: ColumnsSelector): C? = + minOrNull(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.minOrNull(vararg columns: String): Comparable? = + minOrNull(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.minOrNull(vararg columns: ColumnReference): C? = + minOrNull(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> DataFrame.minOrNull(vararg columns: KProperty): C? = + minOrNull(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.minOf( + crossinline expression: RowExpression, +): C & Any = minOf(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.minOfOrNull( + crossinline expression: RowExpression, +): C? = minOfOrNull(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.minBy( + crossinline expression: RowExpression, +): DataRow = minBy(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.minBy(column: String): DataRow = minBy(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.minBy(column: ColumnReference): DataRow = + minBy(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.minBy(column: KProperty): DataRow = + minBy(column, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.minByOrNull( + crossinline expression: RowExpression, +): DataRow? = minByOrNull(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.minByOrNull(column: String): DataRow? = minByOrNull(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.minByOrNull( + column: ColumnReference, +): DataRow? = minByOrNull(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> DataFrame.minByOrNull(column: KProperty): DataRow? = + minByOrNull(column, skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMin1") +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.min(): DataFrame = min(skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMin0") +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.minFor(columns: ColumnsForAggregateSelector): DataFrame = + minFor(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.minFor(vararg columns: String): DataFrame = + minFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.minFor(vararg columns: ColumnReference): DataFrame = + minFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.minFor(vararg columns: KProperty): DataFrame = + minFor(columns = columns, skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMin0") +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.min( + name: String? = null, + columns: ColumnsSelector, +): DataFrame = min(name, skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.min(vararg columns: String, name: String? = null): DataFrame = + min(columns = columns, name = name, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.min( + vararg columns: ColumnReference, + name: String? = null, +): DataFrame = min(columns = columns, name = name, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Grouped.min( + vararg columns: KProperty, + name: String? = null, +): DataFrame = min(columns = columns, name = name, skipNaN = skipNaN_default) + +@Refine +@Interpretable("GroupByMinOf") +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Grouped.minOf( + name: String? = null, + crossinline expression: RowExpression, +): DataFrame = minOf(name, skipNaN = skipNaN_default, expression = expression) + +@Interpretable("GroupByReduceExpression") +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> GroupBy.minBy( + crossinline rowExpression: RowExpression, +): ReducedGroupBy = minBy(skipNaN = skipNaN_default, rowExpression = rowExpression) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> GroupBy.minBy( + column: ColumnReference, +): ReducedGroupBy = minBy(column, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun GroupBy.minBy(column: String): ReducedGroupBy = minBy(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> GroupBy.minBy( + column: KProperty, +): ReducedGroupBy = minBy(column, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.min(separate: Boolean = false): DataRow = min(separate, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.minFor( + separate: Boolean = false, + columns: ColumnsForAggregateSelector, +): DataRow = minFor(separate, skipNaN = skipNaN_default, columns = columns) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.minFor(vararg columns: String, separate: Boolean = false): DataRow = + minFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.minFor( + vararg columns: ColumnReference, + separate: Boolean = false, +): DataRow = minFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.minFor( + vararg columns: KProperty, + separate: Boolean = false, +): DataRow = minFor(columns = columns, separate = separate, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.min(columns: ColumnsSelector): DataRow = + min(skipNaN = skipNaN_default, columns = columns) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.min(vararg columns: ColumnReference): DataRow = + min(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> Pivot.min(vararg columns: KProperty): DataRow = + min(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Pivot.minOf( + crossinline rowExpression: RowExpression, +): DataRow = minOf(skipNaN = skipNaN_default, rowExpression = rowExpression) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Pivot.minBy( + crossinline rowExpression: RowExpression, +): ReducedPivot = minBy(skipNaN = skipNaN_default, rowExpression = rowExpression) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Pivot.minBy(column: ColumnReference): ReducedPivot = + minBy(column, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.minBy(column: String): ReducedPivot = minBy(column, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> Pivot.minBy(column: KProperty): ReducedPivot = + minBy(column, skipNaN = skipNaN_default) + +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.min(separate: Boolean = false): DataFrame = min(separate, skipNaN = skipNaN_default) -public fun > PivotGroupBy.minFor( +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.minFor( separate: Boolean = false, - columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.min.aggregateFor(this, separate, columns) + columns: ColumnsForAggregateSelector, +): DataFrame = minFor(separate, skipNaN = skipNaN_default, columns = columns) +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun PivotGroupBy.minFor(vararg columns: String, separate: Boolean = false): DataFrame = - minFor(separate) { columns.toComparableColumns() } + minFor(columns = columns, separate = separate, skipNaN = skipNaN_default) @AccessApiOverload -public fun > PivotGroupBy.minFor( - vararg columns: ColumnReference, +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.minFor( + vararg columns: ColumnReference, separate: Boolean = false, -): DataFrame = minFor(separate) { columns.toColumnSet() } +): DataFrame = minFor(columns = columns, separate = separate, skipNaN = skipNaN_default) @AccessApiOverload -public fun > PivotGroupBy.minFor( - vararg columns: KProperty, +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.minFor( + vararg columns: KProperty, separate: Boolean = false, -): DataFrame = minFor(separate) { columns.toColumnSet() } +): DataFrame = minFor(columns = columns, separate = separate, skipNaN = skipNaN_default) -public fun > PivotGroupBy.min(columns: ColumnsSelector): DataFrame = - Aggregators.min.aggregateAll(this, columns) +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.min(columns: ColumnsSelector): DataFrame = + min(skipNaN = skipNaN_default, columns = columns) -public fun PivotGroupBy.min(vararg columns: String): DataFrame = min { columns.toComparableColumns() } +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.min(vararg columns: String): DataFrame = + min(columns = columns, skipNaN = skipNaN_default) -public fun > PivotGroupBy.min(vararg columns: ColumnReference): DataFrame = - min { columns.toColumnSet() } +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.min(vararg columns: ColumnReference): DataFrame = + min(columns = columns, skipNaN = skipNaN_default) @AccessApiOverload -public fun > PivotGroupBy.min(vararg columns: KProperty): DataFrame = - min { columns.toColumnSet() } +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun ?> PivotGroupBy.min(vararg columns: KProperty): DataFrame = + min(columns = columns, skipNaN = skipNaN_default) -public fun > PivotGroupBy.minOf(rowExpression: RowExpression): DataFrame = - aggregate { minOf(rowExpression) } +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> PivotGroupBy.minOf( + crossinline rowExpression: RowExpression, +): DataFrame = minOf(skipNaN = skipNaN_default, rowExpression = rowExpression) -public fun > PivotGroupBy.minBy(rowExpression: RowExpression): ReducedPivotGroupBy = - reduce { minByOrNull(rowExpression) } +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> PivotGroupBy.minBy( + crossinline rowExpression: RowExpression, +): ReducedPivotGroupBy = minBy(skipNaN = skipNaN_default, rowExpression = rowExpression) @AccessApiOverload -public fun > PivotGroupBy.minBy(column: ColumnReference): ReducedPivotGroupBy = - reduce { minByOrNull(column) } +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> PivotGroupBy.minBy( + column: ColumnReference, +): ReducedPivotGroupBy = minBy(column, skipNaN = skipNaN_default) -public fun PivotGroupBy.minBy(column: String): ReducedPivotGroupBy = - minBy(column.toColumnAccessor().cast>()) +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.minBy(column: String): ReducedPivotGroupBy = minBy(column, skipNaN = skipNaN_default) @AccessApiOverload -public fun > PivotGroupBy.minBy(column: KProperty): ReducedPivotGroupBy = - minBy(column.toColumnAccessor()) +@Deprecated(MIN_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun ?> PivotGroupBy.minBy( + column: KProperty, +): ReducedPivotGroupBy = minBy(column, skipNaN = skipNaN_default) // endregion diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt index 421817eeb7..7a78adb04a 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/percentile.kt @@ -27,7 +27,7 @@ public fun > DataColumn.percentile(percentile: Double): T percentileOrNull(percentile).suggestIfNull("percentile") public fun > DataColumn.percentileOrNull(percentile: Double): T? = - Aggregators.percentile(percentile).cast().aggregate(this) + Aggregators.percentile(percentile).cast().aggregateSingleColumn(this) public inline fun > DataColumn.percentileOfOrNull( percentile: Double, @@ -44,7 +44,7 @@ public inline fun > DataColumn.percentileOf( // region DataRow public fun AnyRow.rowPercentileOrNull(percentile: Double): Any? = - Aggregators.percentile(percentile).aggregate( + Aggregators.percentile(percentile).aggregateSingleColumn( values().filterIsInstance>().toValueColumn(), ) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/pivot.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/pivot.kt index 03dfaa0610..383be1bbb5 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/pivot.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/pivot.kt @@ -243,6 +243,7 @@ public class ReducedPivot( override fun toString(): String = "ReducedPivot(pivot=$pivot, reducer=$reducer)" } +@PublishedApi internal fun Pivot.reduce(reducer: Selector, DataRow?>) = ReducedPivot(this, reducer) @PublishedApi diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt index 6ff20f4795..a28f781a90 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/std.kt @@ -25,20 +25,20 @@ import kotlin.reflect.typeOf // region DataColumn -public fun DataColumn.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): Double = - Aggregators.std(skipNA, ddof).aggregate(this) ?: .0 +public fun DataColumn.std(skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default): Double = + Aggregators.std(skipNA, ddof).aggregateSingleColumn(this) public inline fun DataColumn.stdOf( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, noinline expression: (T) -> R?, -): Double = Aggregators.std(skipNA, ddof).cast2().aggregateOf(this, expression) ?: .0 +): Double = Aggregators.std(skipNA, ddof).cast2().aggregateOf(this, expression) // endregion // region DataRow -public fun AnyRow.rowStd(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): Double = +public fun AnyRow.rowStd(skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default): Double = values().filterIsInstance().map { it.toDouble() }.std(skipNA, ddof) public inline fun AnyRow.rowStdOf(ddof: Int = ddof_default): Double = @@ -53,39 +53,39 @@ public inline fun AnyRow.rowStdOf(ddof: Int = ddof_default) // region DataFrame -public fun DataFrame.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): DataRow = +public fun DataFrame.std(skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default): DataRow = stdFor(skipNA, ddof, numberColumns()) public fun DataFrame.stdFor( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsForAggregateSelector, ): DataRow = Aggregators.std(skipNA, ddof).aggregateFor(this, columns) public fun DataFrame.stdFor( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(skipNA, ddof) { columns.toColumnsSetOf() } public fun DataFrame.stdFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(skipNA, ddof) { columns.toColumnSet() } @AccessApiOverload public fun DataFrame.stdFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(skipNA, ddof) { columns.toColumnSet() } public fun DataFrame.std( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsSelector, -): Double = Aggregators.std(skipNA, ddof).aggregateAll(this, columns) ?: .0 +): Double = Aggregators.std(skipNA, ddof).aggregateAll(this, columns) public fun DataFrame.std(vararg columns: ColumnReference): Double = std { columns.toColumnSet() } @@ -95,44 +95,44 @@ public fun DataFrame.std(vararg columns: String): Double = std { columns. public fun DataFrame.std(vararg columns: KProperty): Double = std { columns.toColumnSet() } public inline fun DataFrame.stdOf( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, crossinline expression: RowExpression, -): Double = Aggregators.std(skipNA, ddof).aggregateOf(this, expression) ?: .0 +): Double = Aggregators.std(skipNA, ddof).aggregateOf(this, expression) // endregion // region GroupBy @Refine @Interpretable("GroupByStd1") -public fun Grouped.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): DataFrame = +public fun Grouped.std(skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default): DataFrame = stdFor(skipNA, ddof, numberColumns()) @Refine @Interpretable("GroupByStd0") public fun Grouped.stdFor( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateFor(this, columns) public fun Grouped.stdFor( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(skipNA, ddof) { columns.toColumnsSetOf() } @AccessApiOverload public fun Grouped.stdFor( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(skipNA, ddof) { columns.toColumnSet() } @AccessApiOverload public fun Grouped.stdFor( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(skipNA, ddof) { columns.toColumnSet() } @@ -140,7 +140,7 @@ public fun Grouped.stdFor( @Interpretable("GroupByStd0") public fun Grouped.std( name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsSelector, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateAll(this, name, columns) @@ -149,14 +149,14 @@ public fun Grouped.std( public fun Grouped.std( vararg columns: ColumnReference, name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(name, skipNA, ddof) { columns.toColumnSet() } public fun Grouped.std( vararg columns: String, name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(name, skipNA, ddof) { columns.toColumnsSetOf() } @@ -164,7 +164,7 @@ public fun Grouped.std( public fun Grouped.std( vararg columns: KProperty, name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(name, skipNA, ddof) { columns.toColumnSet() } @@ -172,7 +172,7 @@ public fun Grouped.std( @Interpretable("GroupByStdOf") public inline fun Grouped.stdOf( name: String? = null, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, crossinline expression: RowExpression, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateOf(this, name, expression) @@ -183,13 +183,13 @@ public inline fun Grouped.stdOf( public fun Pivot.std( separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(separate, skipNA, ddof, numberColumns()) public fun Pivot.stdFor( separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsForAggregateSelector, ): DataRow = delegate { stdFor(separate, skipNA, ddof, columns) } @@ -197,14 +197,14 @@ public fun Pivot.stdFor( public fun Pivot.stdFor( vararg columns: String, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(separate, skipNA, ddof) { columns.toColumnsSetOf() } public fun Pivot.stdFor( vararg columns: ColumnReference, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(separate, skipNA, ddof) { columns.toColumnSet() } @@ -212,37 +212,37 @@ public fun Pivot.stdFor( public fun Pivot.stdFor( vararg columns: KProperty, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = stdFor(separate, skipNA, ddof) { columns.toColumnSet() } public fun Pivot.std( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsSelector, ): DataRow = delegate { std(skipNA, ddof, columns) } public fun Pivot.std( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = std(skipNA, ddof) { columns.toColumnSet() } public fun Pivot.std( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = std(skipNA, ddof) { columns.toColumnsSetOf() } @AccessApiOverload public fun Pivot.std( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataRow = std(skipNA, ddof) { columns.toColumnSet() } public inline fun Pivot.stdOf( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, crossinline expression: RowExpression, ): DataRow = delegate { stdOf(skipNA, ddof, expression) } @@ -253,13 +253,13 @@ public inline fun Pivot.stdOf( public fun PivotGroupBy.std( separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(separate, skipNA, ddof, numberColumns()) public fun PivotGroupBy.stdFor( separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsForAggregateSelector, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateFor(this, separate, columns) @@ -267,7 +267,7 @@ public fun PivotGroupBy.stdFor( public fun PivotGroupBy.stdFor( vararg columns: String, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(separate, skipNA, ddof) { columns.toColumnsSetOf() } @@ -275,7 +275,7 @@ public fun PivotGroupBy.stdFor( public fun PivotGroupBy.stdFor( vararg columns: ColumnReference, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(separate, skipNA, ddof) { columns.toColumnSet() } @@ -283,12 +283,12 @@ public fun PivotGroupBy.stdFor( public fun PivotGroupBy.stdFor( vararg columns: KProperty, separate: Boolean = false, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = stdFor(separate, skipNA, ddof) { columns.toColumnSet() } public fun PivotGroupBy.std( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, columns: ColumnsSelector, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateAll(this, columns) @@ -296,25 +296,25 @@ public fun PivotGroupBy.std( @AccessApiOverload public fun PivotGroupBy.std( vararg columns: ColumnReference, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(skipNA, ddof) { columns.toColumnSet() } public fun PivotGroupBy.std( vararg columns: String, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(skipNA, ddof) { columns.toColumnsSetOf() } @AccessApiOverload public fun PivotGroupBy.std( vararg columns: KProperty, - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, ): DataFrame = std(skipNA, ddof) { columns.toColumnSet() } public inline fun PivotGroupBy.stdOf( - skipNA: Boolean = skipNA_default, + skipNA: Boolean = skipNaN_default, ddof: Int = ddof_default, crossinline expression: RowExpression, ): DataFrame = Aggregators.std(skipNA, ddof).aggregateOf(this, expression) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt index c786320ac8..491785d536 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/sum.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.modes.aggregateOfRow import org.jetbrains.kotlinx.dataframe.impl.aggregation.primitiveOrMixedNumberColumns import org.jetbrains.kotlinx.dataframe.impl.columns.toNumberColumns import org.jetbrains.kotlinx.dataframe.impl.isPrimitiveOrMixedNumber +import org.jetbrains.kotlinx.dataframe.util.SUM_NO_SKIPNAN import kotlin.experimental.ExperimentalTypeInference import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -42,99 +43,118 @@ import kotlin.reflect.typeOf // region DataColumn @JvmName("sumShort") -public fun DataColumn.sum(): Int = Aggregators.sum.aggregate(this) as Int +public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingleColumn(this) as Int @JvmName("sumByte") -public fun DataColumn.sum(): Int = Aggregators.sum.aggregate(this) as Int +public fun DataColumn.sum(): Int = Aggregators.sum(false).aggregateSingleColumn(this) as Int @Suppress("UNCHECKED_CAST") @JvmName("sumNumber") -public fun DataColumn.sum(): T = Aggregators.sum.aggregate(this) as T +public fun DataColumn.sum(skipNaN: Boolean = skipNaN_default): T = + Aggregators.sum(skipNaN).aggregateSingleColumn(this) as T @JvmName("sumOfShort") @OverloadResolutionByLambdaReturnType public fun DataColumn.sumOf(expression: (C) -> Short?): Int = - Aggregators.sum.aggregateOf(this, expression) as Int + Aggregators.sum(false).aggregateOf(this, expression) as Int @JvmName("sumOfByte") @OverloadResolutionByLambdaReturnType -public fun DataColumn.sumOf(expression: (C) -> Byte?): Int = Aggregators.sum.aggregateOf(this, expression) as Int +public fun DataColumn.sumOf(expression: (C) -> Byte?): Int = + Aggregators.sum(false).aggregateOf(this, expression) as Int @JvmName("sumOfNumber") @OverloadResolutionByLambdaReturnType -public inline fun DataColumn.sumOf(crossinline expression: (C) -> V?): V = - Aggregators.sum.aggregateOf(this, expression) as V +public inline fun DataColumn.sumOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: (C) -> V?, +): V = Aggregators.sum(skipNaN).aggregateOf(this, expression) as V // endregion // region DataRow -public fun AnyRow.rowSum(): Number = Aggregators.sum.aggregateOfRow(this, primitiveOrMixedNumberColumns()) +public fun AnyRow.rowSum(skipNaN: Boolean = skipNaN_default): Number = + Aggregators.sum(skipNaN).aggregateOfRow(this, primitiveOrMixedNumberColumns()) @JvmName("rowSumOfShort") public inline fun AnyRow.rowSumOf(_kClass: KClass = Short::class): Int = - rowSumOf(typeOf()) as Int + rowSumOf(typeOf(), false) as Int @JvmName("rowSumOfByte") public inline fun AnyRow.rowSumOf(_kClass: KClass = Byte::class): Int = - rowSumOf(typeOf()) as Int + rowSumOf(typeOf(), false) as Int @JvmName("rowSumOfInt") public inline fun AnyRow.rowSumOf(_kClass: KClass = Int::class): Int = - rowSumOf(typeOf()) as Int + rowSumOf(typeOf(), false) as Int @JvmName("rowSumOfLong") public inline fun AnyRow.rowSumOf(_kClass: KClass = Long::class): Long = - rowSumOf(typeOf()) as Long + rowSumOf(typeOf(), false) as Long @JvmName("rowSumOfFloat") -public inline fun AnyRow.rowSumOf(_kClass: KClass = Float::class): Float = - rowSumOf(typeOf()) as Float +public inline fun AnyRow.rowSumOf( + skipNaN: Boolean = skipNaN_default, + _kClass: KClass = Float::class, +): Float = rowSumOf(typeOf(), skipNaN) as Float @JvmName("rowSumOfDouble") -public inline fun AnyRow.rowSumOf(_kClass: KClass = Double::class): Double = - rowSumOf(typeOf()) as Double +public inline fun AnyRow.rowSumOf( + skipNaN: Boolean = skipNaN_default, + _kClass: KClass = Double::class, +): Double = rowSumOf(typeOf(), skipNaN) as Double // unfortunately, we cannot make a `reified T : Number?` due to clashes -public fun AnyRow.rowSumOf(type: KType): Number { +public fun AnyRow.rowSumOf(type: KType, skipNaN: Boolean = skipNaN_default): Number { require(type.isPrimitiveOrMixedNumber()) { "Type $type is not a primitive number type. Mean only supports primitive number types." } - return Aggregators.sum.aggregateOfRow(this) { colsOf(type) } + return Aggregators.sum(skipNaN).aggregateOfRow(this) { colsOf(type) } } // endregion // region DataFrame -public fun DataFrame.sum(): DataRow = sumFor(primitiveOrMixedNumberColumns()) +public fun DataFrame.sum(skipNaN: Boolean = skipNaN_default): DataRow = + sumFor(skipNaN, primitiveOrMixedNumberColumns()) -public fun DataFrame.sumFor(columns: ColumnsForAggregateSelector): DataRow = - Aggregators.sum.aggregateFor(this, columns) +public fun DataFrame.sumFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = Aggregators.sum(skipNaN).aggregateFor(this, columns) -public fun DataFrame.sumFor(vararg columns: String): DataRow = sumFor { columns.toColumnsSetOf() } +public fun DataFrame.sumFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + sumFor(skipNaN) { columns.toColumnsSetOf() } @AccessApiOverload -public fun DataFrame.sumFor(vararg columns: ColumnReference): DataRow = - sumFor { columns.toColumnSet() } +public fun DataFrame.sumFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(skipNaN) { columns.toColumnSet() } @AccessApiOverload -public fun DataFrame.sumFor(vararg columns: KProperty): DataRow = - sumFor { columns.toColumnSet() } +public fun DataFrame.sumFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(skipNaN) { columns.toColumnSet() } @JvmName("sumShort") @OverloadResolutionByLambdaReturnType public fun DataFrame.sum(columns: ColumnsSelector): Int = - Aggregators.sum.aggregateAll(this, columns) as Int + Aggregators.sum(false).aggregateAll(this, columns) as Int @JvmName("sumByte") @OverloadResolutionByLambdaReturnType public fun DataFrame.sum(columns: ColumnsSelector): Int = - Aggregators.sum.aggregateAll(this, columns) as Int + Aggregators.sum(false).aggregateAll(this, columns) as Int @JvmName("sumNumber") @OverloadResolutionByLambdaReturnType -public inline fun DataFrame.sum(noinline columns: ColumnsSelector): C = - Aggregators.sum.aggregateAll(this, columns) as C +public inline fun DataFrame.sum( + skipNaN: Boolean = skipNaN_default, + noinline columns: ColumnsSelector, +): C = Aggregators.sum(skipNaN).aggregateAll(this, columns) as C @JvmName("sumShort") @AccessApiOverload @@ -146,10 +166,13 @@ public fun DataFrame.sum(vararg columns: ColumnReference): Int = s @JvmName("sumNumber") @AccessApiOverload -public inline fun DataFrame.sum(vararg columns: ColumnReference): C = - sum { columns.toColumnSet() } +public inline fun DataFrame.sum( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): C = sum(skipNaN) { columns.toColumnSet() } -public fun DataFrame.sum(vararg columns: String): Number = sum { columns.toColumnsSetOf() } +public fun DataFrame.sum(vararg columns: String, skipNaN: Boolean = skipNaN_default): Number = + sum(skipNaN) { columns.toColumnsSetOf() } @JvmName("sumShort") @AccessApiOverload @@ -161,148 +184,433 @@ public fun DataFrame.sum(vararg columns: KProperty): Int = sum { c @JvmName("sumNumber") @AccessApiOverload -public inline fun DataFrame.sum(vararg columns: KProperty): C = - sum { columns.toColumnSet() } +public inline fun DataFrame.sum( + skipNaN: Boolean = skipNaN_default, + vararg columns: KProperty, +): C = sum(skipNaN) { columns.toColumnSet() } @JvmName("sumOfShort") @OverloadResolutionByLambdaReturnType public fun DataFrame.sumOf(expression: RowExpression): Int = - Aggregators.sum.aggregateOf(this, expression) as Int + Aggregators.sum(false).aggregateOf(this, expression) as Int @JvmName("sumOfByte") @OverloadResolutionByLambdaReturnType public fun DataFrame.sumOf(expression: RowExpression): Int = - Aggregators.sum.aggregateOf(this, expression) as Int + Aggregators.sum(false).aggregateOf(this, expression) as Int @JvmName("sumOfNumber") @OverloadResolutionByLambdaReturnType -public inline fun DataFrame.sumOf(crossinline expression: RowExpression): C = - Aggregators.sum.aggregateOf(this, expression) as C +public inline fun DataFrame.sumOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): C = Aggregators.sum(skipNaN).aggregateOf(this, expression) as C // endregion // region GroupBy @Refine @Interpretable("GroupBySum1") -public fun Grouped.sum(): DataFrame = sumFor(primitiveOrMixedNumberColumns()) +public fun Grouped.sum(skipNaN: Boolean = skipNaN_default): DataFrame = + sumFor(skipNaN, primitiveOrMixedNumberColumns()) + +@Refine +@Interpretable("GroupBySum0") +public fun Grouped.sumFor( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, columns) + +public fun Grouped.sumFor(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + sumFor(skipNaN) { columns.toNumberColumns() } + +@AccessApiOverload +public fun Grouped.sumFor( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun Grouped.sumFor( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(skipNaN) { columns.toColumnSet() } + +@Refine +@Interpretable("GroupBySum0") +public fun Grouped.sum( + name: String? = null, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, name, columns) + +public fun Grouped.sum( + vararg columns: String, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(name, skipNaN) { columns.toNumberColumns() } + +@AccessApiOverload +public fun Grouped.sum( + vararg columns: ColumnReference, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(name, skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun Grouped.sum( + vararg columns: KProperty, + name: String? = null, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(name, skipNaN) { columns.toColumnSet() } + +@Refine +@Interpretable("GroupBySumOf") +public inline fun Grouped.sumOf( + resultName: String? = null, + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataFrame = Aggregators.sum(skipNaN).aggregateOf(this, resultName, expression) + +// endregion + +// region Pivot + +public fun Pivot.sum(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataRow = + sumFor(separate, skipNaN, primitiveOrMixedNumberColumns()) + +public fun Pivot.sumFor( + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataRow = delegate { sumFor(separate, skipNaN, columns) } + +public fun Pivot.sumFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(separate, skipNaN) { columns.toNumberColumns() } + +@AccessApiOverload +public fun Pivot.sumFor( + vararg columns: ColumnReference, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(separate, skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun Pivot.sumFor( + vararg columns: KProperty, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataRow = sumFor(separate, skipNaN) { columns.toColumnSet() } + +public fun Pivot.sum( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataRow = delegate { sum(skipNaN, columns) } + +public fun Pivot.sum(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataRow = + sum(skipNaN) { columns.toNumberColumns() } + +@AccessApiOverload +public fun Pivot.sum( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataRow = sum(skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun Pivot.sum(vararg columns: KProperty, skipNaN: Boolean = skipNaN_default): DataRow = + sum(skipNaN) { columns.toColumnSet() } + +public inline fun Pivot.sumOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataRow = delegate { sumOf(skipNaN, expression) } + +// endregion + +// region PivotGroupBy + +public fun PivotGroupBy.sum(separate: Boolean = false, skipNaN: Boolean = skipNaN_default): DataFrame = + sumFor(separate, skipNaN, primitiveOrMixedNumberColumns()) + +public fun PivotGroupBy.sumFor( + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, + columns: ColumnsForAggregateSelector, +): DataFrame = Aggregators.sum(skipNaN).aggregateFor(this, separate, columns) + +public fun PivotGroupBy.sumFor( + vararg columns: String, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(separate, skipNaN) { columns.toNumberColumns() } + +@AccessApiOverload +public fun PivotGroupBy.sumFor( + vararg columns: ColumnReference, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(separate, skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun PivotGroupBy.sumFor( + vararg columns: KProperty, + separate: Boolean = false, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sumFor(separate, skipNaN) { columns.toColumnSet() } + +public fun PivotGroupBy.sum( + skipNaN: Boolean = skipNaN_default, + columns: ColumnsSelector, +): DataFrame = Aggregators.sum(skipNaN).aggregateAll(this, columns) + +public fun PivotGroupBy.sum(vararg columns: String, skipNaN: Boolean = skipNaN_default): DataFrame = + sum(skipNaN) { columns.toNumberColumns() } + +@AccessApiOverload +public fun PivotGroupBy.sum( + vararg columns: ColumnReference, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(skipNaN) { columns.toColumnSet() } + +@AccessApiOverload +public fun PivotGroupBy.sum( + vararg columns: KProperty, + skipNaN: Boolean = skipNaN_default, +): DataFrame = sum(skipNaN) { columns.toColumnSet() } + +public inline fun PivotGroupBy.sumOf( + skipNaN: Boolean = skipNaN_default, + crossinline expression: RowExpression, +): DataFrame = Aggregators.sum(skipNaN).aggregateOf(this, expression) + +// endregion + +// region binary compatibility + +@Suppress("UNCHECKED_CAST") +@JvmName("sumNumber") +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataColumn.sum(): T = sum(skipNaN = skipNaN_default) + +@JvmName("sumOfNumber") +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun DataColumn.sumOf(crossinline expression: (C) -> V?): V = + sumOf(skipNaN = skipNaN_default, expression = expression) + +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun AnyRow.rowSum(): Number = rowSum(skipNaN = skipNaN_default) + +@JvmName("rowSumOfFloat") +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun AnyRow.rowSumOf(_kClass: KClass = Float::class): Float = + rowSumOf(typeOf(), skipNaN = skipNaN_default) as Float + +@JvmName("rowSumOfDouble") +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun AnyRow.rowSumOf(_kClass: KClass = Double::class): Double = + rowSumOf(typeOf(), skipNaN = skipNaN_default) as Double + +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun AnyRow.rowSumOf(type: KType): Number = rowSumOf(type, skipNaN = skipNaN_default) + +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.sum(): DataRow = sum(skipNaN = skipNaN_default) + +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.sumFor(columns: ColumnsForAggregateSelector): DataRow = + sumFor(skipNaN = skipNaN_default, columns = columns) + +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.sumFor(vararg columns: String): DataRow = + sumFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.sumFor(vararg columns: ColumnReference): DataRow = + sumFor(columns = columns, skipNaN = skipNaN_default) + +@AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.sumFor(vararg columns: KProperty): DataRow = + sumFor(columns = columns, skipNaN = skipNaN_default) + +@JvmName("sumNumber") +@OverloadResolutionByLambdaReturnType +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun DataFrame.sum(noinline columns: ColumnsSelector): C = + sum(skipNaN = skipNaN_default, columns = columns) + +@JvmName("sumNumber") +@AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun DataFrame.sum(vararg columns: ColumnReference): C = + sum(columns = columns, skipNaN = skipNaN_default) + +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun DataFrame.sum(vararg columns: String): Number = sum(columns = columns, skipNaN = skipNaN_default) + +@JvmName("sumNumber") +@AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun DataFrame.sum(vararg columns: KProperty): C = + sum(skipNaN = skipNaN_default, columns = columns) + +@JvmName("sumOfNumber") +@OverloadResolutionByLambdaReturnType +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public inline fun DataFrame.sumOf(crossinline expression: RowExpression): C = + sumOf(skipNaN = skipNaN_default, expression = expression) + +@Refine +@Interpretable("GroupBySum1") +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.sum(): DataFrame = sum(skipNaN = skipNaN_default) @Refine @Interpretable("GroupBySum0") +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Grouped.sumFor(columns: ColumnsForAggregateSelector): DataFrame = - Aggregators.sum.aggregateFor(this, columns) + sumFor(skipNaN = skipNaN_default, columns = columns) -public fun Grouped.sumFor(vararg columns: String): DataFrame = sumFor { columns.toNumberColumns() } +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Grouped.sumFor(vararg columns: String): DataFrame = + sumFor(columns = columns, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Grouped.sumFor(vararg columns: ColumnReference): DataFrame = - sumFor { columns.toColumnSet() } + sumFor(columns = columns, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Grouped.sumFor(vararg columns: KProperty): DataFrame = - sumFor { columns.toColumnSet() } + sumFor(columns = columns, skipNaN = skipNaN_default) @Refine @Interpretable("GroupBySum0") +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Grouped.sum(name: String? = null, columns: ColumnsSelector): DataFrame = - Aggregators.sum.aggregateAll(this, name, columns) + sum(name, skipNaN = skipNaN_default, columns = columns) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Grouped.sum(vararg columns: String, name: String? = null): DataFrame = - sum(name) { columns.toNumberColumns() } + sum(columns = columns, name = name, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Grouped.sum(vararg columns: ColumnReference, name: String? = null): DataFrame = - sum(name) { columns.toColumnSet() } + sum(columns = columns, name = name, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Grouped.sum(vararg columns: KProperty, name: String? = null): DataFrame = - sum(name) { columns.toColumnSet() } + sum(columns = columns, name = name, skipNaN = skipNaN_default) @Refine @Interpretable("GroupBySumOf") +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public inline fun Grouped.sumOf( resultName: String? = null, crossinline expression: RowExpression, -): DataFrame = Aggregators.sum.aggregateOf(this, resultName, expression) - -// endregion - -// region Pivot +): DataFrame = sumOf(resultName, skipNaN = skipNaN_default, expression = expression) -public fun Pivot.sum(separate: Boolean = false): DataRow = sumFor(separate, primitiveOrMixedNumberColumns()) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.sum(separate: Boolean = false): DataRow = sum(separate, skipNaN = skipNaN_default) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Pivot.sumFor( separate: Boolean = false, columns: ColumnsForAggregateSelector, -): DataRow = delegate { sumFor(separate, columns) } +): DataRow = sumFor(separate, skipNaN = skipNaN_default, columns = columns) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Pivot.sumFor(vararg columns: String, separate: Boolean = false): DataRow = - sumFor(separate) { columns.toNumberColumns() } + sumFor(columns = columns, separate = separate, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Pivot.sumFor( vararg columns: ColumnReference, separate: Boolean = false, -): DataRow = sumFor(separate) { columns.toColumnSet() } +): DataRow = sumFor(columns = columns, separate = separate, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun Pivot.sumFor(vararg columns: KProperty, separate: Boolean = false): DataRow = - sumFor(separate) { columns.toColumnSet() } + sumFor(columns = columns, separate = separate, skipNaN = skipNaN_default) -public fun Pivot.sum(columns: ColumnsSelector): DataRow = delegate { sum(columns) } +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.sum(columns: ColumnsSelector): DataRow = + sum(skipNaN = skipNaN_default, columns = columns) -public fun Pivot.sum(vararg columns: String): DataRow = sum { columns.toNumberColumns() } +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.sum(vararg columns: String): DataRow = sum(columns = columns, skipNaN = skipNaN_default) @AccessApiOverload -public fun Pivot.sum(vararg columns: ColumnReference): DataRow = sum { columns.toColumnSet() } +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.sum(vararg columns: ColumnReference): DataRow = + sum(columns = columns, skipNaN = skipNaN_default) @AccessApiOverload -public fun Pivot.sum(vararg columns: KProperty): DataRow = sum { columns.toColumnSet() } +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun Pivot.sum(vararg columns: KProperty): DataRow = + sum(columns = columns, skipNaN = skipNaN_default) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public inline fun Pivot.sumOf(crossinline expression: RowExpression): DataRow = - delegate { sumOf(expression) } - -// endregion - -// region PivotGroupBy + sumOf(skipNaN = skipNaN_default, expression = expression) -public fun PivotGroupBy.sum(separate: Boolean = false): DataFrame = - sumFor(separate, primitiveOrMixedNumberColumns()) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.sum(separate: Boolean = false): DataFrame = sum(separate, skipNaN = skipNaN_default) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun PivotGroupBy.sumFor( separate: Boolean = false, columns: ColumnsForAggregateSelector, -): DataFrame = Aggregators.sum.aggregateFor(this, separate, columns) +): DataFrame = sumFor(separate, skipNaN = skipNaN_default, columns = columns) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun PivotGroupBy.sumFor(vararg columns: String, separate: Boolean = false): DataFrame = - sumFor(separate) { columns.toNumberColumns() } + sumFor(columns = columns, separate = separate, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun PivotGroupBy.sumFor( vararg columns: ColumnReference, separate: Boolean = false, -): DataFrame = sumFor(separate) { columns.toColumnSet() } +): DataFrame = sumFor(columns = columns, separate = separate, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun PivotGroupBy.sumFor( vararg columns: KProperty, separate: Boolean = false, -): DataFrame = sumFor(separate) { columns.toColumnSet() } +): DataFrame = sumFor(columns = columns, separate = separate, skipNaN = skipNaN_default) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun PivotGroupBy.sum(columns: ColumnsSelector): DataFrame = - Aggregators.sum.aggregateAll(this, columns) + sum(skipNaN = skipNaN_default, columns = columns) -public fun PivotGroupBy.sum(vararg columns: String): DataFrame = sum { columns.toNumberColumns() } +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) +public fun PivotGroupBy.sum(vararg columns: String): DataFrame = + sum(columns = columns, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun PivotGroupBy.sum(vararg columns: ColumnReference): DataFrame = - sum { columns.toColumnSet() } + sum(columns = columns, skipNaN = skipNaN_default) @AccessApiOverload +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public fun PivotGroupBy.sum(vararg columns: KProperty): DataFrame = - sum { columns.toColumnSet() } + sum(columns = columns, skipNaN = skipNaN_default) +@Deprecated(SUM_NO_SKIPNAN, level = DeprecationLevel.HIDDEN) public inline fun PivotGroupBy.sumOf( crossinline expression: RowExpression, -): DataFrame = Aggregators.sum.aggregateOf(this, expression) +): DataFrame = sumOf(skipNaN = skipNaN_default, expression = expression) // endregion diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/NA.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/NA.kt index e5433a1316..24bac60cbb 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/NA.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/documentation/NA.kt @@ -1,5 +1,7 @@ package org.jetbrains.kotlinx.dataframe.documentation +import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.api.dropNA import org.jetbrains.kotlinx.dataframe.api.fillNA @@ -10,6 +12,10 @@ import org.jetbrains.kotlinx.dataframe.api.fillNA * [Floats][Float] or [Doubles][Double] can be represented as [Float.NaN] or [Double.NaN], respectively, * in cases where a mathematical operation is undefined, such as dividing by zero. * + * A [DataRow] can also be considered `NA` if each value inside is `NA`. + * + * A [DataFrame] is considered `NA` if it has no rows or columns, so if it's empty. + * * You can also use [fillNA][fillNA] to replace `NAs` in certain columns with a given value or expression * or [dropNA][dropNA] to drop rows with `NAs` in them. * diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/SequenceBestBy.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/SequenceBestBy.kt new file mode 100644 index 0000000000..430cec8c15 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/SequenceBestBy.kt @@ -0,0 +1,149 @@ +package org.jetbrains.kotlinx.dataframe.impl + +import org.jetbrains.kotlinx.dataframe.api.isNA +import org.jetbrains.kotlinx.dataframe.documentation.NA + +/** + * Type alias for a function representing a reduction over a sequence of values trying to find the "best" value. + * + * Return `true` if `this` is considered "better" than `other`, else return `false`. + * + * This means that if `this` and `other` are considered equally "good", `false` should be returned. + * + * You add additional constraints to an [IsBetterThan] function in the following fashion: + * + * Let's say you want a value to álways be returned when it satisfies the condition `isPreferred(it)`, + * but in all other cases, you just want the best. + * Then you can write: + * ```kt + * val isBetterThan: IsBetterThan + * val newIsBetterThan: IsBetterThan = { other -> isPreferred(this) || (!isPreferred(other) && this.isBetterThan(other)) } + * ``` + * + * Alternatively, if you prefer a value not be returned when it satisfies the condition `isNotPreferred()`, + * then you can write: + * ```kt + * val isBetterThan: IsBetterThan + * val newIsBetterThan: IsBetterThan = { other -> !isNotPreferred(this) && (isNotPreferred(other) || this.isBetterThan(other)) } + * ``` + * Note that for the latter case, if the source contains only `isNotPreferred()`-satisfying values, + * a non-preferred value will still be returned. + */ +internal typealias IsBetterThan = C.(other: C) -> Boolean + +// region indexOfBestBy + +/** + * Returns the index of the first element in this sequence that is not null and is better than all previous elements. + * + * Returns -1 if there are no elements non-`null` elements in [this]. + * + * @param isBetterThan A function defining what it means for a value to be "better" than another. + */ +internal inline fun Sequence.indexOfBestNotNullBy(isBetterThan: IsBetterThan): Int { + val bestIndex = indexOfBestBy { other -> this != null && (other == null || this.isBetterThan(other)) } + // catch case where all values are null + return if (bestIndex == 0 && first() == null) -1 else bestIndex +} + +/** + * Returns the index of the first element in this sequence + * that is not [NA (null or NaN)][NA] and is better than all previous elements. + * + * Returns -1 if there are no elements non-`NA` elements in [this]. + * + * @param isBetterThan A function defining what it means for a value to be "better" than another. + */ +internal inline fun Sequence.indexOfBestNotNaBy(isBetterThan: IsBetterThan): Int { + val bestIndex = indexOfBestBy { other -> !this.isNA() && (other.isNA() || this.isBetterThan(other)) } + // catch case where all values are NA (null or NaN) + return if (bestIndex == 0 && first().isNA()) -1 else bestIndex +} + +/** + * Returns the index of the first element in this sequence that is better than all previous elements. + * + * Returns -1 if there are no elements in [this]. + * + * Considers the first element in [this] the best if [isBetterThan] only returns `false`. + * + * @param isBetterThan A function defining what it means for a value to be "better" than another. + */ +internal inline fun Sequence.indexOfBestBy(isBetterThan: IsBetterThan): Int = + when { + none() -> -1 + + else -> { + var bestIndex = 0 + reduceIndexed { index, bestFound, next -> + if (next.isBetterThan(bestFound)) { + bestIndex = index + next + } else { + bestFound + } + } + bestIndex + } + } + +// endregion + +// bestNotNaBy + +internal inline fun Sequence.bestNotNaBy(isBetterThan: IsBetterThan): C = + bestNotNaByOrElse(isBetterThan) { throw NoSuchElementException("Sequence is empty") } + +internal inline fun Sequence.bestNotNaByOrNull(isBetterThan: IsBetterThan): C? = + bestNotNaByOrElse(isBetterThan) { null } + +@Suppress("UNCHECKED_CAST") +internal inline fun Sequence.bestNotNaByOrElse( + isBetterThan: IsBetterThan, + ifEmptyOrAllNa: () -> R, +): R = + bestByOrElse( + isBetterThan = { other -> !this.isNA() && (other.isNA() || this.isBetterThan(other)) }, + ifEmpty = ifEmptyOrAllNa, + )?.takeUnless { it.isNA() } ?: ifEmptyOrAllNa() + +// endregion + +// bestNotNullBy + +internal inline fun Sequence.bestNotNullBy(isBetterThan: IsBetterThan): C = + bestNotNullByOrElse(isBetterThan) { throw NoSuchElementException("Sequence is empty") } + +internal inline fun Sequence.bestNotNullByOrNull(isBetterThan: IsBetterThan): C? = + bestNotNullByOrElse(isBetterThan) { null } + +@Suppress("UNCHECKED_CAST") +internal inline fun Sequence.bestNotNullByOrElse( + isBetterThan: IsBetterThan, + ifEmptyOrAllNull: () -> R, +): R = + bestByOrElse( + isBetterThan = { other -> this != null && (other == null || this.isBetterThan(other)) }, + ifEmpty = ifEmptyOrAllNull, + ) ?: ifEmptyOrAllNull() + +// endregion + +// region bestBy + +internal inline fun Sequence.bestBy(isBetterThan: IsBetterThan): C = + bestByOrElse(isBetterThan) { throw NoSuchElementException("Sequence is empty") } + +internal inline fun Sequence.bestByOrNull(isBetterThan: IsBetterThan): C? = + bestByOrElse(isBetterThan) { null } + +internal inline fun Sequence.bestByOrElse(isBetterThan: IsBetterThan, ifEmpty: () -> R): R = + when { + none() -> ifEmpty() + + else -> reduce { bestFound, next -> + if (next.isBetterThan(bestFound)) next else bestFound + } + } + +// endregion 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 d8e24f6d02..581fa737e2 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 @@ -9,6 +9,7 @@ import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.DataFrame import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.api.Infer +import org.jetbrains.kotlinx.dataframe.api.isSubtypeOf import org.jetbrains.kotlinx.dataframe.impl.columns.createColumnGuessingType import org.jetbrains.kotlinx.dataframe.util.GUESS_VALUE_TYPE import java.math.BigDecimal @@ -564,6 +565,9 @@ internal val nullableNothingType: KType = typeOf>().arguments.fir internal fun nothingType(nullable: Boolean): KType = if (nullable) nullableNothingType else nothingType +internal val KType.canBeNaN: Boolean + get() = isSubtypeOf(typeOf()) || isSubtypeOf(typeOf()) + @OptIn(ExperimentalUnsignedTypes::class) private val primitiveArrayClasses = setOf( BooleanArray::class, @@ -690,3 +694,16 @@ internal fun Iterable.types(): Set = mapTo(mutableSetOf()) { if (it == null) nullableNothingType else it::class.createStarProjectedType(false) } + +/** + * Checks whether this KType adheres to `T : Comparable?`, aka, it is comparable with itself. + */ +internal fun KType.isIntraComparable(): Boolean = + this.isSubtypeOf( + Comparable::class.createType( + arguments = listOf( + KTypeProjection(IN, this.withNullability(false)), + ), + nullable = this.isMarkedNullable, + ), + ) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt index e16ce32433..ce625f0351 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/Utils.kt @@ -222,54 +222,6 @@ internal fun DataFrame.getColumnPaths( selector: ColumnsSelector, ): List = getColumnsWithPaths(unresolvedColumnsPolicy, selector).map { it.path } -internal fun > Sequence.indexOfMin(): Int { - val iterator = iterator() - if (!iterator.hasNext()) return -1 - var value = iterator.next() - var index = 0 - while (value == null) { - if (!iterator.hasNext()) return -1 - value = iterator.next() - index++ - } - var min: C = value - var minIndex = index - if (!iterator.hasNext()) return minIndex - do { - val v = iterator.next() - index++ - if (v != null && min > v) { - min = v - minIndex = index - } - } while (iterator.hasNext()) - return minIndex -} - -internal fun > Sequence.indexOfMax(): Int { - val iterator = iterator() - if (!iterator.hasNext()) return -1 - var value = iterator.next() - var index = 0 - while (value == null) { - if (!iterator.hasNext()) return -1 - value = iterator.next() - index++ - } - var max: C = value - var maxIndex = index - if (!iterator.hasNext()) return maxIndex - do { - val v = iterator.next() - index++ - if (v != null && max < v) { - max = v - maxIndex = index - } - } while (iterator.hasNext()) - return maxIndex -} - internal fun createStarProjectedType(klass: KClass<*>, nullable: Boolean): KType = if (klass == Nothing::class) { nothingType(nullable) // would be Void otherwise diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt index 74bbc1a6e9..c5ca55381a 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregator.kt @@ -1,105 +1,231 @@ package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.ReducingAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.SelectingAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers.AnyInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers.NumberInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.FlatteningMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.NoMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.TwoStepMultipleColumnsHandler import kotlin.reflect.KType import kotlin.reflect.full.withNullability /** - * Base interface for all aggregators. + * This class is the main entry-point for creating an aggregator. * - * Aggregators are used to compute a single value from an [Iterable] of values, a single [DataColumn], - * or multiple [DataColumns][DataColumn]. + * Aggregators are used to compute a single value from a [Sequence] of values, + * a single [DataColumn], or multiple [DataColumns][DataColumn]. * - * The [AggregatorBase] class is a base implementation of this interface. + * [Aggregator] follows a dependency injection pattern: * - * @param Value The type of the values to be aggregated. + * Using the constructor or [Aggregator.invoke] function, you can create an [Aggregator] instance with a choice of: + * - [AggregatorInputHandler] - {@include [AggregatorInputHandler]} + * + * Options: [NumberInputHandler], [AnyInputHandler] + * + * - [AggregatorAggregationHandler] - {@include [AggregatorAggregationHandler]} + * + * Options: [ReducingAggregationHandler], [SelectingAggregationHandler] + * + * - [AggregatorMultipleColumnsHandler] - {@include [AggregatorMultipleColumnsHandler]} + * + * Options: [FlatteningMultipleColumnsHandler], [TwoStepMultipleColumnsHandler], [NoMultipleColumnsHandler] + * + * @param Value The non-null type of the values to be aggregated. * The input can always have nulls, they are filtered out. * @param Return The type of the resulting value. Can optionally be nullable. + * @see [invoke] + */ +@PublishedApi +internal class Aggregator( + val aggregationHandler: AggregatorAggregationHandler, + val inputHandler: AggregatorInputHandler, + val multipleColumnsHandler: AggregatorMultipleColumnsHandler, + val name: String, +) : AggregatorInputHandler by inputHandler, + AggregatorMultipleColumnsHandler by multipleColumnsHandler, + AggregatorAggregationHandler by aggregationHandler { + + // Set the aggregator reference in all handlers to this instance + init { + aggregationHandler.init(this) + inputHandler.init(this) + multipleColumnsHandler.init(this) + init(this) + } + + override fun init(aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>) { + this.aggregator = aggregator + } + + override var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? = null + + override fun toString(): String = + "Aggregator(name='$name', aggregationHandler=$aggregationHandler, inputHandler=$inputHandler, multipleColumnsHandler=$multipleColumnsHandler)" + + internal companion object { + + /** + * Factory function for creating an [Aggregator] instance given a name. + * + * @see AggregatorProvider + * @see Aggregator + */ + internal operator fun invoke( + aggregationHandler: AggregatorAggregationHandler, + inputHandler: AggregatorInputHandler, + multipleColumnsHandler: AggregatorMultipleColumnsHandler, + ): AggregatorProvider = + AggregatorProvider { name -> + Aggregator( + aggregationHandler = aggregationHandler, + inputHandler = inputHandler, + multipleColumnsHandler = multipleColumnsHandler, + name = name, + ) + } + } +} + +/** + * Performs aggregation on the given [values], taking [valueType] into account. + * If [valueType] is unknown, see [calculateValueType] or [aggregateCalculatingValueType]. + */ +@PublishedApi +internal fun Aggregator.aggregate( + values: Sequence, + valueType: ValueType, +) = aggregateSequence(values, valueType) + +/** + * Performs aggregation on the given [values], taking [valueType] into account. + * If [valueType] is unknown, see [calculateValueType] or [aggregateCalculatingValueType]. */ @PublishedApi -internal interface Aggregator { - - /** The name of this aggregator. */ - val name: String - - /** - * Base function of [Aggregator]. - * - * Aggregates the given values, taking [type] into account, - * filtering nulls (only if [type.isMarkedNullable][KType.isMarkedNullable]), - * and computes a single resulting value. - * - * When using [AggregatorBase], this can be supplied by the [AggregatorBase.aggregator] argument. - * - * When the exact [type] is unknown, use [aggregateCalculatingType]. - */ - fun aggregate(values: Iterable, type: KType): Return - - /** - * Aggregates the data in the given column and computes a single resulting value. - * Calls [aggregate] (with [Iterable] and [KType]). - * - * See [AggregatorBase.aggregate]. - */ - fun aggregate(column: DataColumn): Return - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - */ - fun aggregate(columns: Iterable>): Return - - /** - * Special case of [aggregate] with [Iterable] that calculates the common type of the values at runtime. - * Without [valueTypes], this is a heavy operation and should be avoided when possible. - * - * @param values The values to be aggregated. - * @param valueTypes The types of the values. - * If provided, this can be used to avoid calculating the types of [values] at runtime with reflection. - * It should contain all types of [values]. - * If `null` or empty, the types of [values] will be calculated at runtime (heavy!). - */ - fun aggregateCalculatingType(values: Iterable, valueTypes: Set? = null): Return - - /** - * Function that can give the return type of [aggregate] as [KType], given the type of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param type The type of the input values. - * @param emptyInput If `true`, the input values are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - fun calculateReturnTypeOrNull(type: KType, emptyInput: Boolean): KType? - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? +internal fun Aggregator.aggregate( + values: Sequence, + valueType: KType, +) = aggregate(values, valueType.toValueType(needsFullConversion = false)) + +/** + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it by combining the set of known [valueTypes] or + * by gathering the types from [values]. + * + * This is a helper function that calls the correct + * [AggregatorInputHandler.calculateValueType] based on the given input. + * + * Giving [valueTypes] is preferred because of efficiency, as it allows for avoiding runtime type checks. + */ +internal fun Aggregator.calculateValueType( + values: Sequence, + valueTypes: Set? = null, +) = if (valueTypes != null && valueTypes.isNotEmpty()) { + calculateValueType(valueTypes) +} else { + calculateValueType(values) } +/** + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it by combining the set of known [valueTypes] or + * by gathering the types from [values] and then aggregating them. + * + * Giving [valueTypes] is preferred because of efficiency, as it allows for avoiding runtime type checks. + */ +internal fun Aggregator.aggregateCalculatingValueType( + values: Sequence, + valueTypes: Set? = null, +) = aggregateSequence( + values = values, + valueType = calculateValueType(values, valueTypes), +) + +/** + * Aggregates the data in the given column and computes a single resulting value. + */ +internal fun Aggregator.aggregate(column: DataColumn) = + aggregateSingleColumn(column) + +/** + * Aggregates the data in the given columns and computes a single resulting value. + */ +internal fun Aggregator.aggregate(columns: Sequence>) = + aggregateMultipleColumns(columns) + +/** + * Gives the index of the aggregation result in the input [values], if it applies. + * This is used for aggregators with an [AggregatorAggregationHandler] where + * [Value][Value]` == `[Return][Return], and where the result exists in the input. + * + * Like for [SelectingAggregationHandler]. + * + * Defaults to `-1`. + * + * If [valueType] is unknown, see [calculateValueType] + */ +@PublishedApi +internal fun Aggregator.indexOfAggregationResult( + values: Sequence, + valueType: ValueType, +): Int = indexOfAggregationResultSingleSequence(values, valueType) + +/** + * Gives the index of the aggregation result in the input [values], if it applies. + * This is used for aggregators with an [AggregatorAggregationHandler] where + * [Value][Value]` == `[Return][Return], and where the result exists in the input. + * + * Like for [SelectingAggregationHandler]. + * + * Defaults to `-1`. + * + * If [valueType] is unknown, see [calculateValueType] + */ +@PublishedApi +internal fun Aggregator.indexOfAggregationResult( + values: Sequence, + valueType: KType, +): Int = indexOfAggregationResultSingleSequence(values, valueType.toValueType(needsFullConversion = false)) + @Suppress("UNCHECKED_CAST") @PublishedApi -internal fun Aggregator<*, *>.cast(): Aggregator = this as Aggregator +internal fun Aggregator<*, *>.cast(): Aggregator = this as Aggregator @Suppress("UNCHECKED_CAST") @PublishedApi -internal fun Aggregator<*, *>.cast2(): Aggregator = this as Aggregator +internal fun Aggregator<*, *>.cast2(): Aggregator = + this as Aggregator + +/** + * Type alias for a function that gives the return type of a [Reducer] or [Selector] + * given some input type and whether the input is empty. + */ +internal typealias CalculateReturnType = (type: KType, emptyInput: Boolean) -> KType -/** Type alias for [Aggregator.calculateReturnTypeOrNull] */ -internal typealias CalculateReturnTypeOrNull = (type: KType, emptyInput: Boolean) -> KType? +/** + * Type alias for a reducer function where the type of the values is provided as [KType]. + * Nulls have already been filtered out when this function is called. + */ +internal typealias Reducer = Sequence.(valueType: KType) -> Return + +/** + * Type alias for a selector function where the type of the values is provided as [KType]. + * + * It is expected that [Value][Value]` : `[Return][Return]` & `[Any][Any], and [Return][Return]` : `[Any?][Any]. + * + * Nulls have already been filtered out when this function is called. + */ +internal typealias Selector = Sequence.(type: KType) -> Return /** - * Type alias for the argument for [Aggregator.aggregate]. - * Nulls have already been filtered out when this argument is called. + * Type alias for a function that returns the index of the result of [Selector] in this sequence. + * If the result is not in the sequence, it returns -1. + * The type of the values is provided as [KType] and the sequence can contain nulls. */ -internal typealias Aggregate = Iterable.(type: KType) -> Return +internal typealias IndexOfResult = Sequence.(type: KType) -> Int -/** Common case for [CalculateReturnTypeOrNull], preserves return type, but makes it nullable for empty inputs. */ -internal val preserveReturnTypeNullIfEmpty: CalculateReturnTypeOrNull = { type, emptyInput -> +/** Common case for [CalculateReturnType], preserves return type, but makes it nullable for empty inputs. */ +internal val preserveReturnTypeNullIfEmpty: CalculateReturnType = { type, emptyInput -> type.withNullability(emptyInput) } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorAggregationHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorAggregationHandler.kt new file mode 100644 index 0000000000..e6eb24a610 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorAggregationHandler.kt @@ -0,0 +1,53 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators + +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.SelectingAggregationHandler +import kotlin.reflect.KType + +/** + * The base functionality of the aggregator, + * which defines how the aggregation of a single [Sequence] or [column][DataColumn] is done. + * It also provides information on which return type will be given, as [KType], given a [value type][ValueType]. + * It can also provide the index of the result in the input values if it is a selecting aggregator. + */ +@PublishedApi +internal interface AggregatorAggregationHandler : AggregatorHandler { + + /** + * Base function of [Aggregator]. + * + * Aggregates the given values, taking [valueType] into account, + * filtering nulls (only if [valueType.type.isMarkedNullable][KType.isMarkedNullable]), + * and computes a single resulting value. + * + * When the exact [valueType] is unknown, use [calculateValueType] or [aggregateCalculatingValueType]. + */ + fun aggregateSequence(values: Sequence, valueType: ValueType): Return + + /** + * Aggregates the data in the given column and computes a single resulting value. + * Calls [aggregateSequence]. + */ + fun aggregateSingleColumn(column: DataColumn): Return + + /** + * Function that can give the return type of [aggregateSequence] as [KType], given the type of the input. + * This allows aggregators to avoid runtime type calculations. + * + * @param valueType The type of the input values. + * @param emptyInput If `true`, the input values are considered empty. This often affects the return type. + * @return The return type of [aggregateSequence] as [KType]. + */ + fun calculateReturnType(valueType: KType, emptyInput: Boolean): KType + + /** + * Function that can give the index of the aggregation result in the input [values], if it applies. + * This is used for [AggregatorAggregationHandlers][AggregatorAggregationHandler] where + * [Value][Value]` == `[Return][Return], and where the result exists in the input. + * + * Like for [SelectingAggregationHandler]. + * + * Defaults to `-1`. + */ + fun indexOfAggregationResultSingleSequence(values: Sequence, valueType: ValueType): Int +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorBase.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorBase.kt deleted file mode 100644 index ada6638ceb..0000000000 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorBase.kt +++ /dev/null @@ -1,114 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators - -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.api.asIterable -import org.jetbrains.kotlinx.dataframe.api.asSequence -import org.jetbrains.kotlinx.dataframe.impl.commonType -import org.jetbrains.kotlinx.dataframe.impl.nothingType -import kotlin.reflect.KType -import kotlin.reflect.full.withNullability - -/** - * Abstract base class for [aggregators][Aggregator]. - * - * Aggregators are used to compute a single value from an [Iterable] of values, a single [DataColumn], - * or multiple [DataColumns][DataColumn]. - * - * @param name The name of this aggregator. - * @param aggregator Functional argument for the [aggregate] function. Nulls are filtered out before this is called. - */ -internal abstract class AggregatorBase( - override val name: String, - protected val getReturnTypeOrNull: CalculateReturnTypeOrNull, - protected val aggregator: Aggregate, -) : Aggregator { - - /** - * Base function of [Aggregator]. - * - * Aggregates the given values, taking [type] into account, - * filtering nulls (only if [type.isMarkedNullable][KType.isMarkedNullable]), - * and computes a single resulting value. - * - * When using [AggregatorBase], this can be supplied by the [AggregatorBase.aggregator] argument. - * - * When the exact [type] is unknown, use [aggregateCalculatingType]. - */ - @Suppress("UNCHECKED_CAST") - override fun aggregate(values: Iterable, type: KType): Return = - aggregator( - // values = - if (type.isMarkedNullable) { - values.asSequence().filterNotNull().asIterable() - } else { - values as Iterable - }, - // type = - type.withNullability(false), - ) - - /** - * Function that can give the return type of [aggregate] as [KType], given the type of the input. - * This allows aggregators to avoid runtime type calculations. - * - * Uses [getReturnTypeOrNull] to calculate the return type. - * - * @param type The type of the input values. - * @param emptyInput If `true`, the input values are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - override fun calculateReturnTypeOrNull(type: KType, emptyInput: Boolean): KType? = - getReturnTypeOrNull(type.withNullability(false), emptyInput) - - /** - * Aggregates the data in the given column and computes a single resulting value. - * - * Nulls are filtered out by default, then [aggregate] (with [Iterable] and [KType]) is called. - */ - @Suppress("UNCHECKED_CAST") - override fun aggregate(column: DataColumn): Return = - aggregate( - values = column.asIterable(), - type = column.type(), - ) - - /** @include [Aggregator.aggregateCalculatingType] */ - override fun aggregateCalculatingType(values: Iterable, valueTypes: Set?): Return { - val commonType = if (valueTypes != null && valueTypes.isNotEmpty()) { - valueTypes.commonType(false) - } else { - var hasNulls = false - val classes = values.mapNotNull { - if (it == null) { - hasNulls = true - null - } else { - it.javaClass.kotlin - } - } - if (classes.isEmpty()) { - nothingType(hasNulls) - } else { - classes.commonType(hasNulls) - } - } - return aggregate(values, commonType) - } - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - * Must be overridden to use. - */ - abstract override fun aggregate(columns: Iterable>): Return - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - abstract override fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? -} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorHandler.kt new file mode 100644 index 0000000000..6d7a87a02d --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorHandler.kt @@ -0,0 +1,22 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators + +/** + * Common interface for [Aggregator] handlers or "injector" objects that can build up an [Aggregator] instance. + * + * When an [Aggregator] is instantiated, + * the [init] function of each [AggregatorAggregationHandlers][AggregatorAggregationHandler] is called, + * which allows the handler to refer to [Aggregator] instance via [aggregator]. + */ +internal interface AggregatorHandler { + + /** + * Reference to the aggregator instance. + * + * Can only be used once [init] has run. + */ + var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? + + fun init(aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>) { + this.aggregator = aggregator + } +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler.kt new file mode 100644 index 0000000000..e3a2bb64ac --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorInputHandler.kt @@ -0,0 +1,39 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators + +import kotlin.reflect.KType + +/** + * The input handler of the aggregator, + * which handles type checks, conversions, and preprocessing of a single sequence of input values. + * It can also calculate a specific [value type][ValueType] from the input values or input types + * if the (specific) type is not known. + */ +internal interface AggregatorInputHandler : AggregatorHandler { + + /** + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it by combining the set of known [valueTypes]. + */ + fun calculateValueType(valueTypes: Set): ValueType + + /** + * WARNING: HEAVY! + * + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it by getting the types of [values] at runtime. + * This is heavy because it uses reflection on each value. + */ + fun calculateValueType(values: Sequence): ValueType + + /** + * Preprocesses the input values before aggregation. + * It's expected that this function converts [values] to the right [valueType.kType][ValueType.kType] + * if [valueType.needsFullConversion][ValueType.needsFullConversion]. + * + * @return A pair of the preprocessed values and the (potentially new) type of the values. + */ + fun preprocessAggregation( + values: Sequence, + valueType: ValueType, + ): Pair, KType> +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorMultipleColumnsHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorMultipleColumnsHandler.kt new file mode 100644 index 0000000000..0530f05ae7 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorMultipleColumnsHandler.kt @@ -0,0 +1,30 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators + +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import kotlin.reflect.KType + +/** + * The multiple columns handler, + * which specifies how to aggregate multiple columns into a single value by using the supplied + * [AggregatorAggregationHandler]. + * It can also calculate the return type of the aggregation given all input column types. + */ +internal interface AggregatorMultipleColumnsHandler : + AggregatorHandler { + + /** + * Aggregates the data in the multiple given columns and computes a single resulting value. + * Calls [Aggregator.aggregateSequence] or [Aggregator.aggregateSingleColumn]. + */ + fun aggregateMultipleColumns(columns: Sequence>): Return + + /** + * Function that can give the return type of [aggregateMultipleColumns], given types of the columns. + * This allows aggregators to avoid runtime type calculations. + * + * @param colTypes The types of the input columns. + * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. + */ + fun calculateReturnTypeMultipleColumns(colTypes: Set, colsEmpty: Boolean): KType +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch.kt index a21b06c401..987771547a 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorOptionSwitch.kt @@ -7,31 +7,34 @@ package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators * @see AggregatorOptionSwitch2 */ @PublishedApi -internal class AggregatorOptionSwitch1>( +internal class AggregatorOptionSwitch1( val name: String, - val getAggregator: (param1: Param1) -> AggregatorProvider, + val getAggregator: (param1: Param1) -> AggregatorProvider, ) { - private val cache: MutableMap = mutableMapOf() + private val cache: MutableMap> = mutableMapOf() - operator fun invoke(param1: Param1): AggregatorType = + operator fun invoke(param1: Param1): Aggregator = cache.getOrPut(param1) { getAggregator(param1).create(name) } - /** - * Creates [AggregatorOptionSwitch1]. - * - * Used like: - * ```kt - * val myAggregator by AggregatorOptionSwitch1.Factory { param1: Param1 -> - * MyAggregator.Factory(param1) - * } - */ - class Factory>( - val getAggregator: (param1: Param1) -> AggregatorProvider, - ) : Provider> by - Provider({ name -> AggregatorOptionSwitch1(name, getAggregator) }) + @Suppress("FunctionName") + companion object { + + /** + * Creates [AggregatorOptionSwitch1]. + * + * Used like: + * ```kt + * val myAggregator by AggregatorOptionSwitch1.Factory { param1: Param1 -> + * MyAggregator.Factory(param1) + * } + */ + fun Factory( + getAggregator: (param1: Param1) -> AggregatorProvider, + ) = Provider { name -> AggregatorOptionSwitch1(name, getAggregator) } + } } /** @@ -41,30 +44,32 @@ internal class AggregatorOptionSwitch1>( +internal class AggregatorOptionSwitch2( val name: String, - val getAggregator: (param1: Param1, param2: Param2) -> AggregatorProvider, + val getAggregator: (param1: Param1, param2: Param2) -> AggregatorProvider, ) { - private val cache: MutableMap, AggregatorType> = mutableMapOf() + private val cache: MutableMap, Aggregator> = mutableMapOf() - operator fun invoke(param1: Param1, param2: Param2): AggregatorType = + operator fun invoke(param1: Param1, param2: Param2): Aggregator = cache.getOrPut(param1 to param2) { getAggregator(param1, param2).create(name) } - /** - * Creates [AggregatorOptionSwitch2]. - * - * Used like: - * ```kt - * val myAggregator by AggregatorOptionSwitch2.Factory { param1: Param1, param2: Param2 -> - * MyAggregator.Factory(param1, param2) - * } - * ``` - */ - class Factory>( - val getAggregator: (param1: Param1, param2: Param2) -> AggregatorProvider, - ) : Provider> by - Provider({ name -> AggregatorOptionSwitch2(name, getAggregator) }) + @Suppress("FunctionName") + companion object { + + /** + * Creates [AggregatorOptionSwitch2]. + * + * Used like: + * ```kt + * val myAggregator by AggregatorOptionSwitch2.Factory { param1: Param1, param2: Param2 -> + * MyAggregator.Factory(param1, param2) + * } + */ + fun Factory( + getAggregator: (param1: Param1, param2: Param2) -> AggregatorProvider, + ) = Provider { name -> AggregatorOptionSwitch2(name, getAggregator) } + } } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorProvider.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorProvider.kt index 9c16fcdb59..fd1ef8db35 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorProvider.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/AggregatorProvider.kt @@ -25,4 +25,4 @@ internal operator fun Provider.getValue(obj: Any?, property: KProperty<*> * val myAggregator by MyAggregator.Factory * ``` */ -internal fun interface AggregatorProvider> : Provider +internal fun interface AggregatorProvider : Provider> diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt index c81f6af8e1..0a287fa085 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/Aggregators.kt @@ -1,8 +1,20 @@ package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.ReducingAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers.SelectingAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers.AnyInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers.NumberInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.FlatteningMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers.TwoStepMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.math.indexOfMax +import org.jetbrains.kotlinx.dataframe.math.indexOfMin +import org.jetbrains.kotlinx.dataframe.math.maxOrNull +import org.jetbrains.kotlinx.dataframe.math.maxTypeConversion import org.jetbrains.kotlinx.dataframe.math.mean import org.jetbrains.kotlinx.dataframe.math.meanTypeConversion import org.jetbrains.kotlinx.dataframe.math.median +import org.jetbrains.kotlinx.dataframe.math.minOrNull +import org.jetbrains.kotlinx.dataframe.math.minTypeConversion import org.jetbrains.kotlinx.dataframe.math.percentile import org.jetbrains.kotlinx.dataframe.math.std import org.jetbrains.kotlinx.dataframe.math.stdTypeConversion @@ -12,119 +24,122 @@ import org.jetbrains.kotlinx.dataframe.math.sumTypeConversion @PublishedApi internal object Aggregators { - /** - * Factory for a simple aggregator that preserves the type of the input values. - * - * @include [TwoStepAggregator] - */ - private fun twoStepPreservingType(aggregator: Aggregate) = - TwoStepAggregator.Factory( - getReturnTypeOrNull = preserveReturnTypeNullIfEmpty, - stepOneAggregator = aggregator, - stepTwoAggregator = aggregator, - ) + // TODO these might need some small refactoring + + private fun twoStepSelectingForAny( + getReturnType: CalculateReturnType, + indexOfResult: IndexOfResult, + stepOneReducer: Reducer, + ) = Aggregator( + aggregationHandler = SelectingAggregationHandler(stepOneReducer, indexOfResult, getReturnType), + inputHandler = AnyInputHandler(), + multipleColumnsHandler = TwoStepMultipleColumnsHandler(), + ) - /** - * Factory for a simple aggregator that changes the type of the input values. - * - * @include [TwoStepAggregator] - */ - private fun twoStepChangingType( - getReturnTypeOrNull: CalculateReturnTypeOrNull, - stepOneAggregator: Aggregate, - stepTwoAggregator: Aggregate, - ) = TwoStepAggregator.Factory( - getReturnTypeOrNull = getReturnTypeOrNull, - stepOneAggregator = stepOneAggregator, - stepTwoAggregator = stepTwoAggregator, + private fun twoStepReducingForAny( + getReturnType: CalculateReturnType, + stepOneReducer: Reducer, + stepTwoReducer: Reducer? = null, + ) = Aggregator( + aggregationHandler = ReducingAggregationHandler(stepOneReducer, getReturnType), + inputHandler = AnyInputHandler(), + multipleColumnsHandler = TwoStepMultipleColumnsHandler( + stepTwoAggregationHandler = stepTwoReducer?.let { + ReducingAggregationHandler(stepTwoReducer, getReturnType) + }, + ), ) - /** - * Factory for a flattening aggregator that preserves the type of the input values. - * - * @include [FlatteningAggregator] - */ - private fun flatteningPreservingTypes(aggregate: Aggregate) = - FlatteningAggregator.Factory( - getReturnTypeOrNull = preserveReturnTypeNullIfEmpty, - aggregator = aggregate, + private fun flattenReducingForAny(reducer: Reducer) = + Aggregator( + aggregationHandler = ReducingAggregationHandler(reducer, preserveReturnTypeNullIfEmpty), + inputHandler = AnyInputHandler(), + multipleColumnsHandler = FlatteningMultipleColumnsHandler(), ) - /** - * Factory for a flattening aggregator that changes the type of the input values. - * - * @include [FlatteningAggregator] - */ - private fun flatteningChangingTypes( - getReturnTypeOrNull: CalculateReturnTypeOrNull, - aggregate: Aggregate, - ) = FlatteningAggregator.Factory( - getReturnTypeOrNull = getReturnTypeOrNull, - aggregator = aggregate, + private fun flattenReducingForAny( + getReturnType: CalculateReturnType, + reducer: Reducer, + ) = Aggregator( + aggregationHandler = ReducingAggregationHandler(reducer, getReturnType), + inputHandler = AnyInputHandler(), + multipleColumnsHandler = FlatteningMultipleColumnsHandler(), ) - /** - * Factory for a two-step aggregator that works only with numbers. - * - * @include [TwoStepNumbersAggregator] - */ - private fun twoStepForNumbers( - getReturnTypeOrNull: CalculateReturnTypeOrNull, - aggregate: Aggregate, - ) = TwoStepNumbersAggregator.Factory( - getReturnTypeOrNull = getReturnTypeOrNull, - aggregate = aggregate, + private fun twoStepReducingForNumbers( + getReturnType: CalculateReturnType, + reducer: Reducer, + ) = Aggregator( + aggregationHandler = ReducingAggregationHandler(reducer, getReturnType), + inputHandler = NumberInputHandler(), + multipleColumnsHandler = TwoStepMultipleColumnsHandler(), ) /** @include [AggregatorOptionSwitch1] */ - private fun > withOneOption( - getAggregator: (Param1) -> AggregatorProvider, + private fun withOneOption( + getAggregator: (Param1) -> AggregatorProvider, ) = AggregatorOptionSwitch1.Factory(getAggregator) /** @include [AggregatorOptionSwitch2] */ - private fun > withTwoOptions( - getAggregator: (Param1, Param2) -> AggregatorProvider, + private fun withTwoOptions( + getAggregator: (Param1, Param2) -> AggregatorProvider, ) = AggregatorOptionSwitch2.Factory(getAggregator) // T: Comparable -> T? - val min by twoStepPreservingType> { - minOrNull() + // T : Comparable? -> T? + fun ?> min(skipNaN: Boolean): Aggregator = min.invoke(skipNaN).cast2() + + private val min by withOneOption { skipNaN: Boolean -> + twoStepSelectingForAny, Comparable?>( + getReturnType = minTypeConversion, + stepOneReducer = { type -> minOrNull(type, skipNaN) }, + indexOfResult = { type -> indexOfMin(type, skipNaN) }, + ) } // T: Comparable -> T? - val max by twoStepPreservingType> { - maxOrNull() + // T : Comparable? -> T? + fun ?> max(skipNaN: Boolean): Aggregator = max.invoke(skipNaN).cast2() + + private val max by withOneOption { skipNaN: Boolean -> + twoStepSelectingForAny, Comparable?>( + getReturnType = maxTypeConversion, + stepOneReducer = { type -> maxOrNull(type, skipNaN) }, + indexOfResult = { type -> indexOfMax(type, skipNaN) }, + ) } // T: Number? -> Double val std by withTwoOptions { skipNA: Boolean, ddof: Int -> - flatteningChangingTypes(stdTypeConversion) { type -> - std(type, skipNA, ddof) + flattenReducingForAny(stdTypeConversion) { type -> + asIterable().std(type, skipNA, ddof) } } // step one: T: Number? -> Double // step two: Double -> Double - val mean by withOneOption { skipNA: Boolean -> - twoStepForNumbers(meanTypeConversion) { type -> - mean(type, skipNA) + val mean by withOneOption { skipNaN: Boolean -> + twoStepReducingForNumbers(meanTypeConversion) { type -> + mean(type, skipNaN) } } // T: Comparable? -> T val percentile by withOneOption { percentile: Double -> - flatteningPreservingTypes> { type -> - percentile(percentile, type) + flattenReducingForAny> { type -> + asIterable().percentile(percentile, type) } } // T: Comparable? -> T - val median by flatteningPreservingTypes> { type -> - median(type) + val median by flattenReducingForAny> { type -> + asIterable().median(type) } // T: Number -> T - val sum by twoStepForNumbers(sumTypeConversion) { type -> - sum(type) + val sum by withOneOption { skipNaN: Boolean -> + twoStepReducingForNumbers(sumTypeConversion) { type -> + sum(type, skipNaN) + } } } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/FlatteningAggregator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/FlatteningAggregator.kt deleted file mode 100644 index 1ba0c41eae..0000000000 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/FlatteningAggregator.kt +++ /dev/null @@ -1,81 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators - -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.impl.commonType -import kotlin.reflect.KType -import kotlin.reflect.full.withNullability - -/** - * Simple [Aggregator] implementation with flattening behavior for multiple columns. - * - * Nulls are filtered out. - * - * When called on multiple columns, - * the columns are flattened into a single list of values, filtering nulls as usual; - * then the aggregation function is called with their common type. - * - * ``` - * Iterable> - * -> Iterable // flattened without nulls - * -> aggregator(Iterable, common colType) - * -> Return - * ``` - * - * This is essential for aggregators that depend on the distribution of all values across the dataframe, like - * the median, percentile, and standard deviation. - * - * See [TwoStepAggregator] for different behavior for multiple columns. - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate] function. - * Note that it must be able to handle `null` values for the [Iterable] overload of [aggregate]. - */ -internal class FlatteningAggregator( - name: String, - getReturnTypeOrNull: CalculateReturnTypeOrNull, - aggregator: Aggregate, -) : AggregatorBase(name, getReturnTypeOrNull, aggregator) { - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - * The columns are flattened into a single list of values, filtering nulls as usual; - * then the aggregation function is with the common type of the columns. - */ - override fun aggregate(columns: Iterable>): Return { - val commonType = columns.map { it.type() }.commonType().withNullability(false) - val allValues = columns.asSequence().flatMap { it.values() }.filterNotNull() - return aggregate(allValues.asIterable(), commonType) - } - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - override fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? { - val commonType = colTypes.commonType().withNullability(false) - return calculateReturnTypeOrNull(commonType, colsEmpty) - } - - /** - * Creates [FlatteningAggregator]. - * - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate] function. - */ - class Factory( - private val getReturnTypeOrNull: CalculateReturnTypeOrNull, - private val aggregator: Aggregate, - ) : AggregatorProvider> by AggregatorProvider({ name -> - FlatteningAggregator( - name = name, - getReturnTypeOrNull = getReturnTypeOrNull, - aggregator = aggregator, - ) - }) -} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator.kt deleted file mode 100644 index b593f4f261..0000000000 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepAggregator.kt +++ /dev/null @@ -1,105 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators - -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.columns.isEmpty -import org.jetbrains.kotlinx.dataframe.impl.commonType -import kotlin.reflect.KType -import kotlin.reflect.full.starProjectedType -import kotlin.reflect.full.withNullability - -/** - * A slightly more advanced [Aggregator] implementation. - * - * Nulls are filtered out. - * - * When called on multiple columns, this [Aggregator] works in two steps: - * First, it aggregates within a [DataColumn]/[Iterable] ([stepOneAggregator]) with their (given) type, - * and then in between different columns ([stepTwoAggregator]) using the results of the first and the newly - * calculated common type of those results. - * - * ``` - * Iterable> - * -> Iterable> // nulls filtered out - * -> stepOneAggregator(Iterable, colType) // called on each iterable - * -> Iterable // nulls filtered out - * -> stepTwoAggregator(Iterable, common valueType) - * -> Return - * ``` - * - * It can also be used as a "simple" aggregator by providing the same function for both steps. - * - * See [FlatteningAggregator] for different behavior for multiple columns. - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param stepOneAggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable]. - * @param stepTwoAggregator Functional argument for the aggregation function used between different columns. - * It is run on the results of [stepOneAggregator]. - */ -internal class TwoStepAggregator( - name: String, - getReturnTypeOrNull: CalculateReturnTypeOrNull, - stepOneAggregator: Aggregate, - private val stepTwoAggregator: Aggregate, -) : AggregatorBase(name, getReturnTypeOrNull, stepOneAggregator) { - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - * - * This function calls [stepOneAggregator] on each column and then [stepTwoAggregator] on the results. - * - * Post-step-one types are calculated by [calculateReturnTypeOrNull]. - */ - override fun aggregate(columns: Iterable>): Return { - val (values, types) = columns.mapNotNull { col -> - // uses stepOneAggregator - val value = aggregate(col) ?: return@mapNotNull null - val type = calculateReturnTypeOrNull( - type = col.type().withNullability(false), - emptyInput = col.isEmpty, - ) ?: value::class.starProjectedType // heavy fallback type calculation - - value to type - }.unzip() - val commonType = types.commonType() - return stepTwoAggregator(values, commonType) - } - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - override fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? { - val typesAfterStepOne = colTypes.map { type -> - calculateReturnTypeOrNull(type = type.withNullability(false), emptyInput = colsEmpty) - } - if (typesAfterStepOne.any { it == null }) return null - return typesAfterStepOne.commonType() - } - - /** - * Creates [TwoStepAggregator]. - * - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param stepOneAggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable]. - * @param stepTwoAggregator Functional argument for the aggregation function used between different columns. - * It is run on the results of [stepOneAggregator]. - */ - class Factory( - private val getReturnTypeOrNull: CalculateReturnTypeOrNull, - private val stepOneAggregator: Aggregate, - private val stepTwoAggregator: Aggregate, - ) : AggregatorProvider> by AggregatorProvider({ name -> - TwoStepAggregator( - name = name, - getReturnTypeOrNull = getReturnTypeOrNull, - stepOneAggregator = stepOneAggregator, - stepTwoAggregator = stepTwoAggregator, - ) - }) -} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepNumbersAggregator.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepNumbersAggregator.kt deleted file mode 100644 index 8cfc4e92a7..0000000000 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/TwoStepNumbersAggregator.kt +++ /dev/null @@ -1,199 +0,0 @@ -package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators - -import io.github.oshai.kotlinlogging.KotlinLogging -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.columns.isEmpty -import org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers -import org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions.Companion.PRIMITIVES_ONLY -import org.jetbrains.kotlinx.dataframe.impl.anyNull -import org.jetbrains.kotlinx.dataframe.impl.convertToUnifiedNumberType -import org.jetbrains.kotlinx.dataframe.impl.isNothing -import org.jetbrains.kotlinx.dataframe.impl.nothingType -import org.jetbrains.kotlinx.dataframe.impl.primitiveNumberTypes -import org.jetbrains.kotlinx.dataframe.impl.renderType -import org.jetbrains.kotlinx.dataframe.impl.types -import org.jetbrains.kotlinx.dataframe.impl.unifiedNumberTypeOrNull -import kotlin.reflect.KType -import kotlin.reflect.full.isSubtypeOf -import kotlin.reflect.full.starProjectedType -import kotlin.reflect.full.withNullability -import kotlin.reflect.typeOf - -private val logger = KotlinLogging.logger { } - -/** - * [Aggregator] made specifically for number calculations. - * Mixed number types are [unified][UnifyingNumbers] to [primitives][PRIMITIVES_ONLY]. - * - * Nulls are filtered out. - * - * When called on multiple columns (with potentially mixed [Number] types), - * this [Aggregator] works in two steps: - * - * First, it aggregates within a [DataColumn]/[Iterable] with their (given) [Number] type - * (potentially unifying the types), and then between different columns - * using the results of the first and the newly calculated [unified number][UnifyingNumbers] type of those results. - * - * ``` - * Iterable> - * -> Iterable> // nulls filtered out - * -> aggregator(Iterable, unified number type of common colType) // called on each iterable - * -> Iterable // nulls filtered out - * -> aggregator(Iterable, unified number type of common valueType) - * -> Return - * ``` - * - * @param name The name of this aggregator. - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable]. - * While it takes a [Number] argument, you can assume that all values are of the same specific type, however, - * this type can be different for different calls to [aggregator]. - */ -internal class TwoStepNumbersAggregator( - name: String, - getReturnTypeOrNull: CalculateReturnTypeOrNull, - aggregator: Aggregate, -) : AggregatorBase(name, getReturnTypeOrNull, aggregator) { - - /** - * Aggregates the data in the multiple given columns and computes a single resulting value. - * - * This function calls [aggregator] on each column and then again on the results. - * - * After the first aggregation, the number types are found by [calculateReturnTypeOrNull] and then - * unified using [aggregateCalculatingType]. - */ - override fun aggregate(columns: Iterable>): Return { - val (values, types) = columns.mapNotNull { col -> - val value = aggregate(col) ?: return@mapNotNull null - val type = calculateReturnTypeOrNull( - type = col.type().withNullability(false), - emptyInput = col.isEmpty, - ) ?: value::class.starProjectedType // heavy fallback type calculation - - value to type - }.unzip() - - return aggregateCalculatingType( - values = values, - valueTypes = types.toSet(), - ) - } - - /** - * Function that can give the return type of [aggregate] with columns as [KType], - * given the multiple types of the input. - * This allows aggregators to avoid runtime type calculations. - * - * @param colTypes The types of the input columns. - * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. - * @return The return type of [aggregate] as [KType]. - */ - @Suppress("UNCHECKED_CAST") - override fun calculateReturnTypeOrNull(colTypes: Set, colsEmpty: Boolean): KType? { - val typesAfterStepOne = colTypes.map { type -> - calculateReturnTypeOrNull(type = type.withNullability(false), emptyInput = colsEmpty) - } - if (typesAfterStepOne.anyNull()) return null - val typeSet = (typesAfterStepOne as List).toSet() - val unifiedType = typeSet.unifiedNumberTypeOrNull(PRIMITIVES_ONLY) - ?.withNullability(false) - ?: throw IllegalArgumentException( - "Cannot calculate the $name of the number types: ${typeSet.joinToString { renderType(it) }}. " + - "Note, only primitive number types are supported in statistics.", - ) - - return unifiedType - } - - /** - * Base function of [Aggregator]. - * - * Aggregates the given values, taking [type] into account, and computes a single resulting value. - * - * Nulls are filtered out (only if [type.isMarkedNullable][KType.isMarkedNullable]). - * - * Uses [aggregator] to compute the result. - * - * This function is modified to call [aggregateCalculatingType] when it encounters mixed number types. - * This is not optimal and should be avoided by calling [aggregateCalculatingType] with known number types directly. - * - * When the exact [type] is unknown, use [aggregateCalculatingType]. - */ - override fun aggregate(values: Iterable, type: KType): Return { - require(type.isSubtypeOf(typeOf())) { - "${TwoStepNumbersAggregator::class.simpleName}: Type $type is not a subtype of Number?" - } - return when (type.withNullability(false)) { - // If the type is not a specific number, but rather a mixed Number, we unify the types first. - // This is heavy and could be avoided by calling aggregate with a specific number type - // or calling aggregateCalculatingType with all known number types - typeOf() -> aggregateCalculatingType(values) - - // Nothing can occur when values are empty - nothingType -> super.aggregate(values, type) - - !in primitiveNumberTypes -> throw IllegalArgumentException( - "Cannot calculate $name of ${renderType(type)}, only primitive numbers are supported.", - ) - - else -> super.aggregate(values, type) - } - } - - /** - * Special case of [aggregate] with [Iterable] that calculates the [unified number type][UnifyingNumbers] - * of the values at runtime and converts all numbers to this type before aggregating. - * Without [valueTypes], this is a heavy operation and should be avoided when possible. - * - * @param values The numbers to be aggregated. - * @param valueTypes The types of the numbers. - * If provided, this can be used to avoid calculating the types of [values] at runtime with reflection. - * It should contain all types of [values]. - * If `null` or empty, the types of [values] will be calculated at runtime (heavy!). - */ - @Suppress("UNCHECKED_CAST") - override fun aggregateCalculatingType(values: Iterable, valueTypes: Set?): Return { - val valueTypes = valueTypes?.takeUnless { it.isEmpty() } ?: values.types() - val unifiedType = valueTypes.unifiedNumberTypeOrNull(PRIMITIVES_ONLY) - ?: throw IllegalArgumentException( - "Cannot calculate the $name of the number types: ${valueTypes.joinToString { renderType(it) }}. " + - "Note, only primitive number types are supported in statistics.", - ) - - if (unifiedType.isSubtypeOf(typeOf()) && - (typeOf() in valueTypes || typeOf() in valueTypes) - ) { - logger.warn { - "Number unification of Long -> Double happened during aggregation. Loss of precision may have occurred." - } - } - if (unifiedType.withNullability(false) !in primitiveNumberTypes && !unifiedType.isNothing) { - throw IllegalArgumentException( - "Cannot calculate $name of ${renderType(unifiedType)}, only primitive numbers are supported.", - ) - } - - return super.aggregate( - values = values.convertToUnifiedNumberType(commonNumberType = unifiedType), - type = unifiedType, - ) - } - - /** - * Creates [TwoStepNumbersAggregator]. - * - * @param getReturnTypeOrNull Functional argument for the [calculateReturnTypeOrNull] function. - * @param aggregator Functional argument for the [aggregate] function, used within a [DataColumn] or [Iterable]. - */ - class Factory( - private val getReturnTypeOrNull: CalculateReturnTypeOrNull, - private val aggregate: Aggregate, - ) : AggregatorProvider> by AggregatorProvider({ name -> - TwoStepNumbersAggregator( - name = name, - getReturnTypeOrNull = getReturnTypeOrNull, - aggregator = aggregate, - ) - }) -} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType.kt new file mode 100644 index 0000000000..be886c9578 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/ValueType.kt @@ -0,0 +1,15 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators + +import kotlin.reflect.KType + +/** + * Represents the type of values in a column as the input of an aggregator. + * + * @param [kType] The target type of the values. + * @param [needsFullConversion] Whether explicit conversion to [kType] is needed + * for the values to become the correct value type. If `false`, the values are already the right type, + * or a simple cast will suffice. + */ +internal data class ValueType(val kType: KType, val needsFullConversion: Boolean = false) + +internal fun KType.toValueType(needsFullConversion: Boolean = false): ValueType = ValueType(this, needsFullConversion) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/aggregationHandlers/ReducingAggregationHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/aggregationHandlers/ReducingAggregationHandler.kt new file mode 100644 index 0000000000..9eb9a45ffc --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/aggregationHandlers/ReducingAggregationHandler.kt @@ -0,0 +1,79 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers + +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.api.asSequence +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Reducer +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.ValueType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregateCalculatingValueType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.calculateValueType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.toValueType +import kotlin.reflect.KType +import kotlin.reflect.full.withNullability + +/** + * Implementation of [AggregatorAggregationHandler] which functions like a reducer: + * it takes a sequence of values and returns a single value, which can be a completely different type. + * + * @param reducer This function actually does the reduction. + * Before it is called, nulls are filtered out. The type of the values is passed as [KType] to the reducer. + * @param getReturnType This function must be supplied to give the return type of [reducer] given some input type and + * whether the input is empty. + * @see [SelectingAggregationHandler] + */ +internal class ReducingAggregationHandler( + val reducer: Reducer, + val getReturnType: CalculateReturnType, +) : AggregatorAggregationHandler { + + /** + * Base function of [Aggregator]. + * + * Aggregates the given values, taking [valueType] into account, + * filtering nulls (only if [valueType.type.isMarkedNullable][KType.isMarkedNullable]), + * and computes a single resulting value. + * + * When the exact [valueType] is unknown, use [calculateValueType] or [aggregateCalculatingValueType]. + * + * Calls the supplied [reducer]. + */ + @Suppress("UNCHECKED_CAST") + override fun aggregateSequence(values: Sequence, valueType: ValueType): Return { + val (values, valueType) = aggregator!!.preprocessAggregation(values, valueType) + return reducer( + // values = + if (valueType.isMarkedNullable) { + values.filterNotNull() + } else { + values as Sequence + }, + // type = + valueType.withNullability(false), + ) + } + + /** + * Aggregates the data in the given column and computes a single resulting value. + * Calls [aggregateSequence]. + */ + @Suppress("UNCHECKED_CAST") + override fun aggregateSingleColumn(column: DataColumn): Return = + aggregateSequence( + values = column.asSequence(), + valueType = column.type().toValueType(), + ) + + /** This function always returns `-1` because the result of a reducer is not in the input values. */ + override fun indexOfAggregationResultSingleSequence(values: Sequence, valueType: ValueType): Int = -1 + + /** + * Give the return type of [reducer] given some input type and whether the input is empty. + * Calls the supplied [getReturnType]. + */ + override fun calculateReturnType(valueType: KType, emptyInput: Boolean): KType = + getReturnType(valueType.withNullability(false), emptyInput) + + override var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? = null +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/aggregationHandlers/SelectingAggregationHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/aggregationHandlers/SelectingAggregationHandler.kt new file mode 100644 index 0000000000..695add4a02 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/aggregationHandlers/SelectingAggregationHandler.kt @@ -0,0 +1,99 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregationHandlers + +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.api.asSequence +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.IndexOfResult +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Selector +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.ValueType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregateCalculatingValueType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.calculateValueType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.toValueType +import kotlin.reflect.KType +import kotlin.reflect.full.withNullability + +/** + * Implementation of [AggregatorAggregationHandler] which functions like a selector: + * it takes a sequence of values and returns a single value, which must exist in the input. + * + * This is reflected in the type constraints. + * + * @param selector This function actually does the selection. + * Before it is called, nulls are filtered out. The type of the values is passed as [KType] to the selector. + * @param indexOfResult This function must be supplied to give the index of the result in the input values. + * @param getReturnType This function must be supplied to give the return type of [selector] given some input type and + * whether the input is empty. + * In practice the return type is always either `typeOf()` or `typeOf()`. + * @see [ReducingAggregationHandler] + */ +internal class SelectingAggregationHandler( + val selector: Selector, + val indexOfResult: IndexOfResult, + val getReturnType: CalculateReturnType, +) : AggregatorAggregationHandler { + + /** + * Function that can give the index of the aggregation result in the input [values]. + * Calls the supplied [indexOfResult] after preprocessing the input. + */ + @Suppress("UNCHECKED_CAST") + override fun indexOfAggregationResultSingleSequence(values: Sequence, valueType: ValueType): Int { + val (values, valueType) = aggregator!!.preprocessAggregation(values, valueType) + return indexOfResult(values, valueType) + } + + /** + * Base function of [Aggregator]. + * + * Aggregates the given values, taking [valueType] into account, + * filtering nulls (only if [valueType.type.isMarkedNullable][KType.isMarkedNullable]), + * and computes a single resulting value. + * + * When the exact [valueType] is unknown, use [calculateValueType] or [aggregateCalculatingValueType]. + * + * Calls the supplied [selector]. + */ + @Suppress("UNCHECKED_CAST") + override fun aggregateSequence(values: Sequence, valueType: ValueType): Return { + val (values, valueType) = aggregator!!.preprocessAggregation(values, valueType) + return selector( + // values = + if (valueType.isMarkedNullable) { + values.filterNotNull() + } else { + values as Sequence + }, + // type = + valueType.withNullability(false), + ) + } + + /** + * Aggregates the data in the given column and computes a single resulting value. + * Calls [aggregateSequence]. + */ + override fun aggregateSingleColumn(column: DataColumn): Return = + aggregateSequence( + values = column.asSequence(), + valueType = column.type().toValueType(), + ) + + /** + * Give the return type of [selector] given some input type and whether the input is empty. + * Calls the supplied [getReturnType]. + * + * In practice the return type is always either `typeOf()` or `typeOf()`. + */ + override fun calculateReturnType(valueType: KType, emptyInput: Boolean): KType = + getReturnType(valueType.withNullability(false), emptyInput).also { + require(it == valueType.withNullability(false) || it == valueType.withNullability(true)) { + "The return type of the selector must be either ${valueType.withNullability(false)} or ${ + valueType.withNullability(true) + }" + } + } + + override var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? = null +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/AnyInputHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/AnyInputHandler.kt new file mode 100644 index 0000000000..b18592e1bf --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/AnyInputHandler.kt @@ -0,0 +1,56 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers + +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.ValueType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregate +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.toValueType +import org.jetbrains.kotlinx.dataframe.impl.commonType +import org.jetbrains.kotlinx.dataframe.impl.nothingType +import kotlin.reflect.KType + +/** + * Input handler for aggregators that can handle any type of input. + * + * When calculating the value type, it will try to find the common type in terms of inheritance. + */ +internal class AnyInputHandler : AggregatorInputHandler { + + /** No preprocessing is done on the input values. */ + override fun preprocessAggregation( + values: Sequence, + valueType: ValueType, + ): Pair, KType> = Pair(values, valueType.kType) + + /** + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it in terms of inheritance by combining the set of known [valueTypes]. + */ + override fun calculateValueType(valueTypes: Set): ValueType = valueTypes.commonType(false).toValueType() + + /** + * WARNING: HEAVY! + * + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it in terms of inheritance by getting the types of [values] at runtime. + * This is heavy because it uses reflection on each value. + */ + override fun calculateValueType(values: Sequence): ValueType { + var hasNulls = false + val classes = values.mapNotNull { + if (it == null) { + hasNulls = true + null + } else { + it.javaClass.kotlin + } + }.toSet() + return if (classes.isEmpty()) { + nothingType(hasNulls) + } else { + classes.commonType(hasNulls) + }.toValueType() + } + + override var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? = null +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt new file mode 100644 index 0000000000..e6803f90e9 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/inputHandlers/NumberInputHandler.kt @@ -0,0 +1,145 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.inputHandlers + +import io.github.oshai.kotlinlogging.KotlinLogging +import org.jetbrains.kotlinx.dataframe.documentation.UnifyingNumbers +import org.jetbrains.kotlinx.dataframe.impl.UnifiedNumberTypeOptions +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.ValueType +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregate +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.toValueType +import org.jetbrains.kotlinx.dataframe.impl.convertToUnifiedNumberType +import org.jetbrains.kotlinx.dataframe.impl.isMixedNumber +import org.jetbrains.kotlinx.dataframe.impl.isNothing +import org.jetbrains.kotlinx.dataframe.impl.isPrimitiveOrMixedNumber +import org.jetbrains.kotlinx.dataframe.impl.nothingType +import org.jetbrains.kotlinx.dataframe.impl.primitiveNumberTypes +import org.jetbrains.kotlinx.dataframe.impl.renderType +import org.jetbrains.kotlinx.dataframe.impl.types +import org.jetbrains.kotlinx.dataframe.impl.unifiedNumberTypeOrNull +import kotlin.reflect.KType +import kotlin.reflect.full.isSubtypeOf +import kotlin.reflect.full.withNullability +import kotlin.reflect.typeOf + +private val logger = KotlinLogging.logger { } + +/** + * Input handler for aggregators that can handle any (mixed) primitive [Number] type of input. + * + * When calculating the value type, + * it will try to find the common type in terms of [number unification][UnifyingNumbers]. + * Preprocessing will handle the conversion of the values in the input to this unified number type. + */ +internal class NumberInputHandler : AggregatorInputHandler { + + /** + * Preprocesses the input values before aggregation. + * + * - If [ValueType.kType] is a primitive number type and [ValueType.needsFullConversion], + * then the values are converted to [ValueType.kType]. + * + * - If [ValueType.kType] is given as [Number]`(?)`, then we first calculate the unified type and convert to that. + * This is heavy and should be avoided if possible. + * + * @throws IllegalArgumentException if the input type is not [Number]`(?)` or a primitive number type. + */ + override fun preprocessAggregation( + values: Sequence, + valueType: ValueType, + ): Pair, KType> { + require(valueType.kType.isSubtypeOf(typeOf())) { + "Type $valueType is not a subtype of Number?, only primitive numbers are supported in ${aggregator!!.name}." + } + return when (valueType.kType.withNullability(false)) { + // If the type is not a specific number, but rather a mixed Number, we unify the types first. + // This is heavy and could be avoided by calling aggregate with a specific number type + // or calling aggregateCalculatingType with all known number types + typeOf() -> { + val unifiedType = calculateValueType(values).kType + + // If calculateValueType returns Number(?), + // it means the values cannot be unified to a primitive number type + require(!unifiedType.isMixedNumber()) { + "Types ${ + values.asIterable().types().toSet() + } are not all primitive numbers, only those are supported in ${aggregator!!.name}." + } + + val unifiedValues = values.convertToUnifiedNumberType( + UnifiedNumberTypeOptions.PRIMITIVES_ONLY, + unifiedType, + ) + Pair(unifiedValues, unifiedType) + } + + // Nothing can occur when values are empty + nothingType -> Pair(values, valueType.kType) + + !in primitiveNumberTypes -> throw IllegalArgumentException( + "Cannot calculate ${aggregator!!.name} of ${ + renderType(valueType.kType) + }, only primitive numbers are supported in statistics.", + ) + + else -> { + val unifiedValues = if (valueType.needsFullConversion) { + values.convertToUnifiedNumberType( + UnifiedNumberTypeOptions.PRIMITIVES_ONLY, + valueType.kType, + ) + } else { + values + } + Pair(unifiedValues, valueType.kType) + } + } + } + + /** + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it in terms of [number unification][UnifyingNumbers] + * + * @throws IllegalArgumentException if the input type is not [Number]`(?)` or a primitive number type. + * @return The (primitive) unified number type of the input values. + * If no valid unification can be found or the input is solely [Number]`(?)`, the type [Number]`(?)` is returned. + */ + override fun calculateValueType(valueTypes: Set): ValueType { + val unifiedType = valueTypes.unifiedNumberTypeOrNull(UnifiedNumberTypeOptions.Companion.PRIMITIVES_ONLY) + ?: typeOf().withNullability(valueTypes.any { it.isMarkedNullable }) + + if (unifiedType.isSubtypeOf(typeOf()) && + (typeOf() in valueTypes || typeOf() in valueTypes) + ) { + logger.warn { + "Number unification of Long -> Double happened during ${aggregator!!.name} aggregation. Loss of precision may have occurred." + } + } + if (!unifiedType.isPrimitiveOrMixedNumber() && !unifiedType.isNothing) { + throw IllegalArgumentException( + "Cannot calculate ${aggregator!!.name} of ${ + renderType(unifiedType) + }, only primitive numbers are supported.", + ) + } + + return unifiedType.toValueType(needsFullConversion = valueTypes.singleOrNull() != unifiedType) + } + + /** + * WARNING: HEAVY! + * + * If the specific [ValueType] of the input is not known, but you still want to call [aggregate], + * this function can be called to calculate it in terms of [number unification][UnifyingNumbers] + * by getting the types of [values] at runtime. + * This is heavy because it uses reflection on each value. + * + * @throws IllegalArgumentException if the input type is not [Number]`(?)` or a primitive number type. + * @return The (primitive) unified number type of the input values. + * If no valid unification can be found or the input is solely [Number]`(?)`, the type [Number]`(?)` is returned. + */ + override fun calculateValueType(values: Sequence): ValueType = + calculateValueType(values.asIterable().types().toSet()) + + override var aggregator: Aggregator? = null +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/FlatteningMultipleColumnsHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/FlatteningMultipleColumnsHandler.kt new file mode 100644 index 0000000000..f933ff09d5 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/FlatteningMultipleColumnsHandler.kt @@ -0,0 +1,43 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers + +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.api.asSequence +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorMultipleColumnsHandler +import kotlin.reflect.KType + +/** + * Implementation of [AggregatorMultipleColumnsHandler] that simply flattens all input columns. + * This is useful for aggregators that depend on the distribution of values across multiple columns. + * + * @see [TwoStepMultipleColumnsHandler] + */ +internal class FlatteningMultipleColumnsHandler : + AggregatorMultipleColumnsHandler { + + /** + * Aggregates the data in the multiple given columns and computes a single resulting value. + * The columns are flattened into a single list of values; + * then the aggregation function is called with the common type of the columns. + */ + override fun aggregateMultipleColumns(columns: Sequence>): Return { + val allValues = columns.flatMap { it.asSequence() } + val commonType = aggregator!!.calculateValueType(columns.map { it.type() }.toSet()) + return aggregator!!.aggregateSequence(allValues, commonType) + } + + /** + * Function that can give the return type of [aggregateMultipleColumns], given types of the columns. + * This allows aggregators to avoid runtime type calculations. + * + * @param colTypes The types of the input columns. + * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. + */ + override fun calculateReturnTypeMultipleColumns(colTypes: Set, colsEmpty: Boolean): KType = + aggregator!!.calculateReturnType( + valueType = aggregator!!.calculateValueType(colTypes).kType, + emptyInput = colsEmpty, + ) + + override var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? = null +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/NoMultipleColumnsHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/NoMultipleColumnsHandler.kt new file mode 100644 index 0000000000..eec939524f --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/NoMultipleColumnsHandler.kt @@ -0,0 +1,16 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers + +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorMultipleColumnsHandler +import kotlin.reflect.KType + +internal class NoMultipleColumnsHandler : + AggregatorMultipleColumnsHandler { + + override fun aggregateMultipleColumns(columns: Sequence>): Return = error("") + + override fun calculateReturnTypeMultipleColumns(colTypes: Set, colsEmpty: Boolean): KType = error("") + + override var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? = null +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/TwoStepMultipleColumnsHandler.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/TwoStepMultipleColumnsHandler.kt new file mode 100644 index 0000000000..e53e6470a4 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/aggregators/multipleColumnsHandlers/TwoStepMultipleColumnsHandler.kt @@ -0,0 +1,92 @@ +package org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.multipleColumnsHandlers + +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.columns.isEmpty +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorAggregationHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorInputHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.AggregatorMultipleColumnsHandler +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregateCalculatingValueType +import kotlin.reflect.KType + +/** + * Implementation of [AggregatorMultipleColumnsHandler] that aggregates the data in two steps: + * - first, it aggregates the data for each of the given columns + * - then, it aggregates the results of the first step into a single value + * + * For the first step, this [aggregator] will be used as usual. + * + * For the second step, a [new][stepTwo] [Aggregator] will be constructed using the supplied handlers: + * [stepTwoAggregationHandler] and [stepTwoInputHandler]. + * For both arguments, it holds that if they are not supplied or `null`, + * the handlers of this [aggregator] will be cast and reused. + * In all cases [NoMultipleColumnsHandler] will be used as [AggregatorMultipleColumnsHandler]. + * + * This is useful for aggregators that do not depend on the distribution of values across multiple columns. + * It may be more memory efficient than [FlatteningMultipleColumnsHandler] and could be parallelized in the future. + * + * @param stepTwoAggregationHandler The [aggregation handler][AggregatorAggregationHandler] for the second step. + * If not supplied, the handler of the first step is reused. + * @param stepTwoInputHandler The [input handler][AggregatorInputHandler] for the second step. + * If not supplied, the handler of the first step is reused. + * @see [FlatteningMultipleColumnsHandler] + */ +internal class TwoStepMultipleColumnsHandler( + stepTwoAggregationHandler: AggregatorAggregationHandler? = null, + stepTwoInputHandler: AggregatorInputHandler? = null, +) : AggregatorMultipleColumnsHandler { + + /** + * The second step [Aggregator] which can take multiple outputs of + * this [aggregator] and aggregate it to a single value. + */ + @Suppress("UNCHECKED_CAST") + val stepTwo by lazy { + Aggregator( + aggregationHandler = stepTwoAggregationHandler + ?: aggregator as AggregatorAggregationHandler, + inputHandler = stepTwoInputHandler ?: aggregator as AggregatorInputHandler, + multipleColumnsHandler = NoMultipleColumnsHandler(), + ).create(aggregator!!.name) + } + + /** + * Aggregates the data in the multiple given columns and computes a single resulting value. + * + * This function calls [aggregator][aggregator] [.aggregateSingleColumn()][Aggregator.aggregateSingleColumn] + * on each column and then [stepTwo] [.aggregateSequence()][Aggregator.aggregateSequence] on the results. + */ + override fun aggregateMultipleColumns(columns: Sequence>): Return { + val (values, types) = columns.map { col -> + val value = aggregator!!.aggregateSingleColumn(col) + val type = aggregator!!.calculateReturnType( + valueType = col.type(), + emptyInput = col.isEmpty, + ) + value to type + }.unzip() + + return stepTwo.aggregateCalculatingValueType(values.asSequence(), types.toSet()) + } + + /** + * Function that can give the return type of [aggregateMultipleColumns], given types of the columns. + * This allows aggregators to avoid runtime type calculations. + * + * @param colTypes The types of the input columns. + * @param colsEmpty If `true`, all the input columns are considered empty. This often affects the return type. + */ + @Suppress("UNCHECKED_CAST") + override fun calculateReturnTypeMultipleColumns(colTypes: Set, colsEmpty: Boolean): KType { + val typesAfterStepOne = colTypes.map { type -> + aggregator!!.calculateReturnType(valueType = type, emptyInput = colsEmpty) + } + val stepTwoValueType = stepTwo.calculateValueType(typesAfterStepOne.toSet()) + return stepTwo.calculateReturnType( + valueType = stepTwoValueType.kType, + emptyInput = colsEmpty, + ) + } + + override var aggregator: Aggregator<@UnsafeVariance Value, @UnsafeVariance Return>? = null +} diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/aggregateBy.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/aggregateBy.kt index 659180a3aa..ebf10a5fd8 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/aggregateBy.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/aggregateBy.kt @@ -1,17 +1,25 @@ 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 Grouped.aggregateBy(body: DataFrameExpression?>): DataFrame { +internal fun Grouped.aggregateByOrNull(body: DataFrameExpression?>): DataFrame { require(this is GroupBy<*, T>) val keyColumns = keys.columnNames().toSet() return aggregateInternal { @@ -21,3 +29,90 @@ internal fun Grouped.aggregateBy(body: DataFrameExpression? } }.cast() } + +/** + * Selects the best matching value in the [sequence][values] + * using the provided [Aggregator] `by` the provided [selector]. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + values: Sequence, + crossinline selector: (T) -> V, +): T? = + values.elementAtOrNull( + indexOfAggregationResult( + values = values.map { selector(it) }, + valueType = typeOf(), + ), + ) + +/** + * Selects the best matching value in the [iterable][values] + * using the provided [Aggregator] `by` the provided [selector]. + * + * Faster implementation than for sequences. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + values: Iterable, + crossinline selector: (T) -> V, +): T? = + values.elementAtOrNull( + indexOfAggregationResult( + values = values.asSequence().map { selector(it) }, + valueType = typeOf(), + ), + ) + +/** + * Selects the best matching value in the [column] using the provided [Aggregator] `by` the provided [selector]. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + column: DataColumn, + crossinline selector: (T) -> V, +): T? = aggregateByOrNull(column.values(), selector) + +/** + * Selects the best matching value in the [dataframe][data] + * using the provided [Aggregator] `by` the provided [rowExpression]. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + data: DataFrame, + crossinline rowExpression: RowExpression, +): DataRow? = + data.getOrNull( + indexOfAggregationResult( + values = data.asSequence().map { rowExpression(it, it) }, + valueType = typeOf(), + ), + ) + +/** + * Selects the best matching value in the [dataframe][data] + * using the provided [Aggregator] `by` the provided [column]. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@PublishedApi +internal inline fun Aggregator.aggregateByOrNull( + data: DataFrame, + column: ColumnReference, +): DataRow? = + data.getOrNull( + indexOfAggregationResult( + values = data.asSequence().map { it[column] }, + valueType = typeOf(), + ), + ) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/forEveryColumn.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/forEveryColumn.kt index 70e55e2f8b..8650779aa0 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/forEveryColumn.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/forEveryColumn.kt @@ -15,7 +15,7 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.internal import org.jetbrains.kotlinx.dataframe.impl.aggregation.receivers.AggregateInternalDsl import org.jetbrains.kotlinx.dataframe.type -internal fun Aggregator<*, R>.aggregateFor( +internal fun Aggregator<*, R>.aggregateFor( data: Grouped, columns: ColumnsForAggregateSelector, ): DataFrame = @@ -23,7 +23,7 @@ internal fun Aggregator<*, R>.aggregateFor( aggregateFor(columns, cast()) } -internal fun Aggregator<*, R>.aggregateFor( +internal fun Aggregator<*, R>.aggregateFor( data: PivotGroupBy, separate: Boolean, columns: ColumnsForAggregateSelector, @@ -32,7 +32,7 @@ internal fun Aggregator<*, R>.aggregateFor( internal().aggregateFor(columns, cast()) } -internal fun Aggregator<*, R>.aggregateFor( +internal fun Aggregator<*, R>.aggregateFor( data: DataFrame, columns: ColumnsForAggregateSelector, ): DataRow = @@ -40,7 +40,7 @@ internal fun Aggregator<*, R>.aggregateFor( internal().aggregateFor(columns, cast()) } -internal fun AggregateInternalDsl.aggregateFor( +internal fun AggregateInternalDsl.aggregateFor( columns: ColumnsForAggregateSelector, aggregator: Aggregator, ) { @@ -48,14 +48,14 @@ internal fun AggregateInternalDsl.aggregateFor( val isSingle = cols.size == 1 cols.forEach { col -> val path = getPath(col, isSingle) - val value = aggregator.aggregate(col.data) - val returnType = aggregator.calculateReturnTypeOrNull(col.data.type, col.data.isEmpty) + val value = aggregator.aggregateSingleColumn(col.data) + val returnType = aggregator.calculateReturnType(col.data.type, col.data.isEmpty) yield( path = path, value = value, type = returnType, default = col.default, - guessType = returnType == null, + guessType = false, ) } } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt index c2ca6a2483..0dd71e7e2d 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/ofRowExpression.kt @@ -6,40 +6,56 @@ import org.jetbrains.kotlinx.dataframe.RowExpression import org.jetbrains.kotlinx.dataframe.aggregation.AggregateBody import org.jetbrains.kotlinx.dataframe.api.Grouped import org.jetbrains.kotlinx.dataframe.api.PivotGroupBy +import org.jetbrains.kotlinx.dataframe.api.asSequence import org.jetbrains.kotlinx.dataframe.api.isEmpty import org.jetbrains.kotlinx.dataframe.api.pathOf import org.jetbrains.kotlinx.dataframe.api.rows 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.aggregate import org.jetbrains.kotlinx.dataframe.impl.aggregation.internal import org.jetbrains.kotlinx.dataframe.impl.emptyPath -import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf +/** + * Aggregates [values] by first applying [transform] to each element of the sequence and then + * applying the [Aggregator] ([this]) to the resulting sequence. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ @PublishedApi -internal inline fun Aggregator.aggregateOf( - values: Iterable, - crossinline transform: (C) -> V?, -): R = - aggregate( - values = values.asSequence().mapNotNull { transform(it) }.asIterable(), - type = typeOf().withNullability(false), - ) +internal inline fun Aggregator.aggregateOf( + values: Sequence, + crossinline transform: (C) -> V, +): R = aggregate(values = values.map { transform(it) }, valueType = typeOf()) +/** + * Aggregates [column] by first applying [transform] to each element of the column and then + * applying the [Aggregator] ([this]) to the resulting sequence. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ @PublishedApi -internal inline fun Aggregator.aggregateOf( +internal inline fun Aggregator.aggregateOf( column: DataColumn, - crossinline transform: (C) -> V?, -): R = aggregateOf(column.values(), transform) + crossinline transform: (C) -> V, +): R = aggregateOf(column.asSequence(), transform) +/** + * Aggregates [frame] by first applying [expression] to each row of the frame and then + * applying the [Aggregator] ([this]) to the resulting sequence. + * + * @param V is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") @PublishedApi -internal inline fun Aggregator<*, R>.aggregateOf( +internal inline fun Aggregator<*, R>.aggregateOf( frame: DataFrame, - crossinline expression: RowExpression, -): R = (this as Aggregator).aggregateOf(frame.rows()) { expression(it, it) } + crossinline expression: RowExpression, +): R = (this as Aggregator).aggregateOf(frame.rows().asSequence()) { expression(it, it) } @PublishedApi -internal fun Aggregator<*, R>.aggregateOfDelegated( +internal fun Aggregator<*, R>.aggregateOfDelegated( frame: Grouped, name: String?, body: AggregateBody, @@ -48,31 +64,44 @@ internal fun Aggregator<*, R>.aggregateOfDelegated( body(this, this) } +/** + * Aggregates [data] by first applying [expression] to each row of the frame and then + * + * @param C is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") @PublishedApi -internal inline fun Aggregator<*, R>.aggregateOf( +internal inline fun Aggregator<*, R>.aggregateOf( data: Grouped, resultName: String? = null, - crossinline expression: RowExpression, + crossinline expression: RowExpression, ): DataFrame = data.aggregateOf(resultName, expression, this as Aggregator) +/** + * @param C is used to infer whether there are nulls in the values fed to the aggregator! + */ +@Suppress("UNCHECKED_CAST") @PublishedApi -internal inline fun Aggregator<*, R>.aggregateOf( +internal inline fun Aggregator<*, R>.aggregateOf( data: PivotGroupBy, - crossinline expression: RowExpression, + crossinline expression: RowExpression, ): DataFrame = data.aggregateOf(expression, this as Aggregator) +/** + * @param C is used to infer whether there are nulls in the values fed to the aggregator! + */ @PublishedApi -internal inline fun Grouped.aggregateOf( +internal inline fun Grouped.aggregateOf( resultName: String?, - crossinline expression: RowExpression, - aggregator: Aggregator, + crossinline expression: RowExpression, + aggregator: Aggregator, ): DataFrame { val path = pathOf(resultName ?: aggregator.name) val expressionResultType = typeOf() return aggregateInternal { val value = aggregator.aggregateOf(df, expression) - val returnType = aggregator.calculateReturnTypeOrNull( - type = expressionResultType, + val returnType = aggregator.calculateReturnType( + valueType = expressionResultType, emptyInput = df.isEmpty(), ) yield( @@ -80,15 +109,18 @@ internal inline fun Grouped.aggregateOf( value = value, type = returnType, default = null, - guessType = returnType == null, + guessType = false, ) } } +/** + * @param C is used to infer whether there are nulls in the values fed to the aggregator! + */ @PublishedApi -internal inline fun PivotGroupBy.aggregateOf( - crossinline expression: RowExpression, - aggregator: Aggregator, +internal inline fun PivotGroupBy.aggregateOf( + crossinline expression: RowExpression, + aggregator: Aggregator, ): DataFrame = aggregate { internal().yield(emptyPath(), aggregator.aggregateOf(this, expression)) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt index d6adab9304..a91b2c26d7 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/row.kt @@ -4,20 +4,24 @@ import org.jetbrains.kotlinx.dataframe.ColumnsSelector import org.jetbrains.kotlinx.dataframe.DataRow import org.jetbrains.kotlinx.dataframe.api.getColumns import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.Aggregator +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.aggregateCalculatingValueType /** * Generic function to apply an [Aggregator] ([this]) to aggregate values of a row. * - * [Aggregator.aggregateCalculatingType] is used to deal with mixed types. + * [Aggregator.aggregateCalculatingValueType] is used to deal with mixed types. * * @param row a row to aggregate * @param columns selector of which columns inside the [row] to aggregate */ @PublishedApi -internal fun Aggregator.aggregateOfRow(row: DataRow, columns: ColumnsSelector): R { - val filteredColumns = row.df().getColumns(columns) - return aggregateCalculatingType( - values = filteredColumns.mapNotNull { row[it] }, +internal fun Aggregator.aggregateOfRow( + row: DataRow, + columns: ColumnsSelector, +): R { + val filteredColumns = row.df().getColumns(columns).asSequence() + return aggregateCalculatingValueType( + values = filteredColumns.map { row[it] }, valueTypes = filteredColumns.map { it.type() }.toSet(), ) } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/withinAllColumns.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/withinAllColumns.kt index 7467f2da3f..593db8f3c6 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/withinAllColumns.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/aggregation/modes/withinAllColumns.kt @@ -15,66 +15,70 @@ import org.jetbrains.kotlinx.dataframe.impl.aggregation.internal import org.jetbrains.kotlinx.dataframe.impl.emptyPath @PublishedApi -internal fun Aggregator<*, R>.aggregateAll(data: DataFrame, columns: ColumnsSelector): R = - data.aggregateAll(cast2(), columns) +internal fun Aggregator<*, R>.aggregateAll( + data: DataFrame, + columns: ColumnsSelector, +): R = data.aggregateAll(cast2(), columns) -internal fun Aggregator<*, R>.aggregateAll( +internal fun Aggregator<*, R>.aggregateAll( data: Grouped, name: String?, - columns: ColumnsSelector, + columns: ColumnsSelector, ): DataFrame = data.aggregateAll(cast(), columns, name) -internal fun Aggregator<*, R>.aggregateAll( +internal fun Aggregator<*, R>.aggregateAll( data: PivotGroupBy, - columns: ColumnsSelector, + columns: ColumnsSelector, ): DataFrame = data.aggregateAll(cast(), columns) -internal fun DataFrame.aggregateAll(aggregator: Aggregator, columns: ColumnsSelector): R = - aggregator.aggregate(get(columns)) +internal fun DataFrame.aggregateAll( + aggregator: Aggregator, + columns: ColumnsSelector, +): R = aggregator.aggregateMultipleColumns(get(columns).asSequence()) -internal fun Grouped.aggregateAll( - aggregator: Aggregator, - columns: ColumnsSelector, +internal fun Grouped.aggregateAll( + aggregator: Aggregator, + columns: ColumnsSelector, name: String?, ): DataFrame = aggregateInternal { val cols = df[columns] if (cols.size == 1) { - yield(pathOf(name ?: cols[0].name()), aggregator.aggregate(cols[0])) + yield(pathOf(name ?: cols[0].name()), aggregator.aggregateSingleColumn(cols[0])) } else { - yield(pathOf(name ?: aggregator.name), aggregator.aggregate(cols)) + yield(pathOf(name ?: aggregator.name), aggregator.aggregateMultipleColumns(cols.asSequence())) } } -internal fun PivotGroupBy.aggregateAll( - aggregator: Aggregator, - columns: ColumnsSelector, +internal fun PivotGroupBy.aggregateAll( + aggregator: Aggregator, + columns: ColumnsSelector, ): DataFrame = aggregate { val cols = get(columns) if (cols.size == 1) { - val returnType = aggregator.calculateReturnTypeOrNull( - type = cols[0].type(), + val returnType = aggregator.calculateReturnType( + valueType = cols[0].type(), emptyInput = cols[0].isEmpty, ) internal().yield( path = emptyPath(), - value = aggregator.aggregate(cols[0]), + value = aggregator.aggregateSingleColumn(cols[0]), type = returnType, default = null, - guessType = returnType == null, + guessType = false, ) } else { - val returnType = aggregator.calculateReturnTypeOrNull( + val returnType = aggregator.calculateReturnTypeMultipleColumns( colTypes = cols.map { it.type() }.toSet(), colsEmpty = cols.any { it.isEmpty }, ) internal().yield( path = emptyPath(), - value = aggregator.aggregate(cols), + value = aggregator.aggregateMultipleColumns(cols.asSequence()), type = returnType, default = null, - guessType = returnType == null, + guessType = false, ) } } diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/mean.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/mean.kt index f94c274a04..ef71fabbbc 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/mean.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/mean.kt @@ -1,31 +1,26 @@ package org.jetbrains.kotlinx.dataframe.math import io.github.oshai.kotlinlogging.KotlinLogging -import org.jetbrains.kotlinx.dataframe.api.skipNA_default -import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnTypeOrNull +import org.jetbrains.kotlinx.dataframe.api.skipNaN_default +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnType import org.jetbrains.kotlinx.dataframe.impl.nothingType import org.jetbrains.kotlinx.dataframe.impl.renderType import java.math.BigDecimal import java.math.BigInteger import kotlin.reflect.KType -import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf private val logger = KotlinLogging.logger { } -@PublishedApi -internal fun Iterable.mean(type: KType, skipNA: Boolean = skipNA_default): Double = - asSequence().mean(type, skipNA) - @Suppress("UNCHECKED_CAST") -internal fun Sequence.mean(type: KType, skipNA: Boolean = skipNA_default): Double { +internal fun Sequence.mean(type: KType, skipNaN: Boolean): Double { if (type.isMarkedNullable) { - return filterNotNull().mean(type.withNullability(false), skipNA) + error("Encountered nullable type ${renderType(type)} in mean function. This should not occur.") } - return when (type.withNullability(false)) { - typeOf() -> (this as Sequence).mean(skipNA) + return when (type) { + typeOf() -> (this as Sequence).mean(skipNaN) - typeOf() -> (this as Sequence).map { it.toDouble() }.mean(skipNA) + typeOf() -> (this as Sequence).map { it.toDouble() }.mean(skipNaN) typeOf() -> (this as Sequence).map { it.toDouble() }.mean(false) @@ -56,16 +51,16 @@ internal fun Sequence.mean(type: KType, skipNA: Boolean = skipN } /** T: Number? -> Double */ -internal val meanTypeConversion: CalculateReturnTypeOrNull = { _, _ -> +internal val meanTypeConversion: CalculateReturnType = { _, _ -> typeOf() } -internal fun Sequence.mean(skipNA: Boolean = skipNA_default): Double { +internal fun Sequence.mean(skipNaN: Boolean = skipNaN_default): Double { var count = 0 var sum: Double = 0.toDouble() for (element in this) { if (element.isNaN()) { - if (skipNA) { + if (skipNaN) { continue } else { return Double.NaN diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/minMax.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/minMax.kt new file mode 100644 index 0000000000..e399237dfd --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/minMax.kt @@ -0,0 +1,92 @@ +package org.jetbrains.kotlinx.dataframe.math + +import org.jetbrains.kotlinx.dataframe.api.isNaN +import org.jetbrains.kotlinx.dataframe.impl.IsBetterThan +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.preserveReturnTypeNullIfEmpty +import org.jetbrains.kotlinx.dataframe.impl.bestByOrNull +import org.jetbrains.kotlinx.dataframe.impl.bestNotNaByOrNull +import org.jetbrains.kotlinx.dataframe.impl.canBeNaN +import org.jetbrains.kotlinx.dataframe.impl.indexOfBestNotNaBy +import org.jetbrains.kotlinx.dataframe.impl.indexOfBestNotNullBy +import org.jetbrains.kotlinx.dataframe.impl.isIntraComparable +import org.jetbrains.kotlinx.dataframe.impl.renderType +import kotlin.reflect.KType + +// region min + +@PublishedApi +internal fun > Sequence.minOrNull(type: KType, skipNaN: Boolean): T? = + bestOrNull(type, skipNaN, "min") { this < it } + +@Suppress("UNCHECKED_CAST") +internal fun > Sequence.indexOfMin(type: KType, skipNaN: Boolean): Int = + indexOfBest(type, skipNaN) { this < it } + +/** T: Comparable -> T(?) */ +internal val minTypeConversion = preserveReturnTypeNullIfEmpty + +// endregion + +// region max + +@PublishedApi +internal fun > Sequence.maxOrNull(type: KType, skipNaN: Boolean): T? = + bestOrNull(type, skipNaN, "max") { this > it } + +@Suppress("UNCHECKED_CAST") +internal fun > Sequence.indexOfMax(type: KType, skipNaN: Boolean): Int = + indexOfBest(type, skipNaN) { this > it } + +/** T: Comparable -> T(?) */ +internal val maxTypeConversion = preserveReturnTypeNullIfEmpty + +// endregion + +// region common + +@Suppress("UNCHECKED_CAST") +private fun > Sequence.bestOrNull( + type: KType, + skipNaN: Boolean, + name: String, + isBetterThan: IsBetterThan, +): T? { + if (type.isMarkedNullable) { + error("Encountered nullable type ${renderType(type)} in $name function. This should not occur.") + } + if (!type.isIntraComparable()) { + error( + "Encountered non-comparable type ${ + renderType(type) + } in $name function. Try converting the values to the same type `T : Comparable`.", + ) + } + + return when { + // filter out NaNs if requested + skipNaN && type.canBeNaN -> bestNotNaByOrNull(isBetterThan) + + // make sure that NaN is returned if it's in the sequence + type.canBeNaN -> bestByOrNull { this.isNaN || (!it.isNaN && this.isBetterThan(it)) } + + else -> bestByOrNull(isBetterThan) + } +} + +@Suppress("UNCHECKED_CAST") +private fun > Sequence.indexOfBest( + type: KType, + skipNaN: Boolean, + isBetterThan: IsBetterThan, +): Int = + when { + // filter out NaNs if requested + skipNaN && type.canBeNaN -> indexOfBestNotNaBy(isBetterThan) + + // make sure the index of the first NaN is returned if it's in the sequence + type.canBeNaN -> indexOfBestNotNullBy { this.isNaN || (!it.isNaN && this.isBetterThan(it)) } + + else -> indexOfBestNotNullBy(isBetterThan) + } + +// endregion diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/std.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/std.kt index a91184985c..af8d7ee936 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/std.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/std.kt @@ -1,8 +1,8 @@ package org.jetbrains.kotlinx.dataframe.math import org.jetbrains.kotlinx.dataframe.api.ddof_default -import org.jetbrains.kotlinx.dataframe.api.skipNA_default -import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnTypeOrNull +import org.jetbrains.kotlinx.dataframe.api.skipNaN_default +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnType import org.jetbrains.kotlinx.dataframe.impl.renderType import java.math.BigDecimal import java.math.BigInteger @@ -14,41 +14,41 @@ import kotlin.reflect.typeOf @PublishedApi internal fun Iterable.std( type: KType, - skipNA: Boolean = skipNA_default, + skipNaN: Boolean = skipNaN_default, ddof: Int = ddof_default, ): Double { if (type.isMarkedNullable) { return when { - skipNA -> filterNotNull().std(type = type.withNullability(false), skipNA = true, ddof = ddof) + skipNaN -> filterNotNull().std(type = type.withNullability(false), skipNaN = true, ddof = ddof) contains(null) -> Double.NaN - else -> std(type = type.withNullability(false), skipNA = false, ddof = ddof) + else -> std(type = type.withNullability(false), skipNaN = false, ddof = ddof) } } return when (type.classifier) { - Double::class -> (this as Iterable).std(skipNA, ddof) - Float::class -> (this as Iterable).std(skipNA, ddof) + Double::class -> (this as Iterable).std(skipNaN, ddof) + Float::class -> (this as Iterable).std(skipNaN, ddof) Int::class, Short::class, Byte::class -> (this as Iterable).std(ddof) Long::class -> (this as Iterable).std(ddof) BigDecimal::class -> (this as Iterable).std(ddof) BigInteger::class -> (this as Iterable).std(ddof) - Number::class -> (this as Iterable).map { it.toDouble() }.std(skipNA, ddof) + Number::class -> (this as Iterable).map { it.toDouble() }.std(skipNaN, ddof) Nothing::class -> Double.NaN else -> throw IllegalArgumentException("Unable to compute the std for type ${renderType(type)}") } } /** T: Number? -> Double */ -internal val stdTypeConversion: CalculateReturnTypeOrNull = { _, _ -> +internal val stdTypeConversion: CalculateReturnType = { _, _ -> typeOf() } @JvmName("doubleStd") -internal fun Iterable.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): Double = - varianceAndMean(skipNA)?.std(ddof) ?: Double.NaN +internal fun Iterable.std(skipNaN: Boolean = skipNaN_default, ddof: Int = ddof_default): Double = + varianceAndMean(skipNaN)?.std(ddof) ?: Double.NaN @JvmName("floatStd") -internal fun Iterable.std(skipNA: Boolean = skipNA_default, ddof: Int = ddof_default): Double = - varianceAndMean(skipNA)?.std(ddof) ?: Double.NaN +internal fun Iterable.std(skipNaN: Boolean = skipNaN_default, ddof: Int = ddof_default): Double = + varianceAndMean(skipNaN)?.std(ddof) ?: Double.NaN @JvmName("intStd") internal fun Iterable.std(ddof: Int = ddof_default): Double = varianceAndMean().std(ddof) diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/stdMean.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/stdMean.kt index b9276c62a4..c3c0a413ce 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/stdMean.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/stdMean.kt @@ -2,7 +2,7 @@ package org.jetbrains.kotlinx.dataframe.math -import org.jetbrains.kotlinx.dataframe.api.skipNA_default +import org.jetbrains.kotlinx.dataframe.api.skipNaN_default import java.math.BigDecimal import java.math.BigInteger import kotlin.math.sqrt @@ -16,12 +16,12 @@ internal data class BasicStats(val count: Int, val mean: Double, val variance: D } @JvmName("doubleVarianceAndMean") -internal fun Iterable.varianceAndMean(skipNA: Boolean = skipNA_default): BasicStats? { +internal fun Iterable.varianceAndMean(skipNaN: Boolean = skipNaN_default): BasicStats? { var count = 0 var sum = .0 for (element in this) { if (element.isNaN()) { - if (skipNA) { + if (skipNaN) { continue } else { return null @@ -41,12 +41,12 @@ internal fun Iterable.varianceAndMean(skipNA: Boolean = skipNA_default): } @JvmName("floatVarianceAndMean") -internal fun Iterable.varianceAndMean(skipNA: Boolean = skipNA_default): BasicStats? { +internal fun Iterable.varianceAndMean(skipNaN: Boolean = skipNaN_default): BasicStats? { var count = 0 var sum = .0 for (element in this) { if (element.isNaN()) { - if (skipNA) { + if (skipNaN) { continue } else { return null diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/sum.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/sum.kt index 7ef56e1147..e845bb49a6 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/sum.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/math/sum.kt @@ -1,26 +1,23 @@ package org.jetbrains.kotlinx.dataframe.math -import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnTypeOrNull +import org.jetbrains.kotlinx.dataframe.impl.aggregation.aggregators.CalculateReturnType import org.jetbrains.kotlinx.dataframe.impl.nothingType import org.jetbrains.kotlinx.dataframe.impl.renderType import kotlin.reflect.KType import kotlin.reflect.full.withNullability import kotlin.reflect.typeOf -import kotlin.sequences.filterNotNull - -internal fun Iterable.sum(type: KType): Number = asSequence().sum(type) @Suppress("UNCHECKED_CAST") @JvmName("sumNullableT") @PublishedApi -internal fun Sequence.sum(type: KType): Number { +internal fun Sequence.sum(type: KType, skipNaN: Boolean): Number { if (type.isMarkedNullable) { - return filterNotNull().sum(type.withNullability(false)) + error("Encountered nullable type ${renderType(type)} in sum function. This should not occur.") } - return when (type.withNullability(false)) { - typeOf() -> (this as Sequence).sum() + return when (type) { + typeOf() -> (this as Sequence).filterNot { skipNaN && it.isNaN() }.sum() - typeOf() -> (this as Sequence).sum() + typeOf() -> (this as Sequence).filterNot { skipNaN && it.isNaN() }.sum() typeOf() -> (this as Sequence).sum() @@ -44,7 +41,7 @@ internal fun Sequence.sum(type: KType): Number { } /** T: Number? -> T */ -internal val sumTypeConversion: CalculateReturnTypeOrNull = { type, _ -> +internal val sumTypeConversion: CalculateReturnType = { type, _ -> when (val type = type.withNullability(false)) { // type changes to Int typeOf(), typeOf() -> typeOf() diff --git a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt index 11ab7599e5..6fab2d6611 100644 --- a/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt +++ b/core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/util/deprecationMessages.kt @@ -74,6 +74,17 @@ internal const val TO_LEFT_REPLACE = "this.toStart()" internal const val TO_RIGHT = "This `toRight` overload will be removed in favor of `toEnd`. $MESSAGE_0_16" internal const val TO_RIGHT_REPLACE = "this.toEnd()" +internal const val ROW_MIN = "`rowMin` is deprecated in favor of `rowMinOf`. $MESSAGE_0_16" +internal const val ROW_MIN_OR_NULL = "`rowMinOrNull` is deprecated in favor of `rowMinOfOrNull`. $MESSAGE_0_16" + +internal const val ROW_MAX = "`rowMax` is deprecated in favor of `rowMaxOf`. $MESSAGE_0_16" +internal const val ROW_MAX_OR_NULL = "`rowMaxOrNull` is deprecated in favor of `rowMaxOfOrNull`. $MESSAGE_0_16" + +internal const val SUM_NO_SKIPNAN = "This function is just here for binary compatibility. $MESSAGE_0_16" +internal const val MAX_NO_SKIPNAN = "This function is just here for binary compatibility. $MESSAGE_0_16" +internal const val MIN_NO_SKIPNAN = "This function is just here for binary compatibility. $MESSAGE_0_16" +internal const val MEAN_NO_SKIPNAN = "This function is just here for binary compatibility. $MESSAGE_0_16" + // endregion // region WARNING in 0.16, ERROR in 0.17 diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/describe.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/describe.kt index 3161e3bc7b..d161b82ae5 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/describe.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/describe.kt @@ -62,9 +62,9 @@ class DescribeTests { nulls shouldBe 0 top shouldBe 1 freq shouldBe 1 - this.mean.shouldBeNaN() + mean.shouldBeNaN() std.shouldBeNaN() - min shouldBe 1.0 // TODO should be NaN too? + min.isNaN shouldBe true p25 shouldBe 1.75 median shouldBe 3.0 p75.isNaN shouldBe true diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/puzzles/BasicTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/puzzles/BasicTests.kt index 4241f7570a..d49928a42a 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/puzzles/BasicTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/puzzles/BasicTests.kt @@ -216,8 +216,8 @@ class BasicTests { "dog", 3.0, Double.NaN, 6.0, ) - val actualDfAcc = df.pivot(inward = false) { visits }.groupBy { animal }.mean(skipNA = true) { age } - val actualDfStr = df.pivot("visits", inward = false).groupBy("animal").mean("age", skipNA = true) + val actualDfAcc = df.pivot(inward = false) { visits }.groupBy { animal }.mean(skipNaN = true) { age } + val actualDfStr = df.pivot("visits", inward = false).groupBy("animal").mean("age", skipNaN = true) actualDfAcc shouldBe expected actualDfStr shouldBe expected diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt index 79f5ef4327..fa4a77415b 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt @@ -54,7 +54,6 @@ import org.jetbrains.kotlinx.dataframe.api.stdOf import org.jetbrains.kotlinx.dataframe.api.sum import org.jetbrains.kotlinx.dataframe.api.sumFor import org.jetbrains.kotlinx.dataframe.api.sumOf -import org.jetbrains.kotlinx.dataframe.api.toDataFrame import org.jetbrains.kotlinx.dataframe.api.valueCounts import org.jetbrains.kotlinx.dataframe.api.values import org.jetbrains.kotlinx.dataframe.explainer.TransformDataFrameExpressions @@ -259,8 +258,8 @@ class Analyze : TestBase() { fun meanModes() { // SampleStart df.mean() // mean of values per every numeric column - df.mean(skipNA = true) { age and weight } // mean of all values in `age` and `weight`, skips NA - df.meanFor(skipNA = true) { age and weight } // mean of values per `age` and `weight` separately, skips NA + df.mean(skipNaN = true) { age and weight } // mean of all values in `age` and `weight`, skips NA + df.meanFor(skipNaN = true) { age and weight } // mean of values per `age` and `weight` separately, skips NA df.meanOf { (weight ?: 0) / age } // median of expression evaluated for every row // SampleEnd } @@ -304,7 +303,7 @@ class Analyze : TestBase() { @TransformDataFrameExpressions fun meanAggregationsSkipNA() { // SampleStart - df.mean(skipNA = true) + df.mean(skipNaN = true) // SampleEnd } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Modify.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Modify.kt index 296dacb8bf..503fde4164 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Modify.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Modify.kt @@ -160,12 +160,12 @@ class Modify : TestBase() { fun updatePerColumn() { val updated = // SampleStart - df.update { colsOf() }.perCol { mean(skipNA = true) } + df.update { colsOf() }.perCol { mean(skipNaN = true) } // SampleEnd updated.age.countDistinct() shouldBe 1 updated.weight.countDistinct() shouldBe 1 - val means = df.meanFor(skipNA = true) { colsOf() } + val means = df.meanFor(skipNaN = true) { colsOf() } df.update { colsOf() }.perCol(means) shouldBe updated df.update { colsOf() }.perCol(means.toMap() as Map) shouldBe updated } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/max.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/max.kt new file mode 100644 index 0000000000..dd2e476edb --- /dev/null +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/max.kt @@ -0,0 +1,347 @@ +package org.jetbrains.kotlinx.dataframe.statistics + +import io.kotest.matchers.collections.shouldNotBeIn +import io.kotest.matchers.doubles.shouldBeNaN +import io.kotest.matchers.floats.shouldBeNaN +import io.kotest.matchers.nulls.shouldBeNull +import io.kotest.matchers.shouldBe +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.api.columnNames +import org.jetbrains.kotlinx.dataframe.api.columnOf +import org.jetbrains.kotlinx.dataframe.api.dataFrameOf +import org.jetbrains.kotlinx.dataframe.api.max +import org.jetbrains.kotlinx.dataframe.api.maxBy +import org.jetbrains.kotlinx.dataframe.api.maxByOrNull +import org.jetbrains.kotlinx.dataframe.api.maxFor +import org.jetbrains.kotlinx.dataframe.api.maxOf +import org.jetbrains.kotlinx.dataframe.api.maxOfOrNull +import org.jetbrains.kotlinx.dataframe.api.maxOrNull +import org.jetbrains.kotlinx.dataframe.api.rowMaxOf +import org.jetbrains.kotlinx.dataframe.impl.nothingType +import org.junit.Ignore +import org.junit.Test + +class MaxTests { + + @Test + fun `max with regular values`() { + val col = columnOf(5, 2, 8, 1, 9) + col.max() shouldBe 9 + } + + @Test + fun `max with null`() { + val colWithNull = columnOf(5, 2, null, 1, 9) + colWithNull.max() shouldBe 9 + } + + @Test + fun `max with different numeric types`() { + // Integer types + columnOf(5, 2, 8, 1, 9).max() shouldBe 9 + columnOf(5L, 2L, 8L, 1L, 9L).max() shouldBe 9L + columnOf(5.toShort(), 2.toShort(), 8.toShort(), 1.toShort(), 9.toShort()).max() shouldBe 9.toShort() + columnOf(5.toByte(), 2.toByte(), 8.toByte(), 1.toByte(), 9.toByte()).max() shouldBe 9.toByte() + + // Floating point types + columnOf(5.0, 2.0, 8.0, 1.0, 9.0).max() shouldBe 9.0 + columnOf(5.0f, 2.0f, 8.0f, 1.0f, 9.0f).max() shouldBe 9.0f + } + + @Ignore + @Test + fun `max with mixed numeric type`() { + // Mixed number types todo https://github.com/Kotlin/dataframe/issues/1113 + // columnOf(5, 2L, 8.0f, 1.0, 9.toShort()).max() shouldBe 9.0 + } + + @Test + fun `max with empty column`() { + DataColumn.createValueColumn("", emptyList(), nothingType(false)).maxOrNull().shouldBeNull() + } + + @Test + fun `max with just nulls`() { + DataColumn.createValueColumn("", listOf(null, null), nothingType(true)).maxOrNull().shouldBeNull() + } + + @Test + fun `max with just NaNs`() { + columnOf(Double.NaN, Double.NaN).max().shouldBeNaN() + columnOf(Double.NaN, Double.NaN).maxOrNull()!!.shouldBeNaN() + + // With skipNaN=true and only NaN values, result should be null + columnOf(Double.NaN, Double.NaN).maxOrNull(skipNaN = true).shouldBeNull() + } + + @Test + fun `max with nans and nulls`() { + // Max functions should return NaN if any value is NaN + columnOf(5.0, 2.0, Double.NaN, 1.0, null).max().shouldBeNaN() + + // With skipNaN=true, NaN values should be ignored + columnOf(5.0, 2.0, Double.NaN, 1.0, null).max(skipNaN = true) shouldBe 5.0 + } + + @Test + fun `maxBy with selector function`() { + // Test with a data class + data class Person(val name: String, val age: Int) + + val people = columnOf( + Person("Alice", 30), + Person("Bob", 25), + Person("Charlie", 35), + ) + + // Find person with maximum age + people.maxBy { it.age } shouldBe Person("Charlie", 35) + + // With null values + val peopleWithNull = columnOf( + Person("Alice", 30), + Person("Bob", 25), + null, + Person("Charlie", 35), + ) + + peopleWithNull.maxBy { it?.age ?: Int.MIN_VALUE } shouldBe Person("Charlie", 35) + peopleWithNull.maxByOrNull { it?.age ?: Int.MIN_VALUE } shouldBe Person("Charlie", 35) + // can sort by null, as it will be filtered out + peopleWithNull.maxBy { it?.age } shouldBe Person("Charlie", 35) + peopleWithNull.maxByOrNull { it?.age } shouldBe Person("Charlie", 35) + } + + @Test + fun `maxOf with transformer function`() { + // Test with strings that can be converted to numbers + val strings = columnOf("5", "2", "8", "1", "9") + strings.maxOf { it.toInt() } shouldBe 9 + strings.maxOfOrNull { it.toInt() } shouldBe 9 + } + + @Test + fun `maxOf with transformer function with nulls`() { + val stringsWithNull = columnOf("5", "2", null, "1", "9") + stringsWithNull.maxOf { it?.toInt() } shouldBe 9 + stringsWithNull.maxOfOrNull { it?.toInt() } shouldBe 9 + } + + @Test + fun `maxOf with transformer function with NaNs`() { + // Max functions should return NaN if any value is NaN + val mixedValues = columnOf("5.0", "2.0", "NaN", "1.0", "9.0") + mixedValues.maxOf { + val num = it.toDoubleOrNull() + if (num == null || num.isNaN()) Double.NaN else num + }.shouldBeNaN() + + // With skipNaN=true, NaN values should be ignored + mixedValues.maxOf(skipNaN = true) { + val num = it.toDoubleOrNull() + if (num == null || num.isNaN()) Double.NaN else num + } shouldBe 9.0 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `rowMaxOf with dataframe`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1f, 2, 3, + 4f, 5, 6, + 7f, 8, 9, + ) + + // Find maximum value in each row + df[0].rowMaxOf() shouldBe 3 + df[1].rowMaxOf() shouldBe 4f + df[2].rowMaxOf() shouldBe 9 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `rowMaxOf with dataframe and nulls`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1f, 2, 3, + 4f, null, 6, + 7f, 8, 9, + ) + + // Find maximum value in each row + df[0].rowMaxOf() shouldBe 3 + df[0].rowMaxOf() shouldBe 3 // TODO? + + df[1].rowMaxOf() shouldBe 4f + df[1].rowMaxOf() shouldBe 6 + df[1].rowMaxOf() shouldBe 6 + + df[2].rowMaxOf() shouldBe 9 + df[2].rowMaxOf() shouldBe 9 // TODO? + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `rowMaxOf with dataframe and NaNs`() { + // Max functions should return NaN if any value is NaN + val dfWithNaN = dataFrameOf( + "a", "b", "c", + )( + 1.0, Double.NaN, 3.0, + Double.NaN, 5.0, 6.0, + 7.0, 8.0, Double.NaN, + ) + + dfWithNaN[0].rowMaxOf().shouldBeNaN() + dfWithNaN[1].rowMaxOf().shouldBeNaN() + dfWithNaN[2].rowMaxOf().shouldBeNaN() + + // With skipNaN=true, NaN values should be ignored + dfWithNaN[0].rowMaxOf(skipNaN = true) shouldBe 3.0 + dfWithNaN[1].rowMaxOf(skipNaN = true) shouldBe 6.0 + dfWithNaN[2].rowMaxOf(skipNaN = true) shouldBe 8.0 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `dataframe max`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2f, 3.0, + 4, 5f, 6.0, + 7, 8f, 9.0, + ) + + // Get row with maximum values for each column + val maxs = df.max() + maxs["a"] shouldBe 7 + maxs["b"] shouldBe 8f + maxs["c"] shouldBe 9.0 + + // Test max for specific columns + val maxFor = df.maxFor("a", "c") + maxFor["a"] shouldBe 7 + maxFor["c"] shouldBe 9.0 + } + + @Ignore + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `dataframe max mixed number types`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2f, 3.0, + 4, 5f, 6.0, + 7, 8f, 9.0, + ) + + // Test max of all columns as a single value + // TODO https://github.com/Kotlin/dataframe/issues/1113 + df.max("a", "b", "c") shouldBe 9 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `dataframe maxBy and maxOf`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + ) + + // Find row with maximum value of column "a" + val maxByA = df.maxBy("a") + maxByA["a"] shouldBe 7 + maxByA["b"] shouldBe 8 + maxByA["c"] shouldBe 9 + + // Find maximum value of a + c for each row + df.maxOf { "a"() + "c"() } shouldBe 16 // 7 + 9 = 16 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `max with NaN values for floating point numbers`() { + // Test with Float.NaN values + val floatWithNaN = columnOf(5.0f, 2.0f, Float.NaN, 1.0f, 9.0f) + floatWithNaN.max().shouldBeNaN() // Max functions should return NaN if any value is NaN + floatWithNaN.max(skipNaN = true) shouldBe 9.0f // With skipNaN=true, NaN values should be ignored + + // Test with Double.NaN values + val doubleWithNaN = columnOf(5.0, 2.0, Double.NaN, 1.0, 9.0) + doubleWithNaN.max().shouldBeNaN() // Max functions should return NaN if any value is NaN + doubleWithNaN.max(skipNaN = true) shouldBe 9.0 // With skipNaN=true, NaN values should be ignored + + // Test with multiple NaN values in different positions + val multipleNaN = columnOf(Float.NaN, 2.0f, Float.NaN, 1.0f, Float.NaN) + multipleNaN.max().shouldBeNaN() // Max functions should return NaN if any value is NaN + multipleNaN.max(skipNaN = true) shouldBe 2.0f // With skipNaN=true, NaN values should be ignored + + // Test with all NaN values + val allNaN = columnOf(Float.NaN, Float.NaN, Float.NaN) + allNaN.max().shouldBeNaN() // All values are NaN, so result is NaN + allNaN.maxOrNull()!!.shouldBeNaN() // All values are NaN, so result is NaN + allNaN.maxOrNull(skipNaN = true).shouldBeNull() // With skipNaN=true and only NaN values, result should be null + + // Test with mixed number types including NaN todo https://github.com/Kotlin/dataframe/issues/1113 +// val mixedWithNaN = columnOf(5, 2.0f, Double.NaN, 1L, 9.0) +// mixedWithNaN.max().shouldBeNaN() // Default behavior: NaN propagates +// mixedWithNaN.max(skipNaN = true) shouldBe 1.0 // Skip NaN values + + // Test with DataFrame containing NaN values + val dfWithNaN = dataFrameOf( + "a", "b", "c", + )( + 5.0, Double.NaN, 3.0, + 4.0, 2.0, Float.NaN, + Double.NaN, 8.0, 1.0, + ) + + // Test DataFrame max with NaN values + val maxsWithNaN = dfWithNaN.max() // Max functions should return NaN if any value is NaN + (maxsWithNaN["a"] as Double).isNaN() shouldBe true // Column 'a' has a NaN value + (maxsWithNaN["b"] as Double).isNaN() shouldBe true // Column 'b' has a NaN value + "c" shouldNotBeIn maxsWithNaN.columnNames() // Column 'c' should be excluded due to mixed number types todo + + // Test DataFrame max with skipNaN=true + val maxsWithSkipNaN = dfWithNaN.max(skipNaN = true) + maxsWithSkipNaN["a"] shouldBe 5.0 // Max of 5.0 and 4.0, skipping NaN + maxsWithSkipNaN["b"] shouldBe 8.0 // Max of 2.0 and 8.0, skipping NaN + // todo maxsWithSkipNaN["c"] shouldBe 1.0 https://github.com/Kotlin/dataframe/issues/1113 + + // Test maxFor with NaN values + val maxForWithNaN = dfWithNaN.maxFor("a", "b") // Max functions should return NaN if any value is NaN + (maxForWithNaN["a"] as Double).isNaN() shouldBe true // Column 'a' has a NaN value + (maxForWithNaN["b"] as Double).isNaN() shouldBe true // Column 'b' has a NaN value + + // Test maxFor with skipNaN=true + val maxForWithSkipNaN = dfWithNaN.maxFor("a", "b", skipNaN = true) + maxForWithSkipNaN["a"] shouldBe 5.0 // Max of 5.0 and 4.0, skipping NaN + maxForWithSkipNaN["b"] shouldBe 8.0 // Max of 2.0 and 8.0, skipping NaN + + // Test max of all columns as a single value + (dfWithNaN.max("a", "b") as Double).isNaN() shouldBe true // Max functions should return NaN if any value is NaN + dfWithNaN.max("a", "b", skipNaN = true) shouldBe 8.0 // With skipNaN=true, NaN values should be ignored + + // Test maxOf with transformation that might produce NaN values + val dfForTransform = dataFrameOf( + "a", "b", + )( + 4.0, 0.0, + 1.0, 2.0, + 0.0, 0.0, + ) + + // Max functions should return NaN if any value is NaN + dfForTransform.maxOf { + val b = "b"() + if (b == 0.0) Double.NaN else "a"() / b + }.shouldBeNaN() + + // With skipNaN=true, NaN values should be ignored + dfForTransform.maxOf(skipNaN = true) { + val b = "b"() + if (b == 0.0) Double.NaN else "a"() / b + } shouldBe 0.5 // Only 1.0/2.0 = 0.5 is valid + } +} diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/mean.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/mean.kt index 16ad780fac..15b867e2bf 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/mean.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/mean.kt @@ -4,7 +4,11 @@ import io.kotest.matchers.doubles.shouldBeNaN import io.kotest.matchers.shouldBe import org.jetbrains.kotlinx.dataframe.DataColumn import org.jetbrains.kotlinx.dataframe.api.columnOf +import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.mean +import org.jetbrains.kotlinx.dataframe.api.meanFor +import org.jetbrains.kotlinx.dataframe.api.meanOf +import org.jetbrains.kotlinx.dataframe.api.rowMean import org.jetbrains.kotlinx.dataframe.impl.nothingType import org.junit.Test import kotlin.reflect.typeOf @@ -20,9 +24,228 @@ class MeanTests { @Test fun `mean with nans and nulls`() { columnOf(10, 20, Double.NaN, null).mean().shouldBeNaN() - columnOf(10, 20, Double.NaN, null).mean(skipNA = true) shouldBe 15 + columnOf(10, 20, Double.NaN, null).mean(skipNaN = true) shouldBe 15 DataColumn.createValueColumn("", emptyList(), nothingType(false)).mean().shouldBeNaN() DataColumn.createValueColumn("", listOf(null), nothingType(true)).mean().shouldBeNaN() } + + @Test + fun `mean with int values`() { + val col = columnOf(1, 2, 3, 4, 5) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1, 2, 3, 4, 5, null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with long values`() { + val col = columnOf(1L, 2L, 3L, 4L, 5L) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1L, 2L, 3L, 4L, 5L, null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with float values`() { + val col = columnOf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with double values`() { + val col = columnOf(1.0, 2.0, 3.0, 4.0, 5.0) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1.0, 2.0, 3.0, 4.0, 5.0, null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with short values`() { + val col = columnOf(1.toShort(), 2.toShort(), 3.toShort(), 4.toShort(), 5.toShort()) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1.toShort(), 2.toShort(), 3.toShort(), 4.toShort(), 5.toShort(), null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with byte values`() { + val col = columnOf(1.toByte(), 2.toByte(), 3.toByte(), 4.toByte(), 5.toByte()) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1.toByte(), 2.toByte(), 3.toByte(), 4.toByte(), 5.toByte(), null) + colWithNull.mean() shouldBe 3.0 + } + + @Test + fun `mean with mixed number types`() { + val col = columnOf(1, 2L, 3.0f, 4.0, 5.toShort()) + col.mean() shouldBe 3.0 + + val colWithNull = columnOf(1, 2L, 3.0f, 4.0, 5.toShort(), null) + colWithNull.mean() shouldBe 3.0 + + // Mix of different integer types + val intMix = columnOf(1, 2L, 3.toShort(), 4.toByte()) + intMix.mean() shouldBe 2.5 + + // Mix of different floating point types + val floatMix = columnOf(1.0f, 2.0, 3.0f, 4.0) + floatMix.mean() shouldBe 2.5 + + // Mix of integer and floating point types + val mixedTypes = columnOf(1, 2.0f, 3L, 4.0) + mixedTypes.mean() shouldBe 2.5 + } + + @Test + fun `meanOf with transformation`() { + val col = columnOf("1", "2", "3", "4", "5") + col.meanOf { it.toInt() } shouldBe 3.0 + + val colWithNull = columnOf("1", "2", "3", null, "5") + colWithNull.meanOf { it?.toInt() } shouldBe 2.75 + } + + @Suppress("ktlint:standard:argument-list-wrapping") + @Test + fun `rowMean with dataframe`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + ) + + df[0].rowMean() shouldBe 2.0 + df[1].rowMean() shouldBe 5.0 + df[2].rowMean() shouldBe 8.0 + } + + @Suppress("ktlint:standard:argument-list-wrapping") + @Test + fun `dataframe mean`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2.0, 3f, + 4, 5.0, 6f, + 7, 8.0, 9f, + ) + + val means = df.mean() + means["a"] shouldBe 4.0 + means["b"] shouldBe 5.0 + means["c"] shouldBe 6.0 + + // Test mean for specific columns + val meanFor = df.meanFor("a", "c") + meanFor["a"] shouldBe 4.0 + meanFor["c"] shouldBe 6.0 + + // Test mean of all columns as a single value + df.mean("a", "b", "c") shouldBe 5.0 + } + + @Suppress("ktlint:standard:argument-list-wrapping") + @Test + fun `dataframe meanOf with transformation`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + ) + + df.meanOf { "a"() + "c"() } shouldBe 10.0 + } + + @Suppress("ktlint:standard:argument-list-wrapping") + @Test + fun `mean with skipNaN for floating point numbers`() { + // Test with Float.NaN values + val floatWithNaN = columnOf(1.0f, 2.0f, Float.NaN, 4.0f, 5.0f) + floatWithNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + floatWithNaN.mean(skipNaN = true) shouldBe 3.0 // Skip NaN values + + // Test with Double.NaN values + val doubleWithNaN = columnOf(1.0, 2.0, Double.NaN, 4.0, 5.0) + doubleWithNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + doubleWithNaN.mean(skipNaN = true) shouldBe 3.0 // Skip NaN values + + // Test with multiple NaN values in different positions + val multipleNaN = columnOf(Float.NaN, 2.0f, Float.NaN, 4.0f, Float.NaN) + multipleNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + multipleNaN.mean(skipNaN = true) shouldBe 3.0 // Skip NaN values + + // Test with all NaN values + val allNaN = columnOf(Float.NaN, Float.NaN, Float.NaN) + allNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + allNaN.mean(skipNaN = true).shouldBeNaN() // No valid values, result is NaN + + // Test with mixed number types including NaN + val mixedWithNaN = columnOf(1, 2.0f, Double.NaN, 4L, 5.0) + mixedWithNaN.mean().shouldBeNaN() // Default behavior: NaN propagates + mixedWithNaN.mean(skipNaN = true) shouldBe 3.0 // Skip NaN values + + // Test with DataFrame containing NaN values + val dfWithNaN = dataFrameOf( + "a", "b", "c", + )( + 1.0, Double.NaN, 3.0, + 4.0, 5.0, Float.NaN, + Double.NaN, 8.0, 9.0, + ) + + // Test DataFrame mean with skipNaN + val meansWithNaN = dfWithNaN.mean() // Default behavior + (meansWithNaN["a"] as Double).shouldBeNaN() // Contains NaN + (meansWithNaN["b"] as Double).shouldBeNaN() // Contains NaN + (meansWithNaN["c"] as Double).shouldBeNaN() // Contains NaN + + val meansSkipNaN = dfWithNaN.mean(skipNaN = true) // Skip NaN values + meansSkipNaN["a"] shouldBe 2.5 // (1.0 + 4.0) / 2 + meansSkipNaN["b"] shouldBe 6.5 // (5.0 + 8.0) / 2 + meansSkipNaN["c"] shouldBe 6.0 // (3.0 + 9.0) / 2 + + // Test meanFor with skipNaN + val meanForWithNaN = dfWithNaN.meanFor("a", "c") // Default behavior + (meanForWithNaN["a"] as Double).shouldBeNaN() // Contains NaN + (meanForWithNaN["c"] as Double).shouldBeNaN() // Contains NaN + + val meanForSkipNaN = dfWithNaN.meanFor("a", "c", skipNaN = true) // Skip NaN values + meanForSkipNaN["a"] shouldBe 2.5 // (1.0 + 4.0) / 2 + meanForSkipNaN["c"] shouldBe 6.0 // (3.0 + 9.0) / 2 + + // Test mean of all columns as a single value with skipNaN + dfWithNaN.mean("a", "b", "c").shouldBeNaN() // Default behavior: NaN propagates + dfWithNaN.mean("a", "b", "c", skipNaN = true) shouldBe 5.0 // Skip NaN values + + // Test meanOf with transformation that might produce NaN values + val dfForTransform = dataFrameOf( + "a", "b", + )( + 1.0, 0.0, + 4.0, 2.0, + 0.0, 0.0, + ) + + // Division by zero produces NaN + dfForTransform.meanOf { "a"() / "b"() }.shouldBeNaN() // Default behavior: NaN propagates + + // Skip NaN values from division by zero + dfForTransform.meanOf(skipNaN = true) { + val b = "b"() + if (b == 0.0) Double.NaN else "a"() / b + } shouldBe 2.0 // Only 4.0/2.0 = 2.0 is valid + } } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/min.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/min.kt new file mode 100644 index 0000000000..63dbe402d2 --- /dev/null +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/min.kt @@ -0,0 +1,342 @@ +package org.jetbrains.kotlinx.dataframe.statistics + +import io.kotest.matchers.collections.shouldNotBeIn +import io.kotest.matchers.doubles.shouldBeNaN +import io.kotest.matchers.floats.shouldBeNaN +import io.kotest.matchers.nulls.shouldBeNull +import io.kotest.matchers.shouldBe +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.api.columnNames +import org.jetbrains.kotlinx.dataframe.api.columnOf +import org.jetbrains.kotlinx.dataframe.api.dataFrameOf +import org.jetbrains.kotlinx.dataframe.api.min +import org.jetbrains.kotlinx.dataframe.api.minBy +import org.jetbrains.kotlinx.dataframe.api.minByOrNull +import org.jetbrains.kotlinx.dataframe.api.minFor +import org.jetbrains.kotlinx.dataframe.api.minOf +import org.jetbrains.kotlinx.dataframe.api.minOfOrNull +import org.jetbrains.kotlinx.dataframe.api.minOrNull +import org.jetbrains.kotlinx.dataframe.api.rowMinOf +import org.jetbrains.kotlinx.dataframe.impl.nothingType +import org.junit.Ignore +import org.junit.Test + +class MinTests { + + @Test + fun `min with regular values`() { + val col = columnOf(5, 2, 8, 1, 9) + col.min() shouldBe 1 + } + + @Test + fun `min with null`() { + val colWithNull = columnOf(5, 2, null, 1, 9) + colWithNull.min() shouldBe 1 + } + + @Test + fun `min with different numeric types`() { + // Integer types + columnOf(5, 2, 8, 1, 9).min() shouldBe 1 + columnOf(5L, 2L, 8L, 1L, 9L).min() shouldBe 1L + columnOf(5.toShort(), 2.toShort(), 8.toShort(), 1.toShort(), 9.toShort()).min() shouldBe 1.toShort() + columnOf(5.toByte(), 2.toByte(), 8.toByte(), 1.toByte(), 9.toByte()).min() shouldBe 1.toByte() + + // Floating point types + columnOf(5.0, 2.0, 8.0, 1.0, 9.0).min() shouldBe 1.0 + columnOf(5.0f, 2.0f, 8.0f, 1.0f, 9.0f).min() shouldBe 1.0f + } + + @Ignore + @Test + fun `min with mixed numeric type`() { + // Mixed number types todo https://github.com/Kotlin/dataframe/issues/1113 + // columnOf(5, 2L, 8.0f, 1.0, 9.toShort()).min() shouldBe 1.0 + } + + @Test + fun `min with empty column`() { + DataColumn.createValueColumn("", emptyList(), nothingType(false)).minOrNull().shouldBeNull() + } + + @Test + fun `min with just nulls`() { + DataColumn.createValueColumn("", listOf(null, null), nothingType(true)).minOrNull().shouldBeNull() + } + + @Test + fun `min with just NaNs`() { + columnOf(Double.NaN, Double.NaN).min().shouldBeNaN() + columnOf(Double.NaN, Double.NaN).minOrNull()!!.shouldBeNaN() + + // With skipNaN=true and only NaN values, result should be null + columnOf(Double.NaN, Double.NaN).minOrNull(skipNaN = true).shouldBeNull() + } + + @Test + fun `min with nans and nulls`() { + // Min functions should return NaN if any value is NaN + columnOf(5.0, 2.0, Double.NaN, 1.0, null).min().shouldBeNaN() + + // With skipNaN=true, NaN values should be ignored + columnOf(5.0, 2.0, Double.NaN, 1.0, null).min(skipNaN = true) shouldBe 1.0 + } + + @Test + fun `minBy with selector function`() { + // Test with a data class + data class Person(val name: String, val age: Int) + + val people = columnOf( + Person("Alice", 30), + Person("Bob", 25), + Person("Charlie", 35), + ) + + // Find person with minimum age + people.minBy { it.age } shouldBe Person("Bob", 25) + + // With null values + val peopleWithNull = columnOf( + Person("Alice", 30), + Person("Bob", 25), + null, + Person("Charlie", 35), + ) + + peopleWithNull.minBy { it?.age ?: Int.MAX_VALUE } shouldBe Person("Bob", 25) + peopleWithNull.minByOrNull { it?.age ?: Int.MAX_VALUE } shouldBe Person("Bob", 25) + // can sort by null, as it will be filtered out + peopleWithNull.minBy { it?.age } shouldBe Person("Bob", 25) + peopleWithNull.minByOrNull { it?.age } shouldBe Person("Bob", 25) + } + + @Test + fun `minOf with transformer function`() { + // Test with strings that can be converted to numbers + val strings = columnOf("5", "2", "8", "1", "9") + strings.minOf { it.toInt() } shouldBe 1 + strings.minOfOrNull { it.toInt() } shouldBe 1 + } + + @Test + fun `minOf with transformer function with nulls`() { + val stringsWithNull = columnOf("5", "2", null, "1", "9") + stringsWithNull.minOf { it?.toInt() } shouldBe 1 + stringsWithNull.minOfOrNull { it?.toInt() } shouldBe 1 + } + + @Test + fun `minOf with transformer function with NaNs`() { + // Min functions should return NaN if any value is NaN + val mixedValues = columnOf("5.0", "2.0", "NaN", "1.0", "9.0") + mixedValues.minOf { + val num = it.toDoubleOrNull() + if (num == null || num.isNaN()) Double.NaN else num + }.shouldBeNaN() + + // With skipNaN=true, NaN values should be ignored + mixedValues.minOf(skipNaN = true) { + val num = it.toDoubleOrNull() + if (num == null || num.isNaN()) Double.NaN else num + } shouldBe 1.0 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `rowMinOf with dataframe`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1f, 2, 3, + 4f, 5, 6, + 7f, 8, 9, + ) + + // Find minimum value in each row + df[0].rowMinOf() shouldBe 2 + df[1].rowMinOf() shouldBe 4f + df[2].rowMinOf() shouldBe 8 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `rowMinOf with dataframe and nulls`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1f, 2, 3, + 4f, null, 6, + 7f, 8, 9, + ) + + // Find minimum value in each row + df[0].rowMinOf() shouldBe 3 + df[0].rowMinOf() shouldBe 2 // TODO? + + df[1].rowMinOf() shouldBe 4f + df[1].rowMinOf() shouldBe 6 + df[1].rowMinOf() shouldBe 6 + + df[2].rowMinOf() shouldBe 9 + df[2].rowMinOf() shouldBe 8 // TODO? + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `rowMinOf with dataframe and NaNs`() { + // Min functions should return NaN if any value is NaN + val dfWithNaN = dataFrameOf( + "a", "b", "c", + )( + 1.0, Double.NaN, 3.0, + Double.NaN, 5.0, 6.0, + 7.0, 8.0, Double.NaN, + ) + + dfWithNaN[0].rowMinOf().shouldBeNaN() + dfWithNaN[1].rowMinOf().shouldBeNaN() + dfWithNaN[2].rowMinOf().shouldBeNaN() + + // With skipNaN=true, NaN values should be ignored + dfWithNaN[0].rowMinOf(skipNaN = true) shouldBe 1.0 + dfWithNaN[1].rowMinOf(skipNaN = true) shouldBe 5.0 + dfWithNaN[2].rowMinOf(skipNaN = true) shouldBe 7.0 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `dataframe min`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2f, 3.0, + 4, 5f, 6.0, + 7, 8f, 9.0, + ) + + // Get row with minimum values for each column + val mins = df.min() + mins["a"] shouldBe 1 + mins["b"] shouldBe 2f + mins["c"] shouldBe 3.0 + + // Test min for specific columns + val minFor = df.minFor("a", "c") + minFor["a"] shouldBe 1 + minFor["c"] shouldBe 3.0 + } + + @Ignore + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `dataframe min mixed number types`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2f, 3.0, + 4, 5f, 6.0, + 7, 8f, 9.0, + ) + + // Test min of all columns as a single value + // TODO https://github.com/Kotlin/dataframe/issues/1113 + df.min("a", "b", "c") shouldBe 1 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `dataframe minBy and minOf`() { + val df = dataFrameOf( + "a", "b", "c", + )( + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + ) + + // Find row with minimum value of column "a" + val minByA = df.minBy("a") + minByA["a"] shouldBe 1 + minByA["b"] shouldBe 2 + minByA["c"] shouldBe 3 + + // Find minimum value of a + c for each row + df.minOf { "a"() + "c"() } shouldBe 4 // 1 + 3 = 4 + } + + @[Test Suppress("ktlint:standard:argument-list-wrapping")] + fun `min with NaN values for floating point numbers`() { + // Test with Float.NaN values + val floatWithNaN = columnOf(5.0f, 2.0f, Float.NaN, 1.0f, 9.0f) + floatWithNaN.min().shouldBeNaN() // Min functions should return NaN if any value is NaN + floatWithNaN.min(skipNaN = true) shouldBe 1.0f // With skipNaN=true, NaN values should be ignored + + // Test with Double.NaN values + val doubleWithNaN = columnOf(5.0, 2.0, Double.NaN, 1.0, 9.0) + doubleWithNaN.min().shouldBeNaN() // Min functions should return NaN if any value is NaN + doubleWithNaN.min(skipNaN = true) shouldBe 1.0 // With skipNaN=true, NaN values should be ignored + + // Test with multiple NaN values in different positions + val multipleNaN = columnOf(Float.NaN, 2.0f, Float.NaN, 1.0f, Float.NaN) + multipleNaN.min().shouldBeNaN() // Min functions should return NaN if any value is NaN + multipleNaN.min(skipNaN = true) shouldBe 1.0f // With skipNaN=true, NaN values should be ignored + + // Test with all NaN values + val allNaN = columnOf(Float.NaN, Float.NaN, Float.NaN) + allNaN.min().shouldBeNaN() // All values are NaN, so result is NaN + allNaN.minOrNull()!!.shouldBeNaN() // All values are NaN, so result is NaN + allNaN.minOrNull(skipNaN = true).shouldBeNull() // With skipNaN=true and only NaN values, result should be null + + // Test with DataFrame containing NaN values + val dfWithNaN = dataFrameOf( + "a", "b", "c", + )( + 5.0, Double.NaN, 3.0, + 4.0, 2.0, Float.NaN, + Double.NaN, 8.0, 1.0, + ) + + // Test DataFrame min with NaN values + val minsWithNaN = dfWithNaN.min() // Min functions should return NaN if any value is NaN + (minsWithNaN["a"] as Double).isNaN() shouldBe true // Column 'a' has a NaN value + (minsWithNaN["b"] as Double).isNaN() shouldBe true // Column 'b' has a NaN value + "c" shouldNotBeIn minsWithNaN.columnNames() // Column 'c' should be excluded due to mixed number types todo + + // Test DataFrame min with skipNaN=true + val minsWithSkipNaN = dfWithNaN.min(skipNaN = true) + minsWithSkipNaN["a"] shouldBe 4.0 // Min of 5.0 and 4.0, skipping NaN + minsWithSkipNaN["b"] shouldBe 2.0 // Min of 2.0 and 8.0, skipping NaN + // todo minsWithSkipNaN["c"] shouldBe 1.0 https://github.com/Kotlin/dataframe/issues/1113 + + // Test minFor with NaN values + val minForWithNaN = dfWithNaN.minFor("a", "b") // Min functions should return NaN if any value is NaN + (minForWithNaN["a"] as Double).isNaN() shouldBe true // Column 'a' has a NaN value + (minForWithNaN["b"] as Double).isNaN() shouldBe true // Column 'b' has a NaN value + + // Test minFor with skipNaN=true + val minForWithSkipNaN = dfWithNaN.minFor("a", "b", skipNaN = true) + minForWithSkipNaN["a"] shouldBe 4.0 // Min of 5.0 and 4.0, skipping NaN + minForWithSkipNaN["b"] shouldBe 2.0 // Min of 2.0 and 8.0, skipping NaN + + // Test min of all columns as a single value + (dfWithNaN.min("a", "b") as Double).isNaN() shouldBe true // Min functions should return NaN if any value is NaN + dfWithNaN.min("a", "b", skipNaN = true) shouldBe 2.0 // With skipNaN=true, NaN values should be ignored + + // Test minOf with transformation that might produce NaN values + val dfForTransform = dataFrameOf( + "a", "b", + )( + 4.0, 0.0, + 1.0, 2.0, + 0.0, 0.0, + ) + + // Min functions should return NaN if any value is NaN + dfForTransform.minOf { + val b = "b"() + if (b == 0.0) Double.NaN else "a"() / b + }.isNaN() shouldBe true + + // With skipNaN=true, NaN values should be ignored + dfForTransform.minOf(skipNaN = true) { + val b = "b"() + if (b == 0.0) Double.NaN else "a"() / b + } shouldBe 0.5 // Only 1.0/2.0 = 0.5 is valid + } +} diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt index 0e158e73d4..6079fa5799 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/statistics/sum.kt @@ -1,13 +1,17 @@ package org.jetbrains.kotlinx.dataframe.statistics import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.doubles.shouldBeNaN +import io.kotest.matchers.floats.shouldBeNaN import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain import org.jetbrains.kotlinx.dataframe.api.columnOf import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.isEmpty import org.jetbrains.kotlinx.dataframe.api.rowSum +import org.jetbrains.kotlinx.dataframe.api.rowSumOf import org.jetbrains.kotlinx.dataframe.api.sum +import org.jetbrains.kotlinx.dataframe.api.sumFor import org.jetbrains.kotlinx.dataframe.api.sumOf import org.jetbrains.kotlinx.dataframe.api.toDataFrame import org.junit.Test @@ -60,10 +64,10 @@ class SumTests { df.sumOf { value3() } shouldBe expected3 df.sum(value1) shouldBe expected1 df.sum(value2) shouldBe expected2 - // TODO sum rework, has Number in results df.sum(value3) shouldBe expected3 + df.sum(value3) shouldBe expected3 df.sum { value1 } shouldBe expected1 df.sum { value2 } shouldBe expected2 - // TODO sum rework, has Number in results df.sum { value3 } shouldBe expected3 + df.sum { value3 } shouldBe expected3 } /** [Issue #1068](https://github.com/Kotlin/dataframe/issues/1068) */ @@ -106,4 +110,75 @@ class SumTests { columnOf(1.0, 2, 3.0.toBigDecimal()).toDataFrame().sum()[0] }.message?.lowercase() shouldContain "primitive" } + + @Test + fun `test skipNaN with float column`() { + val value by columnOf(1.0f, 2.0f, Float.NaN, 3.0f) + val df = dataFrameOf(value) + + // With skipNaN = true (default is false) + value.sum(skipNaN = true) shouldBe 6.0f + df[value].sum(skipNaN = true) shouldBe 6.0f + df.sum(skipNaN = true)[value] shouldBe 6.0f + df.sumOf(skipNaN = true) { value().toInt() } shouldBe 6 + + // With skipNaN = false (default) + value.sum().shouldBeNaN() + df[value].sum().shouldBeNaN() + df.sum()[value].shouldBeNaN() + df.sumOf { value().toDouble() }.shouldBeNaN() + } + + @Test + fun `test skipNaN with double column`() { + val value by columnOf(1.0, 2.0, Double.NaN, 3.0) + val df = dataFrameOf(value) + + // With skipNaN = true (default is false) + value.sum(skipNaN = true) shouldBe 6.0 + df[value].sum(skipNaN = true) shouldBe 6.0 + df.sum(skipNaN = true)[value] shouldBe 6.0 + df.sumOf(skipNaN = true) { value().toLong() } shouldBe 6L + + // With skipNaN = false (default) + value.sum().shouldBeNaN() + df[value].sum().shouldBeNaN() + df.sum()[value].shouldBeNaN() + df.sumOf { value().toFloat() }.shouldBeNaN() + } + + @Test + fun `test rowSum with skipNaN`() { + val row1 = dataFrameOf("a", "b", "c")(1.0, 2.0, 3.0)[0] + val row2 = dataFrameOf("a", "b", "c")(1.0, Double.NaN, 3)[0] + + // With skipNaN = true + row1.rowSum(skipNaN = true) shouldBe 6.0 + row2.rowSum(skipNaN = true) shouldBe 4.0 + + // With skipNaN = false (default) + row1.rowSum() shouldBe 6.0 + (row2.rowSum() as Double).shouldBeNaN() + + // Test rowSumOf + row1.rowSumOf(skipNaN = true) shouldBe 6.0 + row2.rowSumOf(skipNaN = true) shouldBe 1.0 + row1.rowSumOf() shouldBe 6.0 + row2.rowSumOf().shouldBeNaN() + } + + @Test + fun `test sumFor with skipNaN`() { + val value1 by columnOf(1.0, 2.0, 3.0) + val value2 by columnOf(4.0, Float.NaN, 6) + val df = dataFrameOf(value1, value2) + + // With skipNaN = true + df.sumFor(skipNaN = true) { value1 and value2 }[value1] shouldBe 6.0 + df.sumFor(skipNaN = true) { value1 and value2 }[value2] shouldBe 10.0 + + // With skipNaN = false (default) + df.sumFor { value1 and value2 }[value1] shouldBe 6.0 + (df.sumFor { value1 and value2 }[value2] as Double).shouldBeNaN() + } } diff --git a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/animals/AnimalsTests.kt b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/animals/AnimalsTests.kt index 2bc8b69b37..70e70d1702 100644 --- a/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/animals/AnimalsTests.kt +++ b/core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/testSets/animals/AnimalsTests.kt @@ -25,7 +25,7 @@ class AnimalsTests { @Test fun `ignore nans`() { - df.mean("age", skipNA = true) shouldBe 3.4375 + df.mean("age", skipNaN = true) shouldBe 3.4375 } @Test diff --git a/dataframe-jupyter/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/SampleNotebooksTests.kt b/dataframe-jupyter/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/SampleNotebooksTests.kt index 29c0910b4f..37486d2b5d 100644 --- a/dataframe-jupyter/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/SampleNotebooksTests.kt +++ b/dataframe-jupyter/src/test/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/SampleNotebooksTests.kt @@ -4,7 +4,10 @@ import org.jetbrains.jupyter.parser.JupyterParser import org.jetbrains.jupyter.parser.notebook.CodeCell import org.jetbrains.jupyter.parser.notebook.Output import org.jetbrains.kotlinx.dataframe.BuildConfig +import org.jetbrains.kotlinx.jupyter.exceptions.causesSequence +import org.jetbrains.kotlinx.jupyter.repl.result.EvalResultEx import org.junit.Assume +import org.junit.AssumptionViolatedException import org.junit.Before import org.junit.Test import java.io.File @@ -120,9 +123,25 @@ class SampleNotebooksTests : DataFrameJupyterTest() { val codeToExecute = replacer.replace(code) // println("Executing code:\n$codeToExecute") - val cellResult = execRendered(codeToExecute) + val cellResult = execEx(codeToExecute) + if (cellResult is EvalResultEx.AbstractError) { + throw cellResult.error + } + require(cellResult is EvalResultEx.Success) + // println(cellResult) } + } catch (e: Exception) { + if (e.causesSequence() + .filterIsInstance() + .any { it.message?.contains("null DefinitelyNotNullType for") == true } + ) { + // Issue #1116: https://github.com/Kotlin/dataframe/issues/1116 + // Cannot finish test until this is solved, so treat this test as "ignored" + throw AssumptionViolatedException("Test skipped due to issue #1116") + } else { + throw e + } } finally { cleanup() } diff --git a/examples/notebooks/dev/puzzles/40 puzzles.ipynb b/examples/notebooks/dev/puzzles/40 puzzles.ipynb index 5553c6eace..be4da6dfa6 100644 --- a/examples/notebooks/dev/puzzles/40 puzzles.ipynb +++ b/examples/notebooks/dev/puzzles/40 puzzles.ipynb @@ -22,9 +22,9 @@ { "metadata": {}, "cell_type": "code", + "source": "%use dataframe", "outputs": [], - "execution_count": null, - "source": "%use dataframe" + "execution_count": null }, { "metadata": {}, @@ -47,8 +47,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val animal by columnOf(\"cat\", \"cat\", \"snake\", \"dog\", \"dog\", \"cat\", \"snake\", \"cat\", \"dog\", \"dog\")\n", "val age by columnOf(2.5, 3.0, 0.5, Double.NaN, 5.0, 2.0, 4.5, Double.NaN, 7.0, 3.0)\n", @@ -57,7 +55,9 @@ "\n", "val df = dataFrameOf(animal, age, visits, priority)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -67,16 +67,16 @@ { "metadata": {}, "cell_type": "code", + "source": "df.schema()", "outputs": [], - "execution_count": null, - "source": "df.schema()" + "execution_count": null }, { "metadata": {}, "cell_type": "code", + "source": "df.describe()", "outputs": [], - "execution_count": null, - "source": "df.describe()" + "execution_count": null }, { "metadata": {}, @@ -86,8 +86,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df[0 ..< 3] // df[0..2]\n", "\n", @@ -98,7 +96,9 @@ "// or\n", "\n", "df.take(3)" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -108,9 +108,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df[animal, age]", "outputs": [], - "execution_count": null, - "source": "df[animal, age]" + "execution_count": null }, { "metadata": {}, @@ -120,9 +120,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df[3, 4, 8][animal, age]", "outputs": [], - "execution_count": null, - "source": "df[3, 4, 8][animal, age]" + "execution_count": null }, { "metadata": {}, @@ -132,9 +132,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.filter { visits > 2 }", "outputs": [], - "execution_count": null, - "source": "df.filter { visits > 2 }" + "execution_count": null }, { "metadata": {}, @@ -144,9 +144,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.filter { age.isNaN() }", "outputs": [], - "execution_count": null, - "source": "df.filter { age.isNaN() }" + "execution_count": null }, { "metadata": {}, @@ -156,9 +156,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.filter { animal == \"cat\" && age < 3 }", "outputs": [], - "execution_count": null, - "source": "df.filter { animal == \"cat\" && age < 3 }" + "execution_count": null }, { "metadata": {}, @@ -168,9 +168,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.filter { age in 2.0..4.0 }", "outputs": [], - "execution_count": null, - "source": "df.filter { age in 2.0..4.0 }" + "execution_count": null }, { "metadata": {}, @@ -180,9 +180,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.update { age }.at(5).with { 1.5 }", "outputs": [], - "execution_count": null, - "source": "df.update { age }.at(5).with { 1.5 }" + "execution_count": null }, { "metadata": {}, @@ -192,9 +192,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.visits.sum()", "outputs": [], - "execution_count": null, - "source": "df.visits.sum()" + "execution_count": null }, { "metadata": {}, @@ -204,9 +204,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.groupBy { animal }.mean { age }", "outputs": [], - "execution_count": null, - "source": "df.groupBy { animal }.mean { age }" + "execution_count": null }, { "metadata": {}, @@ -216,12 +216,12 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val modifiedDf = df.append(\"dog\", 5.5, 2, \"no\")\n", "modifiedDf.dropLast()" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -231,9 +231,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.groupBy { animal }.count()", "outputs": [], - "execution_count": null, - "source": "df.groupBy { animal }.count()" + "execution_count": null }, { "metadata": {}, @@ -243,9 +243,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.sortBy { age.desc() and visits }", "outputs": [], - "execution_count": null, - "source": "df.sortBy { age.desc() and visits }" + "execution_count": null }, { "metadata": {}, @@ -255,9 +255,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.convert { priority }.with { it == \"yes\" }", "outputs": [], - "execution_count": null, - "source": "df.convert { priority }.with { it == \"yes\" }" + "execution_count": null }, { "metadata": {}, @@ -267,9 +267,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.update { animal }.where { it == \"dog\" }.with { \"corgi\" }", "outputs": [], - "execution_count": null, - "source": "df.update { animal }.where { it == \"dog\" }.with { \"corgi\" }" + "execution_count": null }, { "metadata": {}, @@ -279,9 +279,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.pivot { visits }.groupBy { animal }.mean(skipNaN = true) { age }", "outputs": [], - "execution_count": null, - "source": "df.pivot { visits }.groupBy { animal }.mean(skipNA = true) { age }" + "execution_count": null }, { "metadata": {}, @@ -313,26 +313,26 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val df = dataFrameOf(\"A\")(1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", + "source": "df.filter { prev()?.A != A }", "outputs": [], - "execution_count": null, - "source": "df.filter { prev()?.A != A }" + "execution_count": null }, { "metadata": {}, "cell_type": "code", + "source": "df.filter { diffOrNull { A } != 0 }", "outputs": [], - "execution_count": null, - "source": "df.filter { diffOrNull { A } != 0 }" + "execution_count": null }, { "metadata": {}, @@ -342,9 +342,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.distinct()", "outputs": [], - "execution_count": null, - "source": "df.distinct()" + "execution_count": null }, { "metadata": {}, @@ -361,22 +361,22 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val df = dataFrameOf(\"a\", \"b\", \"c\").randomDouble(5)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df.update { colsOf() }\n", " .with { it - rowMean() }" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -394,20 +394,20 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val names = ('a'..'j').map { it.toString() }\n", "val df = dataFrameOf(names).randomDouble(5)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", + "source": "df.sum().transpose().minBy(\"value\")[\"name\"]", "outputs": [], - "execution_count": null, - "source": "df.sum().transpose().minBy(\"value\")[\"name\"]" + "execution_count": null }, { "metadata": {}, @@ -417,12 +417,12 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val df = dataFrameOf(\"a\", \"b\", \"c\").randomInt(30, 0..2)\n", "df.distinct().count()" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -438,8 +438,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val nan = Double.NaN\n", "val names = ('a'..'j').map { it.toString() }\n", @@ -452,20 +450,22 @@ ")\n", "val df = dataFrameOf(names)(*data.toTypedArray())\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df.mapToColumn(\"res\") { \n", " namedValuesOf()\n", " .filter { it.value.isNaN() }.drop(2)\n", " .firstOrNull()?.name \n", "}" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -491,26 +491,26 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val grps by columnOf(\"a\", \"a\", \"a\", \"b\", \"b\", \"c\", \"a\", \"a\", \"b\", \"c\", \"c\", \"c\", \"b\", \"b\", \"c\")\n", "val vals by columnOf(12, 345, 3, 1, 45, 14, 4, 52, 54, 23, 235, 21, 57, 3, 87)\n", "\n", "val df = dataFrameOf(grps, vals)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df.groupBy { grps }.aggregate { \n", " vals.sortDesc().take(3).sum() into \"res\"\n", "}" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -540,8 +540,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "import kotlin.random.Random\n", "\n", @@ -549,18 +547,20 @@ "val list = List(200) { random.nextInt(1, 101) }\n", "val df = dataFrameOf(\"A\", \"B\")(*list.toTypedArray())\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df.groupBy { A.map { (it - 1) / 10 } }.sum { B }\n", " .sortBy { A }\n", " .convert { A }.with { \"(${it * 10}, ${it * 10 + 10}]\" }" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -593,23 +593,23 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val df = dataFrameOf(\"X\")(7, 2, 0, 3, 4, 2, 5, 0, 3, 4)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df.mapToColumn(\"Y\") {\n", " if (it.X == 0) 0 else (prev()?.newValue() ?: 0) + 1\n", "}" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -626,26 +626,26 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val names = ('a'..'h').map { it.toString() } // val names = (0..7).map { it.toString() }\n", "val random = Random(30)\n", "val list = List(64) { random.nextInt(1, 101) }\n", "val df = dataFrameOf(names)(*list.toTypedArray())\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df.add(\"index\") { index() }\n", " .gather { dropLast() }.into(\"name\", \"vals\")\n", " .sortByDesc(\"vals\").take(3)[\"index\", \"name\"]" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -688,8 +688,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val random = Random(31)\n", "val lab = listOf(\"A\", \"B\")\n", @@ -699,13 +697,13 @@ "\n", "val df = dataFrameOf(vals, grps)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val means = df.filter { vals >= 0 }\n", " .groupBy { grps }.mean()\n", @@ -714,7 +712,9 @@ "df.add(\"patched_values\") {\n", " if (vals < 0) means[grps] else vals.toDouble()\n", "}" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -763,21 +763,19 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val groups by columnOf(\"a\", \"a\", \"b\", \"b\", \"a\", \"b\", \"b\", \"b\", \"a\", \"b\", \"a\", \"b\")\n", "val value by columnOf(1.0, 2.0, 3.0, Double.NaN, 2.0, 3.0, Double.NaN, 1.0, 7.0, 3.0, Double.NaN, 8.0)\n", "\n", "val df = dataFrameOf(groups, value)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df.add(\"id\") { index() }\n", " .groupBy { groups }.add(\"res\") {\n", @@ -785,7 +783,9 @@ " }.concat()\n", " .sortBy(\"id\")\n", " .remove(\"id\")" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -803,15 +803,13 @@ { "metadata": {}, "cell_type": "code", + "source": "import kotlinx.datetime.*", "outputs": [], - "execution_count": null, - "source": "import kotlinx.datetime.*" + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "class DateRangeIterator(first: LocalDate, last: LocalDate, val step: Int) : Iterator {\n", " private val finalElement: LocalDate = last\n", @@ -847,13 +845,13 @@ " }\n", " }\n", "}" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val start = LocalDate(2015, 1, 1)\n", "val end = LocalDate(2016, 1, 1)\n", @@ -864,7 +862,9 @@ "val s = List(dti.size()) { Random.nextDouble() }.toColumn(\"s\")\n", "val df = dataFrameOf(dti, s)\n", "df.head()" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -874,9 +874,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.filter { dti.dayOfWeek == DayOfWeek.TUESDAY }.sum { s }", "outputs": [], - "execution_count": null, - "source": "df.filter { dti.dayOfWeek == DayOfWeek.TUESDAY }.sum { s }" + "execution_count": null }, { "metadata": {}, @@ -886,9 +886,9 @@ { "metadata": {}, "cell_type": "code", + "source": "df.groupBy { dti.map { it.month } named \"month\" }.mean()", "outputs": [], - "execution_count": null, - "source": "df.groupBy { dti.map { it.month } named \"month\" }.mean()" + "execution_count": null }, { "metadata": {}, @@ -898,8 +898,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df.add(\"month4\") {\n", " when (dti.monthNumber) {\n", @@ -908,7 +906,9 @@ " else -> 3\n", " }\n", "}.groupBy(\"month4\").aggregate { maxBy(s) into \"max\" }" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -918,18 +918,16 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "import java.time.temporal.WeekFields\n", "import java.util.*" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val start = LocalDate(2015, 1, 1)\n", "val end = LocalDate(2016, 12, 31)\n", @@ -938,7 +936,9 @@ " it.toJavaLocalDate()[WeekFields.of(Locale.ENGLISH).weekOfMonth()] == 3\n", " && it.dayOfWeek.value == 4\n", "}" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -974,8 +974,6 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val fromTo = listOf(\"LoNDon_paris\", \"MAdrid_miLAN\", \"londON_StockhOlm\", \"Budapest_PaRis\", \"Brussels_londOn\").toColumn(\"From_To\")\n", "val flightNumber = listOf(10045.0, Double.NaN, 10065.0, Double.NaN, 10085.0).toColumn(\"FlightNumber\")\n", @@ -984,7 +982,9 @@ "\n", "var df = dataFrameOf(fromTo, flightNumber, recentDelays, airline)\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -994,14 +994,14 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df = df.fillNaNs { FlightNumber }\n", " .with { prev()!!.FlightNumber + (next()!!.FlightNumber - prev()!!.FlightNumber) / 2 }\n", " .convert { FlightNumber }.toInt()\n", "df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -1011,12 +1011,12 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "var df2 = df.split { From_To }.by(\"_\").into(\"From\", \"To\")\n", "df2" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -1026,12 +1026,12 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df2 = df2.update { From and To }.with { it.lowercase().replaceFirstChar(Char::uppercase) }\n", "df2" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -1041,14 +1041,14 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "df2 = df2.update { Airline }.with {\n", " \"([a-zA-Z\\\\s]+)\".toRegex().find(it)?.value ?: \"\"\n", "}\n", "df2" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {}, @@ -1062,12 +1062,12 @@ { "metadata": {}, "cell_type": "code", - "outputs": [], - "execution_count": null, "source": [ "val prep_df = df2.split { RecentDelays }.into { \"delay_$it\" }\n", "prep_df" - ] + ], + "outputs": [], + "execution_count": null }, { "metadata": {},