Skip to content

Commit 7c090b4

Browse files
Merge pull request #1081 from Kotlin/to_dataframe_imrovements
To dataframe improvements
2 parents eb8ee3e + 3223e9c commit 7c090b4

File tree

15 files changed

+755
-286
lines changed

15 files changed

+755
-286
lines changed

core/api/core.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5399,6 +5399,8 @@ public final class org/jetbrains/kotlinx/dataframe/impl/api/SchemaKt {
53995399
public final class org/jetbrains/kotlinx/dataframe/impl/api/ToDataFrameKt {
54005400
public static final fun convertToDataFrame (Ljava/lang/Iterable;Lkotlin/reflect/KClass;Ljava/util/List;Ljava/util/Set;Ljava/util/Set;Ljava/util/Set;I)Lorg/jetbrains/kotlinx/dataframe/DataFrame;
54015401
public static final fun createDataFrameImpl (Ljava/lang/Iterable;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lorg/jetbrains/kotlinx/dataframe/DataFrame;
5402+
public static final fun getHasProperties (Lkotlin/reflect/KClass;)Z
5403+
public static final fun isValueType (Lkotlin/reflect/KClass;)Z
54025404
}
54035405

54045406
public final class org/jetbrains/kotlinx/dataframe/impl/api/ToSequenceKt {

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

Lines changed: 11 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import org.jetbrains.kotlinx.dataframe.annotations.Refine
1212
import org.jetbrains.kotlinx.dataframe.columns.ColumnPath
1313
import org.jetbrains.kotlinx.dataframe.impl.ColumnNameGenerator
1414
import org.jetbrains.kotlinx.dataframe.impl.api.createDataFrameImpl
15+
import org.jetbrains.kotlinx.dataframe.impl.api.hasProperties
16+
import org.jetbrains.kotlinx.dataframe.impl.api.isValueType
1517
import org.jetbrains.kotlinx.dataframe.impl.asList
1618
import org.jetbrains.kotlinx.dataframe.impl.columnName
1719
import org.jetbrains.kotlinx.dataframe.impl.columns.createColumnGuessingType
@@ -26,7 +28,15 @@ import kotlin.reflect.KProperty
2628
@Interpretable("toDataFrameDefault")
2729
public inline fun <reified T> Iterable<T>.toDataFrame(): DataFrame<T> =
2830
toDataFrame {
29-
properties()
31+
// check if type is value: primitives, primitive arrays, datetime types etc.,
32+
// or has no properties
33+
if (T::class.isValueType || !T::class.hasProperties) {
34+
// create a single `value` column
35+
ValueProperty<T>::value from { it }
36+
} else {
37+
// otherwise creates columns based on properties
38+
properties()
39+
}
3040
}
3141

3242
@Refine
@@ -217,99 +227,6 @@ public inline fun <reified T> Iterable<T>.toDataFrame(columnName: String): DataF
217227

218228
// region toDataFrame overloads for built-in types
219229

220-
/*
221-
Without overloads Iterable<String>.toDataFrame produces unexpected result
222-
223-
224-
```
225-
val string = listOf("aaa", "aa", null)
226-
string.toDataFrame()
227-
```
228-
=>
229-
length
230-
0 3
231-
1 2
232-
2 null
233-
*/
234-
235-
@JvmName("toDataFrameByte")
236-
public inline fun <reified B : Byte?> Iterable<B>.toDataFrame(): DataFrame<ValueProperty<B>> =
237-
toDataFrame {
238-
ValueProperty<B>::value from { it }
239-
}.cast()
240-
241-
@JvmName("toDataFrameShort")
242-
public inline fun <reified S : Short?> Iterable<S>.toDataFrame(): DataFrame<ValueProperty<S>> =
243-
toDataFrame {
244-
ValueProperty<S>::value from { it }
245-
}.cast()
246-
247-
@JvmName("toDataFrameInt")
248-
public inline fun <reified I : Int?> Iterable<I>.toDataFrame(): DataFrame<ValueProperty<I>> =
249-
toDataFrame {
250-
ValueProperty<I>::value from { it }
251-
}.cast()
252-
253-
@JvmName("toDataFrameLong")
254-
public inline fun <reified L : Long?> Iterable<L>.toDataFrame(): DataFrame<ValueProperty<L>> =
255-
toDataFrame {
256-
ValueProperty<L>::value from { it }
257-
}.cast()
258-
259-
@JvmName("toDataFrameString")
260-
public inline fun <reified S : String?> Iterable<S>.toDataFrame(): DataFrame<ValueProperty<S>> =
261-
toDataFrame {
262-
ValueProperty<S>::value from { it }
263-
}.cast()
264-
265-
@JvmName("toDataFrameChar")
266-
public inline fun <reified C : Char?> Iterable<C>.toDataFrame(): DataFrame<ValueProperty<C>> =
267-
toDataFrame {
268-
ValueProperty<C>::value from { it }
269-
}.cast()
270-
271-
@JvmName("toDataFrameBoolean")
272-
public inline fun <reified B : Boolean?> Iterable<B>.toDataFrame(): DataFrame<ValueProperty<B>> =
273-
toDataFrame {
274-
ValueProperty<B>::value from { it }
275-
}.cast()
276-
277-
@JvmName("toDataFrameFloat")
278-
public inline fun <reified F : Float?> Iterable<F>.toDataFrame(): DataFrame<ValueProperty<F>> =
279-
toDataFrame {
280-
ValueProperty<F>::value from { it }
281-
}.cast()
282-
283-
@JvmName("toDataFrameDouble")
284-
public inline fun <reified D : Double?> Iterable<D>.toDataFrame(): DataFrame<ValueProperty<D>> =
285-
toDataFrame {
286-
ValueProperty<D>::value from { it }
287-
}.cast()
288-
289-
@JvmName("toDataFrameUByte")
290-
public inline fun <reified U : UByte?> Iterable<U>.toDataFrame(): DataFrame<ValueProperty<U>> =
291-
toDataFrame {
292-
ValueProperty<U>::value from { it }
293-
}.cast()
294-
295-
@JvmName("toDataFrameUShort")
296-
public inline fun <reified U : UShort?> Iterable<U>.toDataFrame(): DataFrame<ValueProperty<U>> =
297-
toDataFrame {
298-
ValueProperty<U>::value from { it }
299-
}.cast()
300-
301-
@JvmName("toDataFrameUInt")
302-
public inline fun <reified U : UInt?> Iterable<U>.toDataFrame(): DataFrame<ValueProperty<U>> =
303-
toDataFrame {
304-
ValueProperty<U>::value from { it }
305-
}.cast()
306-
307-
@JvmName("toDataFrameULong")
308-
public inline fun <reified U : ULong?> Iterable<U>.toDataFrame(): DataFrame<ValueProperty<U>> =
309-
toDataFrame {
310-
ValueProperty<U>::value from { it }
311-
}.cast()
312-
313230
@DataSchema
314231
public interface ValueProperty<T> {
315232
public val value: T

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

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import org.jetbrains.kotlinx.dataframe.impl.projectUpTo
2323
import org.jetbrains.kotlinx.dataframe.impl.schema.sortWithConstructor
2424
import java.lang.reflect.InvocationTargetException
2525
import java.lang.reflect.Method
26-
import java.time.temporal.Temporal
26+
import java.time.temporal.TemporalAccessor
27+
import java.time.temporal.TemporalAmount
2728
import kotlin.reflect.KCallable
2829
import kotlin.reflect.KClass
2930
import kotlin.reflect.KProperty
@@ -37,23 +38,51 @@ import kotlin.reflect.jvm.isAccessible
3738
import kotlin.reflect.jvm.javaField
3839
import kotlin.reflect.typeOf
3940

41+
// non-standard value types (not supertypes, but exact types)
4042
private val valueTypes = setOf(
43+
Any::class,
44+
Unit::class,
45+
Char::class,
46+
UByte::class,
47+
UShort::class,
48+
UInt::class,
49+
ULong::class,
4150
String::class,
4251
Boolean::class,
4352
kotlin.time.Duration::class,
4453
kotlinx.datetime.LocalDate::class,
4554
kotlinx.datetime.LocalDateTime::class,
4655
kotlinx.datetime.Instant::class,
56+
kotlinx.datetime.TimeZone::class,
57+
kotlinx.datetime.DateTimePeriod::class,
58+
kotlinx.datetime.DateTimeUnit::class,
4759
)
4860

61+
/**
62+
* Checks if `KClass` is a value type (number, datetime, string, etc.)
63+
* Should be aligned with `ConeKotlinType.isValueType()` in
64+
* plugins/kotlin-dataframe/src/org/jetbrains/kotlinx/dataframe/plugin/impl/api/toDataFrame.kt
65+
*/
66+
@PublishedApi
4967
internal val KClass<*>.isValueType: Boolean
5068
get() =
5169
this in valueTypes ||
5270
this.isSubclassOf(Number::class) ||
5371
this.isSubclassOf(Enum::class) ||
54-
this.isSubclassOf(Temporal::class) ||
72+
// all java datetime types
73+
this.isSubclassOf(TemporalAccessor::class) ||
74+
this.isSubclassOf(TemporalAmount::class) ||
5575
this.isArray
5676

77+
/**
78+
* Checks if `KClass` has public properties / getter functions (for pojo-like classes).
79+
*/
80+
@PublishedApi
81+
internal val KClass<*>.hasProperties: Boolean
82+
get() = this.memberProperties.any { it.visibility == KVisibility.PUBLIC } ||
83+
// check pojo-like classes
84+
this.memberFunctions.any { it.visibility == KVisibility.PUBLIC && it.isGetterLike() }
85+
5786
internal class CreateDataFrameDslImpl<T>(
5887
override val source: Iterable<T>,
5988
private val clazz: KClass<*>,

0 commit comments

Comments
 (0)