@@ -5,13 +5,15 @@ import org.jetbrains.kotlinx.dataframe.DataFrame
5
5
import org.jetbrains.kotlinx.dataframe.api.ColumnDescription
6
6
import org.jetbrains.kotlinx.dataframe.api.add
7
7
import org.jetbrains.kotlinx.dataframe.api.after
8
+ import org.jetbrains.kotlinx.dataframe.api.any
8
9
import org.jetbrains.kotlinx.dataframe.api.asColumnGroup
9
10
import org.jetbrains.kotlinx.dataframe.api.asComparable
10
11
import org.jetbrains.kotlinx.dataframe.api.asNumbers
11
12
import org.jetbrains.kotlinx.dataframe.api.cast
12
13
import org.jetbrains.kotlinx.dataframe.api.concat
13
14
import org.jetbrains.kotlinx.dataframe.api.isComparable
14
15
import org.jetbrains.kotlinx.dataframe.api.isNumber
16
+ import org.jetbrains.kotlinx.dataframe.api.map
15
17
import org.jetbrains.kotlinx.dataframe.api.maxOrNull
16
18
import org.jetbrains.kotlinx.dataframe.api.mean
17
19
import org.jetbrains.kotlinx.dataframe.api.medianOrNull
@@ -25,7 +27,9 @@ import org.jetbrains.kotlinx.dataframe.columns.size
25
27
import org.jetbrains.kotlinx.dataframe.columns.values
26
28
import org.jetbrains.kotlinx.dataframe.impl.columns.addPath
27
29
import org.jetbrains.kotlinx.dataframe.impl.columns.asAnyFrameColumn
30
+ import org.jetbrains.kotlinx.dataframe.impl.isBigNumber
28
31
import org.jetbrains.kotlinx.dataframe.impl.renderType
32
+ import org.jetbrains.kotlinx.dataframe.impl.toBigDecimal
29
33
import org.jetbrains.kotlinx.dataframe.index
30
34
import org.jetbrains.kotlinx.dataframe.kind
31
35
import org.jetbrains.kotlinx.dataframe.type
@@ -55,12 +59,12 @@ internal fun describeImpl(cols: List<AnyCol>): DataFrame<ColumnDescription> {
55
59
}
56
60
}
57
61
58
- val all = cols.collectAll(false )
62
+ val allCols = cols.collectAll(false )
59
63
60
- val hasNumeric = all .any { it.isNumber() }
61
- val hasComparable = all .any { it.isComparable() }
62
- val hasLongPaths = all .any { it.path().size > 1 }
63
- var df = all .toDataFrame {
64
+ val hasNumericCols = allCols .any { it.isNumber() }
65
+ val hasInterComparableCols = allCols .any { it.isComparable() }
66
+ val hasLongPaths = allCols .any { it.path().size > 1 }
67
+ var df = allCols .toDataFrame {
64
68
ColumnDescription ::name from { it.name() }
65
69
if (hasLongPaths) {
66
70
ColumnDescription ::path from { it.path() }
@@ -74,21 +78,63 @@ internal fun describeImpl(cols: List<AnyCol>): DataFrame<ColumnDescription> {
74
78
.groupBy { it }.maxByOrNull { it.value.size }
75
79
?.key
76
80
}
77
- if (hasNumeric ) {
81
+ if (hasNumericCols ) {
78
82
ColumnDescription ::mean from { if (it.isNumber()) it.asNumbers().mean() else null }
79
83
ColumnDescription ::std from { if (it.isNumber()) it.asNumbers().std() else null }
80
84
}
81
- if (hasComparable) {
82
- ColumnDescription ::min from inferType { if (it.isComparable()) it.asComparable().minOrNull() else null }
85
+ if (hasInterComparableCols || hasNumericCols) {
86
+ ColumnDescription ::min from inferType {
87
+ when {
88
+ it.isComparable() ->
89
+ it.asComparable().minOrNull()
90
+
91
+ // Found incomparable number types, convert all to Double or BigDecimal first
92
+ it.isNumber() ->
93
+ if (it.any { it?.isBigNumber() == true }) {
94
+ it.map { (it as Number ? )?.toBigDecimal() }.minOrNull()
95
+ } else {
96
+ it.map { (it as Number ? )?.toDouble() }.minOrNull()
97
+ }
98
+
99
+ else -> null
100
+ }
101
+ }
83
102
ColumnDescription ::median from inferType {
84
- if (it.isComparable()) it.asComparable().medianOrNull() else null
103
+ when {
104
+ it.isComparable() ->
105
+ it.asComparable().medianOrNull()
106
+
107
+ // Found incomparable number types, convert all to Double or BigDecimal first
108
+ it.isNumber() ->
109
+ if (it.any { it?.isBigNumber() == true }) {
110
+ it.map { (it as Number ? )?.toBigDecimal() }.medianOrNull()
111
+ } else {
112
+ it.map { (it as Number ? )?.toDouble() }.medianOrNull()
113
+ }
114
+
115
+ else -> null
116
+ }
117
+ }
118
+ ColumnDescription ::max from inferType {
119
+ when {
120
+ it.isComparable() -> it.asComparable().maxOrNull()
121
+
122
+ // Found incomparable number types, convert all to Double or BigDecimal first
123
+ it.isNumber() ->
124
+ if (it.any { it?.isBigNumber() == true }) {
125
+ it.map { (it as Number ? )?.toBigDecimal() }.maxOrNull()
126
+ } else {
127
+ it.map { (it as Number ? )?.toDouble() }.maxOrNull()
128
+ }
129
+
130
+ else -> null
131
+ }
85
132
}
86
- ColumnDescription ::max from inferType { if (it.isComparable()) it.asComparable().maxOrNull() else null }
87
133
}
88
134
}
89
135
df = df.add(ColumnDescription ::freq) {
90
136
val top = it[ColumnDescription ::top]
91
- val data = all [index]
137
+ val data = allCols [index]
92
138
data.values.count { it == top }
93
139
}.move(ColumnDescription ::freq).after(ColumnDescription ::top)
94
140
0 commit comments