From 0e16817d0bf828d99b8b2c844ed361614f42e44f Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Tue, 3 Jun 2025 14:04:53 +0200 Subject: [PATCH 1/9] added IDE sample of exposed->DataFrame --- .../unsupported-data-sources/build.gradle.kts | 34 ++++++ .../examples/exposed/compatibilityLayer.kt | 87 +++++++++++++++ .../dataframe/examples/exposed/main.kt | 75 +++++++++++++ .../dataframe/examples/exposed/tables.kt | 99 ++++++++++++++++++ .../src/main/resources/chinook.db | Bin 0 -> 886784 bytes gradle/libs.versions.toml | 7 ++ settings.gradle.kts | 1 + 7 files changed, 303 insertions(+) create mode 100644 examples/idea-examples/unsupported-data-sources/build.gradle.kts create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/compatibilityLayer.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/main.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/tables.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/resources/chinook.db diff --git a/examples/idea-examples/unsupported-data-sources/build.gradle.kts b/examples/idea-examples/unsupported-data-sources/build.gradle.kts new file mode 100644 index 0000000000..d7872dee99 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/build.gradle.kts @@ -0,0 +1,34 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + application + kotlin("jvm") + + id("org.jetbrains.kotlinx.dataframe") + + // only mandatory if `kotlin.dataframe.add.ksp=false` in gradle.properties + id("com.google.devtools.ksp") +} + +repositories { + mavenLocal() // in case of local dataframe development + mavenCentral() +} + +dependencies { + // implementation("org.jetbrains.kotlinx:dataframe:X.Y.Z") + implementation(project(":")) + + // exposed + sqlite database support + implementation(libs.sqlite) + implementation(libs.exposed.core) + implementation(libs.exposed.kotlin.datetime) + implementation(libs.exposed.jdbc) + implementation(libs.exposed.json) + implementation(libs.exposed.money) +} + +tasks.withType { + compilerOptions.jvmTarget = JvmTarget.JVM_1_8 +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/compatibilityLayer.kt new file mode 100644 index 0000000000..54d705abc4 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/compatibilityLayer.kt @@ -0,0 +1,87 @@ +package org.jetbrains.kotlinx.dataframe.examples.exposed + +import org.jetbrains.exposed.v1.core.BiCompositeColumn +import org.jetbrains.exposed.v1.core.Column +import org.jetbrains.exposed.v1.core.Expression +import org.jetbrains.exposed.v1.core.ExpressionAlias +import org.jetbrains.exposed.v1.core.ResultRow +import org.jetbrains.exposed.v1.core.Table +import org.jetbrains.exposed.v1.jdbc.Query +import org.jetbrains.kotlinx.dataframe.AnyFrame +import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.api.convertTo +import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.dataframe.codeGen.NameNormalizer +import org.jetbrains.kotlinx.dataframe.impl.schema.DataFrameSchemaImpl +import org.jetbrains.kotlinx.dataframe.schema.ColumnSchema +import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema +import kotlin.reflect.KProperty1 +import kotlin.reflect.full.isSubtypeOf +import kotlin.reflect.full.memberProperties +import kotlin.reflect.typeOf + +/** + * Retrieves all columns of any [Iterable][Iterable]`<`[ResultRow][ResultRow]`>`, like [Query][Query], + * from Exposed row by row and converts the resulting [Map] into a [DataFrame], cast to type [T]. + * + * In notebooks, the untyped version works just as well due to runtime inference :) + */ +inline fun Iterable.convertToDataFrame(): DataFrame = + convertToDataFrame().convertTo() + +/** + * Retrieves all columns of any [Iterable][Iterable]`<`[ResultRow][ResultRow]`>`, like [Query][Query], + * from Exposed row by row and converts the resulting [Map] into a [DataFrame]. + */ +@JvmName("convertToAnyFrame") +fun Iterable.convertToDataFrame(): AnyFrame { + val map = mutableMapOf>() + for (row in this) { + for (expression in row.fieldIndex.keys) { + map.getOrPut(expression.readableName) { + mutableListOf() + } += row[expression] + } + } + return map.toDataFrame() +} + +/** + * Retrieves a simple column name from [this] [Expression]. + * + * Might need to be expanded with multiple types of [Expression]. + */ +val Expression<*>.readableName: String + get() = when (this) { + is Column<*> -> name + is ExpressionAlias<*> -> alias + is BiCompositeColumn<*, *, *> -> getRealColumns().joinToString("_") { it.readableName } + else -> toString() + } + +/** + * Creates a [DataFrameSchema] from the declared [Table] instance. + * + * @param columnNameToAccessor Optional [MutableMap] which will be filled with entries mapping + * the SQL column name to the accessor name from the [Table]. + * This can be used to define a [NameNormalizer] later. + */ +@Suppress("UNCHECKED_CAST") +fun Table.toDataFrameSchema(columnNameToAccessor: MutableMap = mutableMapOf()): DataFrameSchema { + val columns = this::class.memberProperties + .filter { it.returnType.isSubtypeOf(typeOf>()) } + .associate { prop -> + prop as KProperty1> + + // retrieve the actual column name + val columnName = prop.get(this).name + // store the actual column name together with the accessor name in the map + columnNameToAccessor[columnName] = prop.name + + // get the column type from `val a: Column` + val type = prop.returnType.arguments.first().type!! + + columnName to ColumnSchema.Value(type) + } + return DataFrameSchemaImpl(columns) +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/main.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/main.kt new file mode 100644 index 0000000000..d53985ba80 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/main.kt @@ -0,0 +1,75 @@ +package org.jetbrains.kotlinx.dataframe.examples.exposed + +import org.jetbrains.exposed.v1.core.Column +import org.jetbrains.exposed.v1.core.StdOutSqlLogger +import org.jetbrains.exposed.v1.jdbc.Database +import org.jetbrains.exposed.v1.jdbc.SchemaUtils +import org.jetbrains.exposed.v1.jdbc.addLogger +import org.jetbrains.exposed.v1.jdbc.batchInsert +import org.jetbrains.exposed.v1.jdbc.deleteAll +import org.jetbrains.exposed.v1.jdbc.selectAll +import org.jetbrains.exposed.v1.jdbc.transactions.transaction +import org.jetbrains.kotlinx.dataframe.api.asSequence +import org.jetbrains.kotlinx.dataframe.api.count +import org.jetbrains.kotlinx.dataframe.api.describe +import org.jetbrains.kotlinx.dataframe.api.groupBy +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.api.sortByDesc +import org.jetbrains.kotlinx.dataframe.size +import java.io.File + +/** + * Describes a simple bridge between [Exposed](https://www.jetbrains.com/exposed/) and DataFrame! + */ +fun main() { + // defining where to find our SQLite database for Exposed + val resourceDb = "chinook.db" + val dbPath = File(object {}.javaClass.classLoader.getResource(resourceDb)!!.toURI()).absolutePath + val db = Database.connect(url = "jdbc:sqlite:$dbPath", driver = "org.sqlite.JDBC") + + // let's read the database! + val df = transaction(db) { + addLogger(StdOutSqlLogger) + + // tables in Exposed need to be defined, see tables.kt + SchemaUtils.create(Customers, Artists, Albums) + + // Perform the specific query you want to read into the DataFrame. + // Note: DataFrames are in-memory structures, so don't make it too large if you don't have the RAM ;) + val query = Customers.selectAll() // .where { Customers.company.isNotNull() } + + // read and convert the query to a typed DataFrame + // see compatibilityLayer.kt for how we created convertToDataFrame<>() + // and see tables.kt for how we created CustomersDf! + query.convertToDataFrame() + } + + println(df.size()) + + // now we have a DataFrame, we can perform DataFrame operations, + // like seeing how often a country is represented + df.groupBy { country }.count() + .sortByDesc { "count"() } + .print(columnTypes = true, borders = true) + + // or just general statistics + df.describe() + .print(columnTypes = true, borders = true) + + // or make plots using Kandy! It's all up to you + + // writing a DataFrame back into an SQL database with Exposed can also be done! + transaction(db) { + addLogger(StdOutSqlLogger) + + // first delete the original contents + Customers.deleteAll() + + // batch insert our rows back into the SQL database + Customers.batchInsert(df.asSequence()) { dfRow -> + for (column in Customers.columns) { + this[column as Column] = dfRow[column.name] + } + } + } +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/tables.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/tables.kt new file mode 100644 index 0000000000..f5c369ce05 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/tables.kt @@ -0,0 +1,99 @@ +package org.jetbrains.kotlinx.dataframe.examples.exposed + +import org.jetbrains.exposed.v1.core.Column +import org.jetbrains.exposed.v1.core.Table +import org.jetbrains.kotlinx.dataframe.annotations.ColumnName +import org.jetbrains.kotlinx.dataframe.annotations.DataSchema +import org.jetbrains.kotlinx.dataframe.api.generateDataClasses +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.codeGen.NameNormalizer + +object Albums : Table() { + val albumId: Column = integer("AlbumId").autoIncrement() + val title: Column = varchar("Title", 160) + val artistId: Column = integer("ArtistId") + + override val primaryKey = PrimaryKey(albumId) +} + +object Artists : Table() { + val artistId: Column = integer("ArtistId").autoIncrement() + val name: Column = varchar("Name", 120) + + override val primaryKey = PrimaryKey(artistId) +} + +object Customers : Table() { + val customerId: Column = integer("CustomerId").autoIncrement() + val firstName: Column = varchar("FirstName", 40) + val lastName: Column = varchar("LastName", 20) + val company: Column = varchar("Company", 80).nullable() + val address: Column = varchar("Address", 70).nullable() + val city: Column = varchar("City", 40).nullable() + val state: Column = varchar("State", 40).nullable() + val country: Column = varchar("Country", 40).nullable() + val postalCode: Column = varchar("PostalCode", 10).nullable() + val phone: Column = varchar("Phone", 24).nullable() + val fax: Column = varchar("Fax", 24).nullable() + val email: Column = varchar("Email", 60) + val supportRepId: Column = integer("SupportRepId").nullable() + + override val primaryKey = PrimaryKey(customerId) +} + +/** + * Exposed requires you to provide [Table] instances to + * provide type-safe access to your columns and data. + * + * While DataFrame can infer types at runtime, which is enough for Kotlin Notebook, + * to get type safe access at compile time, we need to define a [@DataSchema][DataSchema]. + * + * This is what we created the [toDataFrameSchema] function for! + */ +fun main() { + val columnNameToAccessor = mutableMapOf() + val schema = Customers.toDataFrameSchema(columnNameToAccessor) + + // checking whether the schema is converted correctly. + // schema.print() + + // printing a @DataSchema data class to copy-paste into the code. + // we use a NameNormalizer to let DataFrame generate the same accessors as in the Table + // while keeping the correct column names + schema.generateDataClasses( + name = "CustomersDf", + nameNormalizer = NameNormalizer { columnNameToAccessor[it] ?: it }, + ).print() +} + +// created by Customers.toDataFrameSchema() +// The same can be done for the other tables +@DataSchema +data class CustomersDf( + @ColumnName("Address") + val address: String?, + @ColumnName("City") + val city: String?, + @ColumnName("Company") + val company: String?, + @ColumnName("Country") + val country: String?, + @ColumnName("CustomerId") + val customerId: Int, + @ColumnName("Email") + val email: String, + @ColumnName("Fax") + val fax: String?, + @ColumnName("FirstName") + val firstName: String, + @ColumnName("LastName") + val lastName: String, + @ColumnName("Phone") + val phone: String?, + @ColumnName("PostalCode") + val postalCode: String?, + @ColumnName("State") + val state: String?, + @ColumnName("SupportRepId") + val supportRepId: Int?, +) diff --git a/examples/idea-examples/unsupported-data-sources/src/main/resources/chinook.db b/examples/idea-examples/unsupported-data-sources/src/main/resources/chinook.db new file mode 100644 index 0000000000000000000000000000000000000000..327d2a08ba51189e25c9cffb122561d32b2f6767 GIT binary patch literal 886784 zcmeEv34B~t+4nj3O!j^6o|~p^nzl)sbWedYS(|2UlJ1mpletNT%*;*a&ZJFQ@38Ot zCdiH~f`A|*qAXPu0YwBvPy`f35JeG1+`j*F?#yJSNulL?eLwU|e(gDD?sD!~pZ$4G z_l8z?Kv(+>zgG*WOPPal&W==7#@IB*L@)BlUnvSa@?*bp%;mV^G*-Fh4+*%GEM7t? zdd1(wpT!@WIMqp|_swv1sl9!GoGX+U{5|WfeBuNe= ziGucKns^K;TNU1$?}#_W&&5x~kHj8y5dFTkF%R=Qy zmxgkXR#|?eORO%Wi>*aS7g?!D7Y-m

-a%G(+rWsiKvOFNoiZm&CE+De+~oU9^ge zLVb5lfFq>`N=&An#wqau}yseC~9`E_$@Mk1cqy~7@3RM*X9 z@he7q8h>dC_&~s~^$nRBcc%+6UD5mjs*~s8E@6MhvJ_Fuy}HY-?F@_#>t+Js|0J6X zpD*$Md*W^JOY!O?WiH2SGMOBK|I`sElL&mCbu2nC*V>G9j}qavc5PK#8n&v=jXfRB?Wm)zp}j|K@4)|!t*wi~@3w1ReTUk< z$=Ox6&e=7;s(MLzMrwIz4o@nYI+dSVYPUyHrZ#=5?AIE3E4DFo;nTIH#~tv*HD<+< za&=sb$M<&sM;bf28k(EhW$)*YjZV4R)zH|`)zDto&^#_aHwxiKL2kXfm3@ONkzrQ{H#2=_M)6*w2%om-O=BYDWu`gGR)!R8}_+oEWFN=P% zQQH&K%9tAsUd`=^xiukh>kbYN8~#9-J{&VE;oii9wYVqaL0eP+FdM+FAuJ6*edX$* zfj6T6x%eBUm&@$myr?IupB#b75%`RZ0KY7OX4H2YS>-Gl*>m}kOinph^ts!!2o!hTZeCNLtK~IQz$42ho zgLbje&ic1(wnMFy=>Mt8O-%en{0?&eXT;aVz2a7Jjkr{tCPqY`=oXD)iI^t}g`#|* zyr#UUJf(bHxeKpM{!Na+|HcR;PZg}FV_5fV=~DzNuJdT7>F(1!nMHz?Iz0j1@6!VA z5j~|)u&LlMbk}Hd0bZ&1YhEocU$BbqKDXNFR_CdWnlGT4qiK19&FtBvb`Ki6p>Y#z zA)X+H9#8cJ+=eeR2UV|g53B2p;l*9raB?>4+idtfuKX;)7B_hGzJTBGp%shkHN2OW zi3+>s)h_Nff}YF_dRf;-M%6YQEJjYcVC4k zUnOH5{y+#@k>78PBE8S@BK@+ZA-&hyi1Z$-8R^{?HY)#;MdJLsta(W9v|y#nzi5## z|27LIef-uvNWS1fa?3GDZtg*H(>f$K9){$GB}lHHgXFp?NUlw{<$v!n{@!O|I42wN zZyteDGm?^uX3pei*vweOS|yUF#j`(=%Q4(fvu)q<>6o&K#F6_;_P2+>5YK~*mnGJ^ zJszOak7Y{2&m35I7=GYmWQdU}K2DSve&&-TiaiFX0Z0cowl#D$*Uhh5vZ#8zj5J;X z7&Bn;jL4X<7xKTjrw(2Iw@mpSR-IBFZ~r5n6HkjL#G~RNaliPIxJ}#$uHbTUp*UNd zDozx8gkN|>zc@y06Fs6`tP{23FtGx>!U8cz%o0;Xu1FUkR+NvFKPkUc-csIBehTj4 zS^2Sl^D3XL{{P1jQ085<80&cMMZly=>4n>omRwkcwD>}py(=>>*nxD$1xt}my&wf? z(fK=(7Mu@^tmK~$s~9EcJm6d<`@EG%GtL8YRMO9dTuezl7nUECaL9OpE(4qJfT1`(%1N} z+19@Ft+D%u@Fkcx5dEJZPGa!L`+>L{y!}a^#pOBKrpXcbuN;9K$neUY&N@{Ky4;4^ z@Al}^A;depGwAOd)J)x_#^0O;QC?lA-v~eeiJNVm4NVox)DgE!55Ein-{E8T<6q8& z&~G8V67x0M|GCOj3|_hK!0P`8;+ud1H;d1Sv&8X`?QH{1KU4Xq^1kv49-91{9D&d7 z2xLN#U)tfT=o!>2nhdq75JLQ=F>-h{tT{-5Fn?;3Kj<6KXF{6qj4Bk=swGuwg^Ksp zS`8`&b0)<4<8HU>dje{AKp!?|K+wN-|F`RPeORpv2F!Gb{l}CQxsdoTto3Vq-5$5* zQ`>^5KMi94s2U;*LjSq)vbu@3vzZL(f04Y90^$GEHeCs&cRLMdcRdI^`B8 zQ-X@2xRpL-hq77OptL9r%35W$vQ(*1%9Ijix>BHIDd-3P2mcHI1Am9V$$!p&!ha+? z@Y!9N|9dSH+xCGy6r1;f2^Bq$gN+qkkAV>u?T>=66D^OHB3<`L6Vm!`4k11An_y|h z;oksLELJ}ZClRso>&GEo_Vr?=_k*0sS18K^=CQ`?}MM(KQYrr!9^X{EU|8}=P`qwX& zA^qU47Nmc?6YW=ie<#|ny!%D8UwP{ev|oAicC=r4<94)P`T1>Vzw*khV6l~-+)B*; z^Iw>c^oO^!B7Np&u*}L+H^ci~dGe-JNWXRCQAi)Z5!0Z2^9BgNm9Jk9iMaB>br=EV z{_DUXEB9Wz1nFI$hqzq1{hB>UZ@Fd$(i^Wn66v*{L%)=(KZkxPS6+pFDVJW^j`ZRy z{7BEg0&KW)&gEdYl`}6p8tG}5DM&+?&O>_gCF_wMe=%5lW%Obw3zXnRV8fNbh1-z& zE;teC&;=N6W#D{_q0)aIeXH+0`qs{K>08^*!5AuA&c+xj8_%Y1b)7}uYCDs@)p{m< zYuy?2t%lR-TSuNo-&%WGHqx3?mmytw$`+){LdPSm3aLmdEC?BtMg4de_J4mws=O>S zlqUZsM__UU{(DD2c`3!g6(u2gYj$Y{-vyAojEO=1MP!qI2QdO`(i4k1$~klUT>74{ zn}-$*81nbdh%5I_DV*6^75^LXp8Z(%Ja$$*Ghwy|Md;@FmFEtb$Z&cxsKtO`aL;N%q83 zW`4qK{oi_l5&h4_N3W~IRcX-@E^m9KJKX<^gi%ern-1#eXR>DDht!kU?^2t&QD31WY~QmtrR={%f(CV|+6H!9(~g z2n1|}-G>)*YkG9QMXY*ay#S+TKSkqr-bBya8!-A7jZ18GJIaaw7vfdgh%2E3c-t=0 z&&j{Z5ttl-|M(H8PJ-hOdzGu`Nu?~G#eRr#MS|eGvk|61Y>jd)6Cc6<=RrgPyi}Yo zhD8@50M>}vVuo-)`}d*pN9DK5ca_JLo0V(DTZr8ItoWYz79s^+FV2LXa74JEJvdS< z6P552%2r-h9#HNPe-b|xFG8PqC$xznL>AlvPonuERrwXXh@MxzuRN^WfsarAO^(0; zM}XF-SR>OKN)uL7>R2VymGa68O2u-SE|XW5%CwqNN0lruk?CSeMWsyT>KBV-d7(@f zP?}IqsbjuO%jETWGM!6l!W?xwLM+W*PohfM1JeiqjLLHBpSDVe-6IRcX-@Yx*!+SZ8@03=EPz$E}s zBmht(08k_V;0jCyIM3ikERoG+N;Pc%<|?E# zxk|n{%sfX#nYQ42=6D8WqL*w2CH__7QX&j_c_1&TXmuI43Zi^b*sPLlOT$lvjV^6- z)fwYIJpK*)vvKdmeHB7cXtfXYmpC<1-fEqaSTuL8vR#TBBJrLOj;1QMERKnjJ;dIc zAL#Wga=Z2{LL{0%d4Ew-(ekO>N{jYXb}xph49MWF>i7=s|DfGH`*G@5OdUJQw-zQA zRZQi_#eXKuF5B-EAK(-8P%sON;eVe|-J6TgVjawkHalik!^LJ-+>A~i-;0UfIlx+o z*14m6C?~0Clv%N_l&IqiVo9D6qIgHo#ybFbW!jgMh`$37MbI1vp>5RFPP zW&GF1J#2q1`U)+FXhq=v#c#p?zsRxR9|8aWqIms4i+=L@ND(>X}Lh&b5Y@w*0{CO&_;jo0{&r)$ddjZ9#X#eLA+x!1rfrie9MQ=Z(dS8PT z@Jv|s-U&%x4lH}Gha4|KI3XE)R{1L|e9u(gg^e#v2`B$1N8mqf1QgiPD@xiI5(ly1 z=TJFS;kTl!QaS1Egzum{oyrM!iE5OmP+9mB(oxQ&a{9{TuVedsm&&QPBp-+JdsI$7 zHhC7xKc{kHa}w&|uTWY1HDMlh7yo{uP&i)zi)Q{L71{k{@|#DGr2j7QI$ZuMmD95M zizxqz$|;P~#{Vsq6JHj`p!^n<9j7IoKvn*j>QUV23jYyZ=TAFe$gd>Gch5@%KvOuC zlUg|pj`=^SoKPvIV9xj(^4;f;x9xxbgiB(YpltGQas(zv;J|~y35fJDfEZt$i0`#ZIaMqYs>m0~%HNgulwT?@DNiepD)%e5 zDc2|$Dti=1K6^0vX_O^l&%T^Y^-BVt-I|<+w*5=Kdm}Lg zd{mY{M@#{;3GxdQe~j|$^7^^N6tEx5a)_7$_6!l+dlP<*;;t~|kqhhUqqY?{Iag{=TdwZx@r5uamFcr)B zUs3F%;%t67irc6-oi9bPgNg-=%zf&K{!brP#0jiKImv;(orzOFKR}$HT{!=*MhIyA z--UHO|0YM^ zP)2}nr8QZUu>dQujf(l{HxhBH)B02zQCdt_dD;(9tdzynyHQN1qJsbcYoKCE`d4w) zPemo=XSn*Id?2L(m9a;tGKUKf%%rP4wF(zslf@K}&rCATJo$4d?vt+xs#kK$NvW@( z_(i&!lyp9dH&9U|HKDjy){yi#>XpU3G}=dq(8-mo^uOZ)uY4e}23MQqYwQtR?Uz>* zN`-i5Od!Wjln*4d;DIZtn3V7#if759fS`hHm#@hKd4EgAbO#s?c8`2OAz)c6i;M

