Skip to content

Commit a735105

Browse files
authored
Merge pull request #504 from ermolenkodev/0.12.1
Backport #501 to 0.12.1
2 parents 51fa88a + 45c1c86 commit a735105

File tree

8 files changed

+562
-116
lines changed

8 files changed

+562
-116
lines changed

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/Integration.kt

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,9 @@ import org.jetbrains.kotlinx.dataframe.api.SplitWithTransform
3030
import org.jetbrains.kotlinx.dataframe.api.Update
3131
import org.jetbrains.kotlinx.dataframe.api.asColumnGroup
3232
import org.jetbrains.kotlinx.dataframe.api.asDataFrame
33-
import org.jetbrains.kotlinx.dataframe.api.at
3433
import org.jetbrains.kotlinx.dataframe.api.columnsCount
35-
import org.jetbrains.kotlinx.dataframe.api.dataFrameOf
36-
import org.jetbrains.kotlinx.dataframe.api.frames
37-
import org.jetbrains.kotlinx.dataframe.api.into
3834
import org.jetbrains.kotlinx.dataframe.api.isColumnGroup
3935
import org.jetbrains.kotlinx.dataframe.api.name
40-
import org.jetbrains.kotlinx.dataframe.api.toDataFrame
41-
import org.jetbrains.kotlinx.dataframe.api.values
4236
import org.jetbrains.kotlinx.dataframe.codeGen.CodeWithConverter
4337
import org.jetbrains.kotlinx.dataframe.columns.ColumnGroup
4438
import org.jetbrains.kotlinx.dataframe.columns.ColumnReference
@@ -340,35 +334,3 @@ public fun KotlinKernelHost.useSchemas(schemaClasses: Iterable<KClass<*>>) {
340334
public fun KotlinKernelHost.useSchemas(vararg schemaClasses: KClass<*>): Unit = useSchemas(schemaClasses.asIterable())
341335

342336
public inline fun <reified T> KotlinKernelHost.useSchema(): Unit = useSchemas(T::class)
343-
344-
/**
345-
* Converts [dataframeLike] to [AnyFrame].
346-
* If [dataframeLike] is already [AnyFrame] then it is returned as is.
347-
* If it's not possible to convert [dataframeLike] to [AnyFrame] then [IllegalArgumentException] is thrown.
348-
*/
349-
internal fun convertToDataFrame(dataframeLike: Any): AnyFrame =
350-
when (dataframeLike) {
351-
is Pivot<*> -> dataframeLike.frames().toDataFrame()
352-
is ReducedPivot<*> -> dataframeLike.values().toDataFrame()
353-
is PivotGroupBy<*> -> dataframeLike.frames()
354-
is ReducedPivotGroupBy<*> -> dataframeLike.values()
355-
is SplitWithTransform<*, *, *> -> dataframeLike.into()
356-
is Split<*, *> -> dataframeLike.toDataFrame()
357-
is Merge<*, *, *> -> dataframeLike.into("merged")
358-
is Gather<*, *, *, *> -> dataframeLike.into("key", "value")
359-
is Update<*, *> -> dataframeLike.df
360-
is Convert<*, *> -> dataframeLike.df
361-
is FormattedFrame<*> -> dataframeLike.df
362-
is AnyCol -> dataFrameOf(dataframeLike)
363-
is AnyRow -> dataframeLike.toDataFrame()
364-
is GroupBy<*, *> -> dataframeLike.toDataFrame()
365-
is AnyFrame -> dataframeLike
366-
is DisableRowsLimitWrapper -> dataframeLike.value
367-
is MoveClause<*, *> -> dataframeLike.df
368-
is RenameClause<*, *> -> dataframeLike.df
369-
is ReplaceClause<*, *> -> dataframeLike.df
370-
is GroupClause<*, *> -> dataframeLike.into("untitled")
371-
is InsertClause<*> -> dataframeLike.at(0)
372-
is FormatClause<*, *> -> dataframeLike.df
373-
else -> throw IllegalArgumentException("Unsupported type: ${dataframeLike::class}")
374-
}

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/JupyterHtmlRenderer.kt

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,21 @@ package org.jetbrains.kotlinx.dataframe.jupyter
33
import com.beust.klaxon.json
44
import org.jetbrains.kotlinx.dataframe.api.rows
55
import org.jetbrains.kotlinx.dataframe.api.toDataFrame
6-
import org.jetbrains.kotlinx.dataframe.io.*
6+
import org.jetbrains.kotlinx.dataframe.io.DataFrameHtmlData
7+
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
8+
import org.jetbrains.kotlinx.dataframe.io.encodeFrame
9+
import org.jetbrains.kotlinx.dataframe.io.toHTML
10+
import org.jetbrains.kotlinx.dataframe.jupyter.KotlinNotebookPluginUtils.convertToDataFrame
711
import org.jetbrains.kotlinx.dataframe.nrow
812
import org.jetbrains.kotlinx.dataframe.size
9-
import org.jetbrains.kotlinx.jupyter.api.*
1013
import org.jetbrains.kotlinx.jupyter.api.HtmlData
14+
import org.jetbrains.kotlinx.jupyter.api.JupyterClientType
15+
import org.jetbrains.kotlinx.jupyter.api.KotlinKernelVersion
16+
import org.jetbrains.kotlinx.jupyter.api.MimeTypedResult
17+
import org.jetbrains.kotlinx.jupyter.api.Notebook
1118
import org.jetbrains.kotlinx.jupyter.api.libraries.JupyterIntegration
19+
import org.jetbrains.kotlinx.jupyter.api.mimeResult
20+
import org.jetbrains.kotlinx.jupyter.api.renderHtmlAsIFrameIfNeeded
1221

1322
/** Starting from this version, dataframe integration will respond with additional data for rendering in Kotlin Notebooks plugin. */
1423
private const val MIN_KERNEL_VERSION_FOR_NEW_TABLES_UI = "0.11.0.311"

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/jupyter/KotlinNotebookPluginUtils.kt

Lines changed: 140 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,45 @@
11
package org.jetbrains.kotlinx.dataframe.jupyter
22

3+
import org.jetbrains.kotlinx.dataframe.AnyCol
34
import org.jetbrains.kotlinx.dataframe.AnyFrame
5+
import org.jetbrains.kotlinx.dataframe.AnyRow
6+
import org.jetbrains.kotlinx.dataframe.api.Convert
7+
import org.jetbrains.kotlinx.dataframe.api.FormatClause
8+
import org.jetbrains.kotlinx.dataframe.api.FormattedFrame
9+
import org.jetbrains.kotlinx.dataframe.api.Gather
10+
import org.jetbrains.kotlinx.dataframe.api.GroupBy
11+
import org.jetbrains.kotlinx.dataframe.api.GroupClause
12+
import org.jetbrains.kotlinx.dataframe.api.InsertClause
13+
import org.jetbrains.kotlinx.dataframe.api.Merge
14+
import org.jetbrains.kotlinx.dataframe.api.MoveClause
15+
import org.jetbrains.kotlinx.dataframe.api.Pivot
16+
import org.jetbrains.kotlinx.dataframe.api.PivotGroupBy
17+
import org.jetbrains.kotlinx.dataframe.api.ReducedGroupBy
18+
import org.jetbrains.kotlinx.dataframe.api.ReducedPivot
19+
import org.jetbrains.kotlinx.dataframe.api.ReducedPivotGroupBy
20+
import org.jetbrains.kotlinx.dataframe.api.RenameClause
21+
import org.jetbrains.kotlinx.dataframe.api.ReplaceClause
22+
import org.jetbrains.kotlinx.dataframe.api.Split
23+
import org.jetbrains.kotlinx.dataframe.api.SplitWithTransform
24+
import org.jetbrains.kotlinx.dataframe.api.Update
25+
import org.jetbrains.kotlinx.dataframe.api.at
26+
import org.jetbrains.kotlinx.dataframe.api.dataFrameOf
427
import org.jetbrains.kotlinx.dataframe.api.filter
28+
import org.jetbrains.kotlinx.dataframe.api.frames
29+
import org.jetbrains.kotlinx.dataframe.api.into
30+
import org.jetbrains.kotlinx.dataframe.api.sortBy
31+
import org.jetbrains.kotlinx.dataframe.api.toDataFrame
32+
import org.jetbrains.kotlinx.dataframe.api.values
33+
import org.jetbrains.kotlinx.dataframe.columns.ColumnPath
34+
import org.jetbrains.kotlinx.dataframe.columns.toColumnSet
35+
import org.jetbrains.kotlinx.dataframe.impl.ColumnNameGenerator
536

637
/**
738
* A class with utility methods for Kotlin Notebook Plugin integration.
8-
* Kotlin Notebook Plugin is acts as a client of Kotlin Jupyter kernel and use this functionality
39+
* Kotlin Notebook Plugin acts as a client of Kotlin Jupyter kernel and uses this functionality
940
* for dynamic pagination when rendering dataframes.
10-
* The plugin sends Kotlin following code to the kernel to evaluate
11-
* DISPLAY(KotlinNotebooksPluginUtils.getRowsSubsetForRendering(Out[x], 0, 20), "")
41+
* The plugin sends the following code to the kernel to evaluate:
42+
* DISPLAY(KotlinNotebooksPluginUtils.getRowsSubsetForRendering(Out[...], 0, 20), "")
1243
*/
1344
public object KotlinNotebookPluginUtils {
1445
/**
@@ -30,4 +61,110 @@ public object KotlinNotebookPluginUtils {
3061
*/
3162
public fun getRowsSubsetForRendering(df: AnyFrame, startIdx: Int, endIdx: Int): DisableRowsLimitWrapper =
3263
DisableRowsLimitWrapper(df.filter { it.index() in startIdx until endIdx })
64+
65+
/**
66+
* Sorts a dataframe-like object by multiple columns.
67+
*
68+
* @param dataFrameLike The dataframe-like object to sort.
69+
* @param columnPaths The list of columns to sort by. Each element in the list represents a column path
70+
* @param desc The list of booleans indicating whether each column should be sorted in descending order.
71+
* The size of this list should be the same as the size of the `columns` list.
72+
*
73+
* @throws IllegalArgumentException if `dataFrameLike` is `null`.
74+
*
75+
* @return The sorted dataframe.
76+
*/
77+
public fun sortByColumns(
78+
dataFrameLike: Any?,
79+
columnPaths: List<List<String>>,
80+
desc: List<Boolean>
81+
): AnyFrame = when (dataFrameLike) {
82+
null -> throw IllegalArgumentException("Dataframe is null")
83+
else -> sortByColumns(convertToDataFrame(dataFrameLike), columnPaths, desc)
84+
}
85+
86+
/**
87+
* Sorts the given data frame by the specified columns.
88+
*
89+
* @param df The data frame to be sorted.
90+
* @param columnPaths The paths of the columns to be sorted. Each path is represented as a list of strings.
91+
* @param isDesc A list of booleans indicating whether each column should be sorted in descending order.
92+
* The size of this list must be equal to the size of the columnPaths list.
93+
* @return The sorted data frame.
94+
*/
95+
public fun sortByColumns(df: AnyFrame, columnPaths: List<List<String>>, isDesc: List<Boolean>): AnyFrame =
96+
df.sortBy {
97+
require(columnPaths.all { it.isNotEmpty() })
98+
require(columnPaths.size == isDesc.size)
99+
100+
val sortKeys = columnPaths.map { path ->
101+
ColumnPath(path)
102+
}
103+
104+
(sortKeys zip isDesc).map { (key, desc) ->
105+
if (desc) key.desc() else key
106+
}.toColumnSet()
107+
}
108+
109+
/**
110+
* Converts [dataframeLike] to [AnyFrame].
111+
* If [dataframeLike] is already [AnyFrame] then it is returned as is.
112+
* If it's not possible to convert [dataframeLike] to [AnyFrame] then [IllegalArgumentException] is thrown.
113+
*/
114+
public fun convertToDataFrame(dataframeLike: Any): AnyFrame =
115+
when (dataframeLike) {
116+
is Pivot<*> -> dataframeLike.frames().toDataFrame()
117+
is ReducedGroupBy<*, *> -> dataframeLike.values()
118+
is ReducedPivot<*> -> dataframeLike.values().toDataFrame()
119+
is PivotGroupBy<*> -> dataframeLike.frames()
120+
is ReducedPivotGroupBy<*> -> dataframeLike.values()
121+
is SplitWithTransform<*, *, *> -> dataframeLike.into()
122+
is Split<*, *> -> dataframeLike.toDataFrame()
123+
is Merge<*, *, *> -> dataframeLike.into(
124+
generateRandomVariationOfColumnName(
125+
"merged",
126+
dataframeLike.df.columnNames()
127+
)
128+
)
129+
130+
is Gather<*, *, *, *> -> dataframeLike.into(
131+
generateRandomVariationOfColumnName("key", dataframeLike.df.columnNames()),
132+
generateRandomVariationOfColumnName("value", dataframeLike.df.columnNames())
133+
)
134+
135+
is Update<*, *> -> dataframeLike.df
136+
is Convert<*, *> -> dataframeLike.df
137+
is FormattedFrame<*> -> dataframeLike.df
138+
is AnyCol -> dataFrameOf(dataframeLike)
139+
is AnyRow -> dataframeLike.toDataFrame()
140+
is GroupBy<*, *> -> dataframeLike.toDataFrame()
141+
is AnyFrame -> dataframeLike
142+
is DisableRowsLimitWrapper -> dataframeLike.value
143+
is MoveClause<*, *> -> dataframeLike.df
144+
is RenameClause<*, *> -> dataframeLike.df
145+
is ReplaceClause<*, *> -> dataframeLike.df
146+
is GroupClause<*, *> -> dataframeLike.into(
147+
generateRandomVariationOfColumnName(
148+
"untitled",
149+
dataframeLike.df.columnNames()
150+
)
151+
)
152+
153+
is InsertClause<*> -> dataframeLike.at(0)
154+
is FormatClause<*, *> -> dataframeLike.df
155+
else -> throw IllegalArgumentException("Unsupported type: ${dataframeLike::class}")
156+
}
157+
158+
/**
159+
* Generates a random variation of a column name that is unique among the provided used names.
160+
*
161+
* @param preferredName The preferred name for the column.
162+
* @param usedNames The list of already used column names.
163+
* @return A unique random variation of the preferred name.
164+
*/
165+
public fun generateRandomVariationOfColumnName(
166+
preferredName: String,
167+
usedNames: List<String> = emptyList()
168+
): String =
169+
ColumnNameGenerator(usedNames).addUnique(preferredName)
33170
}

0 commit comments

Comments
 (0)