1
1
package org.jetbrains.kotlinx.dataframe.jupyter
2
2
3
+ import org.jetbrains.kotlinx.dataframe.AnyCol
3
4
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
4
27
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
5
36
6
37
/* *
7
38
* 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
9
40
* 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), "")
12
43
*/
13
44
public object KotlinNotebookPluginUtils {
14
45
/* *
@@ -30,4 +61,110 @@ public object KotlinNotebookPluginUtils {
30
61
*/
31
62
public fun getRowsSubsetForRendering (df : AnyFrame , startIdx : Int , endIdx : Int ): DisableRowsLimitWrapper =
32
63
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)
33
170
}
0 commit comments