Bn%HDY5sVIW$N6Qjb6rYgAgfFA`b-UP(;(fB{ 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�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 z

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%0Drh~0Drgy;1AaY@Q3RF_`@}TOQ>o`z_*sES^z#` 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 literal 0 HcmV?d00001 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 99f9edc5ad..d583448611 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,6 +62,7 @@ jai-core = "1.1.3" jts = "1.20.0" kandy = "0.8.1-dev-66" +exposed = "1.0.0-beta-2" [libraries] ksp-gradle = { group = "com.google.devtools.ksp", name = "symbol-processing-gradle-plugin", version.ref = "ksp" } @@ -158,6 +159,12 @@ dataframe-symbol-processor = { group = "org.jetbrains.kotlinx.dataframe", name = duckdb-jdbc = { group = "org.duckdb", name = "duckdb_jdbc", version.ref= "duckdb"} +exposed-core = { group = "org.jetbrains.exposed", name = "exposed-core", version.ref = "exposed" } +exposed-jdbc = { group = "org.jetbrains.exposed", name = "exposed-jdbc", version.ref = "exposed" } +exposed-kotlin-datetime = { group = "org.jetbrains.exposed", name = "exposed-kotlin-datetime", version.ref = "exposed" } +exposed-json = { group = "org.jetbrains.exposed", name = "exposed-json", version.ref = "exposed" } +exposed-money = { group = "org.jetbrains.exposed", name = "exposed-money", version.ref = "exposed" } + [plugins] jupyter-api = { id = "org.jetbrains.kotlin.jupyter.api", version.ref = "kotlinJupyter" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index bade37d6ac..66e67027fc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,6 +25,7 @@ include("examples:idea-examples:titanic") include("examples:idea-examples:movies") include("examples:idea-examples:youtube") include("examples:idea-examples:json") +include("examples:idea-examples:unsupported-data-sources") val jupyterApiTCRepo: String by settings From 211412a494c55ebb4ddfb3b354afcaa2ba4f4078 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Wed, 4 Jun 2025 14:18:21 +0200 Subject: [PATCH 2/9] WIP spark --- .../unsupported-data-sources/build.gradle.kts | 4 ++ .../examples/kotlinSpark/typedDataset.kt | 50 +++++++++++++++++++ .../examples/kotlinSpark/untypedDataset.kt | 5 ++ gradle/libs.versions.toml | 9 +++- 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt diff --git a/examples/idea-examples/unsupported-data-sources/build.gradle.kts b/examples/idea-examples/unsupported-data-sources/build.gradle.kts index d7872dee99..0ab26aba44 100644 --- a/examples/idea-examples/unsupported-data-sources/build.gradle.kts +++ b/examples/idea-examples/unsupported-data-sources/build.gradle.kts @@ -27,6 +27,10 @@ dependencies { implementation(libs.exposed.jdbc) implementation(libs.exposed.json) implementation(libs.exposed.money) + + // (kotlin) spark support + implementation(libs.kotlin.spark) + compileOnly(libs.spark) } tasks.withType { diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt new file mode 100644 index 0000000000..f067d6b1f2 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt @@ -0,0 +1,50 @@ +package org.jetbrains.kotlinx.dataframe.examples.kotlinSpark + +import org.apache.spark.sql.Dataset +import org.jetbrains.kotlinx.dataframe.annotations.DataSchema +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.spark.api.withSpark + +@DataSchema +data class Name(val firstName: String, val lastName: String) + +@DataSchema +data class Person( + val name: Name, + val age: Int, + val city: String?, + val weight: Int?, + val isHappy: Boolean, +) + +object TypedDataset { + + /** + * With the Kotlin Spark API, norm;;al Kotlin data classes are supported, + * meaning we can reuse the same class for Spark and DataFrame! + * + */ + @JvmStatic + fun main(args: Array): Unit = + withSpark { + // Spark Dataset + val rawDataset: Dataset = listOf( + Person(Name("Alice", "Cooper"), 15, "London", 54, true), + Person(Name("Bob", "Dylan"), 45, "Dubai", 87, true), + Person(Name("Charlie", "Daniels"), 20, "Moscow", null, false), + Person(Name("Charlie", "Chaplin"), 40, "Milan", null, true), + Person(Name("Bob", "Marley"), 30, "Tokyo", 68, true), + Person(Name("Alice", "Wolf"), 20, null, 55, false), + Person(Name("Charlie", "Byrd"), 30, "Moscow", 90, true), + ).toDS() + + // we can perform large operations in Spark + val dataset = rawDataset.filter { it.age > 17 } + + // and convert to DataFrame + val dataframe = dataset.collectAsList().toDataFrame() + + dataframe.print(columnTypes = true, borders = true) + } +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt new file mode 100644 index 0000000000..2a47e8b163 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt @@ -0,0 +1,5 @@ +package org.jetbrains.kotlinx.dataframe.examples.kotlinSpark + +fun main() { + +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d583448611..b1236358ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -64,6 +64,10 @@ jts = "1.20.0" kandy = "0.8.1-dev-66" exposed = "1.0.0-beta-2" +# check the versions down in the [libraries] section too! +kotlin-spark = "1.2.4" +spark = "3.3.2" + [libraries] ksp-gradle = { group = "com.google.devtools.ksp", name = "symbol-processing-gradle-plugin", version.ref = "ksp" } ksp-api = { group = "com.google.devtools.ksp", name = "symbol-processing-api", version.ref = "ksp" } @@ -157,7 +161,7 @@ kotlin-jupyter-test-kit = { group = "org.jetbrains.kotlinx", name = "kotlin-jupy kotlinx-benchmark-runtime = { group = "org.jetbrains.kotlinx", name = "kotlinx-benchmark-runtime", version.ref = "benchmark" } dataframe-symbol-processor = { group = "org.jetbrains.kotlinx.dataframe", name = "symbol-processor-all" } -duckdb-jdbc = { group = "org.duckdb", name = "duckdb_jdbc", version.ref= "duckdb"} +duckdb-jdbc = { group = "org.duckdb", name = "duckdb_jdbc", version.ref = "duckdb" } exposed-core = { group = "org.jetbrains.exposed", name = "exposed-core", version.ref = "exposed" } exposed-jdbc = { group = "org.jetbrains.exposed", name = "exposed-jdbc", version.ref = "exposed" } @@ -165,6 +169,9 @@ exposed-kotlin-datetime = { group = "org.jetbrains.exposed", name = "exposed-kot exposed-json = { group = "org.jetbrains.exposed", name = "exposed-json", version.ref = "exposed" } exposed-money = { group = "org.jetbrains.exposed", name = "exposed-money", version.ref = "exposed" } +kotlin-spark = { group = "org.jetbrains.kotlinx.spark", name = "kotlin-spark-api_3.3.2_2.13", version.ref = "kotlin-spark" } +spark = { group = "org.apache.spark", name = "spark-sql_2.13", version.ref = "spark" } + [plugins] jupyter-api = { id = "org.jetbrains.kotlin.jupyter.api", version.ref = "kotlinJupyter" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } From 28866ca1693b0269f52ef04e4677619fa731da93 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Thu, 5 Jun 2025 15:43:28 +0200 Subject: [PATCH 3/9] added working kotlin spark sample --- build.gradle.kts | 2 +- .../unsupported-data-sources/build.gradle.kts | 20 +- .../kotlinSpark/compatibilityLayer.kt | 313 ++++++++++++++++++ .../examples/kotlinSpark/typedDataset.kt | 82 +++-- .../examples/kotlinSpark/untypedDataset.kt | 67 +++- gradle/libs.versions.toml | 3 + 6 files changed, 455 insertions(+), 32 deletions(-) create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/compatibilityLayer.kt diff --git a/build.gradle.kts b/build.gradle.kts index 8c7d94f639..1a3c7648b4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -196,7 +196,7 @@ allprojects { logger.warn("Could not set ktlint config on :${this.name}") } - // set the java toolchain version to 11 for all subprojects for CI stability + // set the java toolchain version to 21 for all subprojects for CI stability extensions.findByType()?.jvmToolchain(21) // Attempts to configure buildConfig for each sub-project that uses it diff --git a/examples/idea-examples/unsupported-data-sources/build.gradle.kts b/examples/idea-examples/unsupported-data-sources/build.gradle.kts index 0ab26aba44..ddc038caf2 100644 --- a/examples/idea-examples/unsupported-data-sources/build.gradle.kts +++ b/examples/idea-examples/unsupported-data-sources/build.gradle.kts @@ -31,8 +31,24 @@ dependencies { // (kotlin) spark support implementation(libs.kotlin.spark) compileOnly(libs.spark) + implementation(libs.log4j.core) + implementation(libs.log4j.api) } -tasks.withType { - compilerOptions.jvmTarget = JvmTarget.JVM_1_8 +/** + * Runs the kotlinSpark/typedDataset example with java 11. + */ +val runKotlinSparkTypedDataset by tasks.registering(JavaExec::class) { + classpath = sourceSets["main"].runtimeClasspath + javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(11) } + mainClass = "org.jetbrains.kotlinx.dataframe.examples.kotlinSpark.TypedDatasetKt" +} + +/** + * Runs the kotlinSpark/untypedDataset example with java 11. + */ +val runKotlinSparkUntypedDataset by tasks.registering(JavaExec::class) { + classpath = sourceSets["main"].runtimeClasspath + javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(11) } + mainClass = "org.jetbrains.kotlinx.dataframe.examples.kotlinSpark.UntypedDatasetKt" } diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/compatibilityLayer.kt new file mode 100644 index 0000000000..13db8c29bc --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/compatibilityLayer.kt @@ -0,0 +1,313 @@ +package org.jetbrains.kotlinx.dataframe.examples.kotlinSpark + +import org.apache.spark.api.java.JavaSparkContext +import org.apache.spark.sql.Dataset +import org.apache.spark.sql.Row +import org.apache.spark.sql.RowFactory +import org.apache.spark.sql.SparkSession +import org.apache.spark.sql.types.ArrayType +import org.apache.spark.sql.types.DataType +import org.apache.spark.sql.types.DataTypes +import org.apache.spark.sql.types.Decimal +import org.apache.spark.sql.types.DecimalType +import org.apache.spark.sql.types.MapType +import org.apache.spark.sql.types.StructType +import org.apache.spark.unsafe.types.CalendarInterval +import org.jetbrains.kotlinx.dataframe.AnyFrame +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.DataRow +import org.jetbrains.kotlinx.dataframe.api.rows +import org.jetbrains.kotlinx.dataframe.api.schema +import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup +import org.jetbrains.kotlinx.dataframe.columns.TypeSuggestion +import org.jetbrains.kotlinx.dataframe.schema.ColumnSchema +import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema +import org.jetbrains.kotlinx.spark.api.toRDD +import java.math.BigDecimal +import java.math.BigInteger +import java.sql.Date +import java.sql.Timestamp +import java.time.Instant +import java.time.LocalDate +import kotlin.reflect.KType +import kotlin.reflect.KTypeProjection +import kotlin.reflect.full.createType +import kotlin.reflect.full.isSubtypeOf +import kotlin.reflect.full.withNullability +import kotlin.reflect.typeOf + +// region Spark to DataFrame + +/** + * Converts an untyped Spark [Dataset] (Dataframe) to a Kotlin [DataFrame]. + * [StructTypes][StructType] are converted to [ColumnGroups][ColumnGroup]. + * + * DataFrame supports type inference to do the conversion automatically. + * This is usually fine for smaller data sets, but when working with larger datasets a type map might be a good idea. + * See [convertToDataFrame] for more information. + */ +fun Dataset.convertToDataFrameByInference( + schema: StructType = schema(), + prefix: List = emptyList(), +): AnyFrame { + val columns = schema.fields().map { field -> + val name = field.name() + when (val dataType = field.dataType()) { + is StructType -> + DataColumn.createColumnGroup( + name = name, + df = convertToDataFrameByInference(dataType, prefix + name), + ) + + else -> + DataColumn.createByInference( + name = name, + values = select((prefix + name).joinToString(".")) + .collectAsList() + .map { it[0] }, + suggestedType = TypeSuggestion.Infer, + nullable = field.nullable(), + ) + } + } + return columns.toDataFrame() +} + +/** + * Converts an untyped Spark [Dataset] (Dataframe) to a Kotlin [DataFrame]. + * [StructTypes][StructType] are converted to [ColumnGroups][ColumnGroup]. + * + * This version uses a [type-map][DataType.convertToDataFrame] to convert the schemas with a fallback to inference. + * For smaller data sets, inference is usually fine too. + * See [convertToDataFrameByInference] for more information. + */ +fun Dataset.convertToDataFrame(schema: StructType = schema(), prefix: List = emptyList()): AnyFrame { + val columns = schema.fields().map { field -> + val name = field.name() + when (val dataType = field.dataType()) { + is StructType -> + DataColumn.createColumnGroup( + name = name, + df = convertToDataFrame(dataType, prefix + name), + ) + + else -> + DataColumn.createByInference( + name = name, + values = select((prefix + name).joinToString(".")) + .collectAsList() + .map { it[0] }, + suggestedType = + dataType.convertToDataFrame() + ?.let(TypeSuggestion::Use) + ?: TypeSuggestion.Infer, // fallback to inference if needed + nullable = field.nullable(), + ) + } + } + return columns.toDataFrame() +} + +/** + * Returns the corresponding Kotlin type for a given Spark DataType. + * + * This list may be incomplete, but it can at least give you a good start. + * + * @return The KType that corresponds to the Spark DataType, or null if no matching KType is found. + */ +fun DataType.convertToDataFrame(): KType? = + when { + this == DataTypes.ByteType -> typeOf() + + this == DataTypes.ShortType -> typeOf() + + this == DataTypes.IntegerType -> typeOf() + + this == DataTypes.LongType -> typeOf() + + this == DataTypes.BooleanType -> typeOf() + + this == DataTypes.FloatType -> typeOf() + + this == DataTypes.DoubleType -> typeOf() + + this == DataTypes.StringType -> typeOf() + + this == DataTypes.DateType -> typeOf() + + this == DataTypes.TimestampType -> typeOf() + + this is DecimalType -> typeOf() + + this == DataTypes.CalendarIntervalType -> typeOf() + + this == DataTypes.NullType -> nullableNothingType + + this == DataTypes.BinaryType -> typeOf() + + this is ArrayType -> { + when (elementType()) { + DataTypes.ShortType -> typeOf() + DataTypes.IntegerType -> typeOf() + DataTypes.LongType -> typeOf() + DataTypes.FloatType -> typeOf() + DataTypes.DoubleType -> typeOf() + DataTypes.BooleanType -> typeOf() + else -> null + } + } + + this is MapType -> { + val key = keyType().convertToDataFrame() ?: return null + val value = valueType().convertToDataFrame() ?: return null + Map::class.createType( + listOf( + KTypeProjection.invariant(key), + KTypeProjection.invariant(value.withNullability(valueContainsNull())), + ), + ) + } + + else -> null + } + +// endregion + +// region DataFrame to Spark + +/** + * Converts the DataFrame to a Spark Dataset of Rows using the provided SparkSession and JavaSparkContext. + * + * Spark needs both the data and the schema to be converted to create a correct [Dataset]. + * + * @param spark The SparkSession object to use for creating the DataFrame. + * @param sc The JavaSparkContext object to use for converting the DataFrame to RDD. + * @return A Dataset of Rows representing the converted DataFrame. + */ +fun DataFrame<*>.convertToSpark(spark: SparkSession, sc: JavaSparkContext): Dataset { + val rows = sc.toRDD(rows().map { it.convertToSpark() }) + return spark.createDataFrame(rows, schema().convertToSpark()) +} + +/** + * Converts a DataRow to a Spark Row object. + * + * @return The converted Spark Row. + */ +fun DataRow<*>.convertToSpark(): Row = + RowFactory.create( + *values().map { + when (it) { + is DataRow<*> -> it.convertToSpark() + else -> it + } + }.toTypedArray(), + ) + +/** + * Converts a DataFrameSchema to a Spark StructType. + * + * @return The converted Spark StructType. + */ +fun DataFrameSchema.convertToSpark(): StructType = + DataTypes.createStructType( + columns.map { (name, schema) -> + DataTypes.createStructField(name, schema.convertToSpark(), schema.nullable) + }, + ) + +/** + * Converts a ColumnSchema object to Spark DataType. + * + * @return The Spark DataType corresponding to the given ColumnSchema object. + * @throws IllegalArgumentException if the column type or kind is unknown. + */ +fun ColumnSchema.convertToSpark(): DataType = + when (this) { + is ColumnSchema.Value -> type.convertToSpark() ?: error("unknown data type: $type") + is ColumnSchema.Group -> schema.convertToSpark() + is ColumnSchema.Frame -> error("nested dataframes are not supported") + else -> error("unknown column kind: $this") + } + +/** + * Returns the corresponding Spark DataType for a given Kotlin type. + * + * This list may be incomplete, but it can at least give you a good start. + * + * @return The Spark DataType that corresponds to the Kotlin type, or null if no matching DataType is found. + */ +fun KType.convertToSpark(): DataType? = + when { + isSubtypeOf(typeOf()) -> DataTypes.ByteType + + isSubtypeOf(typeOf()) -> DataTypes.ShortType + + isSubtypeOf(typeOf()) -> DataTypes.IntegerType + + isSubtypeOf(typeOf()) -> DataTypes.LongType + + isSubtypeOf(typeOf()) -> DataTypes.BooleanType + + isSubtypeOf(typeOf()) -> DataTypes.FloatType + + isSubtypeOf(typeOf()) -> DataTypes.DoubleType + + isSubtypeOf(typeOf()) -> DataTypes.StringType + + isSubtypeOf(typeOf()) -> DataTypes.DateType + + isSubtypeOf(typeOf()) -> DataTypes.DateType + + isSubtypeOf(typeOf()) -> DataTypes.TimestampType + + isSubtypeOf(typeOf()) -> DataTypes.TimestampType + + isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() + + isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() + + isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() + + isSubtypeOf(typeOf()) -> DataTypes.CalendarIntervalType + + isSubtypeOf(nullableNothingType) -> DataTypes.NullType + + isSubtypeOf(typeOf()) -> DataTypes.BinaryType + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.ShortType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.IntegerType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.LongType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.FloatType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.DoubleType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.BooleanType, false) + + isSubtypeOf(typeOf>()) -> + error("non-primitive arrays are not supported for now, you can add it yourself") + + isSubtypeOf(typeOf>()) -> error("lists are not supported for now, you can add it yourself") + + isSubtypeOf(typeOf>()) -> error("sets are not supported for now, you can add it yourself") + + classifier == Map::class -> { + val (key, value) = arguments + DataTypes.createMapType( + key.type?.convertToSpark(), + value.type?.convertToSpark(), + value.type?.isMarkedNullable ?: true, + ) + } + + else -> null + } + +private val nullableNothingType: KType = typeOf>().arguments.first().type!! + +// endregion diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt index f067d6b1f2..d806f7f27e 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt @@ -1,9 +1,19 @@ +@file:Suppress("ktlint:standard:function-signature") + package org.jetbrains.kotlinx.dataframe.examples.kotlinSpark import org.apache.spark.sql.Dataset import org.jetbrains.kotlinx.dataframe.annotations.DataSchema +import org.jetbrains.kotlinx.dataframe.api.aggregate +import org.jetbrains.kotlinx.dataframe.api.groupBy +import org.jetbrains.kotlinx.dataframe.api.max +import org.jetbrains.kotlinx.dataframe.api.mean +import org.jetbrains.kotlinx.dataframe.api.min import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.api.schema +import org.jetbrains.kotlinx.dataframe.api.std import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.dataframe.api.toList import org.jetbrains.kotlinx.spark.api.withSpark @DataSchema @@ -18,33 +28,49 @@ data class Person( val isHappy: Boolean, ) -object TypedDataset { - - /** - * With the Kotlin Spark API, norm;;al Kotlin data classes are supported, - * meaning we can reuse the same class for Spark and DataFrame! - * - */ - @JvmStatic - fun main(args: Array): Unit = - withSpark { - // Spark Dataset - val rawDataset: Dataset = listOf( - Person(Name("Alice", "Cooper"), 15, "London", 54, true), - Person(Name("Bob", "Dylan"), 45, "Dubai", 87, true), - Person(Name("Charlie", "Daniels"), 20, "Moscow", null, false), - Person(Name("Charlie", "Chaplin"), 40, "Milan", null, true), - Person(Name("Bob", "Marley"), 30, "Tokyo", 68, true), - Person(Name("Alice", "Wolf"), 20, null, 55, false), - Person(Name("Charlie", "Byrd"), 30, "Moscow", 90, true), - ).toDS() - - // we can perform large operations in Spark - val dataset = rawDataset.filter { it.age > 17 } - - // and convert to DataFrame - val dataframe = dataset.collectAsList().toDataFrame() - - dataframe.print(columnTypes = true, borders = true) +/** + * With the Kotlin Spark API, normal Kotlin data classes are supported, + * meaning we can reuse the same class for Spark and DataFrame! + * + * Also, since we use an actual class to define the schema, we need no type conversion! + * + * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. + * Use the `runKotlinSparkTypedDataset` Gradle task to do so. + */ +fun main() = withSpark { + // Creating a Spark Dataset. Usually, this is loaded from some server or database. + val rawDataset: Dataset = listOf( + Person(Name("Alice", "Cooper"), 15, "London", 54, true), + Person(Name("Bob", "Dylan"), 45, "Dubai", 87, true), + Person(Name("Charlie", "Daniels"), 20, "Moscow", null, false), + Person(Name("Charlie", "Chaplin"), 40, "Milan", null, true), + Person(Name("Bob", "Marley"), 30, "Tokyo", 68, true), + Person(Name("Alice", "Wolf"), 20, null, 55, false), + Person(Name("Charlie", "Byrd"), 30, "Moscow", 90, true), + ).toDS() + + // we can perform large operations in Spark. + // DataFrames are in-memory structures, so this is a good place to limit the number of rows if you don't have the RAM ;) + val dataset = rawDataset.filter { it.age > 17 } + + // and convert it to DataFrame via a typed List + val dataframe = dataset.collectAsList().toDataFrame() + dataframe.schema().print() + dataframe.print(columnTypes = true, borders = true) + + // now we can use DataFrame-specific functions + val ageStats = dataframe + .groupBy { city }.aggregate { + mean { age } into "meanAge" + std { age } into "stdAge" + min { age } into "minAge" + max { age } into "maxAge" } + + ageStats.print(columnTypes = true, borders = true) + + // and when we want to convert a DataFrame back to Spark, we can do the same trick via a typed List + val sparkDatasetAgain = dataframe.toList().toDS() + sparkDatasetAgain.printSchema() + sparkDatasetAgain.show() } diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt index 2a47e8b163..7d9b4c274a 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt @@ -1,5 +1,70 @@ +@file:Suppress("ktlint:standard:function-signature") + package org.jetbrains.kotlinx.dataframe.examples.kotlinSpark -fun main() { +import org.apache.spark.sql.Dataset +import org.apache.spark.sql.Row +import org.jetbrains.kotlinx.dataframe.api.aggregate +import org.jetbrains.kotlinx.dataframe.api.groupBy +import org.jetbrains.kotlinx.dataframe.api.max +import org.jetbrains.kotlinx.dataframe.api.mean +import org.jetbrains.kotlinx.dataframe.api.min +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.api.schema +import org.jetbrains.kotlinx.dataframe.api.std +import org.jetbrains.kotlinx.spark.api.col +import org.jetbrains.kotlinx.spark.api.gt +import org.jetbrains.kotlinx.spark.api.withSpark + +/** + * Since we don't know the schema at compile time this time, we need to do + * some schema mapping in between Spark and DataFrame. + * + * We will use compatibilityLayer.kt to do this. + * + * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. + * Use the `runKotlinSparkUntypedDataset` Gradle task to do so. + */ +fun main() = withSpark { + // Creating a Spark Dataframe (untyped Dataset). Usually, this is loaded from some server or database. + val rawDataset: Dataset = listOf( + Person(Name("Alice", "Cooper"), 15, "London", 54, true), + Person(Name("Bob", "Dylan"), 45, "Dubai", 87, true), + Person(Name("Charlie", "Daniels"), 20, "Moscow", null, false), + Person(Name("Charlie", "Chaplin"), 40, "Milan", null, true), + Person(Name("Bob", "Marley"), 30, "Tokyo", 68, true), + Person(Name("Alice", "Wolf"), 20, null, 55, false), + Person(Name("Charlie", "Byrd"), 30, "Moscow", 90, true), + ).toDF() + + // we can perform large operations in Spark. + // DataFrames are in-memory structures, so this is a good place to limit the number of rows if you don't have the RAM ;) + val dataset = rawDataset.filter(col("age") gt 17) + + // Using inference + val df1 = dataset.convertToDataFrameByInference() + df1.schema().print() + df1.print(columnTypes = true, borders = true) + + // Using full schema mapping + val df2 = dataset.convertToDataFrame() + df2.schema().print() + df2.print(columnTypes = true, borders = true) + + // now we can use DataFrame-specific functions + val ageStats = df1 + .groupBy("city").aggregate { + mean("age") into "meanAge" + std("age") into "stdAge" + min("age") into "minAge" + max("age") into "maxAge" + } + + ageStats.print(columnTypes = true, borders = true) + // and when we want to convert a DataFrame back to Spark, we will use the `convertToSpark()` extension function + // This performs the necessary schema mapping under the hood. + val sparkDataset = df2.convertToSpark(spark, sc) + sparkDataset.printSchema() + sparkDataset.show() } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b1236358ae..0733498644 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -37,6 +37,7 @@ kotlinDatetime = "0.6.1" openapi = "2.1.24" kotlinLogging = "7.0.3" sl4j = "2.0.16" +log4j = "2.24.3" junit = "4.13.2" junit-jupiter = "5.11.3" @@ -171,6 +172,8 @@ exposed-money = { group = "org.jetbrains.exposed", name = "exposed-money", versi kotlin-spark = { group = "org.jetbrains.kotlinx.spark", name = "kotlin-spark-api_3.3.2_2.13", version.ref = "kotlin-spark" } spark = { group = "org.apache.spark", name = "spark-sql_2.13", version.ref = "spark" } +log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" } +log4j-api = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" } [plugins] jupyter-api = { id = "org.jetbrains.kotlin.jupyter.api", version.ref = "kotlinJupyter" } From 46128e88887c49df88f9d38468427f77a0880a07 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Thu, 5 Jun 2025 18:02:55 +0200 Subject: [PATCH 4/9] added kotlin-spark-api-less example for spark as well --- examples/README.md | 10 + .../unsupported-data-sources/build.gradle.kts | 21 +- .../kotlinSpark/compatibilityLayer.kt | 315 +----------------- .../examples/kotlinSpark/untypedDataset.kt | 5 +- .../examples/spark/compatibilityLayer.kt | 312 +++++++++++++++++ .../dataframe/examples/spark/typedDataset.kt | 108 ++++++ .../examples/spark/untypedDataset.kt | 86 +++++ 7 files changed, 543 insertions(+), 314 deletions(-) create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/compatibilityLayer.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/typedDataset.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt diff --git a/examples/README.md b/examples/README.md index a23741ae95..4bd59e4d4c 100644 --- a/examples/README.md +++ b/examples/README.md @@ -7,6 +7,16 @@ * [json](idea-examples/json) Using OpenAPI support in DataFrame's Gradle and KSP plugins to access data from [API guru](https://apis.guru/) in a type-safe manner * [imdb sql database](https://github.com/zaleslaw/KotlinDataFrame-SQL-Examples) This project prominently showcases how to convert data from an SQL table to a Kotlin DataFrame and how to transform the result of an SQL query into a DataFrame. +* [unsupported-data-sources](idea-examples/unsupported-data-sources) Showcases of how to use DataFrame with + (momentarily) unsupported data libraries such as [Spark](https://spark.apache.org/) and [Exposed](https://github.com/JetBrains/Exposed). +They show how to convert to and from Kotlin Dataframe and their respective tables. + * **JetBrains Exposed**: See the [exposed folder](./idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed) + for an example of using Kotlin Dataframe with [Exposed](https://github.com/JetBrains/Exposed). + * **Apache Spark**: See the [spark folder](./idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark) + for an example of using Kotlin Dataframe with [Spark](https://spark.apache.org/). + * **Spark (with Kotlin Spark API)**: See the [kotlinSpark folder](./idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark) + for an example of using Kotlin DataFrame with the [Kotlin Spark API](https://github.com/JetBrains/kotlin-spark-api). + ### Notebook examples diff --git a/examples/idea-examples/unsupported-data-sources/build.gradle.kts b/examples/idea-examples/unsupported-data-sources/build.gradle.kts index ddc038caf2..bbf8de3ac8 100644 --- a/examples/idea-examples/unsupported-data-sources/build.gradle.kts +++ b/examples/idea-examples/unsupported-data-sources/build.gradle.kts @@ -1,6 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { application kotlin("jvm") @@ -52,3 +49,21 @@ val runKotlinSparkUntypedDataset by tasks.registering(JavaExec::class) { javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(11) } mainClass = "org.jetbrains.kotlinx.dataframe.examples.kotlinSpark.UntypedDatasetKt" } + +/** + * Runs the spark/typedDataset example with java 11. + */ +val runSparkTypedDataset by tasks.registering(JavaExec::class) { + classpath = sourceSets["main"].runtimeClasspath + javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(11) } + mainClass = "org.jetbrains.kotlinx.dataframe.examples.spark.TypedDatasetKt" +} + +/** + * Runs the spark/untypedDataset example with java 11. + */ +val runSparkUntypedDataset by tasks.registering(JavaExec::class) { + classpath = sourceSets["main"].runtimeClasspath + javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(11) } + mainClass = "org.jetbrains.kotlinx.dataframe.examples.spark.UntypedDatasetKt" +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/compatibilityLayer.kt index 13db8c29bc..2b7e2bc824 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/compatibilityLayer.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/compatibilityLayer.kt @@ -1,313 +1,8 @@ -package org.jetbrains.kotlinx.dataframe.examples.kotlinSpark - -import org.apache.spark.api.java.JavaSparkContext -import org.apache.spark.sql.Dataset -import org.apache.spark.sql.Row -import org.apache.spark.sql.RowFactory -import org.apache.spark.sql.SparkSession -import org.apache.spark.sql.types.ArrayType -import org.apache.spark.sql.types.DataType -import org.apache.spark.sql.types.DataTypes -import org.apache.spark.sql.types.Decimal -import org.apache.spark.sql.types.DecimalType -import org.apache.spark.sql.types.MapType -import org.apache.spark.sql.types.StructType -import org.apache.spark.unsafe.types.CalendarInterval -import org.jetbrains.kotlinx.dataframe.AnyFrame -import org.jetbrains.kotlinx.dataframe.DataColumn -import org.jetbrains.kotlinx.dataframe.DataFrame -import org.jetbrains.kotlinx.dataframe.DataRow -import org.jetbrains.kotlinx.dataframe.api.rows -import org.jetbrains.kotlinx.dataframe.api.schema -import org.jetbrains.kotlinx.dataframe.api.toDataFrame -import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup -import org.jetbrains.kotlinx.dataframe.columns.TypeSuggestion -import org.jetbrains.kotlinx.dataframe.schema.ColumnSchema -import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema -import org.jetbrains.kotlinx.spark.api.toRDD -import java.math.BigDecimal -import java.math.BigInteger -import java.sql.Date -import java.sql.Timestamp -import java.time.Instant -import java.time.LocalDate -import kotlin.reflect.KType -import kotlin.reflect.KTypeProjection -import kotlin.reflect.full.createType -import kotlin.reflect.full.isSubtypeOf -import kotlin.reflect.full.withNullability -import kotlin.reflect.typeOf - -// region Spark to DataFrame - -/** - * Converts an untyped Spark [Dataset] (Dataframe) to a Kotlin [DataFrame]. - * [StructTypes][StructType] are converted to [ColumnGroups][ColumnGroup]. - * - * DataFrame supports type inference to do the conversion automatically. - * This is usually fine for smaller data sets, but when working with larger datasets a type map might be a good idea. - * See [convertToDataFrame] for more information. - */ -fun Dataset.convertToDataFrameByInference( - schema: StructType = schema(), - prefix: List = emptyList(), -): AnyFrame { - val columns = schema.fields().map { field -> - val name = field.name() - when (val dataType = field.dataType()) { - is StructType -> - DataColumn.createColumnGroup( - name = name, - df = convertToDataFrameByInference(dataType, prefix + name), - ) - - else -> - DataColumn.createByInference( - name = name, - values = select((prefix + name).joinToString(".")) - .collectAsList() - .map { it[0] }, - suggestedType = TypeSuggestion.Infer, - nullable = field.nullable(), - ) - } - } - return columns.toDataFrame() -} - -/** - * Converts an untyped Spark [Dataset] (Dataframe) to a Kotlin [DataFrame]. - * [StructTypes][StructType] are converted to [ColumnGroups][ColumnGroup]. - * - * This version uses a [type-map][DataType.convertToDataFrame] to convert the schemas with a fallback to inference. - * For smaller data sets, inference is usually fine too. - * See [convertToDataFrameByInference] for more information. - */ -fun Dataset.convertToDataFrame(schema: StructType = schema(), prefix: List = emptyList()): AnyFrame { - val columns = schema.fields().map { field -> - val name = field.name() - when (val dataType = field.dataType()) { - is StructType -> - DataColumn.createColumnGroup( - name = name, - df = convertToDataFrame(dataType, prefix + name), - ) - - else -> - DataColumn.createByInference( - name = name, - values = select((prefix + name).joinToString(".")) - .collectAsList() - .map { it[0] }, - suggestedType = - dataType.convertToDataFrame() - ?.let(TypeSuggestion::Use) - ?: TypeSuggestion.Infer, // fallback to inference if needed - nullable = field.nullable(), - ) - } - } - return columns.toDataFrame() -} - -/** - * Returns the corresponding Kotlin type for a given Spark DataType. - * - * This list may be incomplete, but it can at least give you a good start. - * - * @return The KType that corresponds to the Spark DataType, or null if no matching KType is found. - */ -fun DataType.convertToDataFrame(): KType? = - when { - this == DataTypes.ByteType -> typeOf() - - this == DataTypes.ShortType -> typeOf() - - this == DataTypes.IntegerType -> typeOf() - - this == DataTypes.LongType -> typeOf() - - this == DataTypes.BooleanType -> typeOf() - - this == DataTypes.FloatType -> typeOf() - - this == DataTypes.DoubleType -> typeOf() +@file:Suppress("ktlint:standard:no-empty-file") - this == DataTypes.StringType -> typeOf() - - this == DataTypes.DateType -> typeOf() - - this == DataTypes.TimestampType -> typeOf() - - this is DecimalType -> typeOf() - - this == DataTypes.CalendarIntervalType -> typeOf() - - this == DataTypes.NullType -> nullableNothingType - - this == DataTypes.BinaryType -> typeOf() - - this is ArrayType -> { - when (elementType()) { - DataTypes.ShortType -> typeOf() - DataTypes.IntegerType -> typeOf() - DataTypes.LongType -> typeOf() - DataTypes.FloatType -> typeOf() - DataTypes.DoubleType -> typeOf() - DataTypes.BooleanType -> typeOf() - else -> null - } - } - - this is MapType -> { - val key = keyType().convertToDataFrame() ?: return null - val value = valueType().convertToDataFrame() ?: return null - Map::class.createType( - listOf( - KTypeProjection.invariant(key), - KTypeProjection.invariant(value.withNullability(valueContainsNull())), - ), - ) - } - - else -> null - } - -// endregion - -// region DataFrame to Spark - -/** - * Converts the DataFrame to a Spark Dataset of Rows using the provided SparkSession and JavaSparkContext. - * - * Spark needs both the data and the schema to be converted to create a correct [Dataset]. - * - * @param spark The SparkSession object to use for creating the DataFrame. - * @param sc The JavaSparkContext object to use for converting the DataFrame to RDD. - * @return A Dataset of Rows representing the converted DataFrame. - */ -fun DataFrame<*>.convertToSpark(spark: SparkSession, sc: JavaSparkContext): Dataset { - val rows = sc.toRDD(rows().map { it.convertToSpark() }) - return spark.createDataFrame(rows, schema().convertToSpark()) -} - -/** - * Converts a DataRow to a Spark Row object. - * - * @return The converted Spark Row. - */ -fun DataRow<*>.convertToSpark(): Row = - RowFactory.create( - *values().map { - when (it) { - is DataRow<*> -> it.convertToSpark() - else -> it - } - }.toTypedArray(), - ) - -/** - * Converts a DataFrameSchema to a Spark StructType. - * - * @return The converted Spark StructType. - */ -fun DataFrameSchema.convertToSpark(): StructType = - DataTypes.createStructType( - columns.map { (name, schema) -> - DataTypes.createStructField(name, schema.convertToSpark(), schema.nullable) - }, - ) - -/** - * Converts a ColumnSchema object to Spark DataType. - * - * @return The Spark DataType corresponding to the given ColumnSchema object. - * @throws IllegalArgumentException if the column type or kind is unknown. - */ -fun ColumnSchema.convertToSpark(): DataType = - when (this) { - is ColumnSchema.Value -> type.convertToSpark() ?: error("unknown data type: $type") - is ColumnSchema.Group -> schema.convertToSpark() - is ColumnSchema.Frame -> error("nested dataframes are not supported") - else -> error("unknown column kind: $this") - } +package org.jetbrains.kotlinx.dataframe.examples.kotlinSpark -/** - * Returns the corresponding Spark DataType for a given Kotlin type. - * - * This list may be incomplete, but it can at least give you a good start. - * - * @return The Spark DataType that corresponds to the Kotlin type, or null if no matching DataType is found. +/* + * See ../spark/compatibilityLayer.kt for the implementation. + * It's the same with- and without the Kotlin Spark API. */ -fun KType.convertToSpark(): DataType? = - when { - isSubtypeOf(typeOf()) -> DataTypes.ByteType - - isSubtypeOf(typeOf()) -> DataTypes.ShortType - - isSubtypeOf(typeOf()) -> DataTypes.IntegerType - - isSubtypeOf(typeOf()) -> DataTypes.LongType - - isSubtypeOf(typeOf()) -> DataTypes.BooleanType - - isSubtypeOf(typeOf()) -> DataTypes.FloatType - - isSubtypeOf(typeOf()) -> DataTypes.DoubleType - - isSubtypeOf(typeOf()) -> DataTypes.StringType - - isSubtypeOf(typeOf()) -> DataTypes.DateType - - isSubtypeOf(typeOf()) -> DataTypes.DateType - - isSubtypeOf(typeOf()) -> DataTypes.TimestampType - - isSubtypeOf(typeOf()) -> DataTypes.TimestampType - - isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() - - isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() - - isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() - - isSubtypeOf(typeOf()) -> DataTypes.CalendarIntervalType - - isSubtypeOf(nullableNothingType) -> DataTypes.NullType - - isSubtypeOf(typeOf()) -> DataTypes.BinaryType - - isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.ShortType, false) - - isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.IntegerType, false) - - isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.LongType, false) - - isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.FloatType, false) - - isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.DoubleType, false) - - isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.BooleanType, false) - - isSubtypeOf(typeOf>()) -> - error("non-primitive arrays are not supported for now, you can add it yourself") - - isSubtypeOf(typeOf>()) -> error("lists are not supported for now, you can add it yourself") - - isSubtypeOf(typeOf>()) -> error("sets are not supported for now, you can add it yourself") - - classifier == Map::class -> { - val (key, value) = arguments - DataTypes.createMapType( - key.type?.convertToSpark(), - value.type?.convertToSpark(), - value.type?.isMarkedNullable ?: true, - ) - } - - else -> null - } - -private val nullableNothingType: KType = typeOf>().arguments.first().type!! - -// endregion diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt index 7d9b4c274a..dc22fb92dc 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt @@ -12,6 +12,9 @@ import org.jetbrains.kotlinx.dataframe.api.min import org.jetbrains.kotlinx.dataframe.api.print import org.jetbrains.kotlinx.dataframe.api.schema import org.jetbrains.kotlinx.dataframe.api.std +import org.jetbrains.kotlinx.dataframe.examples.spark.convertToDataFrame +import org.jetbrains.kotlinx.dataframe.examples.spark.convertToDataFrameByInference +import org.jetbrains.kotlinx.dataframe.examples.spark.convertToSpark import org.jetbrains.kotlinx.spark.api.col import org.jetbrains.kotlinx.spark.api.gt import org.jetbrains.kotlinx.spark.api.withSpark @@ -20,7 +23,7 @@ import org.jetbrains.kotlinx.spark.api.withSpark * Since we don't know the schema at compile time this time, we need to do * some schema mapping in between Spark and DataFrame. * - * We will use compatibilityLayer.kt to do this. + * We will use spark/compatibilityLayer.kt to do this. * * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. * Use the `runKotlinSparkUntypedDataset` Gradle task to do so. diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/compatibilityLayer.kt new file mode 100644 index 0000000000..ff28a1cb34 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/compatibilityLayer.kt @@ -0,0 +1,312 @@ +package org.jetbrains.kotlinx.dataframe.examples.spark + +import org.apache.spark.api.java.JavaSparkContext +import org.apache.spark.sql.Dataset +import org.apache.spark.sql.Row +import org.apache.spark.sql.RowFactory +import org.apache.spark.sql.SparkSession +import org.apache.spark.sql.types.ArrayType +import org.apache.spark.sql.types.DataType +import org.apache.spark.sql.types.DataTypes +import org.apache.spark.sql.types.Decimal +import org.apache.spark.sql.types.DecimalType +import org.apache.spark.sql.types.MapType +import org.apache.spark.sql.types.StructType +import org.apache.spark.unsafe.types.CalendarInterval +import org.jetbrains.kotlinx.dataframe.AnyFrame +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.DataRow +import org.jetbrains.kotlinx.dataframe.api.rows +import org.jetbrains.kotlinx.dataframe.api.schema +import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup +import org.jetbrains.kotlinx.dataframe.columns.TypeSuggestion +import org.jetbrains.kotlinx.dataframe.schema.ColumnSchema +import org.jetbrains.kotlinx.dataframe.schema.DataFrameSchema +import java.math.BigDecimal +import java.math.BigInteger +import java.sql.Date +import java.sql.Timestamp +import java.time.Instant +import java.time.LocalDate +import kotlin.reflect.KType +import kotlin.reflect.KTypeProjection +import kotlin.reflect.full.createType +import kotlin.reflect.full.isSubtypeOf +import kotlin.reflect.full.withNullability +import kotlin.reflect.typeOf + +// region Spark to DataFrame + +/** + * Converts an untyped Spark [Dataset] (Dataframe) to a Kotlin [DataFrame]. + * [StructTypes][StructType] are converted to [ColumnGroups][ColumnGroup]. + * + * DataFrame supports type inference to do the conversion automatically. + * This is usually fine for smaller data sets, but when working with larger datasets a type map might be a good idea. + * See [convertToDataFrame] for more information. + */ +fun Dataset.convertToDataFrameByInference( + schema: StructType = schema(), + prefix: List = emptyList(), +): AnyFrame { + val columns = schema.fields().map { field -> + val name = field.name() + when (val dataType = field.dataType()) { + is StructType -> + DataColumn.createColumnGroup( + name = name, + df = convertToDataFrameByInference(dataType, prefix + name), + ) + + else -> + DataColumn.createByInference( + name = name, + values = select((prefix + name).joinToString(".")) + .collectAsList() + .map { it[0] }, + suggestedType = TypeSuggestion.Infer, + nullable = field.nullable(), + ) + } + } + return columns.toDataFrame() +} + +/** + * Converts an untyped Spark [Dataset] (Dataframe) to a Kotlin [DataFrame]. + * [StructTypes][StructType] are converted to [ColumnGroups][ColumnGroup]. + * + * This version uses a [type-map][DataType.convertToDataFrame] to convert the schemas with a fallback to inference. + * For smaller data sets, inference is usually fine too. + * See [convertToDataFrameByInference] for more information. + */ +fun Dataset.convertToDataFrame(schema: StructType = schema(), prefix: List = emptyList()): AnyFrame { + val columns = schema.fields().map { field -> + val name = field.name() + when (val dataType = field.dataType()) { + is StructType -> + DataColumn.createColumnGroup( + name = name, + df = convertToDataFrame(dataType, prefix + name), + ) + + else -> + DataColumn.createByInference( + name = name, + values = select((prefix + name).joinToString(".")) + .collectAsList() + .map { it[0] }, + suggestedType = + dataType.convertToDataFrame() + ?.let(TypeSuggestion::Use) + ?: TypeSuggestion.Infer, // fallback to inference if needed + nullable = field.nullable(), + ) + } + } + return columns.toDataFrame() +} + +/** + * Returns the corresponding Kotlin type for a given Spark DataType. + * + * This list may be incomplete, but it can at least give you a good start. + * + * @return The KType that corresponds to the Spark DataType, or null if no matching KType is found. + */ +fun DataType.convertToDataFrame(): KType? = + when { + this == DataTypes.ByteType -> typeOf() + + this == DataTypes.ShortType -> typeOf() + + this == DataTypes.IntegerType -> typeOf() + + this == DataTypes.LongType -> typeOf() + + this == DataTypes.BooleanType -> typeOf() + + this == DataTypes.FloatType -> typeOf() + + this == DataTypes.DoubleType -> typeOf() + + this == DataTypes.StringType -> typeOf() + + this == DataTypes.DateType -> typeOf() + + this == DataTypes.TimestampType -> typeOf() + + this is DecimalType -> typeOf() + + this == DataTypes.CalendarIntervalType -> typeOf() + + this == DataTypes.NullType -> nullableNothingType + + this == DataTypes.BinaryType -> typeOf() + + this is ArrayType -> { + when (elementType()) { + DataTypes.ShortType -> typeOf() + DataTypes.IntegerType -> typeOf() + DataTypes.LongType -> typeOf() + DataTypes.FloatType -> typeOf() + DataTypes.DoubleType -> typeOf() + DataTypes.BooleanType -> typeOf() + else -> null + } + } + + this is MapType -> { + val key = keyType().convertToDataFrame() ?: return null + val value = valueType().convertToDataFrame() ?: return null + Map::class.createType( + listOf( + KTypeProjection.invariant(key), + KTypeProjection.invariant(value.withNullability(valueContainsNull())), + ), + ) + } + + else -> null + } + +// endregion + +// region DataFrame to Spark + +/** + * Converts the DataFrame to a Spark Dataset of Rows using the provided SparkSession and JavaSparkContext. + * + * Spark needs both the data and the schema to be converted to create a correct [Dataset]. + * + * @param spark The SparkSession object to use for creating the DataFrame. + * @param sc The JavaSparkContext object to use for converting the DataFrame to RDD. + * @return A Dataset of Rows representing the converted DataFrame. + */ +fun DataFrame<*>.convertToSpark(spark: SparkSession, sc: JavaSparkContext): Dataset { + val rows = sc.parallelize(rows().map { it.convertToSpark() }) + return spark.createDataFrame(rows, schema().convertToSpark()) +} + +/** + * Converts a DataRow to a Spark Row object. + * + * @return The converted Spark Row. + */ +fun DataRow<*>.convertToSpark(): Row = + RowFactory.create( + *values().map { + when (it) { + is DataRow<*> -> it.convertToSpark() + else -> it + } + }.toTypedArray(), + ) + +/** + * Converts a DataFrameSchema to a Spark StructType. + * + * @return The converted Spark StructType. + */ +fun DataFrameSchema.convertToSpark(): StructType = + DataTypes.createStructType( + columns.map { (name, schema) -> + DataTypes.createStructField(name, schema.convertToSpark(), schema.nullable) + }, + ) + +/** + * Converts a ColumnSchema object to Spark DataType. + * + * @return The Spark DataType corresponding to the given ColumnSchema object. + * @throws IllegalArgumentException if the column type or kind is unknown. + */ +fun ColumnSchema.convertToSpark(): DataType = + when (this) { + is ColumnSchema.Value -> type.convertToSpark() ?: error("unknown data type: $type") + is ColumnSchema.Group -> schema.convertToSpark() + is ColumnSchema.Frame -> error("nested dataframes are not supported") + else -> error("unknown column kind: $this") + } + +/** + * Returns the corresponding Spark DataType for a given Kotlin type. + * + * This list may be incomplete, but it can at least give you a good start. + * + * @return The Spark DataType that corresponds to the Kotlin type, or null if no matching DataType is found. + */ +fun KType.convertToSpark(): DataType? = + when { + isSubtypeOf(typeOf()) -> DataTypes.ByteType + + isSubtypeOf(typeOf()) -> DataTypes.ShortType + + isSubtypeOf(typeOf()) -> DataTypes.IntegerType + + isSubtypeOf(typeOf()) -> DataTypes.LongType + + isSubtypeOf(typeOf()) -> DataTypes.BooleanType + + isSubtypeOf(typeOf()) -> DataTypes.FloatType + + isSubtypeOf(typeOf()) -> DataTypes.DoubleType + + isSubtypeOf(typeOf()) -> DataTypes.StringType + + isSubtypeOf(typeOf()) -> DataTypes.DateType + + isSubtypeOf(typeOf()) -> DataTypes.DateType + + isSubtypeOf(typeOf()) -> DataTypes.TimestampType + + isSubtypeOf(typeOf()) -> DataTypes.TimestampType + + isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() + + isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() + + isSubtypeOf(typeOf()) -> DecimalType.SYSTEM_DEFAULT() + + isSubtypeOf(typeOf()) -> DataTypes.CalendarIntervalType + + isSubtypeOf(nullableNothingType) -> DataTypes.NullType + + isSubtypeOf(typeOf()) -> DataTypes.BinaryType + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.ShortType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.IntegerType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.LongType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.FloatType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.DoubleType, false) + + isSubtypeOf(typeOf()) -> DataTypes.createArrayType(DataTypes.BooleanType, false) + + isSubtypeOf(typeOf>()) -> + error("non-primitive arrays are not supported for now, you can add it yourself") + + isSubtypeOf(typeOf>()) -> error("lists are not supported for now, you can add it yourself") + + isSubtypeOf(typeOf>()) -> error("sets are not supported for now, you can add it yourself") + + classifier == Map::class -> { + val (key, value) = arguments + DataTypes.createMapType( + key.type?.convertToSpark(), + value.type?.convertToSpark(), + value.type?.isMarkedNullable ?: true, + ) + } + + else -> null + } + +private val nullableNothingType: KType = typeOf>().arguments.first().type!! + +// endregion diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/typedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/typedDataset.kt new file mode 100644 index 0000000000..57db22f397 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/typedDataset.kt @@ -0,0 +1,108 @@ +@file:Suppress("ktlint:standard:function-signature") + +package org.jetbrains.kotlinx.dataframe.examples.spark + +import org.apache.spark.SparkConf +import org.apache.spark.api.java.JavaSparkContext +import org.apache.spark.sql.Dataset +import org.apache.spark.sql.Encoders +import org.apache.spark.sql.SparkSession +import org.jetbrains.kotlinx.dataframe.annotations.DataSchema +import org.jetbrains.kotlinx.dataframe.api.aggregate +import org.jetbrains.kotlinx.dataframe.api.groupBy +import org.jetbrains.kotlinx.dataframe.api.max +import org.jetbrains.kotlinx.dataframe.api.mean +import org.jetbrains.kotlinx.dataframe.api.min +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.api.schema +import org.jetbrains.kotlinx.dataframe.api.std +import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.dataframe.api.toList +import java.io.Serializable + +@DataSchema +data class Name + @JvmOverloads + constructor(var firstName: String = "", var lastName: String = "") : + Serializable { + companion object { + val encoder = Encoders.bean(Name::class.java) + } + } + +@DataSchema +data class Person + @JvmOverloads + constructor( + var name: Name = Name(), + var age: Int = -1, + var city: String? = null, + var weight: Int? = null, + var isHappy: Boolean = false, + ) : Serializable { + companion object { + val encoder = Encoders.bean(Person::class.java) + } + } + +/** + * For Spark, Kotlin data classes are supported if we: + * - Add [@JvmOverloads][JvmOverloads] to the constructor + * - Make all parameter arguments mutable and with defaults + * - Make them [Serializable] + * + * But by adding [@DataSchema][DataSchema] we can reuse the same class for Spark and DataFrame! + * + * Also, since we use an actual class to define the schema, we need no type conversion! + * + * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. + * Use the `runSparkTypedDataset` Gradle task to do so. + */ +fun main() { + val spark = SparkSession.builder() + .master(SparkConf().get("spark.master", "local[*]")) + .appName("Kotlin Spark Sample") + .getOrCreate() + val sc = JavaSparkContext(spark.sparkContext()) + + // Creating a Spark Dataset. Usually, this is loaded from some server or database. + val rawDataset: Dataset = spark.createDataset( + listOf( + Person(Name("Alice", "Cooper"), 15, "London", 54, true), + Person(Name("Bob", "Dylan"), 45, "Dubai", 87, true), + Person(Name("Charlie", "Daniels"), 20, "Moscow", null, false), + Person(Name("Charlie", "Chaplin"), 40, "Milan", null, true), + Person(Name("Bob", "Marley"), 30, "Tokyo", 68, true), + Person(Name("Alice", "Wolf"), 20, null, 55, false), + Person(Name("Charlie", "Byrd"), 30, "Moscow", 90, true), + ), + Person.encoder, + ) + + // we can perform large operations in Spark. + // DataFrames are in-memory structures, so this is a good place to limit the number of rows if you don't have the RAM ;) + val dataset = rawDataset.filter { it.age > 17 } + + // and convert it to DataFrame via a typed List + val dataframe = dataset.collectAsList().toDataFrame() + dataframe.schema().print() + dataframe.print(columnTypes = true, borders = true) + + // now we can use DataFrame-specific functions + val ageStats = dataframe + .groupBy { city }.aggregate { + mean { age } into "meanAge" + std { age } into "stdAge" + min { age } into "minAge" + max { age } into "maxAge" + } + + ageStats.print(columnTypes = true, borders = true) + + // and when we want to convert a DataFrame back to Spark, we can do the same trick via a typed List + val sparkDatasetAgain = spark.createDataset(dataframe.toList(), Person.encoder) + sparkDatasetAgain.printSchema() + sparkDatasetAgain.show() + + spark.stop() +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt new file mode 100644 index 0000000000..7a6c96fe41 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt @@ -0,0 +1,86 @@ +@file:Suppress("ktlint:standard:function-signature") + +package org.jetbrains.kotlinx.dataframe.examples.spark + +import org.apache.spark.SparkConf +import org.apache.spark.api.java.JavaSparkContext +import org.apache.spark.sql.Dataset +import org.apache.spark.sql.Row +import org.apache.spark.sql.SparkSession +import org.jetbrains.kotlinx.dataframe.api.aggregate +import org.jetbrains.kotlinx.dataframe.api.groupBy +import org.jetbrains.kotlinx.dataframe.api.max +import org.jetbrains.kotlinx.dataframe.api.mean +import org.jetbrains.kotlinx.dataframe.api.min +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.api.schema +import org.jetbrains.kotlinx.dataframe.api.std +import org.jetbrains.kotlinx.dataframe.examples.spark.convertToDataFrame +import org.jetbrains.kotlinx.dataframe.examples.spark.convertToDataFrameByInference +import org.jetbrains.kotlinx.dataframe.examples.spark.convertToSpark +import org.jetbrains.kotlinx.spark.api.col +import org.jetbrains.kotlinx.spark.api.gt + +/** + * Since we don't know the schema at compile time this time, we need to do + * some schema mapping in between Spark and DataFrame. + * + * We will use spark/compatibilityLayer.kt to do this. + * + * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. + * Use the `runSparkUntypedDataset` Gradle task to do so. + */ +fun main() { + val spark = SparkSession.builder() + .master(SparkConf().get("spark.master", "local[*]")) + .appName("Kotlin Spark Sample") + .getOrCreate() + val sc = JavaSparkContext(spark.sparkContext()) + + // Creating a Spark Dataframe (untyped Dataset). Usually, this is loaded from some server or database. + val rawDataset: Dataset = spark.createDataset( + listOf( + Person(Name("Alice", "Cooper"), 15, "London", 54, true), + Person(Name("Bob", "Dylan"), 45, "Dubai", 87, true), + Person(Name("Charlie", "Daniels"), 20, "Moscow", null, false), + Person(Name("Charlie", "Chaplin"), 40, "Milan", null, true), + Person(Name("Bob", "Marley"), 30, "Tokyo", 68, true), + Person(Name("Alice", "Wolf"), 20, null, 55, false), + Person(Name("Charlie", "Byrd"), 30, "Moscow", 90, true), + ), + Person.encoder, + ).toDF() + + // we can perform large operations in Spark. + // DataFrames are in-memory structures, so this is a good place to limit the number of rows if you don't have the RAM ;) + val dataset = rawDataset.filter(col("age") gt 17) + + // Using inference + val df1 = dataset.convertToDataFrameByInference() + df1.schema().print() + df1.print(columnTypes = true, borders = true) + + // Using full schema mapping + val df2 = dataset.convertToDataFrame() + df2.schema().print() + df2.print(columnTypes = true, borders = true) + + // now we can use DataFrame-specific functions + val ageStats = df1 + .groupBy("city").aggregate { + mean("age") into "meanAge" + std("age") into "stdAge" + min("age") into "minAge" + max("age") into "maxAge" + } + + ageStats.print(columnTypes = true, borders = true) + + // and when we want to convert a DataFrame back to Spark, we will use the `convertToSpark()` extension function + // This performs the necessary schema mapping under the hood. + val sparkDataset = df2.convertToSpark(spark, sc) + sparkDataset.printSchema() + sparkDataset.show() + + spark.stop() +} From 79eac6cbc7fb6c85b11019880dd17f52f367a758 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Fri, 6 Jun 2025 17:51:06 +0200 Subject: [PATCH 5/9] wip Multik sample --- .../unsupported-data-sources/build.gradle.kts | 4 + .../examples/multik/compatibilityLayer.kt | 138 ++++++++++++++++++ .../kotlinx/dataframe/examples/multik/io.kt | 21 +++ .../kotlinx/dataframe/examples/multik/main.kt | 53 +++++++ .../examples/multik/multikInsideDataFrame.kt | 134 +++++++++++++++++ .../src/main/resources/a1d.npy | Bin 0 -> 152 bytes gradle/libs.versions.toml | 5 + 7 files changed, 355 insertions(+) create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/io.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/multikInsideDataFrame.kt create mode 100644 examples/idea-examples/unsupported-data-sources/src/main/resources/a1d.npy diff --git a/examples/idea-examples/unsupported-data-sources/build.gradle.kts b/examples/idea-examples/unsupported-data-sources/build.gradle.kts index bbf8de3ac8..c6560cdae9 100644 --- a/examples/idea-examples/unsupported-data-sources/build.gradle.kts +++ b/examples/idea-examples/unsupported-data-sources/build.gradle.kts @@ -30,6 +30,10 @@ dependencies { compileOnly(libs.spark) implementation(libs.log4j.core) implementation(libs.log4j.api) + + // multik support + implementation(libs.multik.core) + implementation(libs.multik.default) } /** diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt new file mode 100644 index 0000000000..e28e291b79 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt @@ -0,0 +1,138 @@ +@file:OptIn(ExperimentalTypeInference::class) + +package org.jetbrains.kotlinx.dataframe.examples.multik + +import org.jetbrains.kotlinx.dataframe.AnyFrame +import org.jetbrains.kotlinx.dataframe.ColumnSelector +import org.jetbrains.kotlinx.dataframe.ColumnsSelector +import org.jetbrains.kotlinx.dataframe.DataColumn +import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.api.ValueProperty +import org.jetbrains.kotlinx.dataframe.api.cast +import org.jetbrains.kotlinx.dataframe.api.colsOf +import org.jetbrains.kotlinx.dataframe.api.column +import org.jetbrains.kotlinx.dataframe.api.dataFrameOf +import org.jetbrains.kotlinx.dataframe.api.getColumn +import org.jetbrains.kotlinx.dataframe.api.getColumns +import org.jetbrains.kotlinx.dataframe.api.map +import org.jetbrains.kotlinx.dataframe.api.named +import org.jetbrains.kotlinx.dataframe.api.toColumn +import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.multik.api.mk +import org.jetbrains.kotlinx.multik.api.ndarray +import org.jetbrains.kotlinx.multik.ndarray.complex.Complex +import org.jetbrains.kotlinx.multik.ndarray.data.D1Array +import org.jetbrains.kotlinx.multik.ndarray.data.D2Array +import org.jetbrains.kotlinx.multik.ndarray.data.get +import org.jetbrains.kotlinx.multik.ndarray.operations.toList +import kotlin.experimental.ExperimentalTypeInference +import kotlin.reflect.KClass +import kotlin.reflect.full.isSubtypeOf +import kotlin.reflect.typeOf + +// region 1D + +/** Converts a one-dimensional array ([D1Array]) to a [DataColumn] with optional [name]. */ +inline fun D1Array.convertToColumn(name: String = ""): DataColumn = column(toList()) named name + +/** Converts a [DataColumn] to a one-dimensional array ([D1Array]). */ +@JvmName("convertNumberColumnToMultik") +inline fun DataColumn.convertToMultik(): D1Array where N : Number, N : Comparable = + mk.ndarray(toList()) + +/** Converts a [DataColumn] to a one-dimensional array ([D1Array]). */ +@JvmName("convertComplexColumnToMultik") +inline fun DataColumn.convertToMultik(): D1Array = mk.ndarray(toList()) + +@JvmName("convertNumberColumnFromDfToMultik") +@OverloadResolutionByLambdaReturnType +inline fun DataFrame.convertToMultik( + crossinline column: ColumnSelector, +): D1Array + where N : Number, N : Comparable = getColumn { column(it) }.convertToMultik() + +@JvmName("convertComplexColumnFromDfToMultik") +@OverloadResolutionByLambdaReturnType +inline fun DataFrame.convertToMultik(crossinline column: ColumnSelector): D1Array = + getColumn { column(it) }.convertToMultik() + +/** + * Converts a one-dimensional array ([D1Array]) of type [N] into a DataFrame. + * The resulting DataFrame contains a single column named "value", where each element of the array becomes a row in the DataFrame. + * + * @return a DataFrame where each element of the source array is represented as a row in a column named "value" under the schema [ValueProperty]. + */ +inline fun D1Array.convertToDataFrame(): DataFrame> = + dataFrameOf(ValueProperty<*>::value.name to column(toList())) + .cast() + +// endregion + +// region 2D + +/** + * Converts a two-dimensional array ([D2Array]) to a DataFrame. + * It will contain `shape[0]` rows and `shape[1]` columns. + * + * Column names can be specified using the [columnNameGenerator] lambda. + * + * The conversion enforces that `multikArray[x][y] == dataframe[x][y]` + */ +inline fun D2Array.convertToDataFrame(columnNameGenerator: (Int) -> String = { "col$it" }): AnyFrame = + (0.. + this[0.. AnyFrame.convertToMultikOf(_klass: KClass = Complex::class): D2Array = + convertToMultik { colsOf() } + +@JvmName("convertToMultikOfNumber") +inline fun AnyFrame.convertToMultikOf( + _klass: KClass = Number::class, +): D2Array where N : Number, N : Comparable = convertToMultik { colsOf() } + +@JvmName("convertToMultikGuess") +fun AnyFrame.convertToMultik(): D2Array<*> { + val columnTypes = columnTypes().distinct() + return when { + columnTypes.size != 1 -> error("found column types: $columnTypes") + columnTypes.single() == typeOf() -> convertToMultik { colsOf() } + columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + else -> error("found column types: $columnTypes") + } +} + +@JvmName("convertNumberColumnsFromDfToMultik") +@OverloadResolutionByLambdaReturnType +inline fun DataFrame.convertToMultik( + crossinline columns: ColumnsSelector, +): D2Array + where N : Number, N : Comparable = getColumns { columns(it) }.convertToMultik() + +@JvmName("convertComplexColumnsFromDfToMultik") +@OverloadResolutionByLambdaReturnType +inline fun DataFrame.convertToMultik( + crossinline columns: ColumnsSelector, +): D2Array = getColumns { columns(it) }.convertToMultik() + +@JvmName("convertNumberColumnsToMultik") +inline fun List>.convertToMultik(): D2Array where N : Number, N : Comparable = + mk.ndarray( + toDataFrame().map { it.values() as List }, + ) + +@JvmName("convertComplexColumnsToMultik") +inline fun List>.convertToMultik(): D2Array = + mk.ndarray( + toDataFrame().map { it.values() as List }, + ) + +// endregion diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/io.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/io.kt new file mode 100644 index 0000000000..64437bd852 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/io.kt @@ -0,0 +1,21 @@ +package org.jetbrains.kotlinx.dataframe.examples.multik + +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.multik.api.io.readNPY +import org.jetbrains.kotlinx.multik.api.mk +import org.jetbrains.kotlinx.multik.ndarray.data.D1 +import java.io.File + +/** + * Multik can read/write data from NPY/NPZ files. + * We can use this from DataFrame too! + */ +fun main() { + val npyFilename = "a1d.npy" + val npyFile = File(object {}.javaClass.classLoader.getResource(npyFilename)!!.toURI()) + + val mk1 = mk.readNPY(npyFile) + val df1 = mk1.convertToDataFrame() + + df1.print(borders = true, columnTypes = true) +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt new file mode 100644 index 0000000000..ee543d4152 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt @@ -0,0 +1,53 @@ +package org.jetbrains.kotlinx.dataframe.examples.multik + +import org.jetbrains.kotlinx.dataframe.api.describe +import org.jetbrains.kotlinx.dataframe.api.mean +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.api.value +import org.jetbrains.kotlinx.multik.api.mk +import org.jetbrains.kotlinx.multik.api.rand +import org.jetbrains.kotlinx.multik.ndarray.data.get + +/** + * Let's explore some ways we can combine Multik with Kotlin DataFrame. + * + * We will use compatibilityLayer.kt for the conversions. + */ +fun main() { + oneDimension() + twoDimensions() +} + +fun oneDimension() { + // we can convert a 1D ndarray to a column of a DataFrame: + val mk1 = mk.rand(50) + val col1 by mk1.convertToColumn() + println(col1) + + // or straight to a DataFrame. It will become the `value` column. + val df1 = mk1.convertToDataFrame() + println(df1) + + // this allows us to perform any DF operation: + println(df1.mean { value }) + df1.describe().print(borders = true) + + // we can convert back to Multik: + val mk2 = df1.convertToMultik { value } + // or + df1.value.convertToMultik() + + println(mk2) +} + +fun twoDimensions() { + // we can also convert a 2D ndarray to a DataFrame + val mk1 = mk.rand(5, 10) + println(mk1) + + val df = mk1.convertToDataFrame() + df.print() + + val mk2 = df.convertToMultikOf() + println(mk2) +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/multikInsideDataFrame.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/multikInsideDataFrame.kt new file mode 100644 index 0000000000..e36222bab9 --- /dev/null +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/multikInsideDataFrame.kt @@ -0,0 +1,134 @@ +package org.jetbrains.kotlinx.dataframe.examples.multik + +import org.jetbrains.kotlinx.dataframe.annotations.DataSchema +import org.jetbrains.kotlinx.dataframe.api.print +import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.dataframe.io.toStandaloneHtml +import org.jetbrains.kotlinx.multik.api.identity +import org.jetbrains.kotlinx.multik.api.mk +import org.jetbrains.kotlinx.multik.ndarray.data.D2Array +import org.jetbrains.kotlinx.multik.ndarray.data.set +import kotlin.math.cos +import kotlin.math.sin +import kotlin.math.tan + +@DataSchema +data class Transformation( + val type: TransformationType, + val parameters: Map, + val note: String, + val matrix: D2Array, +) + +enum class TransformationType { + IDENTITY, + TRANSLATION, + SCALING, + ROTATION, + SHEARING, + REFLECTION_ABOUT_ORIGIN, + REFLECTION_ABOUT_X_AXIS, + REFLECTION_ABOUT_Y_AXIS, +} + +/** + * IDK yet about this one... TODO + */ +fun main() { + // DataFrames can store anything inside, including Multik nd arrays. + // This can be useful for storing matrices for easier access later, + // such as affine transformations when making 2D graphics! + // (https://en.wikipedia.org/wiki/Affine_transformation) + + // let's make a transformation sequence that rotates and scales an image in place. + // It's currently 100x50, positioned with its left bottom corner at (x=10, y=0) + val transformations = listOf( + Transformation( + type = TransformationType.TRANSLATION, + parameters = mapOf("x" to -10.0, "y" to 0.0), + note = "Translate so left-bottom touches origin", + matrix = translationMatrixOf(x = -10.0, y = 0.0), + ), + Transformation( + type = TransformationType.SCALING, + parameters = mapOf("w" to 2.0, "h" to 2.0), + note = "Scale by x2", + matrix = scaleMatrixOf(w = 2.0, h = 2.0), + ), + Transformation( + type = TransformationType.TRANSLATION, + parameters = mapOf("x" to -100.0, "y" to -50.0), + note = "Translate so the new image center is at the origin", + matrix = translationMatrixOf(x = -100.0, y = -50.0), + ), + Transformation( + type = TransformationType.ROTATION, + parameters = mapOf("angle" to 45.0), + note = "Rotate by 45 degrees", + matrix = rotationMatrixOf(angle = 45.0), + ), + Transformation( + type = TransformationType.TRANSLATION, + parameters = mapOf("x" to 10.0 + 50.0, "y" to 0.0 + 25.0), + note = "Translate back so the center is at the same original position", + matrix = translationMatrixOf(x = 10.0 + 50.0, y = 0.0 + 25.0), + ), + ).toDataFrame() + + transformations.print(borders = true) + transformations.toStandaloneHtml().openInBrowser() +} + +fun identityMatrix(): D2Array = mk.identity(3) + +/** Returns a 3x3 affine transformation matrix that translates by (x, y) */ +fun translationMatrixOf(x: Double = 0.0, y: Double = 0.0): D2Array = + identityMatrix().apply { + this[0, 2] = x + this[1, 2] = y + } + +/** Returns a 3x3 affine transformation matrix that scales by (w, h) about the origin */ +fun scaleMatrixOf(w: Double = 1.0, h: Double = 1.0): D2Array = + identityMatrix().apply { + this[0, 0] = w + this[1, 1] = h + } + +/** Returns a 3x3 affine transformation matrix that rotates by [angle] degrees about the origin */ +fun rotationMatrixOf(angle: Double): D2Array { + val cos = cos(angle) + val sin = sin(angle) + return identityMatrix().apply { + this[0, 0] = cos + this[0, 1] = -sin + this[1, 0] = sin + this[1, 1] = cos + } +} + +/** Returns a 3x3 affine transformation matrix that shears by [x] and [y] */ +fun shearingMatrixOf(x: Double = 0.0, y: Double = 0.0): D2Array = + identityMatrix().apply { + this[0, 1] = tan(x) + this[1, 0] = tan(y) + } + +/** Returns a 3x3 affine transformation matrix that reflects about the origin */ +fun reflectionAboutOriginMatrix(): D2Array = + identityMatrix().apply { + this[0, 0] = -1.0 + this[1, 1] = -1.0 + } + +/** Returns a 3x3 affine transformation matrix that reflects about the x-axis */ +fun reflectionAboutXAxisMatrix(): D2Array = + identityMatrix().apply { + this[1, 1] = -1.0 + } + +/** Returns a 3x3 affine transformation matrix that reflects about the y-axis */ +fun reflectionAboutYAxisMatrix(): D2Array = + identityMatrix().apply { + this[0, 0] = -1.0 + } diff --git a/examples/idea-examples/unsupported-data-sources/src/main/resources/a1d.npy b/examples/idea-examples/unsupported-data-sources/src/main/resources/a1d.npy new file mode 100644 index 0000000000000000000000000000000000000000..80c6ff86eba9352a6bb1b027bcde26b38dc749fc GIT binary patch literal 152 zcmbR27wQ`j$;eQ~P_3SlTAW;@Zl$1ZlWC!@qoAIaUsO_*m=~X4l#&V(cT3DEP6dh= eXCxM+0{I%oI+{8PwF(pfE=C3jV1m-jP#OT|KpSTO literal 0 HcmV?d00001 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7bd3911ef5..578d0d75fc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -69,6 +69,8 @@ exposed = "1.0.0-beta-2" kotlin-spark = "1.2.4" spark = "3.3.2" +multik = "0.2.3" + [libraries] ksp-gradle = { group = "com.google.devtools.ksp", name = "symbol-processing-gradle-plugin", version.ref = "ksp" } ksp-api = { group = "com.google.devtools.ksp", name = "symbol-processing-api", version.ref = "ksp" } @@ -175,6 +177,9 @@ spark = { group = "org.apache.spark", name = "spark-sql_2.13", version.ref = "sp log4j-core = { group = "org.apache.logging.log4j", name = "log4j-core", version.ref = "log4j" } log4j-api = { group = "org.apache.logging.log4j", name = "log4j-api", version.ref = "log4j" } +multik-core = { group = "org.jetbrains.kotlinx", name = "multik-core", version.ref = "multik" } +multik-default = { group = "org.jetbrains.kotlinx", name = "multik-default", version.ref = "multik" } + [plugins] jupyter-api = { id = "org.jetbrains.kotlin.jupyter.api", version.ref = "kotlinJupyter" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } From 70c8ee8e10a57f4420b1b80f8149127182df5c9c Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Tue, 10 Jun 2025 13:59:13 +0200 Subject: [PATCH 6/9] updating multik example, 2d --- examples/README.md | 2 + .../examples/multik/compatibilityLayer.kt | 125 ++++++++++++------ .../kotlinx/dataframe/examples/multik/main.kt | 21 ++- 3 files changed, 105 insertions(+), 43 deletions(-) diff --git a/examples/README.md b/examples/README.md index 4bd59e4d4c..46399c44f8 100644 --- a/examples/README.md +++ b/examples/README.md @@ -16,6 +16,8 @@ They show how to convert to and from Kotlin Dataframe and their respective table for an example of using Kotlin Dataframe with [Spark](https://spark.apache.org/). * **Spark (with Kotlin Spark API)**: See the [kotlinSpark folder](./idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark) for an example of using Kotlin DataFrame with the [Kotlin Spark API](https://github.com/JetBrains/kotlin-spark-api). + * **Multik**: See the [multik folder](./idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik) + for an example of using Kotlin Dataframe with [Multik](https://github.com/Kotlin/multik). ### Notebook examples diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt index e28e291b79..7539ee6092 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt @@ -35,6 +35,16 @@ import kotlin.reflect.typeOf /** Converts a one-dimensional array ([D1Array]) to a [DataColumn] with optional [name]. */ inline fun D1Array.convertToColumn(name: String = ""): DataColumn = column(toList()) named name +/** + * Converts a one-dimensional array ([D1Array]) of type [N] into a DataFrame. + * The resulting DataFrame contains a single column named "value", where each element of the array becomes a row in the DataFrame. + * + * @return a DataFrame where each element of the source array is represented as a row in a column named "value" under the schema [ValueProperty]. + */ +inline fun D1Array.convertToDataFrame(): DataFrame> = + dataFrameOf(ValueProperty<*>::value.name to column(toList())) + .cast() + /** Converts a [DataColumn] to a one-dimensional array ([D1Array]). */ @JvmName("convertNumberColumnToMultik") inline fun DataColumn.convertToMultik(): D1Array where N : Number, N : Comparable = @@ -44,6 +54,7 @@ inline fun DataColumn.convertToMultik(): D1Array where N : Num @JvmName("convertComplexColumnToMultik") inline fun DataColumn.convertToMultik(): D1Array = mk.ndarray(toList()) +/** Converts a [DataColumn] selected by [column] to a one-dimensional array ([D1Array]). */ @JvmName("convertNumberColumnFromDfToMultik") @OverloadResolutionByLambdaReturnType inline fun DataFrame.convertToMultik( @@ -51,21 +62,12 @@ inline fun DataFrame.convertToMultik( ): D1Array where N : Number, N : Comparable = getColumn { column(it) }.convertToMultik() +/** Converts a [DataColumn] selected by [column] to a one-dimensional array ([D1Array]). */ @JvmName("convertComplexColumnFromDfToMultik") @OverloadResolutionByLambdaReturnType inline fun DataFrame.convertToMultik(crossinline column: ColumnSelector): D1Array = getColumn { column(it) }.convertToMultik() -/** - * Converts a one-dimensional array ([D1Array]) of type [N] into a DataFrame. - * The resulting DataFrame contains a single column named "value", where each element of the array becomes a row in the DataFrame. - * - * @return a DataFrame where each element of the source array is represented as a row in a column named "value" under the schema [ValueProperty]. - */ -inline fun D1Array.convertToDataFrame(): DataFrame> = - dataFrameOf(ValueProperty<*>::value.name to column(toList())) - .cast() - // endregion // region 2D @@ -85,31 +87,15 @@ inline fun D2Array.convertToDataFrame(columnNameGenerator: (Int) .toColumn(columnNameGenerator(col)) }.toDataFrame() -@JvmName("convertToMultikOfComplex") -inline fun AnyFrame.convertToMultikOf(_klass: KClass = Complex::class): D2Array = - convertToMultik { colsOf() } - -@JvmName("convertToMultikOfNumber") -inline fun AnyFrame.convertToMultikOf( - _klass: KClass = Number::class, -): D2Array where N : Number, N : Comparable = convertToMultik { colsOf() } - -@JvmName("convertToMultikGuess") -fun AnyFrame.convertToMultik(): D2Array<*> { - val columnTypes = columnTypes().distinct() - return when { - columnTypes.size != 1 -> error("found column types: $columnTypes") - columnTypes.single() == typeOf() -> convertToMultik { colsOf() } - columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } - columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } - columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } - columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } - columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } - columnTypes.single().isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } - else -> error("found column types: $columnTypes") - } -} - +/** + * Converts a [DataFrame] to a two-dimensional array ([D2Array]). + * You'll need to specify which columns to convert using the [columns] selector. + * + * All column need to be of the same type. If no column are supplied, the function + * will only succeed if all columns are of the same type. + * + * @see convertToMultikOf + */ @JvmName("convertNumberColumnsFromDfToMultik") @OverloadResolutionByLambdaReturnType inline fun DataFrame.convertToMultik( @@ -117,22 +103,79 @@ inline fun DataFrame.convertToMultik( ): D2Array where N : Number, N : Comparable = getColumns { columns(it) }.convertToMultik() +/** + * Converts a [DataFrame] to a two-dimensional array ([D2Array]). + * You'll need to specify which columns to convert using the [columns] selector. + * + * All column need to be of the same type. If no column are supplied, the function + * will only succeed if all columns are of the same type. + * + * @see convertToMultikOf + */ @JvmName("convertComplexColumnsFromDfToMultik") @OverloadResolutionByLambdaReturnType inline fun DataFrame.convertToMultik( crossinline columns: ColumnsSelector, ): D2Array = getColumns { columns(it) }.convertToMultik() +/** + * Converts a [DataFrame] to a two-dimensional array ([D2Array]). + * You'll need to specify which columns to convert using the `columns` selector. + * + * All column need to be of the same type. If no column are supplied, the function + * will only succeed if all columns are of the same type. + * + * @see convertToMultikOf + */ +@JvmName("convertToMultikGuess") +fun AnyFrame.convertToMultik(): D2Array<*> { + val columnTypes = columnTypes().distinct() + val type = columnTypes.singleOrNull() ?: error("found column types: $columnTypes") + return when { + type == typeOf() -> convertToMultik { colsOf() } + type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } + else -> error("found column types: $columnTypes") + } +} + +/** + * Converts a [DataFrame] to a two-dimensional array ([D2Array]) by taking all + * columns of type [N]. + * + * @see convertToMultik + */ +@JvmName("convertToMultikOfComplex") +@Suppress("LocalVariableName") +inline fun AnyFrame.convertToMultikOf( + // unused param to avoid overload resolution ambiguity + _klass: KClass = Complex::class, +): D2Array = + convertToMultik { colsOf() } + +/** + * Converts a [DataFrame] to a two-dimensional array ([D2Array]) by taking all + * columns of type [N]. + * + * @see convertToMultik + */ +@JvmName("convertToMultikOfNumber") +@Suppress("LocalVariableName") +inline fun AnyFrame.convertToMultikOf( + // unused param to avoid overload resolution ambiguity + _klass: KClass = Number::class, +): D2Array where N : Number, N : Comparable = convertToMultik { colsOf() } + @JvmName("convertNumberColumnsToMultik") inline fun List>.convertToMultik(): D2Array where N : Number, N : Comparable = - mk.ndarray( - toDataFrame().map { it.values() as List }, - ) + mk.ndarray(toDataFrame().map { it.values() as List }) @JvmName("convertComplexColumnsToMultik") inline fun List>.convertToMultik(): D2Array = - mk.ndarray( - toDataFrame().map { it.values() as List }, - ) + mk.ndarray(toDataFrame().map { it.values() as List }) // endregion diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt index ee543d4152..ec02649d60 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt @@ -1,7 +1,10 @@ package org.jetbrains.kotlinx.dataframe.examples.multik +import org.jetbrains.kotlinx.dataframe.api.cast +import org.jetbrains.kotlinx.dataframe.api.colsOf import org.jetbrains.kotlinx.dataframe.api.describe import org.jetbrains.kotlinx.dataframe.api.mean +import org.jetbrains.kotlinx.dataframe.api.meanFor import org.jetbrains.kotlinx.dataframe.api.print import org.jetbrains.kotlinx.dataframe.api.value import org.jetbrains.kotlinx.multik.api.mk @@ -42,12 +45,26 @@ fun oneDimension() { fun twoDimensions() { // we can also convert a 2D ndarray to a DataFrame + // This conversion will create columns like "col0", "col1", etc. + // but will allow for similar access like in multik + // aka: `multikArray[x][y] == dataframe[x][y]` val mk1 = mk.rand(5, 10) println(mk1) - val df = mk1.convertToDataFrame() df.print() - val mk2 = df.convertToMultikOf() + // this allows us to perform any DF operation: + val means = df.meanFor { ("col0".."col9").cast() } + means.print() + + // we can convert back to Multik in multiple ways. + // Multik can only store one type of data, so we need to specify the type or select + // only the columns we want: + val mk2 = df.convertToMultik { colsOf() } + // or + df.convertToMultikOf() + // or if all columns are of the same type: + df.convertToMultik() + println(mk2) } From 05fd49eb0ac85837f99ad18c6348b7221cc3cceb Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Wed, 11 Jun 2025 12:29:45 +0200 Subject: [PATCH 7/9] added multik n-dim example --- .../examples/kotlinSpark/untypedDataset.kt | 1 + .../examples/multik/compatibilityLayer.kt | 130 +++++++++++++++++- .../kotlinx/dataframe/examples/multik/main.kt | 29 ++++ .../examples/spark/untypedDataset.kt | 1 + 4 files changed, 158 insertions(+), 3 deletions(-) diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt index dc22fb92dc..b5aeebecc9 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/untypedDataset.kt @@ -24,6 +24,7 @@ import org.jetbrains.kotlinx.spark.api.withSpark * some schema mapping in between Spark and DataFrame. * * We will use spark/compatibilityLayer.kt to do this. + * Take a look at that file for the implementation details! * * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. * Use the `runKotlinSparkUntypedDataset` Gradle task to do so. diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt index 7539ee6092..58aa6adc8e 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt @@ -17,16 +17,24 @@ import org.jetbrains.kotlinx.dataframe.api.getColumns import org.jetbrains.kotlinx.dataframe.api.map import org.jetbrains.kotlinx.dataframe.api.named import org.jetbrains.kotlinx.dataframe.api.toColumn +import org.jetbrains.kotlinx.dataframe.api.toColumnGroup import org.jetbrains.kotlinx.dataframe.api.toDataFrame +import org.jetbrains.kotlinx.dataframe.columns.BaseColumn +import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup import org.jetbrains.kotlinx.multik.api.mk import org.jetbrains.kotlinx.multik.api.ndarray import org.jetbrains.kotlinx.multik.ndarray.complex.Complex import org.jetbrains.kotlinx.multik.ndarray.data.D1Array import org.jetbrains.kotlinx.multik.ndarray.data.D2Array +import org.jetbrains.kotlinx.multik.ndarray.data.D3Array +import org.jetbrains.kotlinx.multik.ndarray.data.MultiArray +import org.jetbrains.kotlinx.multik.ndarray.data.NDArray import org.jetbrains.kotlinx.multik.ndarray.data.get import org.jetbrains.kotlinx.multik.ndarray.operations.toList +import org.jetbrains.kotlinx.multik.ndarray.operations.toListD2 import kotlin.experimental.ExperimentalTypeInference import kotlin.reflect.KClass +import kotlin.reflect.KType import kotlin.reflect.full.isSubtypeOf import kotlin.reflect.typeOf @@ -41,6 +49,7 @@ inline fun D1Array.convertToColumn(name: String = ""): DataColumn * * @return a DataFrame where each element of the source array is represented as a row in a column named "value" under the schema [ValueProperty]. */ +@JvmName("convert1dArrayToDataFrame") inline fun D1Array.convertToDataFrame(): DataFrame> = dataFrameOf(ValueProperty<*>::value.name to column(toList())) .cast() @@ -80,11 +89,12 @@ inline fun DataFrame.convertToMultik(crossinline col * * The conversion enforces that `multikArray[x][y] == dataframe[x][y]` */ +@JvmName("convert2dArrayToDataFrame") inline fun D2Array.convertToDataFrame(columnNameGenerator: (Int) -> String = { "col$it" }): AnyFrame = - (0.. - this[0.. + this[0.. List>.convertToMultik(): D2Array< mk.ndarray(toDataFrame().map { it.values() as List }) // endregion + +// region higher dimensions + +/** + * Converts a three-dimensional array ([D3Array]) to a DataFrame. + * It will contain `shape[0]` rows and `shape[1]` columns containing lists of size `shape[2]`. + * + * Column names can be specified using the [columnNameGenerator] lambda. + * + * The conversion enforces that `multikArray[x][y][z] == dataframe[x][y][z]` + */ +inline fun D3Array.convertToDataFrameWithLists( + columnNameGenerator: (Int) -> String = { "col$it" }, +): AnyFrame = + List(shape[1]) { y -> + this[0.. D3Array.convertToDataFrame(columnNameGenerator: (Int) -> String = { "col$it" }): AnyFrame = + List(shape[1]) { y -> + this[0.. + list.toColumn(columnNameGenerator(z)) + } // we get shape[2] columns inside each column group + .toColumnGroup(columnNameGenerator(y)) + }.toDataFrame() + +/** + * Exploratory recursive function to convert a [MultiArray] of any number of dimensions + * to a `List>` of the same number of dimensions. + */ +fun MultiArray.toListDn(): List<*> { + // Recursive helper function to handle traversal across dimensions + fun toListRecursive(indices: IntArray): List<*> { + // If we are at the last dimension (1D case) + if (indices.size == shape.lastIndex) { + return List(shape[indices.size]) { i -> + this[intArrayOf(*indices, i)] // Collect values for this dimension + } + } + + // For higher dimensions, recursively process smaller dimensions + return List(shape[indices.size]) { i -> + toListRecursive(indices + i) // Add `i` to the current index array + } + } + return toListRecursive(intArrayOf()) +} + +/** + * Converts a multidimensional array ([NDArray]) to a DataFrame. + * Inspired by [toListDn]. + * + * For a single-dimensional array, it will call [D1Array.convertToDataFrame]. + * + * Column names can be specified using the [columnNameGenerator] lambda. + * + * The conversion enforces that `multikArray[a][b][c][d]... == dataframe[a][b][c][d]...` + */ +inline fun NDArray.convertToDataFrameNestedGroups( + noinline columnNameGenerator: (Int) -> String = { "col$it" }, +): AnyFrame { + if (shape.size == 1) return (this as D1Array).convertToDataFrame() + + // push the first dimension to the end, because this represents the rows in DataFrame, + // and they are accessed by []'s first + return transpose(*(1..(), + columnNameGenerator = columnNameGenerator, + ).let { dataFrameOf((it as ColumnGroup<*>).columns()) } +} + +// Recursive helper function to handle traversal across dimensions +@PublishedApi +internal fun NDArray<*, *>.convertToDataFrameNestedGroupsRecursive( + indices: IntArray, + type: KType, + columnNameGenerator: (Int) -> String = { "col$it" }, +): BaseColumn<*> { + // If we are at the last dimension (1D case) + if (indices.size == shape.lastIndex) { + return List(shape[indices.size]) { i -> + this[intArrayOf(*indices, i)] // Collect values for this dimension + }.let { + DataColumn.createByType(name = "", values = it, type = type) + } + } + + // For higher dimensions, recursively process smaller dimensions + return List(shape[indices.size]) { i -> + convertToDataFrameNestedGroupsRecursive( + indices = indices + i, // Add `i` to the current index array + type = type, + columnNameGenerator = columnNameGenerator, + ).rename(columnNameGenerator(i)) + }.toColumnGroup("") +} + +// endregion diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt index ec02649d60..c75e763a70 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/main.kt @@ -15,10 +15,12 @@ import org.jetbrains.kotlinx.multik.ndarray.data.get * Let's explore some ways we can combine Multik with Kotlin DataFrame. * * We will use compatibilityLayer.kt for the conversions. + * Take a look at that file for the implementation details! */ fun main() { oneDimension() twoDimensions() + higherDimensions() } fun oneDimension() { @@ -46,6 +48,7 @@ fun oneDimension() { fun twoDimensions() { // we can also convert a 2D ndarray to a DataFrame // This conversion will create columns like "col0", "col1", etc. + // (careful, when the number of columns is too large, this can cause problems) // but will allow for similar access like in multik // aka: `multikArray[x][y] == dataframe[x][y]` val mk1 = mk.rand(5, 10) @@ -68,3 +71,29 @@ fun twoDimensions() { println(mk2) } + +fun higherDimensions() { + // Multik can store higher dimensions as well + // however; to convert this to a DataFrame, we need to specify how to do a particular conversion + // for instance, for 3d, we could store a list in each cell of the DF to represent the extra dimension: + val mk1 = mk.rand(5, 4, 3) + + println(mk1) + + val df1 = mk1.convertToDataFrameWithLists() + df1.print() + + // Alternatively, this could be solved using column groups. + // This subdivides each column into more columns, while ensuring `multikArray[x][y][z] == dataframe[x][y][z]` + val df2 = mk1.convertToDataFrame() + df2.print() + + // For even higher dimensions, we can keep adding more column groups + val mk2 = mk.rand(5, 4, 3, 2) + val df3 = mk2.convertToDataFrameNestedGroups() + df3.print() + + // ...or use nested DataFrames (in FrameColumns) + // (for instance, a 4D matrix could be stored in a 2D DataFrame where each cell is another DataFrame) + // but, we'll leave that as an exercise for the reader :) +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt index 7a6c96fe41..f100b23f59 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlinx.spark.api.gt * some schema mapping in between Spark and DataFrame. * * We will use spark/compatibilityLayer.kt to do this. + * Take a look at that file for the implementation details! * * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. * Use the `runSparkUntypedDataset` Gradle task to do so. From 7817357d196dac6b41a277186d7f698a4e501254 Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Wed, 11 Jun 2025 17:16:02 +0200 Subject: [PATCH 8/9] small docs and readme updates regarding main concepts --- README.md | 6 ++-- docs/StardustDocs/topics/overview.md | 36 ++++++++++--------- .../StardustDocs/topics/schemasInheritance.md | 2 +- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 09370b8cd4..cdb1a0170f 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,16 @@ Kotlin DataFrame aims to reconcile Kotlin's static typing with the dynamic nature of data by utilizing both the full power of the Kotlin language and the opportunities provided by intermittent code execution in Jupyter notebooks and REPL. * **Hierarchical** — represents hierarchical data structures, such as JSON or a tree of JVM objects. -* **Functional** — data processing pipeline is organized in a chain of `DataFrame` transformation operations. Every operation returns a new instance of `DataFrame` reusing underlying storage wherever it's possible. +* **Functional** — the data processing pipeline is organized in a chain of `DataFrame` transformation operations. +* **Immutable** — every operation returns a new instance of `DataFrame` reusing underlying storage wherever it's possible. * **Readable** — data transformation operations are defined in DSL close to natural language. * **Practical** — provides simple solutions for common problems and the ability to perform complex tasks. * **Minimalistic** — simple, yet powerful data model of three column kinds. -* **Interoperable** — convertable with Kotlin data classes and collections. +* **Interoperable** — convertable with Kotlin data classes and collections. This also means conversion to/from other libraries' data structures is usually quite straightforward! * **Generic** — can store objects of any type, not only numbers or strings. * **Typesafe** — on-the-fly generation of extension properties for type safe data access with Kotlin-style care for null safety. * **Polymorphic** — type compatibility derives from column schema compatibility. You can define a function that requires a special subset of columns in a dataframe but doesn't care about other columns. + In notebooks this works out-of-the-box. In ordinary projects this requires casting (for now). Integrates with [Kotlin kernel for Jupyter](https://github.com/Kotlin/kotlin-jupyter). Inspired by [krangl](https://github.com/holgerbrandl/krangl), Kotlin Collections and [pandas](https://pandas.pydata.org/) diff --git a/docs/StardustDocs/topics/overview.md b/docs/StardustDocs/topics/overview.md index 6d00883f77..3db41198b3 100644 --- a/docs/StardustDocs/topics/overview.md +++ b/docs/StardustDocs/topics/overview.md @@ -36,30 +36,32 @@ The goal of data wrangling is to assure quality and useful data. ## Main Features and Concepts -* [**Hierarchical**](hierarchical.md) — the Kotlin DataFrame library provides an ability to read and present data from different sources including not only plain **CSV** but also **JSON** or **[SQL databases](readSqlDatabases.md)**. -That’s why it has been designed hierarchical and allows nesting of columns and cells. - -* [**Interoperable**](collectionsInterop.md) — hierarchical data layout also opens a possibility of converting any objects -structure in application memory to a data frame and vice versa. - -* **Safe** — the Kotlin DataFrame library provides a mechanism of on-the-fly [**generation of extension properties**](extensionPropertiesApi.md) +* [**Hierarchical**](hierarchical.md) — the Kotlin DataFrame library provides an ability to read and present data from different sources, +including not only plain **CSV** but also **JSON** or **[SQL databases](readSqlDatabases.md)**. +This is why it was designed to be hierarchical and allows nesting of columns and cells. +* **Functional** — the data processing pipeline is organized in a chain of [`DataFrame`](DataFrame.md) transformation operations. +* **Immutable** — every operation returns a new instance of [`DataFrame`](DataFrame.md) reusing underlying storage wherever it's possible. +* **Readable** — data transformation operations are defined in DSL close to natural language. +* **Practical** — provides simple solutions for common problems and the ability to perform complex tasks. +* **Minimalistic** — simple, yet powerful data model of three [column kinds](DataColumn.md#column-kinds). +* [**Interoperable**](collectionsInterop.md) — convertable with Kotlin data classes and collections. + This also means conversion to/from other libraries' data structures is usually quite straightforward! + See our examples for some conversions between DataFrame and [Apache Spark](TODO), [Multik](TODO), and [JetBrains Exposed](TODO). +* **Generic** — can store objects of any type, not only numbers or strings. +* **Typesafe** — the Kotlin DataFrame library provides a mechanism of on-the-fly [**generation of extension properties**](extensionPropertiesApi.md) that correspond to the columns of a data frame. In interactive notebooks like Jupyter or Datalore, the generation runs after each cell execution. In IntelliJ IDEA there's a Gradle plugin for generation properties based on CSV file or JSON file. Also, we’re working on a compiler plugin that infers and transforms [`DataFrame`](DataFrame.md) schema while typing. You can now clone this [project with many examples](https://github.com/koperagen/df-plugin-demo) showcasing how it allows you to reliably use our most convenient extension properties API. The generated properties ensure you’ll never misspell column name and don’t mess up with its type, and of course nullability is also preserved. - -* **Generic** — columns can store objects of any type, not only numbers or strings. - * [**Polymorphic**](schemas.md) — - if all columns of [`DataFrame`](DataFrame.md) are presented in some other dataframes, - then the first one could be a superclass for latter. -Thus, - one can define a function on an interface with some set of columns - and then execute it in a safe way on any [`DataFrame`](DataFrame.md) which contains this set of columns. - -* **Immutable** — all operations on [`DataFrame`](DataFrame.md) produce new instance, while underlying data is reused wherever it's possible + if all columns of a [`DataFrame`](DataFrame.md) instance are presented in another dataframe, + then the first one will be seen as a superclass for the latter. +This means you can define a function on an interface with some set of columns + and then execute it safely on any [`DataFrame`](DataFrame.md) which contains this same set of columns. + In notebooks, this works out-of-the-box. + In ordinary projects, this requires casting (for now). ## Syntax diff --git a/docs/StardustDocs/topics/schemasInheritance.md b/docs/StardustDocs/topics/schemasInheritance.md index 3cb37b4422..f6b888dd7a 100644 --- a/docs/StardustDocs/topics/schemasInheritance.md +++ b/docs/StardustDocs/topics/schemasInheritance.md @@ -18,7 +18,7 @@ New schema interface for `filtered` variable will be derived from previously gen interface DataFrameType1 : DataFrameType ``` -Extension properties for data access are generated only for new and overriden members of `DataFrameType1` interface: +Extension properties for data access are generated only for new and overridden members of `DataFrameType1` interface: ```kotlin val ColumnsContainer.age: DataColumn get() = this["age"] as DataColumn From 27fd209f14a226f428027f4f937ec392c06946af Mon Sep 17 00:00:00 2001 From: Jolan Rensen Date: Thu, 12 Jun 2025 15:38:24 +0200 Subject: [PATCH 9/9] expanded on all comments and made all steps of unsupported data source examples clearer and more reproducible --- .../examples/exposed/compatibilityLayer.kt | 28 +++- .../dataframe/examples/exposed/main.kt | 5 +- .../dataframe/examples/exposed/tables.kt | 5 +- .../examples/kotlinSpark/typedDataset.kt | 26 +-- .../examples/multik/compatibilityLayer.kt | 149 +++++++++++++----- .../kotlinx/dataframe/examples/multik/io.kt | 2 + .../examples/spark/compatibilityLayer.kt | 60 ++++--- .../dataframe/examples/spark/typedDataset.kt | 51 +++--- .../examples/spark/untypedDataset.kt | 2 +- 9 files changed, 218 insertions(+), 110 deletions(-) diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/compatibilityLayer.kt index 54d705abc4..04b84fd8c0 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/compatibilityLayer.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/compatibilityLayer.kt @@ -9,6 +9,7 @@ import org.jetbrains.exposed.v1.core.Table import org.jetbrains.exposed.v1.jdbc.Query import org.jetbrains.kotlinx.dataframe.AnyFrame import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.annotations.DataSchema import org.jetbrains.kotlinx.dataframe.api.convertTo import org.jetbrains.kotlinx.dataframe.api.toDataFrame import org.jetbrains.kotlinx.dataframe.codeGen.NameNormalizer @@ -30,8 +31,9 @@ inline fun Iterable.convertToDataFrame(): DataFrame convertToDataFrame().convertTo() /** - * Retrieves all columns of any [Iterable][Iterable]`<`[ResultRow][ResultRow]`>`, like [Query][Query], - * from Exposed row by row and converts the resulting [Map] into a [DataFrame]. + * Retrieves all columns of an [Iterable][Iterable]`<`[ResultRow][ResultRow]`>` from Exposed, like [Query][Query], + * row by row and converts the resulting [Map] of lists into a [DataFrame] by calling + * [Map.toDataFrame]. */ @JvmName("convertToAnyFrame") fun Iterable.convertToDataFrame(): AnyFrame { @@ -62,26 +64,44 @@ val Expression<*>.readableName: String /** * Creates a [DataFrameSchema] from the declared [Table] instance. * + * This is not needed for conversion, but it can be useful to create a DataFrame [@DataSchema][DataSchema] instance. + * * @param columnNameToAccessor Optional [MutableMap] which will be filled with entries mapping * the SQL column name to the accessor name from the [Table]. * This can be used to define a [NameNormalizer] later. + * @see toDataFrameSchemaWithNameNormalizer */ @Suppress("UNCHECKED_CAST") fun Table.toDataFrameSchema(columnNameToAccessor: MutableMap = mutableMapOf()): DataFrameSchema { + // we use reflection to go over all `Column<*>` properties in the Table object val columns = this::class.memberProperties .filter { it.returnType.isSubtypeOf(typeOf>()) } .associate { prop -> prop as KProperty1> - // retrieve the actual column name + // retrieve the SQL column name val columnName = prop.get(this).name - // store the actual column name together with the accessor name in the map + // store the SQL column name together with the accessor name in the map columnNameToAccessor[columnName] = prop.name // get the column type from `val a: Column` val type = prop.returnType.arguments.first().type!! + // and we add the name and column shema type to the `columns` map :) columnName to ColumnSchema.Value(type) } return DataFrameSchemaImpl(columns) } + +/** + * Creates a [DataFrameSchema] from the declared [Table] instance with a [NameNormalizer] to + * convert the SQL column names to the corresponding Kotlin property names. + * + * This is not needed for conversion, but it can be useful to create a DataFrame [@DataSchema][DataSchema] instance. + * + * @see toDataFrameSchema + */ +fun Table.toDataFrameSchemaWithNameNormalizer(): Pair { + val columnNameToAccessor = mutableMapOf() + return Pair(toDataFrameSchema(), NameNormalizer { columnNameToAccessor[it] ?: it }) +} diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/main.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/main.kt index d53985ba80..cf157eb423 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/main.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/main.kt @@ -58,15 +58,16 @@ fun main() { // or make plots using Kandy! It's all up to you - // writing a DataFrame back into an SQL database with Exposed can also be done! + // writing a DataFrame back into an SQL database with Exposed can also be done easily! transaction(db) { addLogger(StdOutSqlLogger) // first delete the original contents Customers.deleteAll() - // batch insert our rows back into the SQL database + // batch-insert our dataframe back into the SQL database as a sequence of rows Customers.batchInsert(df.asSequence()) { dfRow -> + // we simply go over each value in the row and put it in the right place in the Exposed statement for (column in Customers.columns) { this[column as Column] = dfRow[column.name] } diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/tables.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/tables.kt index f5c369ce05..500c62d039 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/tables.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/exposed/tables.kt @@ -51,8 +51,7 @@ object Customers : Table() { * This is what we created the [toDataFrameSchema] function for! */ fun main() { - val columnNameToAccessor = mutableMapOf() - val schema = Customers.toDataFrameSchema(columnNameToAccessor) + val (schema, nameNormalizer) = Customers.toDataFrameSchemaWithNameNormalizer() // checking whether the schema is converted correctly. // schema.print() @@ -62,7 +61,7 @@ fun main() { // while keeping the correct column names schema.generateDataClasses( name = "CustomersDf", - nameNormalizer = NameNormalizer { columnNameToAccessor[it] ?: it }, + nameNormalizer = nameNormalizer, ).print() } diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt index d806f7f27e..59715ceddc 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/kotlinSpark/typedDataset.kt @@ -16,24 +16,14 @@ import org.jetbrains.kotlinx.dataframe.api.toDataFrame import org.jetbrains.kotlinx.dataframe.api.toList import org.jetbrains.kotlinx.spark.api.withSpark -@DataSchema -data class Name(val firstName: String, val lastName: String) - -@DataSchema -data class Person( - val name: Name, - val age: Int, - val city: String?, - val weight: Int?, - val isHappy: Boolean, -) - /** * With the Kotlin Spark API, normal Kotlin data classes are supported, * meaning we can reuse the same class for Spark and DataFrame! * * Also, since we use an actual class to define the schema, we need no type conversion! * + * See [Person] and [Name] for an example. + * * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. * Use the `runKotlinSparkTypedDataset` Gradle task to do so. */ @@ -74,3 +64,15 @@ fun main() = withSpark { sparkDatasetAgain.printSchema() sparkDatasetAgain.show() } + +@DataSchema +data class Name(val firstName: String, val lastName: String) + +@DataSchema +data class Person( + val name: Name, + val age: Int, + val city: String?, + val weight: Int?, + val isHappy: Boolean, +) diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt index 58aa6adc8e..5e71993dac 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/compatibilityLayer.kt @@ -41,7 +41,12 @@ import kotlin.reflect.typeOf // region 1D /** Converts a one-dimensional array ([D1Array]) to a [DataColumn] with optional [name]. */ -inline fun D1Array.convertToColumn(name: String = ""): DataColumn = column(toList()) named name +inline fun D1Array.convertToColumn(name: String = ""): DataColumn { + // we can simply convert the 1D array to a typed list and create a typed column from it + // by using the reified type parameter, DataFrame needs to do no inference :) + val values = this.toList() + return column(values) named name +} /** * Converts a one-dimensional array ([D1Array]) of type [N] into a DataFrame. @@ -50,18 +55,28 @@ inline fun D1Array.convertToColumn(name: String = ""): DataColumn * @return a DataFrame where each element of the source array is represented as a row in a column named "value" under the schema [ValueProperty]. */ @JvmName("convert1dArrayToDataFrame") -inline fun D1Array.convertToDataFrame(): DataFrame> = - dataFrameOf(ValueProperty<*>::value.name to column(toList())) - .cast() +inline fun D1Array.convertToDataFrame(): DataFrame> { + // do the conversion like above, but name the column "value"... + val column = this.convertToColumn(ValueProperty<*>::value.name) + // ...so we can cast it to a ValueProperty DataFrame + return dataFrameOf(column).cast>() +} /** Converts a [DataColumn] to a one-dimensional array ([D1Array]). */ @JvmName("convertNumberColumnToMultik") -inline fun DataColumn.convertToMultik(): D1Array where N : Number, N : Comparable = - mk.ndarray(toList()) +inline fun DataColumn.convertToMultik(): D1Array where N : Number, N : Comparable { + // we can convert our column to a typed list again to convert it to a multik array + val values = this.toList() + return mk.ndarray(values) +} /** Converts a [DataColumn] to a one-dimensional array ([D1Array]). */ @JvmName("convertComplexColumnToMultik") -inline fun DataColumn.convertToMultik(): D1Array = mk.ndarray(toList()) +inline fun DataColumn.convertToMultik(): D1Array { + // we can convert our column to a typed list again to convert it to a multik array + val values = this.toList() + return mk.ndarray(values) +} /** Converts a [DataColumn] selected by [column] to a one-dimensional array ([D1Array]). */ @JvmName("convertNumberColumnFromDfToMultik") @@ -69,13 +84,20 @@ inline fun DataColumn.convertToMultik(): D1Array = m inline fun DataFrame.convertToMultik( crossinline column: ColumnSelector, ): D1Array - where N : Number, N : Comparable = getColumn { column(it) }.convertToMultik() + where N : Number, N : Comparable { + // use the selector to get the column from this DataFrame and convert it + val col = this.getColumn { column(it) } + return col.convertToMultik() +} /** Converts a [DataColumn] selected by [column] to a one-dimensional array ([D1Array]). */ @JvmName("convertComplexColumnFromDfToMultik") @OverloadResolutionByLambdaReturnType -inline fun DataFrame.convertToMultik(crossinline column: ColumnSelector): D1Array = - getColumn { column(it) }.convertToMultik() +inline fun DataFrame.convertToMultik(crossinline column: ColumnSelector): D1Array { + // use the selector to get the column from this DataFrame and convert it + val col = this.getColumn { column(it) } + return col.convertToMultik() +} // endregion @@ -90,18 +112,22 @@ inline fun DataFrame.convertToMultik(crossinline col * The conversion enforces that `multikArray[x][y] == dataframe[x][y]` */ @JvmName("convert2dArrayToDataFrame") -inline fun D2Array.convertToDataFrame(columnNameGenerator: (Int) -> String = { "col$it" }): AnyFrame = - List(shape[1]) { i -> +inline fun D2Array.convertToDataFrame(columnNameGenerator: (Int) -> String = { "col$it" }): AnyFrame { + // Turning the 2D array into a list of typed columns first, no inference needed + val columns: List> = List(shape[1]) { i -> this[0..(name = columnNameGenerator(i)) + } + // and make a DataFrame from it + return columns.toDataFrame() +} /** * Converts a [DataFrame] to a two-dimensional array ([D2Array]). * You'll need to specify which columns to convert using the [columns] selector. * - * All column need to be of the same type. If no column are supplied, the function + * All columns need to be of the same type. If no columns are supplied, the function * will only succeed if all columns are of the same type. * * @see convertToMultikOf @@ -111,13 +137,17 @@ inline fun D2Array.convertToDataFrame(columnNameGenerator: (Int) inline fun DataFrame.convertToMultik( crossinline columns: ColumnsSelector, ): D2Array - where N : Number, N : Comparable = getColumns { columns(it) }.convertToMultik() + where N : Number, N : Comparable { + // use the selector to get the columns from this DataFrame and convert them + val cols = this.getColumns { columns(it) } + return cols.convertToMultik() +} /** * Converts a [DataFrame] to a two-dimensional array ([D2Array]). * You'll need to specify which columns to convert using the [columns] selector. * - * All column need to be of the same type. If no column are supplied, the function + * All columns need to be of the same type. If no columns are supplied, the function * will only succeed if all columns are of the same type. * * @see convertToMultikOf @@ -126,21 +156,25 @@ inline fun DataFrame.convertToMultik( @OverloadResolutionByLambdaReturnType inline fun DataFrame.convertToMultik( crossinline columns: ColumnsSelector, -): D2Array = getColumns { columns(it) }.convertToMultik() +): D2Array { + // use the selector to get the columns from this DataFrame and convert them + val cols = this.getColumns { columns(it) } + return cols.convertToMultik() +} /** * Converts a [DataFrame] to a two-dimensional array ([D2Array]). * You'll need to specify which columns to convert using the `columns` selector. * - * All column need to be of the same type. If no column are supplied, the function - * will only succeed if all columns are of the same type. + * All columns need to be of the same type. If no columns are supplied, the function + * will only succeed if all columns in [this] are of the same type. * * @see convertToMultikOf */ @JvmName("convertToMultikGuess") fun AnyFrame.convertToMultik(): D2Array<*> { - val columnTypes = columnTypes().distinct() - val type = columnTypes.singleOrNull() ?: error("found column types: $columnTypes") + val columnTypes = this.columnTypes().distinct() + val type = columnTypes.singleOrNull() ?: error("found multiple column types: $columnTypes") return when { type == typeOf() -> convertToMultik { colsOf() } type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } @@ -149,7 +183,7 @@ fun AnyFrame.convertToMultik(): D2Array<*> { type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } type.isSubtypeOf(typeOf()) -> convertToMultik { colsOf() } - else -> error("found column types: $columnTypes") + else -> error("found multiple column types: $columnTypes") } } @@ -157,6 +191,8 @@ fun AnyFrame.convertToMultik(): D2Array<*> { * Converts a [DataFrame] to a two-dimensional array ([D2Array]) by taking all * columns of type [N]. * + * Allows you to write `df.convertToMultikOf()`. + * * @see convertToMultik */ @JvmName("convertToMultikOfComplex") @@ -171,6 +207,8 @@ inline fun AnyFrame.convertToMultikOf( * Converts a [DataFrame] to a two-dimensional array ([D2Array]) by taking all * columns of type [N]. * + * Allows you to write `df.convertToMultikOf()`. + * * @see convertToMultik */ @JvmName("convertToMultikOfNumber") @@ -180,13 +218,31 @@ inline fun AnyFrame.convertToMultikOf( _klass: KClass = Number::class, ): D2Array where N : Number, N : Comparable = convertToMultik { colsOf() } +/** + * Helper function to convert a list of same-typed [DataColumn]s to a two-dimensional array ([D2Array]). + * We cannot enforce all columns have the same type if we require just a [DataFrame]. + */ +@Suppress("UNCHECKED_CAST") @JvmName("convertNumberColumnsToMultik") -inline fun List>.convertToMultik(): D2Array where N : Number, N : Comparable = - mk.ndarray(toDataFrame().map { it.values() as List }) +inline fun List>.convertToMultik(): D2Array where N : Number, N : Comparable { + // to get the list of columns as a list of rows, we need to convert them back to a dataframe first, + // then we can get the values of each row + val rows = this.toDataFrame().map { row -> row.values() as List } + return mk.ndarray(rows) +} +/** + * Helper function to convert a list of same-typed [DataColumn]s to a two-dimensional array ([D2Array]). + * We cannot enforce all columns have the same type if we require just a [DataFrame]. + */ +@Suppress("UNCHECKED_CAST") @JvmName("convertComplexColumnsToMultik") -inline fun List>.convertToMultik(): D2Array = - mk.ndarray(toDataFrame().map { it.values() as List }) +inline fun List>.convertToMultik(): D2Array { + // to get the list of columns as a list of rows, we need to convert them back to a dataframe first, + // then we can get the values of each row + val rows = this.toDataFrame().map { row -> row.values() as List } + return mk.ndarray(rows) +} // endregion @@ -202,12 +258,14 @@ inline fun List>.convertToMultik(): D2Array< */ inline fun D3Array.convertToDataFrameWithLists( columnNameGenerator: (Int) -> String = { "col$it" }, -): AnyFrame = - List(shape[1]) { y -> +): AnyFrame { + val columns: List>> = List(shape[1]) { y -> this[0..>(name = columnNameGenerator(y)) + } + return columns.toDataFrame() +} /** * Converts a three-dimensional array ([D3Array]) to a DataFrame. @@ -218,16 +276,18 @@ inline fun D3Array.convertToDataFrameWithLists( * The conversion enforces that `multikArray[x][y][z] == dataframe[x][y][z]` */ @JvmName("convert3dArrayToDataFrame") -inline fun D3Array.convertToDataFrame(columnNameGenerator: (Int) -> String = { "col$it" }): AnyFrame = - List(shape[1]) { y -> +inline fun D3Array.convertToDataFrame(columnNameGenerator: (Int) -> String = { "col$it" }): AnyFrame { + val columns: List> = List(shape[1]) { y -> this[0.. - list.toColumn(columnNameGenerator(z)) + list.toColumn(name = columnNameGenerator(z)) } // we get shape[2] columns inside each column group - .toColumnGroup(columnNameGenerator(y)) - }.toDataFrame() + .toColumnGroup(name = columnNameGenerator(y)) + } + return columns.toDataFrame() +} /** * Exploratory recursive function to convert a [MultiArray] of any number of dimensions @@ -261,6 +321,7 @@ fun MultiArray.toListDn(): List<*> { * * The conversion enforces that `multikArray[a][b][c][d]... == dataframe[a][b][c][d]...` */ +@Suppress("UNCHECKED_CAST") inline fun NDArray.convertToDataFrameNestedGroups( noinline columnNameGenerator: (Int) -> String = { "col$it" }, ): AnyFrame { @@ -271,17 +332,25 @@ inline fun NDArray.convertToDataFrameNestedGroups( return transpose(*(1..(), + type = typeOf(), // cannot inline a recursive function, so pass the type explicitly columnNameGenerator = columnNameGenerator, - ).let { dataFrameOf((it as ColumnGroup<*>).columns()) } + ).let { + // we could just cast this to a DataFrame<*>, because a ColumnGroup<*>: DataFrame + // however, this can sometimes cause issues where instance checks are done at runtime + // this converts it to an actual DataFrame instance + dataFrameOf((it as ColumnGroup<*>).columns()) + } } -// Recursive helper function to handle traversal across dimensions +/** + * Recursive helper function to handle traversal across dimensions. Do not call directly, + * use [convertToDataFrameNestedGroups] instead. + */ @PublishedApi internal fun NDArray<*, *>.convertToDataFrameNestedGroupsRecursive( indices: IntArray, type: KType, - columnNameGenerator: (Int) -> String = { "col$it" }, + columnNameGenerator: (Int) -> String, ): BaseColumn<*> { // If we are at the last dimension (1D case) if (indices.size == shape.lastIndex) { diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/io.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/io.kt index 64437bd852..64581538a1 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/io.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/multik/io.kt @@ -9,6 +9,8 @@ import java.io.File /** * Multik can read/write data from NPY/NPZ files. * We can use this from DataFrame too! + * + * We use compatibilityLayer.kt for the conversions, check it out for the implementation details of the conversion! */ fun main() { val npyFilename = "a1d.npy" diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/compatibilityLayer.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/compatibilityLayer.kt index ff28a1cb34..080a2e1f60 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/compatibilityLayer.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/compatibilityLayer.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlinx.dataframe.examples.spark +import org.apache.spark.api.java.JavaRDD import org.apache.spark.api.java.JavaSparkContext import org.apache.spark.sql.Dataset import org.apache.spark.sql.Row @@ -44,7 +45,7 @@ import kotlin.reflect.typeOf * [StructTypes][StructType] are converted to [ColumnGroups][ColumnGroup]. * * DataFrame supports type inference to do the conversion automatically. - * This is usually fine for smaller data sets, but when working with larger datasets a type map might be a good idea. + * This is usually fine for smaller data sets, but when working with larger datasets, a type map might be a good idea. * See [convertToDataFrame] for more information. */ fun Dataset.convertToDataFrameByInference( @@ -55,18 +56,23 @@ fun Dataset.convertToDataFrameByInference( val name = field.name() when (val dataType = field.dataType()) { is StructType -> + // a column group can be easily created from a dataframe and a name DataColumn.createColumnGroup( name = name, - df = convertToDataFrameByInference(dataType, prefix + name), + df = this.convertToDataFrameByInference(dataType, prefix + name), ) else -> + // we can use DataFrame type inference to create a column with the correct type + // from Spark we use `select()` to select a single column + // and `collectAsList()` to get all the values in a list of single-celled rows DataColumn.createByInference( name = name, - values = select((prefix + name).joinToString(".")) + values = this.select((prefix + name).joinToString(".")) .collectAsList() .map { it[0] }, suggestedType = TypeSuggestion.Infer, + // Spark provides nullability :) you can leave this out if you want this to be inferred too nullable = field.nullable(), ) } @@ -87,12 +93,16 @@ fun Dataset.convertToDataFrame(schema: StructType = schema(), prefix: List< val name = field.name() when (val dataType = field.dataType()) { is StructType -> + // a column group can be easily created from a dataframe and a name DataColumn.createColumnGroup( name = name, df = convertToDataFrame(dataType, prefix + name), ) else -> + // we create a column with the correct type using our type-map with fallback to inference + // from Spark we use `select()` to select a single column + // and `collectAsList()` to get all the values in a list of single-celled rows DataColumn.createByInference( name = name, values = select((prefix + name).joinToString(".")) @@ -110,11 +120,11 @@ fun Dataset.convertToDataFrame(schema: StructType = schema(), prefix: List< } /** - * Returns the corresponding Kotlin type for a given Spark DataType. + * Returns the corresponding [Kotlin type][KType] for a given Spark [DataType]. * * This list may be incomplete, but it can at least give you a good start. * - * @return The KType that corresponds to the Spark DataType, or null if no matching KType is found. + * @return The [KType] that corresponds to the Spark [DataType], or null if no matching [KType] is found. */ fun DataType.convertToDataFrame(): KType? = when { @@ -177,50 +187,58 @@ fun DataType.convertToDataFrame(): KType? = // region DataFrame to Spark /** - * Converts the DataFrame to a Spark Dataset of Rows using the provided SparkSession and JavaSparkContext. + * Converts the [DataFrame] to a Spark [Dataset] of [Rows][Row] using the provided [SparkSession] and [JavaSparkContext]. * - * Spark needs both the data and the schema to be converted to create a correct [Dataset]. + * Spark needs both the data and the schema to be converted to create a correct [Dataset], + * so we need to map our types somehow. * - * @param spark The SparkSession object to use for creating the DataFrame. - * @param sc The JavaSparkContext object to use for converting the DataFrame to RDD. - * @return A Dataset of Rows representing the converted DataFrame. + * @param spark The [SparkSession] object to use for creating the [DataFrame]. + * @param sc The [JavaSparkContext] object to use for converting the [DataFrame] to [RDD][JavaRDD]. + * @return A [Dataset] of [Rows][Row] representing the converted DataFrame. */ fun DataFrame<*>.convertToSpark(spark: SparkSession, sc: JavaSparkContext): Dataset { - val rows = sc.parallelize(rows().map { it.convertToSpark() }) - return spark.createDataFrame(rows, schema().convertToSpark()) + // Convert each row to spark rows + val rows = sc.parallelize(this.rows().map { it.convertToSpark() }) + // convert the data schema to a spark StructType + val schema = this.schema().convertToSpark() + return spark.createDataFrame(rows, schema) } /** - * Converts a DataRow to a Spark Row object. + * Converts a [DataRow] to a Spark [Row] object. * - * @return The converted Spark Row. + * @return The converted Spark [Row]. */ fun DataRow<*>.convertToSpark(): Row = RowFactory.create( *values().map { when (it) { + // a row can be nested inside another row if it's a column group is DataRow<*> -> it.convertToSpark() + + is DataFrame<*> -> error("nested dataframes are not supported") + else -> it } }.toTypedArray(), ) /** - * Converts a DataFrameSchema to a Spark StructType. + * Converts a [DataFrameSchema] to a Spark [StructType]. * - * @return The converted Spark StructType. + * @return The converted Spark [StructType]. */ fun DataFrameSchema.convertToSpark(): StructType = DataTypes.createStructType( - columns.map { (name, schema) -> + this.columns.map { (name, schema) -> DataTypes.createStructField(name, schema.convertToSpark(), schema.nullable) }, ) /** - * Converts a ColumnSchema object to Spark DataType. + * Converts a [ColumnSchema] object to Spark [DataType]. * - * @return The Spark DataType corresponding to the given ColumnSchema object. + * @return The Spark [DataType] corresponding to the given [ColumnSchema] object. * @throws IllegalArgumentException if the column type or kind is unknown. */ fun ColumnSchema.convertToSpark(): DataType = @@ -232,11 +250,11 @@ fun ColumnSchema.convertToSpark(): DataType = } /** - * Returns the corresponding Spark DataType for a given Kotlin type. + * Returns the corresponding Spark [DataType] for a given [Kotlin type][KType]. * * This list may be incomplete, but it can at least give you a good start. * - * @return The Spark DataType that corresponds to the Kotlin type, or null if no matching DataType is found. + * @return The Spark [DataType] that corresponds to the [Kotlin type][KType], or null if no matching [DataType] is found. */ fun KType.convertToSpark(): DataType? = when { diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/typedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/typedDataset.kt index 57db22f397..5f16f0fe08 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/typedDataset.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/typedDataset.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlinx.dataframe.examples.spark import org.apache.spark.SparkConf import org.apache.spark.api.java.JavaSparkContext import org.apache.spark.sql.Dataset +import org.apache.spark.sql.Encoder import org.apache.spark.sql.Encoders import org.apache.spark.sql.SparkSession import org.jetbrains.kotlinx.dataframe.annotations.DataSchema @@ -20,31 +21,6 @@ import org.jetbrains.kotlinx.dataframe.api.toDataFrame import org.jetbrains.kotlinx.dataframe.api.toList import java.io.Serializable -@DataSchema -data class Name - @JvmOverloads - constructor(var firstName: String = "", var lastName: String = "") : - Serializable { - companion object { - val encoder = Encoders.bean(Name::class.java) - } - } - -@DataSchema -data class Person - @JvmOverloads - constructor( - var name: Name = Name(), - var age: Int = -1, - var city: String? = null, - var weight: Int? = null, - var isHappy: Boolean = false, - ) : Serializable { - companion object { - val encoder = Encoders.bean(Person::class.java) - } - } - /** * For Spark, Kotlin data classes are supported if we: * - Add [@JvmOverloads][JvmOverloads] to the constructor @@ -53,6 +29,8 @@ data class Person * * But by adding [@DataSchema][DataSchema] we can reuse the same class for Spark and DataFrame! * + * See [Person] and [Name] for an example. + * * Also, since we use an actual class to define the schema, we need no type conversion! * * NOTE: You will likely need to run this function with Java 8 or 11 for it to work correctly. @@ -76,7 +54,7 @@ fun main() { Person(Name("Alice", "Wolf"), 20, null, 55, false), Person(Name("Charlie", "Byrd"), 30, "Moscow", 90, true), ), - Person.encoder, + beanEncoderOf(), ) // we can perform large operations in Spark. @@ -100,9 +78,28 @@ fun main() { ageStats.print(columnTypes = true, borders = true) // and when we want to convert a DataFrame back to Spark, we can do the same trick via a typed List - val sparkDatasetAgain = spark.createDataset(dataframe.toList(), Person.encoder) + val sparkDatasetAgain = spark.createDataset(dataframe.toList(), beanEncoderOf()) sparkDatasetAgain.printSchema() sparkDatasetAgain.show() spark.stop() } + +/** Creates a [bean encoder][Encoders.bean] for the given [T] instance. */ +inline fun beanEncoderOf(): Encoder = Encoders.bean(T::class.java) + +@DataSchema +data class Name + @JvmOverloads + constructor(var firstName: String = "", var lastName: String = "") : Serializable + +@DataSchema +data class Person + @JvmOverloads + constructor( + var name: Name = Name(), + var age: Int = -1, + var city: String? = null, + var weight: Int? = null, + var isHappy: Boolean = false, + ) : Serializable diff --git a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt index f100b23f59..b037d70bc8 100644 --- a/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt +++ b/examples/idea-examples/unsupported-data-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/examples/spark/untypedDataset.kt @@ -49,7 +49,7 @@ fun main() { Person(Name("Alice", "Wolf"), 20, null, 55, false), Person(Name("Charlie", "Byrd"), 30, "Moscow", 90, true), ), - Person.encoder, + beanEncoderOf(), ).toDF() // we can perform large operations in Spark.