Skip to content

Commit b3f3331

Browse files
authored
Merge pull request #465 from Kotlin/groupby-docs
update groupBy documentation
2 parents 54d2c74 + d123db8 commit b3f3331

File tree

18 files changed

+1893
-117
lines changed

18 files changed

+1893
-117
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ import kotlin.reflect.KProperty
1717

1818
// region DataFrame
1919

20+
/**
21+
*
22+
* @param cols key columns; Column for grouping can be created inplace
23+
*
24+
* `df.groupBy { expr("columnName") { "someColumn"<Int>() + 15 } }`
25+
*
26+
* is equivalent to
27+
*
28+
* `df.add("columnName") { "someColumn"<Int>() + 15 }.groupBy("columnName")`
29+
*/
2030
public fun <T> DataFrame<T>.groupBy(moveToTop: Boolean = true, cols: ColumnsSelector<T, *>): GroupBy<T, T> =
2131
groupByImpl(moveToTop, cols)
2232

core/generated-sources/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/html.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,17 +254,15 @@ public fun <T> DataFrame<T>.html(): String = toStandaloneHTML().toString()
254254
public fun <T> DataFrame<T>.toStandaloneHTML(
255255
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
256256
cellRenderer: CellRenderer = DefaultCellRenderer,
257-
includeStatic: Boolean = true,
258257
getFooter: (DataFrame<T>) -> String? = { "DataFrame [${it.size}]" },
259-
): DataFrameHtmlData = toHTML(configuration, cellRenderer, includeStatic, getFooter).withTableDefinitions()
258+
): DataFrameHtmlData = toHTML(configuration, cellRenderer, getFooter).withTableDefinitions()
260259

