Skip to content

Commit 63ee929

Browse files
committed
fixup! added describe support for incomparable number types (converting them to either double or bigdecimal) and added tests
1 parent 966447d commit 63ee929

File tree

1 file changed

+44
-65
lines changed
  • core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/impl/api

1 file changed

+44
-65
lines changed
Lines changed: 44 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.jetbrains.kotlinx.dataframe.impl.api
22

33
import org.jetbrains.kotlinx.dataframe.AnyCol
4+
import org.jetbrains.kotlinx.dataframe.DataColumn
45
import org.jetbrains.kotlinx.dataframe.DataFrame
56
import org.jetbrains.kotlinx.dataframe.api.ColumnDescription
67
import org.jetbrains.kotlinx.dataframe.api.add
@@ -35,30 +36,6 @@ import org.jetbrains.kotlinx.dataframe.kind
3536
import org.jetbrains.kotlinx.dataframe.type
3637

3738
internal fun describeImpl(cols: List<AnyCol>): DataFrame<ColumnDescription> {
38-
fun List<AnyCol>.collectAll(atAnyDepth: Boolean): List<AnyCol> =
39-
flatMap { col ->
40-
when (col.kind) {
41-
ColumnKind.Frame ->
42-
col.asAnyFrameColumn()
43-
.concat()
44-
.columns()
45-
.map { it.addPath(col.path() + it.name) }
46-
.collectAll(true)
47-
48-
ColumnKind.Group ->
49-
if (atAnyDepth) {
50-
col.asColumnGroup()
51-
.columns()
52-
.map { it.addPath(col.path() + it.name) }
53-
.collectAll(true)
54-
} else {
55-
listOf(col)
56-
}
57-
58-
ColumnKind.Value -> listOf(col)
59-
}
60-
}
61-
6239
val allCols = cols.collectAll(false)
6340

6441
val hasNumericCols = allCols.any { it.isNumber() }
@@ -84,51 +61,13 @@ internal fun describeImpl(cols: List<AnyCol>): DataFrame<ColumnDescription> {
8461
}
8562
if (hasInterComparableCols || hasNumericCols) {
8663
ColumnDescription::min from inferType {
87-
when {
88-
it.isInterComparable() ->
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-
}
64+
it.convertToInterComparableOrNull()?.minOrNull()
10165
}
10266
ColumnDescription::median from inferType {
103-
when {
104-
it.isInterComparable() ->
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-
}
67+
it.convertToInterComparableOrNull()?.medianOrNull()
11768
}
11869
ColumnDescription::max from inferType {
119-
when {
120-
it.isInterComparable() -> 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-
}
70+
it.convertToInterComparableOrNull()?.maxOrNull()
13271
}
13372
}
13473
}
@@ -140,3 +79,43 @@ internal fun describeImpl(cols: List<AnyCol>): DataFrame<ColumnDescription> {
14079

14180
return df.cast()
14281
}
82+
83+
private fun List<AnyCol>.collectAll(atAnyDepth: Boolean): List<AnyCol> =
84+
flatMap { col ->
85+
when (col.kind) {
86+
ColumnKind.Frame ->
87+
col.asAnyFrameColumn()
88+
.concat()
89+
.columns()
90+
.map { it.addPath(col.path() + it.name) }
91+
.collectAll(true)
92+
93+
ColumnKind.Group ->
94+
if (atAnyDepth) {
95+
col.asColumnGroup()
96+
.columns()
97+
.map { it.addPath(col.path() + it.name) }
98+
.collectAll(true)
99+
} else {
100+
listOf(col)
101+
}
102+
103+
ColumnKind.Value -> listOf(col)
104+
}
105+
}
106+
107+
/** Converts a column to a comparable column if it is not already comparable. */
108+
private fun DataColumn<Any?>.convertToInterComparableOrNull(): DataColumn<Comparable<Any?>>? =
109+
when {
110+
isInterComparable() -> asComparable()
111+
112+
// Found incomparable number types, convert all to Double or BigDecimal first
113+
isNumber() ->
114+
if (any { it?.isBigNumber() == true }) {
115+
map { (it as Number?)?.toBigDecimal() }
116+
} else {
117+
map { (it as Number?)?.toDouble() }
118+
}.cast()
119+
120+
else -> null
121+
}

0 commit comments

Comments
 (0)