Skip to content

Commit efef26e

Browse files
Kanish2002Jolanrensen
authored andcommitted
Fix valueCounts review cases and preserve empty value column nullability
1 parent 69a6f4b commit efef26e

3 files changed

Lines changed: 32 additions & 11 deletions

File tree

‎core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/api/valueCounts.kt‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,9 @@ public fun <T> DataColumn<T>.valueCounts(
149149
if (dropNA) grouped = grouped.filter { !it.first.isNA }
150150
val nulls = if (dropNA) false else hasNulls()
151151
val values =
152-
if (grouped.isEmpty()) {
153-
// #2034, keep the original name and type of the column even when the input is empty
154-
// nullability is irrelevant, but let's keep it for consistency
155-
take(0).setNullable(nulls)
152+
if (grouped.isEmpty() && !isValueColumn()) {
153+
// Preserve nested columns when there are no counted values.
154+
take(0)
156155
} else {
157156
DataColumn.createByType(name(), grouped.map { it.first }, type().withNullability(nulls))
158157
}

‎core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/api/valueCounts.kt‎

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

33
import io.kotest.matchers.shouldBe
4+
import org.jetbrains.kotlinx.dataframe.DataColumn
45
import org.jetbrains.kotlinx.dataframe.nrow
56
import org.junit.Test
67
import kotlin.reflect.typeOf
@@ -104,6 +105,30 @@ class ValueCountsTests {
104105
result.rowsCount() shouldBe 0
105106
}
106107

108+
@Test
109+
fun `value counts of an empty nullable value column preserves type when NA values are included`() {
110+
val input = DataColumn.createByType("city", emptyList<String?>(), typeOf<String?>())
111+
val result = input.valueCounts(dropNA = false)
112+
113+
result.columnNames() shouldBe listOf("city", "count")
114+
result.nrow shouldBe 0
115+
result["city"].isValueColumn() shouldBe true
116+
result["city"].type() shouldBe typeOf<String?>()
117+
result["count"].type() shouldBe typeOf<Int>()
118+
}
119+
120+
@Test
121+
fun `value counts of an empty nullable value column drops nullability when NA values are excluded`() {
122+
val input = DataColumn.createByType("city", emptyList<String?>(), typeOf<String?>())
123+
val result = input.valueCounts()
124+
125+
result.columnNames() shouldBe listOf("city", "count")
126+
result.nrow shouldBe 0
127+
result["city"].isValueColumn() shouldBe true
128+
result["city"].type() shouldBe typeOf<String>()
129+
result["count"].type() shouldBe typeOf<Int>()
130+
}
131+
107132
@Test
108133
fun `value counts of a column with a result column name clashing with the column name`() {
109134
val count by columnOf("a", "b", "a")
@@ -288,12 +313,12 @@ class ValueCountsTests {
288313

289314
@Test
290315
fun `value counts retains selected columns when every row is dropped`() {
291-
val input = dataFrameOf("city" to columnOf<String?>(null, null))
316+
val input = dataFrameOf("city" to columnOf("London", null)).drop(1)
292317
val result = input.valueCounts("city")
293318

294319
result.columnNames() shouldBe listOf("city", "count")
295320
result.nrow shouldBe 0
296-
result["city"].type() shouldBe typeOf<String?>() // TODO #2034
321+
result["city"].type() shouldBe typeOf<String>()
297322
result["count"].type() shouldBe typeOf<Int>()
298323
}
299324

@@ -305,8 +330,8 @@ class ValueCountsTests {
305330
result.columnNames() shouldBe listOf("details", "count")
306331
result["details"].asColumnGroup().columnNames() shouldBe listOf("name", "city")
307332
result.nrow shouldBe 0
308-
result["details"].asColumnGroup()["name"].type() shouldBe typeOf<String?>() // TODO #2034
309-
result["details"].asColumnGroup()["city"].type() shouldBe typeOf<String?>() // TODO #2034
333+
result["details"].asColumnGroup()["name"].type() shouldBe typeOf<String>()
334+
result["details"].asColumnGroup()["city"].type() shouldBe typeOf<String>()
310335
result["count"].type() shouldBe typeOf<Int>()
311336
}
312337

‎docs/StardustDocs/topics/valueCounts.md‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ df.valueCounts("name", dropNA = false)
7878

7979
<!---END-->
8080

81-
If no observations are counted, the result has zero rows and retains the observed-value columns and count column.
82-
This includes empty input and rows excluded by `dropNA`.
83-
8481
This operation can also be applied to a [`DataColumn`](DataColumn.md):
8582

8683
<!---FUN valueCountsColumn-->

0 commit comments

Comments
 (0)