261260
/**
262261
* @return DataFrameHtmlData without additional definitions. Can be rendered in Jupyter kernel environments
263262
*/
264263
public fun <T> DataFrame<T>.toHTML(
265264
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
266265
cellRenderer: CellRenderer = DefaultCellRenderer,
267-
includeStatic: Boolean = true,
268266
getFooter: (DataFrame<T>) -> String? = { "DataFrame [${it.size}]" },
269267
): DataFrameHtmlData {
270268
val limit = configuration.rowsLimit ?: Int.MAX_VALUE
@@ -285,7 +283,7 @@ public fun <T> DataFrame<T>.toHTML(
285283

286284
var tableHtml = toHtmlData(configuration, cellRenderer)
287285

288-
if (includeStatic) {
286+
if (configuration.enableFallbackStaticTables) {
289287
tableHtml += toStaticHtml(configuration, DefaultCellRenderer)
290288
}
291289

@@ -368,6 +366,8 @@ public data class DataFrameHtmlData(
368366
/**
369367
* @param rowsLimit null to disable rows limit
370368
* @param cellContentLimit -1 to disable content trimming
369+
* @param enableFallbackStaticTables true to add additional pure HTML table that will be visible only if JS is disabled;
370+
* For example hosting *.ipynb files with outputs on GitHub
371371
*/
372372
public data class DisplayConfiguration(
373373
var rowsLimit: Int? = 20,
@@ -378,6 +378,7 @@ public data class DisplayConfiguration(
378378
var isolatedOutputs: Boolean = flagFromEnv("LETS_PLOT_HTML_ISOLATED_FRAME"),
379379
internal val localTesting: Boolean = flagFromEnv("KOTLIN_DATAFRAME_LOCAL_TESTING"),
380380
var useDarkColorScheme: Boolean = false,
381+
var enableFallbackStaticTables: Boolean = true,
381382
) {
382383
public companion object {
383384
public val DEFAULT: DisplayConfiguration = DisplayConfiguration()

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/explainer/PluginCallbackProxy.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import org.jetbrains.kotlinx.dataframe.api.where
2727
import org.jetbrains.kotlinx.dataframe.api.with
2828
import org.jetbrains.kotlinx.dataframe.columns.ColumnSet
2929
import org.jetbrains.kotlinx.dataframe.io.DataFrameHtmlData
30-
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
3130
import org.jetbrains.kotlinx.dataframe.io.sessionId
3231
import org.jetbrains.kotlinx.dataframe.io.tableInSessionId
3332
import org.jetbrains.kotlinx.dataframe.io.toHTML
@@ -244,8 +243,8 @@ object PluginCallbackProxy : PluginCallback {
244243
}
245244

246245
private fun convertToHTML(dataframeLike: Any): DataFrameHtmlData {
247-
fun DataFrame<*>.toHTML() = toHTML(DisplayConfiguration(), getFooter = { "" })
248-
fun FormattedFrame<*>.toHTML1() = toHTML(DisplayConfiguration())
246+
fun DataFrame<*>.toHTML() = toHTML(SamplesDisplayConfiguration, getFooter = { "" })
247+
fun FormattedFrame<*>.toHTML1() = toHTML(SamplesDisplayConfiguration)
249248

250249
return when (dataframeLike) {
251250
is Pivot<*> -> dataframeLike.frames().toDataFrame().toHTML()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.jetbrains.kotlinx.dataframe.explainer
2+
3+
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
4+
5+
val SamplesDisplayConfiguration = DisplayConfiguration(enableFallbackStaticTables = false)

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/Analyze.kt

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,6 @@ class Analyze : TestBase() {
577577
df.groupBy { name }
578578
df.groupBy { city and name.lastName }
579579
df.groupBy { age / 10 named "ageDecade" }
580-
df.groupBy { expr { name.firstName.length + name.lastName.length } named "nameLength" }
581580
// SampleEnd
582581
}
583582

@@ -601,7 +600,6 @@ class Analyze : TestBase() {
601600

602601
df.groupBy { age / 10 named "ageDecade" }
603602

604-
df.groupBy { expr { firstName().length + lastName().length } named "nameLength" }
605603
// SampleEnd
606604
}
607605

@@ -612,10 +610,53 @@ class Analyze : TestBase() {
612610
df.groupBy("name")
613611
df.groupBy { "city" and "name"["lastName"] }
614612
df.groupBy { "age"<Int>() / 10 named "ageDecade" }
613+
// SampleEnd
614+
}
615+
616+
@Test
617+
@TransformDataFrameExpressions
618+
fun groupByExpr_properties() {
619+
// SampleStart
620+
df.groupBy { expr { name.firstName.length + name.lastName.length } named "nameLength" }
621+
// SampleEnd
622+
}
623+
624+
@Test
625+
@TransformDataFrameExpressions
626+
fun groupByExpr_accessors() {
627+
// SampleStart
628+
val name by columnGroup()
629+
val lastName by name.column<String>()
630+
val firstName by name.column<String>()
631+
632+
df.groupBy { expr { firstName().length + lastName().length } named "nameLength" }
633+
// SampleEnd
634+
}
635+
636+
@Test
637+
@TransformDataFrameExpressions
638+
fun groupByExpr_strings() {
639+
// SampleStart
615640
df.groupBy { expr { "name"["firstName"]<String>().length + "name"["lastName"]<String>().length } named "nameLength" }
616641
// SampleEnd
617642
}
618643

644+
@Test
645+
@TransformDataFrameExpressions
646+
fun groupByMoveToTop() {
647+
// SampleStart
648+
df.groupBy(moveToTop = true) { name.lastName }
649+
// SampleEnd
650+
}
651+
652+
@Test
653+
@TransformDataFrameExpressions
654+
fun groupByMoveToTopFalse() {
655+
// SampleStart
656+
df.groupBy(moveToTop = false) { name.lastName }
657+
// SampleEnd
658+
}
659+
619660
@Test
620661
@TransformDataFrameExpressions
621662
fun dataFrameToGroupBy() {

core/generated-sources/src/test/kotlin/org/jetbrains/kotlinx/dataframe/samples/api/JoinWith.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import org.jetbrains.kotlinx.dataframe.api.rightJoin
2929
import org.jetbrains.kotlinx.dataframe.api.rightJoinWith
3030
import org.jetbrains.kotlinx.dataframe.api.with
3131
import org.jetbrains.kotlinx.dataframe.explainer.PluginCallbackProxy
32+
import org.jetbrains.kotlinx.dataframe.explainer.SamplesDisplayConfiguration
3233
import org.jetbrains.kotlinx.dataframe.explainer.TransformDataFrameExpressions
3334
import org.jetbrains.kotlinx.dataframe.io.DataFrameHtmlData
3435
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
@@ -131,7 +132,7 @@ class JoinWith : TestBase() {
131132
private fun AnyFrame.toColoredHTML() = toHTML(
132133
getFooter = { null },
133134
cellRenderer = renderer,
134-
configuration = DisplayConfiguration.DEFAULT.copy(
135+
configuration = SamplesDisplayConfiguration.copy(
135136
cellFormatter = { row, col ->
136137
val value = row[col]
137138
if (value is ColoredValue<*>) {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ import kotlin.reflect.KProperty
1717

1818
// region DataFrame
1919

20+
/**
21+
*
22+
* @param cols key columns; Column for grouping can be created inplace
23+
*
24+
* `df.groupBy { expr("columnName") { "someColumn"<Int>() + 15 } }`
25+
*
26+
* is equivalent to
27+
*
28+
* `df.add("columnName") { "someColumn"<Int>() + 15 }.groupBy("columnName")`
29+
*/
2030
public fun <T> DataFrame<T>.groupBy(moveToTop: Boolean = true, cols: ColumnsSelector<T, *>): GroupBy<T, T> =
2131
groupByImpl(moveToTop, cols)
2232

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/html.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,17 +254,15 @@ public fun <T> DataFrame<T>.html(): String = toStandaloneHTML().toString()
254254
public fun <T> DataFrame<T>.toStandaloneHTML(
255255
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
256256
cellRenderer: CellRenderer = DefaultCellRenderer,
257-
includeStatic: Boolean = true,
258257
getFooter: (DataFrame<T>) -> String? = { "DataFrame [${it.size}]" },
259-
): DataFrameHtmlData = toHTML(configuration, cellRenderer, includeStatic, getFooter).withTableDefinitions()
258+
): DataFrameHtmlData = toHTML(configuration, cellRenderer, getFooter).withTableDefinitions()
260259

261260
/**
262261
* @return DataFrameHtmlData without additional definitions. Can be rendered in Jupyter kernel environments
263262
*/
264263
public fun <T> DataFrame<T>.toHTML(
265264
configuration: DisplayConfiguration = DisplayConfiguration.DEFAULT,
266265
cellRenderer: CellRenderer = DefaultCellRenderer,
267-
includeStatic: Boolean = true,
268266
getFooter: (DataFrame<T>) -> String? = { "DataFrame [${it.size}]" },
269267
): DataFrameHtmlData {
270268
val limit = configuration.rowsLimit ?: Int.MAX_VALUE
@@ -285,7 +283,7 @@ public fun <T> DataFrame<T>.toHTML(
285283

286284
var tableHtml = toHtmlData(configuration, cellRenderer)
287285

288-
if (includeStatic) {
286+
if (configuration.enableFallbackStaticTables) {
289287
tableHtml += toStaticHtml(configuration, DefaultCellRenderer)
290288
}
291289

@@ -368,6 +366,8 @@ public data class DataFrameHtmlData(
368366
/**
369367
* @param rowsLimit null to disable rows limit
370368
* @param cellContentLimit -1 to disable content trimming
369+
* @param enableFallbackStaticTables true to add additional pure HTML table that will be visible only if JS is disabled;
370+
* For example hosting *.ipynb files with outputs on GitHub
371371
*/
372372
public data class DisplayConfiguration(
373373
var rowsLimit: Int? = 20,
@@ -378,6 +378,7 @@ public data class DisplayConfiguration(
378378
var isolatedOutputs: Boolean = flagFromEnv("LETS_PLOT_HTML_ISOLATED_FRAME"),
379379
internal val localTesting: Boolean = flagFromEnv("KOTLIN_DATAFRAME_LOCAL_TESTING"),
380380
var useDarkColorScheme: Boolean = false,
381+
var enableFallbackStaticTables: Boolean = true,
381382
) {
382383
public companion object {
383384
public val DEFAULT: DisplayConfiguration = DisplayConfiguration()

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ internal inline fun <reified T : Any> JupyterHtmlRenderer.render(
5050
includeCss = true,
5151
).plus(
5252
df.toHTML(
53-
configuration = reifiedDisplayConfiguration,
53+
// is added later to make sure it's put outside of potential iFrames
54+
configuration = reifiedDisplayConfiguration.copy(enableFallbackStaticTables = false),
5455
cellRenderer = contextRenderer,
55-
includeStatic = false, // is added later to make sure it's put outside of potential iFrames
5656
) { footer }
5757
).toJupyterHtmlData()
5858

core/src/test/kotlin/org/jetbrains/kotlinx/dataframe/explainer/PluginCallbackProxy.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import org.jetbrains.kotlinx.dataframe.api.where
2727
import org.jetbrains.kotlinx.dataframe.api.with
2828
import org.jetbrains.kotlinx.dataframe.columns.ColumnSet
2929
import org.jetbrains.kotlinx.dataframe.io.DataFrameHtmlData
30-
import org.jetbrains.kotlinx.dataframe.io.DisplayConfiguration
3130
import org.jetbrains.kotlinx.dataframe.io.sessionId
3231
import org.jetbrains.kotlinx.dataframe.io.tableInSessionId
3332
import org.jetbrains.kotlinx.dataframe.io.toHTML
@@ -244,8 +243,8 @@ object PluginCallbackProxy : PluginCallback {
244243
}
245244

246245
private fun convertToHTML(dataframeLike: Any): DataFrameHtmlData {
247-
fun DataFrame<*>.toHTML() = toHTML(DisplayConfiguration(), getFooter = { "" })
248-
fun FormattedFrame<*>.toHTML1() = toHTML(DisplayConfiguration())
246+
fun DataFrame<*>.toHTML() = toHTML(SamplesDisplayConfiguration, getFooter = { "" })
247+
fun FormattedFrame<*>.toHTML1() = toHTML(SamplesDisplayConfiguration)
249248

250249
return when (dataframeLike) {
251250
is Pivot<*> -> dataframeLike.frames().toDataFrame().toHTML()

0 commit comments

Comments
 (0)