From c568c3f04aaea3fcb0db7736df8c1293e73f453e Mon Sep 17 00:00:00 2001 From: Nikita Klimenko Date: Wed, 19 Nov 2025 01:06:41 +0200 Subject: [PATCH 1/3] Setup compiler plugin --- gradle/libs.versions.toml | 3 ++- .../serializers/MeasurementSerializer.kt | 4 ++-- kandy-lets-plot/build.gradle.kts | 4 ++++ .../kotlinx/kandy/letsplot/translator/scaleWrap.kt | 14 ++++++-------- .../kotlinx/kandy/letsplot/dsl/dataset.kt | 3 ++- .../kandy/letsplot/samples/guides/boxplot.kt | 8 +++++--- .../kandy/letsplot/samples/guides/countPlot.kt | 4 ++-- .../kandy/letsplot/samples/guides/exportToFile.kt | 3 ++- 8 files changed, 25 insertions(+), 18 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8627a4f37..20bba12ad 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,6 +1,6 @@ [versions] # plugins version -kotlin = "2.2.20" +kotlin = "2.3.0-RC" dokka = "2.0.0" korro = "0.1.6" nexus = "2.0.0" @@ -50,6 +50,7 @@ mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin-dataframe = { id = "org.jetbrains.kotlin.plugin.dataframe", version.ref = "kotlin" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } kotlin-jupyter-api = { id = "org.jetbrains.kotlin.jupyter.api", version.ref = "jupyterApi" } diff --git a/kandy-echarts/src/main/kotlin/org/jetbrains/kotlinx/kandy/echarts/translator/serializers/MeasurementSerializer.kt b/kandy-echarts/src/main/kotlin/org/jetbrains/kotlinx/kandy/echarts/translator/serializers/MeasurementSerializer.kt index 62627bb8e..43863acf9 100644 --- a/kandy-echarts/src/main/kotlin/org/jetbrains/kotlinx/kandy/echarts/translator/serializers/MeasurementSerializer.kt +++ b/kandy-echarts/src/main/kotlin/org/jetbrains/kotlinx/kandy/echarts/translator/serializers/MeasurementSerializer.kt @@ -30,12 +30,12 @@ internal object MeasurementSerializer : KSerializer { is Measurement.Pair<*> -> encoder.encodeSerializableValue( Measurement.Pair.serializer(SizeUnit.serializer()), - value as Measurement.Pair + value ) is Measurement.Rectangle<*> -> encoder.encodeSerializableValue( Measurement.Rectangle.serializer(SizeUnit.serializer()), - value as Measurement.Rectangle + value ) } } diff --git a/kandy-lets-plot/build.gradle.kts b/kandy-lets-plot/build.gradle.kts index 539a5e934..37c7d478a 100644 --- a/kandy-lets-plot/build.gradle.kts +++ b/kandy-lets-plot/build.gradle.kts @@ -4,6 +4,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { with(libs.plugins) { alias(kotlin.jvm) + alias(kotlin.dataframe) alias(kotlin.jupyter.api) alias(korro) } @@ -92,6 +93,9 @@ korro { funSuffix("_collections") { replaceText("NAME", "Collections") } + funSuffix("_dataframeCompilerPlugin") { + replaceText("NAME", "DataFrame (With compiler plugin)") + } beforeGroup.set("\n") afterGroup.set("") } diff --git a/kandy-lets-plot/src/main/kotlin/org/jetbrains/kotlinx/kandy/letsplot/translator/scaleWrap.kt b/kandy-lets-plot/src/main/kotlin/org/jetbrains/kotlinx/kandy/letsplot/translator/scaleWrap.kt index 550900b3f..fe01f51a0 100644 --- a/kandy-lets-plot/src/main/kotlin/org/jetbrains/kotlinx/kandy/letsplot/translator/scaleWrap.kt +++ b/kandy-lets-plot/src/main/kotlin/org/jetbrains/kotlinx/kandy/letsplot/translator/scaleWrap.kt @@ -302,7 +302,7 @@ internal fun Scale.wrap( when (aes) { SIZE -> if (rangeValues != null) { scaleSizeManual( - values = rangeValues!!.map { it as Number }, + values = rangeValues.map { it as Number }, limits = domainCategories?.wrap(), name = name, breaks = breaks?.wrap(), @@ -339,7 +339,7 @@ internal fun Scale.wrap( } else { scaleColorManual( limits = domainCategories?.wrap(), - values = rangeValues!!.map { (it as Color).wrap() }, + values = rangeValues.map { (it as Color).wrap() }, name = name, breaks = breaks?.wrap(), labels = labels, @@ -364,7 +364,7 @@ internal fun Scale.wrap( } else { scaleFillManual( limits = domainCategories?.wrap(), - values = rangeValues!!.map { (it as Color).wrap() }, + values = rangeValues.map { (it as Color).wrap() }, name = name, breaks = breaks?.wrap(), labels = labels, @@ -378,7 +378,7 @@ internal fun Scale.wrap( ALPHA -> if (rangeValues != null) { scaleAlphaManual( limits = domainCategories?.wrap(), - values = rangeValues!!.map { it as Double }, + values = rangeValues.map { it as Double }, name = name, breaks = breaks?.wrap(), labels = labels, @@ -402,7 +402,7 @@ internal fun Scale.wrap( LINE_TYPE -> if (rangeValues != null) { scaleLinetypeManual( limits = domainCategories?.wrap(), - values = rangeValues!!.map { (it as LineType).codeNumber }, + values = rangeValues.map { (it as LineType).codeNumber }, name = name, breaks = breaks?.wrap(), labels = labels, @@ -436,7 +436,7 @@ internal fun Scale.wrap( } else { scaleShapeManual( limits = domainCategories?.wrap(), - values = rangeValues!!.map { (it as Symbol).shape }, + values = rangeValues.map { (it as Symbol).shape }, name = name, breaks = breaks?.wrap(), @@ -788,10 +788,8 @@ internal fun Scale.wrap( else -> error("Unexpected aes: $aes") } - else -> error("Unexpected scale: ${this::class}") } - else -> error("Unexpected scale: ${this::class}") } } diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/dsl/dataset.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/dsl/dataset.kt index 3f4e0fec7..2c00d08a9 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/dsl/dataset.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/dsl/dataset.kt @@ -1,9 +1,10 @@ package org.jetbrains.kotlinx.kandy.letsplot.dsl +import org.jetbrains.kotlinx.dataframe.AnyFrame import org.jetbrains.kotlinx.dataframe.api.column import org.jetbrains.kotlinx.dataframe.api.dataFrameOf -internal val dataset = dataFrameOf( +internal val dataset: AnyFrame = dataFrameOf( "time" to listOf(1, 2), "type" to listOf("a", "b") ) diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/boxplot.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/boxplot.kt index 690fc851c..3c77e7158 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/boxplot.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/boxplot.kt @@ -2,7 +2,9 @@ package org.jetbrains.kotlinx.kandy.letsplot.samples.guides import org.apache.commons.math3.distribution.NormalDistribution import org.apache.commons.math3.distribution.UniformRealDistribution +import org.jetbrains.kotlinx.dataframe.AnyFrame import org.jetbrains.kotlinx.dataframe.DataFrame +import org.jetbrains.kotlinx.dataframe.api.GroupBy import org.jetbrains.kotlinx.dataframe.api.column import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.groupBy @@ -36,7 +38,7 @@ class Boxplot : SampleHelper("stat", "guides") { private val rateA = NormalDistribution(37.8, 4.3).sample(5000).toList() private val rateB = UniformRealDistribution(20.0, 50.0).sample(1000).toList() private val rateC = (rateA + rateB).filter { it >= 36.0 } - val df = dataFrameOf( + val df: AnyFrame = dataFrameOf( "rate" to rateA + rateB + rateC, "cond" to List(rateA.size) { "A" } + List(rateB.size) { "B" } + List(rateC.size) { "C" } ) @@ -310,8 +312,8 @@ class Boxplot : SampleHelper("stat", "guides") { private val `class` = column("class") private val hwy = column("hwy") private val drv = column("drv") - private val mpgShortDF = mpgDF.select { `class` and hwy and drv } - private val groupedDF = mpgShortDF.groupBy { drv } + private val mpgShortDF: AnyFrame = mpgDF.select { `class` and hwy and drv } + private val groupedDF: GroupBy<*, *> = mpgShortDF.groupBy { drv } @Test diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/countPlot.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/countPlot.kt index 521837bbf..c02b2e4d8 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/countPlot.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/countPlot.kt @@ -35,7 +35,7 @@ class CountPlot : SampleHelper("stat", "guides") { private val `class` = column("class") private val drv = column("drv") private val hwy = column("hwy") - private val df = mpgDF.select { `class` and drv and hwy } + private val df: DataFrame<*> = mpgDF.select { `class` and drv and hwy } @Test fun guideCountReadAutoDf() { @@ -222,7 +222,7 @@ class CountPlot : SampleHelper("stat", "guides") { } // Grouped data - private val groupedDF = df.groupBy { drv } + private val groupedDF: org.jetbrains.kotlinx.dataframe.api.GroupBy<*, *> = df.groupBy { drv } @Test @Suppress("UNUSED_EXPRESSION") diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/exportToFile.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/exportToFile.kt index 5a6b3f295..9105f5a72 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/exportToFile.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/exportToFile.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlinx.kandy.letsplot.samples.guides +import org.jetbrains.kotlinx.dataframe.AnyFrame import org.jetbrains.kotlinx.dataframe.api.column import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.kandy.dsl.plot @@ -13,7 +14,7 @@ class ExportToFile : SampleHelper("other", "guides") { private val rand = java.util.Random(42) private val n = 500 - private val dataset = dataFrameOf( + private val dataset: AnyFrame = dataFrameOf( "rating" to List(n / 2) { rand.nextGaussian() } + List(n / 2) { rand.nextGaussian() * 1.5 + 1.5 }, "cond" to List(n / 2) { "A" } + List(n / 2) { "B" } ) From ac6ee6048f8d1df68561b0370e99eeebc03acbf5 Mon Sep 17 00:00:00 2001 From: Nikita Klimenko Date: Wed, 19 Nov 2025 16:04:33 +0200 Subject: [PATCH 2/3] Add category of examples with dataframe compiler plugin --- docs/topics/Overview.md | 40 +++ docs/topics/samples/area/Area-Settings.md | 28 +++ .../samples/area/Area-with-Mark-Line.md | 48 ++++ .../samples/area/Area-with-Reversed-Axis.md | 23 ++ .../samples/area/Fixed-Area-Coordinate.md | 37 +++ docs/topics/samples/area/Several-Areas.md | 33 +++ docs/topics/samples/area/Simple-Area.md | 17 ++ docs/topics/samples/bars/Bar-Gradient.md | 24 ++ docs/topics/samples/bars/Bar-Settings.md | 31 +++ .../samples/bars/Bar-with-Reversed-Axis.md | 20 ++ docs/topics/samples/bars/Grouped-Bars.md | 27 ++ docs/topics/samples/bars/Horizontal-Bars.md | 25 ++ docs/topics/samples/bars/Simple-Bars.md | 18 ++ docs/topics/samples/bars/Stacked-Bars.md | 28 +++ .../candlestick/Candlestick-Settings-DSL.md | 30 +++ .../Candlestick-Settings-Stat-API.md | 32 +++ .../samples/candlestick/Candlestick-Simple.md | 17 ++ .../samples/countPlot/Count-Plot-Grouped.md | 38 +++ .../countPlot/Count-Plot-Horizontal.md | 39 +++ .../samples/countPlot/Count-Plot-Settings.md | 26 ++ .../samples/countPlot/Count-Plot-Simple.md | 23 ++ .../densityPlot/Density-Plot-Grouped.md | 49 ++++ .../densityPlot/Density-Plot-Settings.md | 36 +++ .../densityPlot/Density-Plot-Simple.md | 18 ++ .../samples/errorBars/ErrorBars-Settings.md | 24 ++ .../samples/errorBars/ErrorBars-with-Line.md | 26 ++ .../samples/errorBars/Fixed-ErrorBars.md | 20 ++ .../samples/errorBars/Grouped-ErrorBars.md | 21 ++ .../samples/errorBars/Simple-ErrorBars.md | 19 ++ docs/topics/samples/heatmap/Heatmap-Simple.md | 44 ++++ .../samples/histogram/Histogram-Grouped.md | 19 ++ .../samples/histogram/Histogram-Settings.md | 34 +++ .../samples/histogram/Histogram-Simple.md | 14 ++ .../samples/histogram/Histogram-With-Line.md | 28 +++ .../samples/line/Fixed-Line-Coordinate.md | 31 +++ docs/topics/samples/line/Line-Gradient.md | 29 +++ docs/topics/samples/line/Line-Settings.md | 31 +++ docs/topics/samples/line/Line-with-Points.md | 24 ++ .../samples/line/Line-with-Reversed-Axis.md | 23 ++ docs/topics/samples/line/Marked-Line.md | 45 ++++ docs/topics/samples/line/Several-Lines.md | 24 ++ docs/topics/samples/line/Simple-Line.md | 17 ++ docs/topics/samples/pie/Nightingale-Chart.md | 22 ++ docs/topics/samples/pie/Pie-Base.md | 17 ++ docs/topics/samples/pie/Pie-Settings.md | 30 +++ docs/topics/samples/pie/Pie-With-Count.md | 26 ++ docs/topics/samples/pie/Pie-With-Explode.md | 21 ++ .../topics/samples/pie/Pie-With-Void-Style.md | 18 ++ .../samples/points/Basic-Points-Plot.md | 27 ++ docs/topics/samples/points/Jittered-Points.md | 23 ++ docs/topics/samples/points/Points-Settings.md | 30 +++ .../samples/points/Points-with-ABLine.md | 32 +++ .../points/Points-with-Color-by-Category.md | 38 +++ docs/topics/samples/ribbon/Ribbon-Settings.md | 30 +++ docs/topics/samples/ribbon/Simple-Ribbon.md | 19 ++ .../samples/tiles/Tiles-Color-Categories.md | 34 +++ docs/topics/samples/tiles/Tiles-Gradient.md | 38 +++ docs/topics/samples/tiles/Tiles-Settings.md | 31 +++ .../kotlinx/kandy/letsplot/samples/area.kt | 192 ++++++++++++++ .../kotlinx/kandy/letsplot/samples/bars.kt | 180 ++++++++++++++ .../kotlinx/kandy/letsplot/samples/boxplot.kt | 91 +++++++ .../kandy/letsplot/samples/candlestick.kt | 82 ++++++ .../kandy/letsplot/samples/countPlot.kt | 132 ++++++++++ .../kandy/letsplot/samples/densityPlot.kt | 106 ++++++++ .../kandy/letsplot/samples/errorBars.kt | 113 +++++++++ .../letsplot/samples/guides/densityPlot.kt | 8 +- .../kotlinx/kandy/letsplot/samples/heatmap.kt | 45 ++++ .../kandy/letsplot/samples/histogram.kt | 99 ++++++++ .../kotlinx/kandy/letsplot/samples/lines.kt | 234 +++++++++++++++++- .../kotlinx/kandy/letsplot/samples/pie.kt | 140 +++++++++++ .../kotlinx/kandy/letsplot/samples/points.kt | 154 ++++++++++++ .../kandy/letsplot/samples/quickstart.kt | 41 +++ .../kotlinx/kandy/letsplot/samples/ribbon.kt | 51 ++++ .../kotlinx/kandy/letsplot/samples/tiles.kt | 104 ++++++++ .../kandy/letsplot/samples/SampleHelper.kt | 4 +- 75 files changed, 3387 insertions(+), 5 deletions(-) diff --git a/docs/topics/Overview.md b/docs/topics/Overview.md index b24eaa766..1fa14229c 100644 --- a/docs/topics/Overview.md +++ b/docs/topics/Overview.md @@ -270,6 +270,46 @@ plot(weatherData) { // Begin plotting } ``` + + + +```kotlin +val weatherData = dataFrameOf( + "time" to listOf(0, 1, 2, 4, 5, 7, 8, 9), + "temperature" to listOf(12.0, 14.2, 15.1, 15.9, 17.9, 15.6, 14.2, 24.3), + "humidity" to listOf(0.5, 0.32, 0.11, 0.89, 0.68, 0.57, 0.56, 0.5) +) + +weatherData.plot { // Begin plotting + x(time) // Set x-axis with time data + y(temperature) { // Set y-axis with temperature data + // Define scale for temperature (y-axis) + scale = continuous(0.0..25.5) + } + + bars { // Add a bar layer + fillColor(humidity) { // Customizing bar colors based on humidity + // Setting the color range + scale = continuous(range = Color.YELLOW..Color.RED) + } + borderLine.width = 0.0 // Define border line width + } + + line { + width = 3.0 // Set line width + color = Color.hex("#6e5596") // Define line color + type = LineType.DOTDASH // Specify the line type + } + + layout { // Set plot layout + title = "Simple plot with kandy-lets-plot" // Add title + // Add caption + caption = "See `examples` section for more\n complicated and interesting examples!" + size = 700 to 450 // Plot dimension settings + } +} +``` + diff --git a/docs/topics/samples/area/Area-Settings.md b/docs/topics/samples/area/Area-Settings.md index 56ec518f2..4794148bc 100644 --- a/docs/topics/samples/area/Area-Settings.md +++ b/docs/topics/samples/area/Area-Settings.md @@ -71,6 +71,34 @@ plot { } ``` + + + +```kotlin +val loadServer = dataFrameOf( + "time" to columnOf("00:00", "03:00", "06:00", "09:00", "12:00", "15:00", "18:00", "21:00"), + "load" to columnOf(10, 5, 15, 50, 75, 60, 80, 40) +) + +loadServer.plot { + layout.title = "Daily Server Load Dynamics" + area { + x(time) { axis.name = "Time" } + y(load) { + axis.name = "Load (%)" + scale = continuous(0..100) + } + borderLine { + color = Color.ORANGE + type = LineType.DASHED + width = 2.5 + } + fillColor = Color.RED + alpha = 0.7 + } +} +``` + diff --git a/docs/topics/samples/area/Area-with-Mark-Line.md b/docs/topics/samples/area/Area-with-Mark-Line.md index 397e53b77..28a35ce7f 100644 --- a/docs/topics/samples/area/Area-with-Mark-Line.md +++ b/docs/topics/samples/area/Area-with-Mark-Line.md @@ -113,6 +113,54 @@ df.plot { } ``` + + + +```kotlin +val months = listOf( + "January", "February", + "March", "April", "May", + "June", "July", "August", + "September", "October", "November", + "December" +) +val tempBerlin = + listOf(-0.5, 0.0, 4.8, 9.0, 14.3, 17.5, 19.2, 18.9, 14.5, 9.7, 4.7, 1.0) +val tempMadrid = + listOf(6.3, 7.9, 11.2, 12.9, 16.7, 21.1, 24.7, 24.2, 20.3, 15.4, 9.9, 6.6) + +val df = dataFrameOf( + "month" to months + months, + "temperature" to tempBerlin + tempMadrid, + "city" to List(12) { "Berlin" } + List(12) { "Madrid" } +) + +df.plot { + area { + x(month) + y(temperature) + fillColor(city) { + scale = categorical("Berlin" to Color.hex("#07C3F2"), "Madrid" to Color.hex("#FDB60D")) + } + alpha = 0.5 + borderLine.width = 1.5 + } + hLine { + yIntercept.constant(tempBerlin.average()) + color = Color.BLACK + width = 2.0 + type = LineType.DASHED + } + hLine { + yIntercept.constant(tempMadrid.average()) + color = Color.RED + width = 2.0 + type = LineType.DASHED + } + layout.size = 1000 to 450 +} +``` + diff --git a/docs/topics/samples/area/Area-with-Reversed-Axis.md b/docs/topics/samples/area/Area-with-Reversed-Axis.md index 676ec4705..eb573e359 100644 --- a/docs/topics/samples/area/Area-with-Reversed-Axis.md +++ b/docs/topics/samples/area/Area-with-Reversed-Axis.md @@ -61,6 +61,29 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "Day of the Week" to columnOf("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"), + "Star Rating (Reversed)" to columnOf(4, 2, 1, 2, 3, 4, 1) +) + +df.plot { + layout.title = "Weekly Star Ratings" + layout.subtitle = "A reversed perspective" + area { + x(`Day of the Week`) + y(`Star Rating (Reversed)`) { + scale = continuous(0..5, transform = Transformation.REVERSE) + } + fillColor = Color.hex("#FCF84A") + alpha = 0.75 + } +} +``` + diff --git a/docs/topics/samples/area/Fixed-Area-Coordinate.md b/docs/topics/samples/area/Fixed-Area-Coordinate.md index 2cce32d8e..7a0e5545d 100644 --- a/docs/topics/samples/area/Fixed-Area-Coordinate.md +++ b/docs/topics/samples/area/Fixed-Area-Coordinate.md @@ -92,6 +92,43 @@ plot(reservoirDf) { } ``` + + + +```kotlin +val reservoirDf = dataFrameOf( + "month" to columnOf( + "January", "February", + "March", "April", "May", + "June", "July", "August", + "September", "October", "November", + "December" + ), + "waterLvl" to columnOf(4.5, 4.7, 5.0, 5.5, 6.0, 6.5, 6.7, 6.2, 5.8, 5.3, 4.8, 4.6) +) + +plot(reservoirDf) { + layout { + title = "Water Level" + subtitle = "Annual Water Level Fluctuations in Reservoir" + yAxisLabel = "Month" + xAxisLabel = "Water Level (meters)" + } + + x(month) + y { axis.limits = 3.0..8.0 } + line { + y(waterLvl) + } + area { + y.constant(5.0) + borderLine.type = LineType.DOTTED + alpha = 0.5 + fillColor = Color.RED + } +} +``` + diff --git a/docs/topics/samples/area/Several-Areas.md b/docs/topics/samples/area/Several-Areas.md index eb12aa702..1e17f80c7 100644 --- a/docs/topics/samples/area/Several-Areas.md +++ b/docs/topics/samples/area/Several-Areas.md @@ -92,6 +92,39 @@ plot(dataset) { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "year" to columnOf("2016", "2017", "2018", "2019", "2020", "2021"), + "Apple" to columnOf(700, 800, 750, 900, 850, 950), + "Google" to columnOf(1000, 950, 1200, 1150, 1250, 1300), + "Microsoft" to columnOf(600, 700, 650, 700, 750, 800), + "Meta" to columnOf(1100, 1200, 1150, 1300, 1250, 1350), + "Amazon" to columnOf(300, 400, 350, 450, 500, 600) +).gather { Apple and Google and Microsoft and Meta and Amazon }.into("company", "users") + +dataset.groupBy { company }.plot { + layout.title = "User Growth Dynamics" + area { + x(year) + y(users) + fillColor(company) { + scale = categorical( + "Apple" to Color.hex("#FF45ED"), + "Google" to Color.hex("#3DEA62"), + "Microsoft" to Color.BLACK, + "Meta" to Color.hex("#FDB60D"), + "Amazon" to Color.hex("#087CFA") + ) + } + borderLine.color(company) + alpha = 0.3 + } +} +``` + diff --git a/docs/topics/samples/area/Simple-Area.md b/docs/topics/samples/area/Simple-Area.md index f5cd4bb8b..ed4ed744d 100644 --- a/docs/topics/samples/area/Simple-Area.md +++ b/docs/topics/samples/area/Simple-Area.md @@ -49,6 +49,23 @@ plot { } ``` + + + +```kotlin +val dataframe = dataFrameOf( + "years" to columnOf("2017", "2018", "2019", "2020", "2021", "2022", "2023"), + "cost" to columnOf(56.1, 22.7, 34.7, 82.1, 53.7, 68.5, 39.9) +) + +dataframe.plot { + area { + x(years) + y(cost) + } +} +``` + diff --git a/docs/topics/samples/bars/Bar-Gradient.md b/docs/topics/samples/bars/Bar-Gradient.md index 81a28f394..d070b59f1 100644 --- a/docs/topics/samples/bars/Bar-Gradient.md +++ b/docs/topics/samples/bars/Bar-Gradient.md @@ -66,6 +66,30 @@ dataset.plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "cities" to columnOf("London", "Paris", "Berlin", "Madrid", "Rome", "Amsterdam", "Prague"), + "airPollution" to columnOf(70, 65, 50, 60, 55, 45, 53), + "numberOfCars" to columnOf(3000, 2800, 1800, 2500, 2100, 1300, 2000) +) + +dataset.plot { + layout.title = "Air Pollution and Vehicle Count Analysis" + bars { + x(cities) { axis.name = "City" } + y(numberOfCars) { axis.name = "Number of cars (thousands)" } + fillColor(airPollution) { + legend.name = "Air Pollution\n Level (AQI)" + scale = continuous(Color.GREEN..Color.RED) + } + alpha = 0.8 + } +} +``` + diff --git a/docs/topics/samples/bars/Bar-Settings.md b/docs/topics/samples/bars/Bar-Settings.md index 48d396740..6756a1825 100644 --- a/docs/topics/samples/bars/Bar-Settings.md +++ b/docs/topics/samples/bars/Bar-Settings.md @@ -76,6 +76,37 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "candy" to columnOf( + "Honey Stars", "Fairy Tale Caramels", " ChocoDream", "Fruity Clouds", + "Minty Spheres", "Sour Strips", "Vanilla Bars" + ), + "sugar" to columnOf(65, 58, 53, 35, 40, 45, 50) +) + +dataset.plot { + layout { + title = "Sugar content" + xAxisLabel = "Candy Name" + yAxisLabel = "Sugar Content (g per 100g)" + } + bars { + x(candy) + y(sugar) { scale = continuous(0..100) } + fillColor = Color.ORANGE + alpha = 0.85 + borderLine { + color = Color.GREY + width = 1.3 + } + } +} +``` + diff --git a/docs/topics/samples/bars/Bar-with-Reversed-Axis.md b/docs/topics/samples/bars/Bar-with-Reversed-Axis.md index 70fd64856..7e68916de 100644 --- a/docs/topics/samples/bars/Bar-with-Reversed-Axis.md +++ b/docs/topics/samples/bars/Bar-with-Reversed-Axis.md @@ -59,6 +59,26 @@ dataset.plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "task" to columnOf("a", "b", "c", "d", "e"), + "time" to columnOf(30, 25, 20, 35, 28) +) + +dataset.plot { + bars { + x(task) + y(time) { + scale = continuous(transform = Transformation.REVERSE) + } + fillColor = Color.hex("#07C3F2") + } +} +``` + diff --git a/docs/topics/samples/bars/Grouped-Bars.md b/docs/topics/samples/bars/Grouped-Bars.md index 26abe6342..2b3bcbf59 100644 --- a/docs/topics/samples/bars/Grouped-Bars.md +++ b/docs/topics/samples/bars/Grouped-Bars.md @@ -78,6 +78,33 @@ dataset.plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "day" to columnOf("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"), + "coffee" to columnOf(0.81, 0.78, 0.72, 0.65, 0.73, 0.49, 0.38), + "tea" to columnOf(0.12, 0.16, 0.21, 0.26, 0.24, 0.22, 0.30), + "soda" to columnOf(0.07, 0.06, 0.07, 0.09, 0.03, 0.29, 0.32), +).gather { coffee and tea and soda }.into("drink", "amount") + +dataset.groupBy { drink }.plot { + layout.title = "Weekly Beverage Consumption Trends" + bars { + x(day) + y(amount) + fillColor(drink) { + scale = categorical( + "coffee" to Color.hex("#6F4E37"), + "tea" to Color.hex("#C2D4AB"), + "soda" to Color.hex("#B5651D") + ) + } + } +} +``` + diff --git a/docs/topics/samples/bars/Horizontal-Bars.md b/docs/topics/samples/bars/Horizontal-Bars.md index cca580fe3..8dbb7f28a 100644 --- a/docs/topics/samples/bars/Horizontal-Bars.md +++ b/docs/topics/samples/bars/Horizontal-Bars.md @@ -68,6 +68,31 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "actors" to columnOf( + "John Doe", "Emma Stone", "Ryan Gosling", "Natalie Portman", + "Brad Pitt", "Marilyn Monroe", "Leonardo DiCaprio" + ), + "screenTime" to columnOf(90, 75, 60, 85, 50, 40, 95) +) + +dataset.plot { + layout.title = "Screen Time of Hollywood Actors" + barsH { + y(actors) { axis.name = "Actors" } + x(screenTime) { axis.name = "minutes" } + alpha = 0.75 + fillColor(actors) { + scale = categoricalColorHue() + } + } +} +``` + diff --git a/docs/topics/samples/bars/Simple-Bars.md b/docs/topics/samples/bars/Simple-Bars.md index 14bc5860b..54479de13 100644 --- a/docs/topics/samples/bars/Simple-Bars.md +++ b/docs/topics/samples/bars/Simple-Bars.md @@ -53,6 +53,24 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "city" to columnOf("London", "Paris", "Berlin", "Madrid", "Rome"), + "perc" to columnOf(45, 50, 60, 40, 30) +) + +dataset.plot { + layout.title = "Public Transport Usage in European Cities" + bars { + x(city) { axis.name = "City" } + y(perc) { axis.name = "Public Transport Usage (%)" } + } +} +``` + diff --git a/docs/topics/samples/bars/Stacked-Bars.md b/docs/topics/samples/bars/Stacked-Bars.md index fc823d7e1..5b33d7beb 100644 --- a/docs/topics/samples/bars/Stacked-Bars.md +++ b/docs/topics/samples/bars/Stacked-Bars.md @@ -79,6 +79,34 @@ dataset.plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "day" to columnOf("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"), + "coffee" to columnOf(0.81, 0.78, 0.72, 0.65, 0.73, 0.49, 0.38), + "tea" to columnOf(0.12, 0.16, 0.21, 0.26, 0.24, 0.22, 0.30), + "soda" to columnOf(0.07, 0.06, 0.07, 0.09, 0.03, 0.29, 0.32), +).gather { coffee and tea and soda }.into("drink", "amount") + +dataset.groupBy { drink }.plot { + layout.title = "Weekly Beverage Consumption Trends" + bars { + x(day) + y(amount) + fillColor(drink) { + scale = categorical( + "coffee" to Color.hex("#6F4E37"), + "tea" to Color.hex("#C2D4AB"), + "soda" to Color.hex("#B5651D") + ) + } + position = Position.stack() + } +} +``` + diff --git a/docs/topics/samples/candlestick/Candlestick-Settings-DSL.md b/docs/topics/samples/candlestick/Candlestick-Settings-DSL.md index 84c715250..fdbc71381 100644 --- a/docs/topics/samples/candlestick/Candlestick-Settings-DSL.md +++ b/docs/topics/samples/candlestick/Candlestick-Settings-DSL.md @@ -78,6 +78,36 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "date" to (1..10).map { LocalDate(2022, 1, it) }.toColumn(), + "open" to columnOf(10.0, 15.0, 12.0, 18.0, 14.0, 16.0, 20.0, 22.0, 19.0, 25.0), + "high" to columnOf(18.0, 17.0, 20.0, 22.0, 18.0, 22.0, 25.0, 24.0, 27.0, 28.0), + "low" to columnOf(8.0, 10.0, 9.0, 11.0, 12.0, 15.0, 18.0, 17.0, 18.0, 22.0), + "close" to columnOf(15.0, 12.0, 18.0, 14.0, 16.0, 20.0, 22.0, 19.0, 25.0, 23.0) +) + +df.plot { + candlestick(date, open, high, low, close) { + increase { + fillColor = Color.hex("#00fefe") + alpha = 0.9 + } + decrease { + fillColor = Color.hex("#ea2211") + alpha = 0.5 + } + borderLine.color = Color.GREY + width = 0.7 + } + y.axis.name = "Price, €" + x.axis.name = "Date" +} +``` + diff --git a/docs/topics/samples/candlestick/Candlestick-Settings-Stat-API.md b/docs/topics/samples/candlestick/Candlestick-Settings-Stat-API.md index 3da00ffbf..52c7318d3 100644 --- a/docs/topics/samples/candlestick/Candlestick-Settings-Stat-API.md +++ b/docs/topics/samples/candlestick/Candlestick-Settings-Stat-API.md @@ -82,6 +82,38 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "year" to columnOf("2018", "2019", "2020", "2021", "2022", "2023"), + "open" to columnOf(10.0, 15.0, 12.0, 18.0, 14.0, 16.0), + "high" to columnOf(18.0, 17.0, 20.0, 22.0, 18.0, 22.0), + "low" to columnOf(8.0, 10.0, 9.0, 11.0, 12.0, 15.0), + "close" to columnOf(15.0, 12.0, 18.0, 14.0, 16.0, 20.0) +) + +df.plot { + candlestick(year, open, high, low, close) { + alpha(Stat.isIncreased) { + scale = categorical(true to 1.0, false to 0.05) + legend { + name = "" + breaksLabeled(true to "increase", false to "decrease") + } + } + fillColor = Color.GREY + borderLine.color = Color.GREY + } + x.axis { + name = "Year" + breaks(format = "d") + } + layout.size = 750 to 400 +} +``` + diff --git a/docs/topics/samples/candlestick/Candlestick-Simple.md b/docs/topics/samples/candlestick/Candlestick-Simple.md index d7dda66fa..c9332233d 100644 --- a/docs/topics/samples/candlestick/Candlestick-Simple.md +++ b/docs/topics/samples/candlestick/Candlestick-Simple.md @@ -51,6 +51,23 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "month" to columnOf("Jan", "Feb", "Mar", "Apr", "May"), + "open" to columnOf(14.2, 6.7, 8.8, 11.2, 4.0), + "high" to columnOf(15.5, 9.6, 10.7, 11.7, 9.9), + "low" to columnOf(7.5, 6.1, 8.5, 5.4, 4.0), + "close" to columnOf(8.0, 8.6, 10.7, 6.5, 9.8) +) + +df.plot { + candlestick(month, open, high, low, close) +} +``` + diff --git a/docs/topics/samples/countPlot/Count-Plot-Grouped.md b/docs/topics/samples/countPlot/Count-Plot-Grouped.md index 17dfae68d..a17b841aa 100644 --- a/docs/topics/samples/countPlot/Count-Plot-Grouped.md +++ b/docs/topics/samples/countPlot/Count-Plot-Grouped.md @@ -97,6 +97,44 @@ dataset.plot { } ``` + + + +```kotlin +val categories = listOf( + "easy", "medium", "hard", "medium", "easy", + "hard", "hard", "easy", "easy", "hard", "medium", + "hard", "easy", "easy", "easy", "medium", + "hard", "hard", "hard", "medium", "easy", + "hard", "medium", "hard", "hard", "hard", + "medium", "medium", "easy", "medium", "hard", + "hard", "easy", "hard", "medium", "medium", + "hard", "hard", "hard", "easy", "hard", + "hard", "easy", "medium", "medium", "hard", + "medium", "medium", "easy", "hard", "medium", + "hard", "medium", "easy", "easy", +) + +val years = listOf( + "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", + "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", + "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", + "2022", "2022", "2023", "2023", "2023", "2023", "2023", "2023", + "2023", "2023", "2023", "2023", "2023", "2023", "2023", "2023", + "2023", "2023", "2023", "2023", "2023", "2023", "2023", "2023", + "2023", "2023", "2023", "2023", "2023", "2023", "2023" +) + +val df = dataFrameOf( + "category" to categories, + "year" to years +) + +df.groupBy { category }.plot { + countPlot(year) +} +``` + diff --git a/docs/topics/samples/countPlot/Count-Plot-Horizontal.md b/docs/topics/samples/countPlot/Count-Plot-Horizontal.md index 3445e0224..ef756d477 100644 --- a/docs/topics/samples/countPlot/Count-Plot-Horizontal.md +++ b/docs/topics/samples/countPlot/Count-Plot-Horizontal.md @@ -97,6 +97,45 @@ plot { } ``` + + + +```kotlin +val transportsDF = dataFrameOf( + "transports" to listOf( + "metro", "bicycle", "car", "bus", "bus", "bicycle", "bicycle", + "bus", "bus", "bus", "bus", "bus", "bus", "bus", "bicycle", "bicycle", + "bus", "bicycle", "bus", "car", "metro", "bus", "metro", "metro", + "bus", "bus", "bus", "metro", "bicycle", "metro", "bus", "metro", + "bicycle", "metro", "bicycle", "bicycle", "bus", "bicycle", "metro", + "bicycle", "metro", "bicycle", "bus", "bicycle", "bus", "bicycle", + "bicycle", "bicycle", "bus", "bicycle", "metro", "bus", "bicycle", + "bus", "bus", "bus", "bus", "bus", "bus", "metro", "metro", "bicycle", + "metro", "bus", "bus", "metro", "metro", "bicycle", "bus", "metro", + "metro", "bicycle", "bus", "bus", "bicycle", "car", "bus", "bicycle", + "bus", "metro", "bus", "metro", "bicycle", "metro", "bicycle", "bicycle" + ) +) + +transportsDF.plot { + statCount(transports) { + val transport = Stat.x named "transport" + barsH { + x(Stat.count) + y(transport) + fillColor(transport) { + scale = categorical( + "bus" to Color.hex("#FFD700"), + "car" to Color.hex("#FF6347"), + "bicycle" to Color.hex("#32CD32"), + "metro" to Color.hex("#4169E1") + ) + } + } + } +} +``` + diff --git a/docs/topics/samples/countPlot/Count-Plot-Settings.md b/docs/topics/samples/countPlot/Count-Plot-Settings.md index 1a5248167..04676ef2e 100644 --- a/docs/topics/samples/countPlot/Count-Plot-Settings.md +++ b/docs/topics/samples/countPlot/Count-Plot-Settings.md @@ -74,6 +74,32 @@ plot { } ``` + + + +```kotlin +val classesDF = dataFrameOf( + "classes" to columnOf( + "First", "Second", "Third", "Third", "Second", + "Third", "First", "Second", "Third", "First", + "Third", "Second", "Third", "First", "Second", + "Third", "First", "Third", "Second", "Third", + "First", "Second", "Third", "First", "Third", + "Second", "Third", "First", "Second", "Third", + "First", "Third", "Second", "Third", "First", + "Second", "Third", "First", "Second", "Third" + ) +) + +classesDF.plot { + countPlot(classes) { + alpha = 0.8 + fillColor(Stat.x) { legend.type = LegendType.None } + x.axis.name = "class" + } +} +``` + diff --git a/docs/topics/samples/countPlot/Count-Plot-Simple.md b/docs/topics/samples/countPlot/Count-Plot-Simple.md index b27760543..8c700834e 100644 --- a/docs/topics/samples/countPlot/Count-Plot-Simple.md +++ b/docs/topics/samples/countPlot/Count-Plot-Simple.md @@ -62,6 +62,29 @@ plot { } ``` + + + +```kotlin +val dataframe = dataFrameOf( + "categories" to columnOf( + "A", "B", "C", "C", "B", + "A", "C", "B", "A", "B", + "C", "A", "B", "A", "A", + "C", "A", "A", "B", "C", + "C", "A", "A", "C", "B", + "C", "C", "A", "A", "A", + "B", "C", "B", "A", "B", + "C", "A", "A", "B", "A", + "C", "A", "C", "A", "C" + ) +) + +dataframe.plot { + countPlot(categories) +} +``` + diff --git a/docs/topics/samples/densityPlot/Density-Plot-Grouped.md b/docs/topics/samples/densityPlot/Density-Plot-Grouped.md index 69abc388f..82e8abe00 100644 --- a/docs/topics/samples/densityPlot/Density-Plot-Grouped.md +++ b/docs/topics/samples/densityPlot/Density-Plot-Grouped.md @@ -113,6 +113,55 @@ df.groupBy("group").plot { } ``` + + + +```kotlin +val macaqueWeights = listOf( + 1.563, 2.173, 2.118, 2.722, 2.384, 1.789, 2.649, + 1.299, 1.566, 1.821, 2.151, 1.554, 1.464, 1.611, + 2.178, 2.652, 2.031, 2.265, 1.919, 1.283, 2.365, + 2.540, 2.779, 2.040, 2.138, 1.783, 1.442, 1.413, + 2.224, 2.345, 1.753, 2.284, 2.465, 1.430, 2.617, + 1.667, 2.462, 1.777, 2.104, 2.404, 1.276, 1.489, + 2.662, 1.853, 2.315, 1.589, 1.586, 2.569, 1.888, + 1.414, 1.623, 2.084, 2.484, 2.348, 1.496, 2.238, + 1.778, 2.173, 2.411, 2.540, 2.325, 1.324, 2.252, + 1.978, 2.075, 2.585, 2.414, 2.162, 1.584, 2.399, + 1.757, 2.109, 1.436, 2.628, 2.370, 1.679, 1.970, + 2.360, 2.005, 2.179, 2.177, 1.941, 2.282, 2.067, + 2.288, 1.481, 1.638, 2.164, 2.485, 1.797, 2.369, + 1.690, 2.143, 1.743, 2.357, 2.280, 1.824, 1.678, + 2.531, 1.958, 1.466, 1.877, 2.005 +) +val chimpanzeeWeights = listOf( + 4.530, 4.257, 4.381, 4.935, 3.392, 4.611, 2.499, 4.306, + 4.119, 3.622, 4.099, 4.832, 2.456, 3.411, 4.426, 2.940, + 4.529, 3.635, 2.991, 4.372, 2.319, 4.358, 1.882, 3.472, + 4.828, 4.005, 3.452, 3.854, 3.455, 2.996, 4.031, 4.382, + 2.947, 4.752, 2.466, 4.558, 2.548, 3.172, 3.010, 3.472, + 5.258, 2.746, 4.022, 3.013, 4.942, 3.206, 3.779, 4.367, + 3.853, 2.483, 3.957, 2.943, 4.791, 3.432, 3.530, 2.576, + 2.833, 4.650, 5.515, 4.413, 2.699, 3.310, 5.047, 3.047, + 4.095, 4.712, 2.600, 3.523, 3.106, 4.110, 2.894, 3.373, + 2.656, 3.684, 5.171, 4.049, 4.773, 3.456, 4.420, 2.090, + 3.155, 4.678, 3.240, +) + +val df = dataFrameOf( + "weight" to macaqueWeights + chimpanzeeWeights, + "group" to macaqueWeights.map { "macaque" } + chimpanzeeWeights.map { "chimpanzee" } +) + +df.groupBy { group }.plot { + densityPlot(weight) { + x(Stat.x.map { it.toFloat() }) + y(Stat.density.map { it.toFloat() }) + alpha = 0.5 + } +} +``` + diff --git a/docs/topics/samples/densityPlot/Density-Plot-Settings.md b/docs/topics/samples/densityPlot/Density-Plot-Settings.md index c32f411a9..49ae18f59 100644 --- a/docs/topics/samples/densityPlot/Density-Plot-Settings.md +++ b/docs/topics/samples/densityPlot/Density-Plot-Settings.md @@ -84,6 +84,42 @@ plot { } ``` + + + +```kotlin +val experimentalData = dataFrameOf( + "length" to listOf( + 5.92, 6.44, 5.87, 4.99, 5.23, + 5.67, 4.89, 5.34, 5.78, 5.12, + 5.56, 5.23, 5.78, 6.01, 5.56, + 5.67, 5.89, 5.45, 6.12, 5.78, + 6.34, 5.67, 6.45, 5.34, 5.89, + 6.01, 5.78, 5.23, 5.67, 6.12, + 6.23, 5.45, 5.56, 5.67, 5.78, + 5.56, 6.23, 5.78, 6.34, 6.12, + 5.89, 6.45, 5.78, 6.34, 5.67, + 6.56, 5.45, 5.78, 5.89, 6.12, + 4.67, 4.79, 5.14, 5.28, 5.22, + ) +) + +experimentalData.plot { + densityPlot(length, adjust = 0.8) { + x(Stat.x.map { it.toFloat() }) + y(Stat.density.map { it.toFloat() }) + alpha = 0.5 + fillColor = Color.RED + borderLine { + color = Color.GREEN + width = 0.5 + } + x.axis.name = "length" + } + layout.title = "Flight length experiment" +} +``` + diff --git a/docs/topics/samples/densityPlot/Density-Plot-Simple.md b/docs/topics/samples/densityPlot/Density-Plot-Simple.md index 62d41497c..fbbb466a6 100644 --- a/docs/topics/samples/densityPlot/Density-Plot-Simple.md +++ b/docs/topics/samples/densityPlot/Density-Plot-Simple.md @@ -46,6 +46,24 @@ plot { } ``` + + + +```kotlin +val random = java.util.Random(42) + +val dataframe = dataFrameOf( + "sample" to List(1000) { random.nextGaussian() } +) + +dataframe.plot { + densityPlot(sample) { + x(Stat.x.map { it.toFloat() }) + y(Stat.density.map { it.toFloat() }) + } +} +``` + diff --git a/docs/topics/samples/errorBars/ErrorBars-Settings.md b/docs/topics/samples/errorBars/ErrorBars-Settings.md index f25a20f4f..5ffe44aff 100644 --- a/docs/topics/samples/errorBars/ErrorBars-Settings.md +++ b/docs/topics/samples/errorBars/ErrorBars-Settings.md @@ -62,6 +62,30 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "costMin" to columnOf(62.7, 64.7, 72.1, 73.7, 68.5), + "costMax" to columnOf(68.9, 71.3, 78.9, 76.5, 72.1) +) + +dataset.plot { + errorBars { + x(years) + yMin(costMin) + yMax(costMax) + width = 1.1 + borderLine { + width = 1.5 + color = Color.RED + } + } +} +``` + diff --git a/docs/topics/samples/errorBars/ErrorBars-with-Line.md b/docs/topics/samples/errorBars/ErrorBars-with-Line.md index 032b7a4cf..504cc2c49 100644 --- a/docs/topics/samples/errorBars/ErrorBars-with-Line.md +++ b/docs/topics/samples/errorBars/ErrorBars-with-Line.md @@ -69,6 +69,32 @@ plot { } ``` + + + +```kotlin +val years = listOf("2018", "2019", "2020", "2021", "2022") +val costMin = listOf(62.7, 64.7, 72.1, 73.7, 68.5) +val costMax = listOf(68.9, 71.3, 78.9, 76.5, 72.1) +val mid = costMin.zip(costMax).map { (a, b) -> (a + b) / 2.0 } +val dataset = dataFrameOf( + years.toColumn("years"), + costMin.toColumn("min"), + costMax.toColumn("max"), + mid.toColumn("mid") +) +dataset.plot { + x(years) + y(mid) + line { color = Color.BLUE } + errorBars { + yMin("min") + yMax("max") + borderLine.type = LineType.LONGDASH + } +} +``` + diff --git a/docs/topics/samples/errorBars/Fixed-ErrorBars.md b/docs/topics/samples/errorBars/Fixed-ErrorBars.md index d24033e8e..55d3f8d6f 100644 --- a/docs/topics/samples/errorBars/Fixed-ErrorBars.md +++ b/docs/topics/samples/errorBars/Fixed-ErrorBars.md @@ -55,6 +55,26 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "max" to columnOf(68.9, 71.3, 78.9, 76.5, 72.1) +) + +plot(dataset) { + errorBars { + x(years) + yMin.constant(20.0) + yMax(max) + width = 0.5 + borderLine.width = 1.3 + } +} +``` + diff --git a/docs/topics/samples/errorBars/Grouped-ErrorBars.md b/docs/topics/samples/errorBars/Grouped-ErrorBars.md index be0f8358a..5101e60c1 100644 --- a/docs/topics/samples/errorBars/Grouped-ErrorBars.md +++ b/docs/topics/samples/errorBars/Grouped-ErrorBars.md @@ -65,6 +65,27 @@ dataset.plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "time" to (1..5).toList().let { (it + it).toColumn() }, + "min" to (listOf(2.0, 3.4, 3.5, 5.5, 2.5) + listOf(1.0, 2.0, 3.0, 4.0, 3.7)).toColumn(), + "max" to (listOf(3.0, 5.2, 5.0, 5.8, 3.4) + listOf(5.0, 4.0, 3.5, 5.0, 4.2)).toColumn(), + "category" to (List(5) { "a" } + List(5) { "b" }).toColumn() +) + +dataset.groupBy { category }.plot { + errorBars { + x(time) { axis.breaks((1..5).toList(), format = "d") } + yMin(min) + yMax(max) + borderLine.color(category) + } +} +``` + diff --git a/docs/topics/samples/errorBars/Simple-ErrorBars.md b/docs/topics/samples/errorBars/Simple-ErrorBars.md index 712ff1ee1..17aa80538 100644 --- a/docs/topics/samples/errorBars/Simple-ErrorBars.md +++ b/docs/topics/samples/errorBars/Simple-ErrorBars.md @@ -51,6 +51,25 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "costMin" to columnOf(62.7, 64.7, 72.1, 73.7, 68.5), + "costMax" to columnOf(68.9, 71.3, 78.9, 76.5, 72.1) +) + +df.plot { + errorBars { + x(years) + yMin(costMin) + yMax(costMax) + } +} +``` + diff --git a/docs/topics/samples/heatmap/Heatmap-Simple.md b/docs/topics/samples/heatmap/Heatmap-Simple.md index 42ded420a..dbc8df78b 100644 --- a/docs/topics/samples/heatmap/Heatmap-Simple.md +++ b/docs/topics/samples/heatmap/Heatmap-Simple.md @@ -104,6 +104,50 @@ plot { } ``` + + + +```kotlin +val dataframe = dataFrameOf( + "days" to columnOf( + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Sun", + "Sat", "Thu", "Fri", "Tue", "Wed", "Sun", "Mon", "Thu", + "Sun", "Sat", "Tue", "Mon", "Thu", "Wed", "Fri", "Sat", + "Tue", "Sun", "Fri", "Sat", "Thu", "Mon", "Wed", "Tue", + "Thu", "Mon", "Sun", "Fri", "Wed", "Sat", "Tue", "Thu", + "Sat", "Tue", "Sun", "Mon", "Wed", "Fri", "Thu", "Sat", + "Thu", "Fri", "Sun", "Tue", "Sat", "Wed", "Mon", "Thu", + "Wed", "Tue", "Sat", "Fri", "Sun", "Thu", "Mon", "Tue", + "Fri", "Thu", "Wed", "Sun", "Sat", "Mon", "Tue", "Thu", + "Tue", "Wed", "Sun", "Mon", "Thu", "Sat", "Fri", "Tue", + "Thu", "Sun", "Fri", "Sat", "Mon", "Wed", "Tue", "Thu", + "Sat", "Mon", "Tue", "Thu", "Fri", "Sun", "Wed", "Sat", + "Sun", "Fri", "Tue", "Thu", "Sat", "Mon", "Wed", "Sun", + "Mon", "Wed", "Sat", "Fri", "Thu", "Tue", "Sun", "Sat", + ), + "drinks" to columnOf( + "soda", "tea", "coffee", "tea", "soda", "tea", "coffee", "soda", + "coffee", "soda", "tea", "coffee", "soda", "tea", "coffee", "tea", + "coffee", "soda", "tea", "soda", "coffee", "tea", "soda", "coffee", + "soda", "tea", "coffee", "tea", "soda", "coffee", "tea", "soda", + "tea", "soda", "coffee", "tea", "soda", "coffee", "soda", "tea", + "coffee", "soda", "tea", "soda", "coffee", "tea", "soda", "coffee", + "soda", "coffee", "tea", "soda", "coffee", "soda", "tea", "coffee", + "soda", "coffee", "tea", "soda", "tea", "soda", "coffee", "tea", + "tea", "coffee", "soda", "tea", "coffee", "soda", "tea", "soda", + "tea", "soda", "coffee", "soda", "tea", "coffee", "soda", "coffee", + "tea", "coffee", "soda", "tea", "soda", "coffee", "soda", "tea", + "coffee", "soda", "tea", "coffee", "tea", "soda", "coffee", "soda", + "soda", "tea", "coffee", "soda", "tea", "coffee", "soda", "tea", + "coffee", "tea", "soda", "coffee", "tea", "soda", "coffee", "soda" + ) +) + +dataframe.plot { + heatmap(days, drinks) +} +``` + diff --git a/docs/topics/samples/histogram/Histogram-Grouped.md b/docs/topics/samples/histogram/Histogram-Grouped.md index 5ebc38a37..373f81c71 100644 --- a/docs/topics/samples/histogram/Histogram-Grouped.md +++ b/docs/topics/samples/histogram/Histogram-Grouped.md @@ -59,6 +59,25 @@ dataset.plot { } ``` + + + +```kotlin +val random = java.util.Random(42) + +val sampleA = List(1000) { random.nextGaussian() * 0.7 + 2.0 } +val sampleB = List(1000) { random.nextGaussian() * 1.4 + 3.5 } + +val df = dataFrameOf( + "sample" to sampleA + sampleB, + "group" to sampleA.map { "A" } + sampleB.map { "B" } +) + +df.groupBy { group }.plot { + histogram(sample) +} +``` + diff --git a/docs/topics/samples/histogram/Histogram-Settings.md b/docs/topics/samples/histogram/Histogram-Settings.md index 9a6e5dc5d..4cb868c08 100644 --- a/docs/topics/samples/histogram/Histogram-Settings.md +++ b/docs/topics/samples/histogram/Histogram-Settings.md @@ -85,6 +85,40 @@ plot { } ``` + + + +```kotlin +val experimentalData = dataFrameOf( + "length" to columnOf( + 5.92, 6.44, 5.87, 4.99, 5.23, + 5.67, 4.89, 5.34, 5.78, 5.12, + 5.56, 5.23, 5.78, 6.01, 5.56, + 5.67, 5.89, 5.45, 6.12, 5.78, + 6.34, 5.67, 6.45, 5.34, 5.89, + 6.01, 5.78, 5.23, 5.67, 6.12, + 6.23, 5.45, 5.56, 5.67, 5.78, + 5.56, 6.23, 5.78, 6.34, 6.12, + 5.89, 6.45, 5.78, 6.34, 5.67, + 6.56, 5.45, 5.78, 5.89, 6.12, + 4.67, 4.79, 5.14, 5.28, 5.22, + ) +) +experimentalData.plot { + histogram(length, binsOption = BinsOption.byNumber(12)) { + width = 0.8 + alpha = 0.9 + fillColor = Color.RED + borderLine { + color = Color.GREEN + width = 0.5 + } + x.axis.name = "length" + } + layout.title = "Flight length experiment" +} +``` + diff --git a/docs/topics/samples/histogram/Histogram-Simple.md b/docs/topics/samples/histogram/Histogram-Simple.md index 8f3d61917..936047b8f 100644 --- a/docs/topics/samples/histogram/Histogram-Simple.md +++ b/docs/topics/samples/histogram/Histogram-Simple.md @@ -46,6 +46,20 @@ plot { } ``` + + + +```kotlin +val random = java.util.Random(42) +val dataframe = dataFrameOf( + "sample" to List(1000) { random.nextGaussian() } +) + +dataframe.plot { + histogram(sample) +} +``` + diff --git a/docs/topics/samples/histogram/Histogram-With-Line.md b/docs/topics/samples/histogram/Histogram-With-Line.md index 1dadb4913..5ce42150c 100644 --- a/docs/topics/samples/histogram/Histogram-With-Line.md +++ b/docs/topics/samples/histogram/Histogram-With-Line.md @@ -72,6 +72,34 @@ plot { } ``` + + + +```kotlin +val random = java.util.Random(42) + +val sampleDf = dataFrameOf( + "sample" to List(1000) { random.nextGaussian() } +) + +sampleDf.plot { + statBin(sample, binsOption = BinsOption.byNumber(15)) { + bars { + alpha = 0.9 + x(Stat.x) + y(Stat.count) + } + line { + x(Stat.x) + y(Stat.count) + color = Color.RED + width = 1.5 + type = LineType.LONGDASH + } + } +} +``` + diff --git a/docs/topics/samples/line/Fixed-Line-Coordinate.md b/docs/topics/samples/line/Fixed-Line-Coordinate.md index 1cf339a59..d77e06321 100644 --- a/docs/topics/samples/line/Fixed-Line-Coordinate.md +++ b/docs/topics/samples/line/Fixed-Line-Coordinate.md @@ -69,6 +69,37 @@ plot { } ``` + + + +```kotlin +data class DayTemperature(val day: String, val temp: Int) + +val weeklyTemp = listOf( + DayTemperature("Mon", 10), + DayTemperature("Tue", 6), + DayTemperature("Wed", 5), + DayTemperature("Thu", 7), + DayTemperature("Fri", 7), + DayTemperature("Sat", 11), + DayTemperature("Sun", 9) +).toDataFrame() + +weeklyTemp.plot { + x(day) + line { + y(temp) + color = Color.BLUE + } + line { + y.constant(weeklyTemp.temp.mean()) + color = Color.GREEN + type = LineType.DOTTED + width = 2.5 + } +} +``` + diff --git a/docs/topics/samples/line/Line-Gradient.md b/docs/topics/samples/line/Line-Gradient.md index e7c8f6d43..94a5cb2b7 100644 --- a/docs/topics/samples/line/Line-Gradient.md +++ b/docs/topics/samples/line/Line-Gradient.md @@ -79,6 +79,35 @@ monthTemp.plot { } ``` + + + +```kotlin +val monthTemp = dataFrameOf("month", "temp")( + "January", -5, + "February", -3, + "March", 2, + "April", 10, + "May", 16, + "June", 20, + "July", 22, + "August", 21, + "September", 15, + "October", 9, + "November", 3, + "December", -2 +) + +monthTemp.plot { + line { + x(month) + y(temp) { scale = continuous(-10..25) } + color(temp) { scale = continuous(Color.BLUE..Color.RED) } + width = 3.0 + } +} +``` + diff --git a/docs/topics/samples/line/Line-Settings.md b/docs/topics/samples/line/Line-Settings.md index 485d6e504..b1f845b69 100644 --- a/docs/topics/samples/line/Line-Settings.md +++ b/docs/topics/samples/line/Line-Settings.md @@ -73,6 +73,37 @@ plot { } ``` + + + +```kotlin +val museumVisitors = dataFrameOf( + "date" to columnOf( + LocalDate(2023, 1, 1).toString(), + LocalDate(2023, 1, 15).toString(), + LocalDate(2023, 2, 1).toString(), + LocalDate(2023, 2, 15).toString(), + LocalDate(2023, 3, 1).toString(), + LocalDate(2023, 3, 15).toString(), + LocalDate(2023, 4, 1).toString(), + LocalDate(2023, 4, 15).toString(), + LocalDate(2023, 5, 1).toString(), + LocalDate(2023, 5, 15).toString() + ), + "visitors" to columnOf(120, 95, 110, 123, 130, 140, 150, 160, 175, 180) +) + +museumVisitors.plot { + line { + x(date) + y(visitors) + type = LineType.DASHED + color = Color.PURPLE + width = 2.5 + } +} +``` + diff --git a/docs/topics/samples/line/Line-with-Points.md b/docs/topics/samples/line/Line-with-Points.md index adf54c867..6c62fa0a1 100644 --- a/docs/topics/samples/line/Line-with-Points.md +++ b/docs/topics/samples/line/Line-with-Points.md @@ -60,6 +60,30 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "area" to columnOf(30, 40, 50, 60, 70, 80, 90), + "price" to columnOf(60000, 80000, 75000, 90000, 85000, 95000, 90000) +) + +df.plot { + x(price) + y(area) + line { + color = Color.BLUE + type = LineType.LONGDASH + } + points { + size = 3.5 + symbol = Symbol.CIRCLE_OPEN + color = Color.BLUE + } +} +``` + diff --git a/docs/topics/samples/line/Line-with-Reversed-Axis.md b/docs/topics/samples/line/Line-with-Reversed-Axis.md index b93cbf618..6193293ac 100644 --- a/docs/topics/samples/line/Line-with-Reversed-Axis.md +++ b/docs/topics/samples/line/Line-with-Reversed-Axis.md @@ -58,6 +58,29 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "product" to ('A'..'F').map { it.toString() }.toColumn(), + "rating" to columnOf(10, 7, 3, 5, 2, 1) +) + +plot(dataset) { + line { + x(rating) { + scale = continuous(min = 0, max = 12) + } + y(product) { + scale = continuous(transform = Transformation.REVERSE) + } + color = Color.RED + alpha = 0.85 + } +} +``` + diff --git a/docs/topics/samples/line/Marked-Line.md b/docs/topics/samples/line/Marked-Line.md index 6dc12de23..214ff5dea 100644 --- a/docs/topics/samples/line/Marked-Line.md +++ b/docs/topics/samples/line/Marked-Line.md @@ -110,6 +110,51 @@ df.plot { } ``` + + + +```kotlin +val months = listOf( + "January", "February", + "March", "April", "May", + "June", "July", "August", + "September", "October", "November", + "December" +) +val tempBerlin = + listOf(-0.5, 0.0, 4.8, 9.0, 14.3, 17.5, 19.2, 18.9, 14.5, 9.7, 4.7, 1.0) +val tempMadrid = + listOf(6.3, 7.9, 11.2, 12.9, 16.7, 21.1, 24.7, 24.2, 20.3, 15.4, 9.9, 6.6) + +val df = dataFrameOf( + "month" to months + months, + "temperature" to tempBerlin + tempMadrid, + "city" to List(12) { "Berlin" } + List(12) { "Madrid" } +) + +df.plot { + line { + x(month) + y(temperature) + color(city) { scale = categorical("Berlin" to Color.PURPLE, "Madrid" to Color.ORANGE) } + width = 1.5 + } + hLine { + yIntercept.constant(tempBerlin.average()) + color = Color.PURPLE + alpha = 0.9 + type = LineType.DASHED + } + hLine { + yIntercept.constant(tempMadrid.average()) + color = Color.ORANGE + alpha = 0.9 + type = LineType.DASHED + } + layout.size = 1000 to 450 +} +``` + diff --git a/docs/topics/samples/line/Several-Lines.md b/docs/topics/samples/line/Several-Lines.md index 0c487d5d8..596de1143 100644 --- a/docs/topics/samples/line/Several-Lines.md +++ b/docs/topics/samples/line/Several-Lines.md @@ -65,6 +65,30 @@ dataset.plot { } ``` + + + +```kotlin +val months = listOf(1, 2, 3, 4, 5) +val salesProducts = listOf(200.0, 220.0, 180.0, 240.0, 210.0) +val salesClothes = listOf(150.0, 130.0, 160.0, 140.0, 170.0) +val salesElectronics = listOf(300.0, 320.0, 310.0, 330.0, 340.0) + +val dataset = dataFrameOf( + "month" to months + months + months, + "sales" to salesProducts + salesClothes + salesElectronics, + "category" to List(5) { "Products" } + List(5) { "Clothes" } + List(5) { "Electronics" } +) + +dataset.groupBy { category }.plot { + line { + x(month) + y(sales) + color(category) + } +} +``` + diff --git a/docs/topics/samples/line/Simple-Line.md b/docs/topics/samples/line/Simple-Line.md index f2f8a8afe..0a19cd6e9 100644 --- a/docs/topics/samples/line/Simple-Line.md +++ b/docs/topics/samples/line/Simple-Line.md @@ -49,6 +49,23 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "cost" to columnOf(62.7, 64.7, 72.1, 73.7, 68.5) +) + +df.plot { + line { + x(years) + y(cost) + } +} +``` + diff --git a/docs/topics/samples/pie/Nightingale-Chart.md b/docs/topics/samples/pie/Nightingale-Chart.md index b0708c07b..4e1969c4a 100644 --- a/docs/topics/samples/pie/Nightingale-Chart.md +++ b/docs/topics/samples/pie/Nightingale-Chart.md @@ -62,6 +62,28 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "month" to columnOf("Jan", "Feb", "Mar", "May", "Apr"), + "amount" to columnOf(34.4, 25.1, 33.6, 20.0, 15.9) +) + +df.plot { + pie { + slice(amount) + fillColor(month) + size(amount) { + scale = continuous(10.0..25.0) + legend.type = LegendType.None + } + } + layout { style(Style.Void) } +} +``` + diff --git a/docs/topics/samples/pie/Pie-Base.md b/docs/topics/samples/pie/Pie-Base.md index 31aa4d369..02586a174 100644 --- a/docs/topics/samples/pie/Pie-Base.md +++ b/docs/topics/samples/pie/Pie-Base.md @@ -48,6 +48,23 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "value" to columnOf(15, 22, 40, 7, 31), + "type" to columnOf("A", "B", "C", "A", "D") +) + +df.plot { + pie { + slice(value) + fillColor(type) + } +} +``` + diff --git a/docs/topics/samples/pie/Pie-Settings.md b/docs/topics/samples/pie/Pie-Settings.md index 9e0e4547b..13f4426b8 100644 --- a/docs/topics/samples/pie/Pie-Settings.md +++ b/docs/topics/samples/pie/Pie-Settings.md @@ -75,6 +75,36 @@ plot { } ``` + + + +```kotlin +val usersLanguages = dataFrameOf( + "language" to columnOf("Kotlin", "Java", "C++", "JavaScript", "C#", "Other"), + "users" to columnOf(563, 481, 202, 406, 150, 312) +) + +usersLanguages.plot { + pie { + slice(users) + fillColor(language) { + scale = categorical( + "Kotlin" to Color.hex("#1E88E5"), + "Java" to Color.hex("#D32F2F"), + "C++" to Color.hex("#7B1FA2"), + "JavaScript" to Color.hex("#FBC02D"), + "C#" to Color.hex("#388E3C"), + "Other" to Color.hex("#757575") + ) + } + size = 33.0 + hole = 0.8 + alpha = 0.8 + } + layout.style(Style.Void) +} +``` + diff --git a/docs/topics/samples/pie/Pie-With-Count.md b/docs/topics/samples/pie/Pie-With-Count.md index d0906d3b7..7f73d8402 100644 --- a/docs/topics/samples/pie/Pie-With-Count.md +++ b/docs/topics/samples/pie/Pie-With-Count.md @@ -66,6 +66,32 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "continent" to columnOf( + "EU", "AF", "SA", "OC", "EU", "AF", "SA", "AF", "AS", "SA", + "OC", "OC", "SA", "NA", "AF", "NA", "EU", "AF", "OC", "SA", + "AF", "SA", "OC", "EU", "AF" + ) +) + +df.plot { + statCount(continent) { + pie { + slice(Stat.count) + fillColor(Stat.x named "continent") + size = 25.0 + } + } + layout { + style(Style.Void) + } +} +``` + diff --git a/docs/topics/samples/pie/Pie-With-Explode.md b/docs/topics/samples/pie/Pie-With-Explode.md index 1393a3105..00ad66184 100644 --- a/docs/topics/samples/pie/Pie-With-Explode.md +++ b/docs/topics/samples/pie/Pie-With-Explode.md @@ -64,6 +64,27 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "range" to columnOf("0-10m", "10-20m", "20-40m", "40-100m", "100-250m", ">250m"), + "share" to columnOf(0.42, 0.23, 0.15, 0.11, 0.06, 0.03), + "explode" to columnOf(0.20, 0.0, 0.04, 0.08, 0.12, 0.16) +) + +df.plot { + pie { + slice(share) + fillColor(range) { scale = continuous(Color.RED..Color.LIGHT_GREEN) } + explode(explode) + size = 25.0 + } + layout { style(Style.Void) } +} +``` + diff --git a/docs/topics/samples/pie/Pie-With-Void-Style.md b/docs/topics/samples/pie/Pie-With-Void-Style.md index ea8f8e295..88d23d08f 100644 --- a/docs/topics/samples/pie/Pie-With-Void-Style.md +++ b/docs/topics/samples/pie/Pie-With-Void-Style.md @@ -53,6 +53,24 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "platform" to columnOf("Linux", "MacOS", "Windows"), + "count" to columnOf(30, 239, 566) +) + +df.plot { + pie { + slice(count) + fillColor(platform) + } + layout { style(Style.Void) } +} +``` + diff --git a/docs/topics/samples/points/Basic-Points-Plot.md b/docs/topics/samples/points/Basic-Points-Plot.md index 9914100c5..b07eaf98b 100644 --- a/docs/topics/samples/points/Basic-Points-Plot.md +++ b/docs/topics/samples/points/Basic-Points-Plot.md @@ -71,6 +71,33 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "xs" to columnOf( + 5.93, 9.15, 3.76, 5.04, 2.23, + 7.47, 2.59, 11.67, 7.90, 3.71, + 0.03, 2.73, 4.61, 5.44, 1.76, + 14.46, 1.89 + ), + "ys" to columnOf( + 14.66, 13.80, 5.37, 6.40, 6.86, + 2.98, 6.69, 5.48, 3.67, 12.36, + 0.01, 14.47, 14.56, 9.19, 12.86, + 5.37, 0.90 + ) +) + +dataset.plot { + points { + x(xs) + y(ys) + } +} +``` + diff --git a/docs/topics/samples/points/Jittered-Points.md b/docs/topics/samples/points/Jittered-Points.md index 1514f19f8..7cca2136f 100644 --- a/docs/topics/samples/points/Jittered-Points.md +++ b/docs/topics/samples/points/Jittered-Points.md @@ -61,6 +61,29 @@ plot { } ``` + + + +```kotlin +val random = kotlin.random.Random(42) +val dataset = dataFrameOf( + "type" to (List(50) { "a" } + List(50) { "b" }).toColumn(), + "value" to ( + List(50) { kotlin.random.Random.nextDouble(0.1, 0.6) } + + List(50) { random.nextDouble(-0.5, 0.4) } + ).toColumn() +) + +dataset.plot { + points { + x(type) + y(value) + position = Position.jitter(width = 0.1, height = 0.1) + color = Color.hex("#05C3DE") + } +} +``` + diff --git a/docs/topics/samples/points/Points-Settings.md b/docs/topics/samples/points/Points-Settings.md index a4fabb2d9..e1d5d36f8 100644 --- a/docs/topics/samples/points/Points-Settings.md +++ b/docs/topics/samples/points/Points-Settings.md @@ -77,6 +77,36 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "xs" to columnOf( + 5.93, 9.15, 3.76, 5.04, 2.23, + 7.47, 2.59, 11.67, 7.90, 3.71, + 0.03, 2.73, 4.61, 5.44, 1.76, + 14.46, 1.89 + ), + "ys" to columnOf( + 14.66, 13.80, 5.37, 6.40, 6.86, + 2.98, 6.69, 5.48, 3.67, 12.36, + 0.01, 14.47, 14.56, 9.19, 12.86, + 5.37, 0.90 + ) +) + +dataset.plot { + points { + x(xs) + y(ys) + size = 10.0 + color = Color.BLUE + symbol = Symbol.DIAMOND + } +} +``` + diff --git a/docs/topics/samples/points/Points-with-ABLine.md b/docs/topics/samples/points/Points-with-ABLine.md index 0707d009f..46debbba9 100644 --- a/docs/topics/samples/points/Points-with-ABLine.md +++ b/docs/topics/samples/points/Points-with-ABLine.md @@ -78,6 +78,38 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "xValues" to columnOf( + 7.13, 9.30, 7.84, 7.08, 5.51, + 8.40, 5.69, 11.59, 12.53, 4.98, + 10.29, 6.88, 7.38, 12.03, 0.92 + ), + "yValues" to columnOf( + 7.05, 8.23, 6.74, 7.95, 5.38, + 7.47, 4.88, 9.17, 9.30, 6.17, + 6.58, 5.87, 6.45, 10.53, 3.13 + ) +) + +dataset.plot { + points { + x(xValues) + y(yValues) + size = 7.0 + color = Color.LIGHT_BLUE + } + abLine { + slope.constant(0.5) + intercept.constant(3) + color = Color.RED + } +} +``` + diff --git a/docs/topics/samples/points/Points-with-Color-by-Category.md b/docs/topics/samples/points/Points-with-Color-by-Category.md index 7df065ca9..4d185990b 100644 --- a/docs/topics/samples/points/Points-with-Color-by-Category.md +++ b/docs/topics/samples/points/Points-with-Color-by-Category.md @@ -99,6 +99,44 @@ plot(dataset) { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "xShot" to columnOf( + 4.02, 5.24, 4.41, 3.99, 3.10, 4.73, 3.20, 6.53, 7.05, 2.81, + 5.80, 3.87, 4.16, 6.78, 0.52, 0.64, 0.15, 6.09, 5.70, 6.37 + ), + "yShot" to columnOf( + 2.39, 1.95, 1.13, 1.90, 0.29, 1.56, 0.35, 2.30, 1.27, 1.01, + 0.65, 1.89, 1.11, 1.39, 0.05, 1.51, 1.49, 1.51, 2.30, 1.66 + ), + "outcome" to columnOf( + false, true, false, true, true, true, true, true, true, false, + true, true, false, false, true, false, false, true, true, false + ) +) + +dataset.plot { + points { + x(xShot) { axis.name = "Horizontal Position (meters)" } + y(yShot) { axis.name = "Vertical Position (meters)" } + size = 8.5 + color(outcome) { + scale = categorical( + true to Color.GREEN, false to Color.RED + ) + legend { + name = "Outcome" + breaksLabeled(true to "Goal", false to "Miss") + } + } + } + layout.title = "Penalty Shot Outcomes Analysis" +} +``` + diff --git a/docs/topics/samples/ribbon/Ribbon-Settings.md b/docs/topics/samples/ribbon/Ribbon-Settings.md index 666ed8df0..d72ed77ee 100644 --- a/docs/topics/samples/ribbon/Ribbon-Settings.md +++ b/docs/topics/samples/ribbon/Ribbon-Settings.md @@ -73,6 +73,36 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "year" to columnOf("2019", "2020", "2021", "2022", "2023"), + "minCost" to columnOf(56.5, 59.9, 60.8, 78.9, 75.5), + "maxCost" to columnOf(58.1, 69.3, 66.4, 108.3, 92.2) +) + +df.plot { + ribbon { + x(year) + y { + axis.name = "cost" + scale = continuous(55.0..110.0) + } + yMin(minCost) + yMax(maxCost) + fillColor = Color.hex(0x3f21e6) + alpha = 0.65 + borderLine { + color = Color.RED + width = 0.8 + type = LineType.DASHED + } + } +} +``` + diff --git a/docs/topics/samples/ribbon/Simple-Ribbon.md b/docs/topics/samples/ribbon/Simple-Ribbon.md index 4c6ffb9c4..62d885b02 100644 --- a/docs/topics/samples/ribbon/Simple-Ribbon.md +++ b/docs/topics/samples/ribbon/Simple-Ribbon.md @@ -51,6 +51,25 @@ plot { } ``` + + + +```kotlin +val df = dataFrameOf( + "xs" to columnOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0), + "mins" to columnOf(0.2, 0.9, 0.55, 1.32, 2.2, 1.5), + "maxs" to columnOf(0.7, 1.4, 1.1, 2.1, 2.6, 2.2) +) + +df.plot { + ribbon { + x(xs) + yMin(mins) + yMax(maxs) + } +} +``` + diff --git a/docs/topics/samples/tiles/Tiles-Color-Categories.md b/docs/topics/samples/tiles/Tiles-Color-Categories.md index d4403e320..4e65edc6c 100644 --- a/docs/topics/samples/tiles/Tiles-Color-Categories.md +++ b/docs/topics/samples/tiles/Tiles-Color-Categories.md @@ -84,6 +84,40 @@ plot { } ``` + + + +```kotlin +val cities = listOf("Yerevan", "Berlin", "Amsterdam", "Paphos") +val types = listOf("A", "B", "C") +val random = kotlin.random.Random(42) +val year22 = List(4) { types.random(random) } +val year23 = List(4) { types.random(random) } +val year24 = List(4) { types.random(random) } + +val dataset = dataFrameOf( + "city" to cities, + "2022" to year22, + "2023" to year23, + "2024" to year24 +).gather { `2022` and `2023` and `2024` }.into("year", "value") + +plot(dataset) { + tiles { + x(city) + y(year) { + scale = categorical() + axis.breaks(format = "d") + } + width = 0.5 + height = 0.9 + fillColor(value) { + legend.breaks(types) + } + } +} +``` + diff --git a/docs/topics/samples/tiles/Tiles-Gradient.md b/docs/topics/samples/tiles/Tiles-Gradient.md index b636fa516..c0eb6de95 100644 --- a/docs/topics/samples/tiles/Tiles-Gradient.md +++ b/docs/topics/samples/tiles/Tiles-Gradient.md @@ -74,6 +74,44 @@ dataset.plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "x" to columnOf( + 1.0, 2.0, 3.0, 4.0, 5.0, + 1.0, 2.0, 3.0, 4.0, 5.0, + 1.0, 2.0, 3.0, 4.0, 5.0 + ), + "y" to columnOf( + 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, + 3.0, 3.0, 3.0, 3.0, 3.0 + ), + "value" to columnOf( + 6, 7, 8, 4, 2, + 7, 5, 6, 4, 3, + 8, 6, 5, 8, 4 + ) +) +val xCol = column("x") +val yCol = column("y") + +dataset.plot { + tiles { + x(xCol) { axis.name = "x" } + y(yCol) { axis.name = "y" } + fillColor(value) { + legend.type = LegendType.None + scale = continuous(Color.hex("#E1F5FE")..Color.hex("#01579B")) + } + borderLine.width = 0.25 + } + layout.style(Style.Void) +} +``` + diff --git a/docs/topics/samples/tiles/Tiles-Settings.md b/docs/topics/samples/tiles/Tiles-Settings.md index e4278f273..3223e6196 100644 --- a/docs/topics/samples/tiles/Tiles-Settings.md +++ b/docs/topics/samples/tiles/Tiles-Settings.md @@ -77,6 +77,37 @@ plot { } ``` + + + +```kotlin +val dataset = dataFrameOf( + "store" to columnOf("A", "B", "C", "A", "B", "C", "A", "B", "C"), + "time" to columnOf( + "morning", "morning", "morning", + "afternoon", "afternoon", "afternoon", + "evening", "evening", "evening" + ), + "money" to columnOf(75, 64, 59, 82, 88, 91, 69, 77, 73) +) + +dataset.plot { + tiles { + x(store) + y(time) + height = 0.7 + borderLine { + width = 0.8 + color = Color.BLACK + } + fillColor(money) { + scale = continuous(Color.RED..Color.GREEN) + } + alpha = 0.5 + } +} +``` + diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/area.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/area.kt index f1ea5a74b..4fda5faa5 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/area.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/area.kt @@ -43,6 +43,24 @@ class Area : SampleHelper("area") { .saveSample() } + @Test + fun simple_area_dataframeCompilerPlugin() { + // SampleStart + val dataframe = dataFrameOf( + "years" to columnOf("2017", "2018", "2019", "2020", "2021", "2022", "2023"), + "cost" to columnOf(56.1, 22.7, 34.7, 82.1, 53.7, 68.5, 39.9) + ) + + dataframe.plot { + area { + x(years) + y(cost) + } + } + // SampleEnd + .saveSample() + } + @Test fun simple_area_collections() { // SampleStart @@ -89,6 +107,35 @@ class Area : SampleHelper("area") { .saveSample() } + @Test + fun area_settings_dataframeCompilerPlugin() { + // SampleStart + val loadServer = dataFrameOf( + "time" to columnOf("00:00", "03:00", "06:00", "09:00", "12:00", "15:00", "18:00", "21:00"), + "load" to columnOf(10, 5, 15, 50, 75, 60, 80, 40) + ) + + loadServer.plot { + layout.title = "Daily Server Load Dynamics" + area { + x(time) { axis.name = "Time" } + y(load) { + axis.name = "Load (%)" + scale = continuous(0..100) + } + borderLine { + color = Color.ORANGE + type = LineType.DASHED + width = 2.5 + } + fillColor = Color.RED + alpha = 0.7 + } + } + // SampleEnd + .saveSample() + } + @Test fun area_settings_collections() { // SampleStart @@ -149,6 +196,44 @@ class Area : SampleHelper("area") { .saveSample() } + @Test + fun area_fixed_dataframeCompilerPlugin() { + // SampleStart + val reservoirDf = dataFrameOf( + "month" to columnOf( + "January", "February", + "March", "April", "May", + "June", "July", "August", + "September", "October", "November", + "December" + ), + "waterLvl" to columnOf(4.5, 4.7, 5.0, 5.5, 6.0, 6.5, 6.7, 6.2, 5.8, 5.3, 4.8, 4.6) + ) + + plot(reservoirDf) { + layout { + title = "Water Level" + subtitle = "Annual Water Level Fluctuations in Reservoir" + yAxisLabel = "Month" + xAxisLabel = "Water Level (meters)" + } + + x(month) + y { axis.limits = 3.0..8.0 } + line { + y(waterLvl) + } + area { + y.constant(5.0) + borderLine.type = LineType.DOTTED + alpha = 0.5 + fillColor = Color.RED + } + } + // SampleEnd + .saveSample() + } + @Test fun area_fixed_collections() { // SampleStart @@ -208,6 +293,30 @@ class Area : SampleHelper("area") { .saveSample() } + @Test + fun area_with_reversed_axis_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "Day of the Week" to columnOf("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"), + "Star Rating (Reversed)" to columnOf(4, 2, 1, 2, 3, 4, 1) + ) + + df.plot { + layout.title = "Weekly Star Ratings" + layout.subtitle = "A reversed perspective" + area { + x(`Day of the Week`) + y(`Star Rating (Reversed)`) { + scale = continuous(0..5, transform = Transformation.REVERSE) + } + fillColor = Color.hex("#FCF84A") + alpha = 0.75 + } + } + // SampleEnd + .saveSample() + } + @Test fun area_with_reversed_axis_collections() { // SampleStart @@ -264,6 +373,40 @@ class Area : SampleHelper("area") { .saveSample() } + @Test + fun several_areas_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "year" to columnOf("2016", "2017", "2018", "2019", "2020", "2021"), + "Apple" to columnOf(700, 800, 750, 900, 850, 950), + "Google" to columnOf(1000, 950, 1200, 1150, 1250, 1300), + "Microsoft" to columnOf(600, 700, 650, 700, 750, 800), + "Meta" to columnOf(1100, 1200, 1150, 1300, 1250, 1350), + "Amazon" to columnOf(300, 400, 350, 450, 500, 600) + ).gather { Apple and Google and Microsoft and Meta and Amazon }.into("company", "users") + + dataset.groupBy { company }.plot { + layout.title = "User Growth Dynamics" + area { + x(year) + y(users) + fillColor(company) { + scale = categorical( + "Apple" to Color.hex("#FF45ED"), + "Google" to Color.hex("#3DEA62"), + "Microsoft" to Color.BLACK, + "Meta" to Color.hex("#FDB60D"), + "Amazon" to Color.hex("#087CFA") + ) + } + borderLine.color(company) + alpha = 0.3 + } + } + // SampleEnd + .saveSample() + } + @Test fun several_areas_collections() { // SampleStart @@ -372,6 +515,55 @@ class Area : SampleHelper("area") { .saveSample(true) } + @Test + fun area_with_mark_line_dataframeCompilerPlugin() { + // SampleStart + val months = listOf( + "January", "February", + "March", "April", "May", + "June", "July", "August", + "September", "October", "November", + "December" + ) + val tempBerlin = + listOf(-0.5, 0.0, 4.8, 9.0, 14.3, 17.5, 19.2, 18.9, 14.5, 9.7, 4.7, 1.0) + val tempMadrid = + listOf(6.3, 7.9, 11.2, 12.9, 16.7, 21.1, 24.7, 24.2, 20.3, 15.4, 9.9, 6.6) + + val df = dataFrameOf( + "month" to months + months, + "temperature" to tempBerlin + tempMadrid, + "city" to List(12) { "Berlin" } + List(12) { "Madrid" } + ) + + df.plot { + area { + x(month) + y(temperature) + fillColor(city) { + scale = categorical("Berlin" to Color.hex("#07C3F2"), "Madrid" to Color.hex("#FDB60D")) + } + alpha = 0.5 + borderLine.width = 1.5 + } + hLine { + yIntercept.constant(tempBerlin.average()) + color = Color.BLACK + width = 2.0 + type = LineType.DASHED + } + hLine { + yIntercept.constant(tempMadrid.average()) + color = Color.RED + width = 2.0 + type = LineType.DASHED + } + layout.size = 1000 to 450 + } + // SampleEnd + .saveSample(true) + } + @Test fun area_with_mark_line_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/bars.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/bars.kt index f46d9d939..48b1ca328 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/bars.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/bars.kt @@ -41,6 +41,25 @@ class Bars : SampleHelper("bars") { .saveSample() } + @Test + fun simple_bar_plot_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "city" to columnOf("London", "Paris", "Berlin", "Madrid", "Rome"), + "perc" to columnOf(45, 50, 60, 40, 30) + ) + + dataset.plot { + layout.title = "Public Transport Usage in European Cities" + bars { + x(city) { axis.name = "City" } + y(perc) { axis.name = "Public Transport Usage (%)" } + } + } + // SampleEnd + .saveSample() + } + @Test fun simple_bar_plot_collections() { // SampleStart @@ -88,6 +107,38 @@ class Bars : SampleHelper("bars") { .saveSample() } + @Test + fun bar_settings_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "candy" to columnOf( + "Honey Stars", "Fairy Tale Caramels", " ChocoDream", "Fruity Clouds", + "Minty Spheres", "Sour Strips", "Vanilla Bars" + ), + "sugar" to columnOf(65, 58, 53, 35, 40, 45, 50) + ) + + dataset.plot { + layout { + title = "Sugar content" + xAxisLabel = "Candy Name" + yAxisLabel = "Sugar Content (g per 100g)" + } + bars { + x(candy) + y(sugar) { scale = continuous(0..100) } + fillColor = Color.ORANGE + alpha = 0.85 + borderLine { + color = Color.GREY + width = 1.3 + } + } + } + // SampleEnd + .saveSample() + } + @Test fun bar_settings_collections() { // SampleStart @@ -142,6 +193,31 @@ class Bars : SampleHelper("bars") { .saveSample() } + @Test + fun bar_gradient_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "cities" to columnOf("London", "Paris", "Berlin", "Madrid", "Rome", "Amsterdam", "Prague"), + "airPollution" to columnOf(70, 65, 50, 60, 55, 45, 53), + "numberOfCars" to columnOf(3000, 2800, 1800, 2500, 2100, 1300, 2000) + ) + + dataset.plot { + layout.title = "Air Pollution and Vehicle Count Analysis" + bars { + x(cities) { axis.name = "City" } + y(numberOfCars) { axis.name = "Number of cars (thousands)" } + fillColor(airPollution) { + legend.name = "Air Pollution\n Level (AQI)" + scale = continuous(Color.GREEN..Color.RED) + } + alpha = 0.8 + } + } + // SampleEnd + .saveSample() + } + @Test fun bar_gradient_collections() { // SampleStart @@ -208,6 +284,27 @@ class Bars : SampleHelper("bars") { .saveSample() } + @Test + fun bar_with_reversed_axis_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "task" to columnOf("a", "b", "c", "d", "e"), + "time" to columnOf(30, 25, 20, 35, 28) + ) + + dataset.plot { + bars { + x(task) + y(time) { + scale = continuous(transform = Transformation.REVERSE) + } + fillColor = Color.hex("#07C3F2") + } + } + // SampleEnd + .saveSample() + } + @Test fun bar_with_reversed_axis_collections() { // SampleStart @@ -254,6 +351,32 @@ class Bars : SampleHelper("bars") { .saveSample() } + @Test + fun horizontal_bars_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "actors" to columnOf( + "John Doe", "Emma Stone", "Ryan Gosling", "Natalie Portman", + "Brad Pitt", "Marilyn Monroe", "Leonardo DiCaprio" + ), + "screenTime" to columnOf(90, 75, 60, 85, 50, 40, 95) + ) + + dataset.plot { + layout.title = "Screen Time of Hollywood Actors" + barsH { + y(actors) { axis.name = "Actors" } + x(screenTime) { axis.name = "minutes" } + alpha = 0.75 + fillColor(actors) { + scale = categoricalColorHue() + } + } + } + // SampleEnd + .saveSample() + } + @Test fun horizontal_bars_collections() { // SampleStart @@ -306,6 +429,34 @@ class Bars : SampleHelper("bars") { .saveSample() } + @Test + fun grouped_bars_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "day" to columnOf("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"), + "coffee" to columnOf(0.81, 0.78, 0.72, 0.65, 0.73, 0.49, 0.38), + "tea" to columnOf(0.12, 0.16, 0.21, 0.26, 0.24, 0.22, 0.30), + "soda" to columnOf(0.07, 0.06, 0.07, 0.09, 0.03, 0.29, 0.32), + ).gather { coffee and tea and soda }.into("drink", "amount") + + dataset.groupBy { drink }.plot { + layout.title = "Weekly Beverage Consumption Trends" + bars { + x(day) + y(amount) + fillColor(drink) { + scale = categorical( + "coffee" to Color.hex("#6F4E37"), + "tea" to Color.hex("#C2D4AB"), + "soda" to Color.hex("#B5651D") + ) + } + } + } + // SampleEnd + .saveSample() + } + @Test fun grouped_bars_collections() { // SampleStart @@ -367,6 +518,35 @@ class Bars : SampleHelper("bars") { .saveSample() } + @Test + fun stacked_bars_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "day" to columnOf("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"), + "coffee" to columnOf(0.81, 0.78, 0.72, 0.65, 0.73, 0.49, 0.38), + "tea" to columnOf(0.12, 0.16, 0.21, 0.26, 0.24, 0.22, 0.30), + "soda" to columnOf(0.07, 0.06, 0.07, 0.09, 0.03, 0.29, 0.32), + ).gather { coffee and tea and soda }.into("drink", "amount") + + dataset.groupBy { drink }.plot { + layout.title = "Weekly Beverage Consumption Trends" + bars { + x(day) + y(amount) + fillColor(drink) { + scale = categorical( + "coffee" to Color.hex("#6F4E37"), + "tea" to Color.hex("#C2D4AB"), + "soda" to Color.hex("#B5651D") + ) + } + position = Position.stack() + } + } + // SampleEnd + .saveSample() + } + @Test fun stacked_bars_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/boxplot.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/boxplot.kt index 8f81bfafa..6f203ff2f 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/boxplot.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/boxplot.kt @@ -49,6 +49,41 @@ class Boxplot : SampleHelper("boxplot") { .saveSample() } + @Test + fun boxplot_expr_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "expr0" to columnOf( + 850, 740, 900, 1070, 930, 850, 950, 980, 980, + 880, 1000, 980, 930, 650, 760, 810, 1000, 1000, 960, 960 + ), + "expr1" to columnOf( + 960, 940, 960, 940, 880, 800, 850, 880, 900, 840, 830, + 790, 810, 880, 880, 830, 800, 790, 760, 800 + ), + "expr2" to columnOf( + 880, 880, 880, 860, 720, 720, 620, 860, 970, 950, + 880, 910, 850, 870, 840, 840, 850, 840, 840, 840 + ), + "expr3" to columnOf( + 890, 810, 810, 820, 800, 770, 760, 740, 750, + 760, 910, 920, 890, 860, 880, 720, 840, 850, 850, 780 + ), + "expr4" to columnOf( + 890, 840, 780, 810, 760, 810, 790, 810, 820, + 850, 870, 870, 810, 740, 810, 940, 950, 800, 810, 870 + ) + ).gather { expr0 and expr1 and expr2 and expr3 and expr4 }.into("expr", "value") + + df.plot { + boxplot("expr", "value") { + boxes { borderLine.color = Color.BLUE } + } + } + // SampleEnd + .saveSample() + } + @Test fun boxplot_life_exp() { // SampleStart @@ -114,6 +149,62 @@ class Boxplot : SampleHelper("boxplot") { .saveSample() } + @Test + fun boxplot_life_exp_dataframeCompilerPlugin() { + // SampleStart + val countries = arrayOf("Australia", "Canada", "China", "Germany", "Japan", "United Kingdom", "United States") + val lifeExpectancyData = dataFrameOf( + "Australia" to columnOf( + 87.29, 83.20, 84.93, 88.72, 87.60, 79.07, 84.85, 81.55, 81.69, 83.23, + 82.43, 86.36, 84.28, 82.37, 83.33, 83.00, 86.48, 81.38, 82.94, 79.44, 74.34, 83.96, 84.59, 79.77, 88.81, + 77.64, 82.14, 81.44, 86.60, 86.41, 82.46, 83.13, 79.34, 76.06, 80.96, 82.47, 85.69, 85.61, 80.84, 81.09, + 78.85, 77.74, 76.88, 87.85, 80.47, 80.69, 78.24, 84.33, 77.16, 81.36 + ), + "Canada" to columnOf( + 77.42, 82.55, 78.96, 76.28, 80.89, 82.71, 81.27, 82.21, 78.46, 79.55, 78.31, + 79.56, 77.75, 74.09, 81.71, 79.39, 74.48, 82.85, 77.37, 81.21, 83.92, 81.52, 85.56, 76.06, 82.61, 78.26, + 77.52, 78.68, 79.75, 81.22, 76.34, 84.60, 82.86, 74.86, 86.95, 88.58, 85.72, 80.28, 76.72, 85.22, 79.39, + 85.89, 81.83, 84.91, 82.43, 83.83, 81.04, 80.07, 90.56, 79.77 + ), + "China" to columnOf( + 76.08, 88.39, 75.42, 80.75, 79.44, 80.96, 86.69, 77.30, 81.14, 76.65, 63.39, + 88.37, 78.89, 73.96, 87.45, 84.74, 82.90, 78.07, 89.43, 86.43, 78.80, 73.51, 85.01, 81.11, 79.09, 83.57, + 83.69, 82.95, 77.55, 82.13, 79.85, 79.99, 78.67, 78.90, 79.85, 88.72, 72.23, 76.12, 74.75, 79.22, 85.58, + 81.17, 74.86, 72.02, 85.43, 73.34, 81.60, 83.86, 79.86, 75.95 + ), + "Germany" to columnOf( + 75.98, 73.25, 80.70, 69.84, 83.00, 82.91, 84.36, 75.75, 75.16, 85.21, 87.71, + 80.55, 92.80, 80.20, 86.26, 74.87, 81.98, 85.70, 83.06, 78.86, 79.04, 73.85, 79.78, 79.95, 78.07, 81.57, + 73.08, 72.05, 92.45, 76.85, 84.82, 80.43, 80.90, 80.26, 82.40, 80.84, 88.51, 87.48, 78.37, 71.97, 81.41, + 88.58, 84.84, 89.01, 80.05, 82.32, 81.44, 89.74, 79.14, 86.96 + ), + "Japan" to columnOf( + 82.72, 83.77, 83.78, 78.10, 84.92, 80.83, 80.85, 80.02, 84.13, 82.95, 83.10, + 84.34, 83.39, 79.09, 82.43, 86.71, 81.56, 80.90, 86.52, 80.25, 81.95, 82.91, 78.74, 82.05, 80.53, 84.14, + 82.10, 81.56, 81.85, 87.35, 80.59, 83.85, 80.55, 85.67, 85.42, 83.47, 85.73, 80.95, 81.38, 82.91, 85.21, + 87.31, 83.02, 78.46, 78.69, 82.79, 88.07, 81.24, 72.21, 89.26 + ), + "United Kingdom" to columnOf( + 76.66, 82.38, 75.41, 77.95, 82.04, 81.03, 79.85, 75.26, 81.20, 81.83, 78.43, + 83.02, 79.70, 80.96, 81.24, 80.68, 75.77, 81.59, 77.71, 75.22, 82.07, 82.25, 79.45, 80.73, 79.35, 80.89, + 85.13, 78.91, 79.96, 82.28, 84.67, 77.76, 79.54, 85.25, 80.17, 80.98, 78.61, 78.73, 80.07, 77.14, 80.86, + 81.71, 78.17, 79.85, 73.72, 75.23, 77.12, 80.75, 79.22, 83.58 + ), + "United States" to columnOf( + 71.47, 86.29, 77.41, 74.60, 73.04, 77.52, 80.27, 76.45, 80.95, 72.47, 74.96, + 79.30, 79.07, 77.33, 83.71, 77.28, 74.23, 75.89, 81.34, 82.65, 82.96, 82.33, 83.89, 76.20, 77.53, 75.34, + 75.93, 78.74, 79.43, 74.50, 73.26, 77.73, 74.55, 73.39, 79.32, 74.14, 77.21, 73.90, 75.62, 72.88, 78.65, + 80.89, 79.75, 73.08, 72.05, 71.45, 73.85, 80.82, 79.43, 80.90 + ) + ).gather { colsOf() }.into("country", "lifeExp") + + lifeExpectancyData.boxplot("country", "lifeExp").configure { + coordinatesTransformation = CoordinatesTransformation.cartesianFlipped() + } + // SampleEnd + .saveSample() + } + @Test fun boxplot_categories() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/candlestick.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/candlestick.kt index a2449497f..bb227b4c8 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/candlestick.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/candlestick.kt @@ -32,6 +32,24 @@ class Candlestick : SampleHelper("candlestick") { .saveSample() } + @Test + fun candlestick_simple_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "month" to columnOf("Jan", "Feb", "Mar", "Apr", "May"), + "open" to columnOf(14.2, 6.7, 8.8, 11.2, 4.0), + "high" to columnOf(15.5, 9.6, 10.7, 11.7, 9.9), + "low" to columnOf(7.5, 6.1, 8.5, 5.4, 4.0), + "close" to columnOf(8.0, 8.6, 10.7, 6.5, 9.8) + ) + + df.plot { + candlestick(month, open, high, low, close) + } + // SampleEnd + .saveSample() + } + @Test fun candlestick_simple_collections() { // SampleStart @@ -78,6 +96,37 @@ class Candlestick : SampleHelper("candlestick") { .saveSample() } + @Test + fun candlestick_settings_dsl_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "date" to (1..10).map { LocalDate(2022, 1, it) }.toColumn(), + "open" to columnOf(10.0, 15.0, 12.0, 18.0, 14.0, 16.0, 20.0, 22.0, 19.0, 25.0), + "high" to columnOf(18.0, 17.0, 20.0, 22.0, 18.0, 22.0, 25.0, 24.0, 27.0, 28.0), + "low" to columnOf(8.0, 10.0, 9.0, 11.0, 12.0, 15.0, 18.0, 17.0, 18.0, 22.0), + "close" to columnOf(15.0, 12.0, 18.0, 14.0, 16.0, 20.0, 22.0, 19.0, 25.0, 23.0) + ) + + df.plot { + candlestick(date, open, high, low, close) { + increase { + fillColor = Color.hex("#00fefe") + alpha = 0.9 + } + decrease { + fillColor = Color.hex("#ea2211") + alpha = 0.5 + } + borderLine.color = Color.GREY + width = 0.7 + } + y.axis.name = "Price, €" + x.axis.name = "Date" + } + // SampleEnd + .saveSample() + } + @Test fun candlestick_settings_dsl_collections() { // SampleStart @@ -139,6 +188,39 @@ class Candlestick : SampleHelper("candlestick") { .saveSample(savePreview = true) } + @Test + fun candlestick_settings_stat_api_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "year" to columnOf("2018", "2019", "2020", "2021", "2022", "2023"), + "open" to columnOf(10.0, 15.0, 12.0, 18.0, 14.0, 16.0), + "high" to columnOf(18.0, 17.0, 20.0, 22.0, 18.0, 22.0), + "low" to columnOf(8.0, 10.0, 9.0, 11.0, 12.0, 15.0), + "close" to columnOf(15.0, 12.0, 18.0, 14.0, 16.0, 20.0) + ) + + df.plot { + candlestick(year, open, high, low, close) { + alpha(Stat.isIncreased) { + scale = categorical(true to 1.0, false to 0.05) + legend { + name = "" + breaksLabeled(true to "increase", false to "decrease") + } + } + fillColor = Color.GREY + borderLine.color = Color.GREY + } + x.axis { + name = "Year" + breaks(format = "d") + } + layout.size = 750 to 400 + } + // SampleEnd + .saveSample(savePreview = true) + } + @Test fun candlestick_settings_stat_api_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/countPlot.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/countPlot.kt index d14a9d9bc..d85ab05f1 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/countPlot.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/countPlot.kt @@ -39,6 +39,30 @@ class CountPlot : SampleHelper("countPlot") { .saveSample() } + @Test + fun countPlot_simple_dataframeCompilerPlugin() { + // SampleStart + val dataframe = dataFrameOf( + "categories" to columnOf( + "A", "B", "C", "C", "B", + "A", "C", "B", "A", "B", + "C", "A", "B", "A", "A", + "C", "A", "A", "B", "C", + "C", "A", "A", "C", "B", + "C", "C", "A", "A", "A", + "B", "C", "B", "A", "B", + "C", "A", "A", "B", "A", + "C", "A", "C", "A", "C" + ) + ) + + dataframe.plot { + countPlot(categories) + } + // SampleEnd + .saveSample() + } + @Test fun countPlot_simple_collections() { // SampleStart @@ -90,6 +114,33 @@ class CountPlot : SampleHelper("countPlot") { .saveSample() } + @Test + fun countPlot_settings_dataframeCompilerPlugin() { + // SampleStart + val classesDF = dataFrameOf( + "classes" to columnOf( + "First", "Second", "Third", "Third", "Second", + "Third", "First", "Second", "Third", "First", + "Third", "Second", "Third", "First", "Second", + "Third", "First", "Third", "Second", "Third", + "First", "Second", "Third", "First", "Third", + "Second", "Third", "First", "Second", "Third", + "First", "Third", "Second", "Third", "First", + "Second", "Third", "First", "Second", "Third" + ) + ) + + classesDF.plot { + countPlot(classes) { + alpha = 0.8 + fillColor(Stat.x) { legend.type = LegendType.None } + x.axis.name = "class" + } + } + // SampleEnd + .saveSample() + } + @Test fun countPlot_settings_collections() { // SampleStart @@ -156,6 +207,45 @@ class CountPlot : SampleHelper("countPlot") { .saveSample() } + @Test + fun countPlot_grouped_dataframeCompilerPlugin() { + // SampleStart + val categories = listOf( + "easy", "medium", "hard", "medium", "easy", + "hard", "hard", "easy", "easy", "hard", "medium", + "hard", "easy", "easy", "easy", "medium", + "hard", "hard", "hard", "medium", "easy", + "hard", "medium", "hard", "hard", "hard", + "medium", "medium", "easy", "medium", "hard", + "hard", "easy", "hard", "medium", "medium", + "hard", "hard", "hard", "easy", "hard", + "hard", "easy", "medium", "medium", "hard", + "medium", "medium", "easy", "hard", "medium", + "hard", "medium", "easy", "easy", + ) + + val years = listOf( + "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", + "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", + "2022", "2022", "2022", "2022", "2022", "2022", "2022", "2022", + "2022", "2022", "2023", "2023", "2023", "2023", "2023", "2023", + "2023", "2023", "2023", "2023", "2023", "2023", "2023", "2023", + "2023", "2023", "2023", "2023", "2023", "2023", "2023", "2023", + "2023", "2023", "2023", "2023", "2023", "2023", "2023" + ) + + val df = dataFrameOf( + "category" to categories, + "year" to years + ) + + df.groupBy { category }.plot { + countPlot(year) + } + // SampleEnd + .saveSample() + } + @Test fun countPlot_grouped_collections() { // SampleStart @@ -238,6 +328,48 @@ class CountPlot : SampleHelper("countPlot") { .saveSample() } + @Test + fun countPlot_horizontal_dataframeCompilerPlugin() { + // SampleStart + val transportsDF = dataFrameOf( + "transports" to listOf( + "metro", "bicycle", "car", "bus", "bus", "bicycle", "bicycle", + "bus", "bus", "bus", "bus", "bus", "bus", "bus", "bicycle", "bicycle", + "bus", "bicycle", "bus", "car", "metro", "bus", "metro", "metro", + "bus", "bus", "bus", "metro", "bicycle", "metro", "bus", "metro", + "bicycle", "metro", "bicycle", "bicycle", "bus", "bicycle", "metro", + "bicycle", "metro", "bicycle", "bus", "bicycle", "bus", "bicycle", + "bicycle", "bicycle", "bus", "bicycle", "metro", "bus", "bicycle", + "bus", "bus", "bus", "bus", "bus", "bus", "metro", "metro", "bicycle", + "metro", "bus", "bus", "metro", "metro", "bicycle", "bus", "metro", + "metro", "bicycle", "bus", "bus", "bicycle", "car", "bus", "bicycle", + "bus", "metro", "bus", "metro", "bicycle", "metro", "bicycle", "bicycle" + ) + ) + + transportsDF.plot { + statCount(transports) { + val transport = Stat.x named "transport" + barsH { + x(Stat.count) + y(transport) + fillColor(transport) { + scale = categorical( + "bus" to Color.hex("#FFD700"), + "car" to Color.hex("#FF6347"), + "bicycle" to Color.hex("#32CD32"), + "metro" to Color.hex("#4169E1") + ) + legend.type = LegendType.None + } + } + } + layout.title = "Distribution of transport used by students" + } + // SampleEnd + .saveSample() + } + @Test fun countPlot_horizontal_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/densityPlot.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/densityPlot.kt index 295cbc3a1..3875eb2b7 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/densityPlot.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/densityPlot.kt @@ -36,6 +36,25 @@ class DensityPlot : SampleHelper("densityPlot") { .saveSample() } + @Test + fun densityPlot_simple_dataframeCompilerPlugin() { + // SampleStart + val random = java.util.Random(42) + + val dataframe = dataFrameOf( + "sample" to List(1000) { random.nextGaussian() } + ) + + dataframe.plot { + densityPlot(sample) { + x(Stat.x.map { it.toFloat() }) + y(Stat.density.map { it.toFloat() }) + } + } + // SampleEnd + .saveSample() + } + @Test fun densityPlot_simple_collections() { // SampleStart @@ -86,6 +105,43 @@ class DensityPlot : SampleHelper("densityPlot") { .saveSample() } + @Test + fun densityPlot_settings_dataframeCompilerPlugin() { + // SampleStart + val experimentalData = dataFrameOf( + "length" to listOf( + 5.92, 6.44, 5.87, 4.99, 5.23, + 5.67, 4.89, 5.34, 5.78, 5.12, + 5.56, 5.23, 5.78, 6.01, 5.56, + 5.67, 5.89, 5.45, 6.12, 5.78, + 6.34, 5.67, 6.45, 5.34, 5.89, + 6.01, 5.78, 5.23, 5.67, 6.12, + 6.23, 5.45, 5.56, 5.67, 5.78, + 5.56, 6.23, 5.78, 6.34, 6.12, + 5.89, 6.45, 5.78, 6.34, 5.67, + 6.56, 5.45, 5.78, 5.89, 6.12, + 4.67, 4.79, 5.14, 5.28, 5.22, + ) + ) + + experimentalData.plot { + densityPlot(length, adjust = 0.8) { + x(Stat.x.map { it.toFloat() }) + y(Stat.density.map { it.toFloat() }) + alpha = 0.5 + fillColor = Color.RED + borderLine { + color = Color.GREEN + width = 0.5 + } + x.axis.name = "length" + } + layout.title = "Flight length experiment" + } + // SampleEnd + .saveSample() + } + @Test fun densityPlot_settings_collections() { // SampleStart @@ -168,6 +224,56 @@ class DensityPlot : SampleHelper("densityPlot") { .saveSample() } + @Test + fun densityPlot_grouped_dataframeCompilerPlugin() { + // SampleStart + val macaqueWeights = listOf( + 1.563, 2.173, 2.118, 2.722, 2.384, 1.789, 2.649, + 1.299, 1.566, 1.821, 2.151, 1.554, 1.464, 1.611, + 2.178, 2.652, 2.031, 2.265, 1.919, 1.283, 2.365, + 2.540, 2.779, 2.040, 2.138, 1.783, 1.442, 1.413, + 2.224, 2.345, 1.753, 2.284, 2.465, 1.430, 2.617, + 1.667, 2.462, 1.777, 2.104, 2.404, 1.276, 1.489, + 2.662, 1.853, 2.315, 1.589, 1.586, 2.569, 1.888, + 1.414, 1.623, 2.084, 2.484, 2.348, 1.496, 2.238, + 1.778, 2.173, 2.411, 2.540, 2.325, 1.324, 2.252, + 1.978, 2.075, 2.585, 2.414, 2.162, 1.584, 2.399, + 1.757, 2.109, 1.436, 2.628, 2.370, 1.679, 1.970, + 2.360, 2.005, 2.179, 2.177, 1.941, 2.282, 2.067, + 2.288, 1.481, 1.638, 2.164, 2.485, 1.797, 2.369, + 1.690, 2.143, 1.743, 2.357, 2.280, 1.824, 1.678, + 2.531, 1.958, 1.466, 1.877, 2.005 + ) + val chimpanzeeWeights = listOf( + 4.530, 4.257, 4.381, 4.935, 3.392, 4.611, 2.499, 4.306, + 4.119, 3.622, 4.099, 4.832, 2.456, 3.411, 4.426, 2.940, + 4.529, 3.635, 2.991, 4.372, 2.319, 4.358, 1.882, 3.472, + 4.828, 4.005, 3.452, 3.854, 3.455, 2.996, 4.031, 4.382, + 2.947, 4.752, 2.466, 4.558, 2.548, 3.172, 3.010, 3.472, + 5.258, 2.746, 4.022, 3.013, 4.942, 3.206, 3.779, 4.367, + 3.853, 2.483, 3.957, 2.943, 4.791, 3.432, 3.530, 2.576, + 2.833, 4.650, 5.515, 4.413, 2.699, 3.310, 5.047, 3.047, + 4.095, 4.712, 2.600, 3.523, 3.106, 4.110, 2.894, 3.373, + 2.656, 3.684, 5.171, 4.049, 4.773, 3.456, 4.420, 2.090, + 3.155, 4.678, 3.240, + ) + + val df = dataFrameOf( + "weight" to macaqueWeights + chimpanzeeWeights, + "group" to macaqueWeights.map { "macaque" } + chimpanzeeWeights.map { "chimpanzee" } + ) + + df.groupBy { group }.plot { + densityPlot(weight) { + x(Stat.x.map { it.toFloat() }) + y(Stat.density.map { it.toFloat() }) + alpha = 0.5 + } + } + // SampleEnd + .saveSample() + } + @Test fun densityPlot_grouped_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/errorBars.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/errorBars.kt index 97974a672..17fc716bf 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/errorBars.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/errorBars.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlinx.kandy.letsplot.samples +import org.jetbrains.kotlinx.dataframe.api.add import org.jetbrains.kotlinx.dataframe.api.columnOf import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.groupBy @@ -36,6 +37,26 @@ class ErrorBars : SampleHelper("errorBars") { .saveSample() } + @Test + fun simple_error_bar_plot_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "costMin" to columnOf(62.7, 64.7, 72.1, 73.7, 68.5), + "costMax" to columnOf(68.9, 71.3, 78.9, 76.5, 72.1) + ) + + df.plot { + errorBars { + x(years) + yMin(costMin) + yMax(costMax) + } + } + // SampleEnd + .saveSample() + } + @Test fun simple_error_bar_plot_collections() { // SampleStart @@ -77,6 +98,31 @@ class ErrorBars : SampleHelper("errorBars") { .saveSample() } + @Test + fun error_bars_settings_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "costMin" to columnOf(62.7, 64.7, 72.1, 73.7, 68.5), + "costMax" to columnOf(68.9, 71.3, 78.9, 76.5, 72.1) + ) + + dataset.plot { + errorBars { + x(years) + yMin(costMin) + yMax(costMax) + width = 1.1 + borderLine { + width = 1.5 + color = Color.RED + } + } + } + // SampleEnd + .saveSample() + } + @Test fun error_bars_settings_collections() { // SampleStart @@ -129,6 +175,30 @@ class ErrorBars : SampleHelper("errorBars") { .saveSample() } + @Test + fun error_bars_with_line_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "costMin" to columnOf(62.7, 64.7, 72.1, 73.7, 68.5), + "costMax" to columnOf(68.9, 71.3, 78.9, 76.5, 72.1), + ).add("mid") { + (costMin + costMax) / 2 + } + dataset.plot { + x(years) + y(mid) + line { color = Color.BLUE } + errorBars { + yMin(costMin) + yMax(costMax) + borderLine.type = LineType.LONGDASH + } + } + // SampleEnd + .saveSample() + } + @Test fun error_bars_with_line_collections() { // SampleStart @@ -173,6 +243,27 @@ class ErrorBars : SampleHelper("errorBars") { .saveSample() } + @Test + fun fixed_error_bars_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "max" to columnOf(68.9, 71.3, 78.9, 76.5, 72.1) + ) + + plot(dataset) { + errorBars { + x(years) + yMin.constant(20.0) + yMax(max) + width = 0.5 + borderLine.width = 1.3 + } + } + // SampleEnd + .saveSample() + } + @Test fun fixed_error_bars_collections() { // SampleStart @@ -240,6 +331,28 @@ class ErrorBars : SampleHelper("errorBars") { .saveSample() } + @Test + fun grouped_error_bars_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "time" to (1..5).toList().let { (it + it).toColumn() }, + "min" to (listOf(2.0, 3.4, 3.5, 5.5, 2.5) + listOf(1.0, 2.0, 3.0, 4.0, 3.7)).toColumn(), + "max" to (listOf(3.0, 5.2, 5.0, 5.8, 3.4) + listOf(5.0, 4.0, 3.5, 5.0, 4.2)).toColumn(), + "category" to (List(5) { "a" } + List(5) { "b" }).toColumn() + ) + + dataset.groupBy { category }.plot { + errorBars { + x(time) { axis.breaks((1..5).toList(), format = "d") } + yMin(min) + yMax(max) + borderLine.color(category) + } + } + // SampleEnd + .saveSample() + } + @Test fun grouped_error_bars_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/densityPlot.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/densityPlot.kt index bb399c534..8582919d2 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/densityPlot.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/guides/densityPlot.kt @@ -2,6 +2,8 @@ package org.jetbrains.kotlinx.kandy.letsplot.samples.guides import org.apache.commons.math3.distribution.NormalDistribution import org.apache.commons.math3.distribution.UniformRealDistribution +import org.jetbrains.kotlinx.dataframe.AnyFrame +import org.jetbrains.kotlinx.dataframe.api.GroupBy import org.jetbrains.kotlinx.dataframe.api.column import org.jetbrains.kotlinx.dataframe.api.dataFrameOf import org.jetbrains.kotlinx.dataframe.api.groupBy @@ -34,7 +36,7 @@ class DensityPlot : SampleHelper("stat", "guides") { private val depthList = NormalDistribution(500.0, 100.0).sample(1000).toList() private val coeffList = UniformRealDistribution(0.0, 1.0).sample(1000).toList() - val df = dataFrameOf( + val df: AnyFrame = dataFrameOf( "depth" to depthList, "coeff" to coeffList ) @@ -241,13 +243,13 @@ class DensityPlot : SampleHelper("stat", "guides") { private val rangesB = NormalDistribution(400.0, 80.0).sample(5000).toList() // Gather them into `DataFrame` with "A" and "B" keys in the "category" column - private val rangesDF = dataFrameOf( + private val rangesDF: AnyFrame = dataFrameOf( "range" to rangesA + rangesB, "category" to List(5000) { "A" } + List(5000) { "B" } ) private val range = column("range") private val category = column("category") - private val groupedRangesDF = rangesDF.groupBy { category } + private val groupedRangesDF: GroupBy = rangesDF.groupBy { category } @Test fun guideDensityGenerateGroupedData() { diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/heatmap.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/heatmap.kt index b4b228632..35d0db644 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/heatmap.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/heatmap.kt @@ -58,6 +58,51 @@ class Heatmap : SampleHelper("heatmap") { .saveSample() } + @Test + fun heatmap_simple_dataframeCompilerPlugin() { + // SampleStart + val dataframe = dataFrameOf( + "days" to columnOf( + "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Sun", + "Sat", "Thu", "Fri", "Tue", "Wed", "Sun", "Mon", "Thu", + "Sun", "Sat", "Tue", "Mon", "Thu", "Wed", "Fri", "Sat", + "Tue", "Sun", "Fri", "Sat", "Thu", "Mon", "Wed", "Tue", + "Thu", "Mon", "Sun", "Fri", "Wed", "Sat", "Tue", "Thu", + "Sat", "Tue", "Sun", "Mon", "Wed", "Fri", "Thu", "Sat", + "Thu", "Fri", "Sun", "Tue", "Sat", "Wed", "Mon", "Thu", + "Wed", "Tue", "Sat", "Fri", "Sun", "Thu", "Mon", "Tue", + "Fri", "Thu", "Wed", "Sun", "Sat", "Mon", "Tue", "Thu", + "Tue", "Wed", "Sun", "Mon", "Thu", "Sat", "Fri", "Tue", + "Thu", "Sun", "Fri", "Sat", "Mon", "Wed", "Tue", "Thu", + "Sat", "Mon", "Tue", "Thu", "Fri", "Sun", "Wed", "Sat", + "Sun", "Fri", "Tue", "Thu", "Sat", "Mon", "Wed", "Sun", + "Mon", "Wed", "Sat", "Fri", "Thu", "Tue", "Sun", "Sat", + ), + "drinks" to columnOf( + "soda", "tea", "coffee", "tea", "soda", "tea", "coffee", "soda", + "coffee", "soda", "tea", "coffee", "soda", "tea", "coffee", "tea", + "coffee", "soda", "tea", "soda", "coffee", "tea", "soda", "coffee", + "soda", "tea", "coffee", "tea", "soda", "coffee", "tea", "soda", + "tea", "soda", "coffee", "tea", "soda", "coffee", "soda", "tea", + "coffee", "soda", "tea", "soda", "coffee", "tea", "soda", "coffee", + "soda", "coffee", "tea", "soda", "coffee", "soda", "tea", "coffee", + "soda", "coffee", "tea", "soda", "tea", "soda", "coffee", "tea", + "tea", "coffee", "soda", "tea", "coffee", "soda", "tea", "soda", + "tea", "soda", "coffee", "soda", "tea", "coffee", "soda", "coffee", + "tea", "coffee", "soda", "tea", "soda", "coffee", "soda", "tea", + "coffee", "soda", "tea", "coffee", "tea", "soda", "coffee", "soda", + "soda", "tea", "coffee", "soda", "tea", "coffee", "soda", "tea", + "coffee", "tea", "soda", "coffee", "tea", "soda", "coffee", "soda" + ) + ) + + dataframe.plot { + heatmap(days, drinks) + } + // SampleEnd + .saveSample() + } + @Test fun heatmap_simple_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/histogram.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/histogram.kt index d246b2386..e7d328c4d 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/histogram.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/histogram.kt @@ -32,6 +32,21 @@ class Histogram : SampleHelper("histogram") { .saveSample() } + @Test + fun histogram_simple_dataframeCompilerPlugin() { + // SampleStart + val random = java.util.Random(42) + val dataframe = dataFrameOf( + "sample" to List(1000) { random.nextGaussian() } + ) + + dataframe.plot { + histogram(sample) + } + // SampleEnd + .saveSample() + } + @Test fun histogram_simple_collections() { // SampleStart @@ -80,6 +95,41 @@ class Histogram : SampleHelper("histogram") { .saveSample() } + @Test + fun histogram_settings_dataframeCompilerPlugin() { + // SampleStart + val experimentalData = dataFrameOf( + "length" to columnOf( + 5.92, 6.44, 5.87, 4.99, 5.23, + 5.67, 4.89, 5.34, 5.78, 5.12, + 5.56, 5.23, 5.78, 6.01, 5.56, + 5.67, 5.89, 5.45, 6.12, 5.78, + 6.34, 5.67, 6.45, 5.34, 5.89, + 6.01, 5.78, 5.23, 5.67, 6.12, + 6.23, 5.45, 5.56, 5.67, 5.78, + 5.56, 6.23, 5.78, 6.34, 6.12, + 5.89, 6.45, 5.78, 6.34, 5.67, + 6.56, 5.45, 5.78, 5.89, 6.12, + 4.67, 4.79, 5.14, 5.28, 5.22, + ) + ) + experimentalData.plot { + histogram(length, binsOption = BinsOption.byNumber(12)) { + width = 0.8 + alpha = 0.9 + fillColor = Color.RED + borderLine { + color = Color.GREEN + width = 0.5 + } + x.axis.name = "length" + } + layout.title = "Flight length experiment" + } + // SampleEnd + .saveSample() + } + @Test fun histogram_settings_collections() { // SampleStart @@ -133,6 +183,26 @@ class Histogram : SampleHelper("histogram") { .saveSample() } + @Test + fun histogram_grouped_dataframeCompilerPlugin() { + // SampleStart + val random = java.util.Random(42) + + val sampleA = List(1000) { random.nextGaussian() * 0.7 + 2.0 } + val sampleB = List(1000) { random.nextGaussian() * 1.4 + 3.5 } + + val df = dataFrameOf( + "sample" to sampleA + sampleB, + "group" to sampleA.map { "A" } + sampleB.map { "B" } + ) + + df.groupBy { group }.plot { + histogram(sample) + } + // SampleEnd + .saveSample() + } + @Test fun histogram_grouped_collections() { // SampleStart @@ -182,6 +252,35 @@ class Histogram : SampleHelper("histogram") { .saveSample() } + @Test + fun histogram_with_line_dataframeCompilerPlugin() { + // SampleStart + val random = java.util.Random(42) + + val sampleDf = dataFrameOf( + "sample" to List(1000) { random.nextGaussian() } + ) + + sampleDf.plot { + statBin(sample, binsOption = BinsOption.byNumber(15)) { + bars { + alpha = 0.9 + x(Stat.x) + y(Stat.count) + } + line { + x(Stat.x) + y(Stat.count) + color = Color.RED + width = 1.5 + type = LineType.LONGDASH + } + } + } + // SampleEnd + .saveSample() + } + @Test fun histogram_with_line_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/lines.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/lines.kt index b1b3cbd69..634ae09c3 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/lines.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/lines.kt @@ -43,6 +43,24 @@ class Lines : SampleHelper("line") { .saveSample() } + @Test + fun simple_line_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "years" to columnOf("2018", "2019", "2020", "2021", "2022"), + "cost" to columnOf(62.7, 64.7, 72.1, 73.7, 68.5) + ) + + df.plot { + line { + x(years) + y(cost) + } + } + // SampleEnd + .saveSample() + } + @Test fun simple_line_collections() { // SampleStart @@ -87,6 +105,38 @@ class Lines : SampleHelper("line") { .saveSample() } + @Test + fun simple_line_settings_dataframeCompilerPlugin() { + // SampleStart + val museumVisitors = dataFrameOf( + "date" to columnOf( + LocalDate(2023, 1, 1).toString(), + LocalDate(2023, 1, 15).toString(), + LocalDate(2023, 2, 1).toString(), + LocalDate(2023, 2, 15).toString(), + LocalDate(2023, 3, 1).toString(), + LocalDate(2023, 3, 15).toString(), + LocalDate(2023, 4, 1).toString(), + LocalDate(2023, 4, 15).toString(), + LocalDate(2023, 5, 1).toString(), + LocalDate(2023, 5, 15).toString() + ), + "visitors" to columnOf(120, 95, 110, 123, 130, 140, 150, 160, 175, 180) + ) + + museumVisitors.plot { + line { + x(date) + y(visitors) + type = LineType.DASHED + color = Color.PURPLE + width = 2.5 + } + } + // SampleEnd + .saveSample() + } + @Test fun simple_line_settings_collections() { // SampleStart @@ -139,6 +189,31 @@ class Lines : SampleHelper("line") { .saveSample() } + @Test + fun line_with_points_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "area" to columnOf(30, 40, 50, 60, 70, 80, 90), + "price" to columnOf(60000, 80000, 75000, 90000, 85000, 95000, 90000) + ) + + df.plot { + x(price) + y(area) + line { + color = Color.BLUE + type = LineType.LONGDASH + } + points { + size = 3.5 + symbol = Symbol.CIRCLE_OPEN + color = Color.BLUE + } + } + // SampleEnd + .saveSample() + } + @Test fun line_with_points_collections() { // SampleStart @@ -193,6 +268,38 @@ class Lines : SampleHelper("line") { .saveSample() } + @Test + fun line_fixed_coord_dataframeCompilerPlugin() { + // SampleStart + data class DayTemperature(val day: String, val temp: Int) + + val weeklyTemp = listOf( + DayTemperature("Mon", 10), + DayTemperature("Tue", 6), + DayTemperature("Wed", 5), + DayTemperature("Thu", 7), + DayTemperature("Fri", 7), + DayTemperature("Sat", 11), + DayTemperature("Sun", 9) + ).toDataFrame() + + weeklyTemp.plot { + x(day) + line { + y(temp) + color = Color.BLUE + } + line { + y.constant(weeklyTemp.temp.mean()) + color = Color.GREEN + type = LineType.DOTTED + width = 2.5 + } + } + // SampleEnd + .saveSample() + } + @Test fun line_fixed_coord_collections() { // SampleStart @@ -249,6 +356,36 @@ class Lines : SampleHelper("line") { .saveSample() } + @Test + fun line_color_gradient_dataframeCompilerPlugin() { + // SampleStart + val monthTemp = dataFrameOf("month", "temp")( + "January", -5, + "February", -3, + "March", 2, + "April", 10, + "May", 16, + "June", 20, + "July", 22, + "August", 21, + "September", 15, + "October", 9, + "November", 3, + "December", -2 + ) + + monthTemp.plot { + line { + x(month) + y(temp) { scale = continuous(-10..25) } + color(temp) { scale = continuous(Color.BLUE..Color.RED) } + width = 3.0 + } + } + // SampleEnd + .saveSample() + } + @Test fun line_color_gradient_collections() { // SampleStart @@ -301,6 +438,30 @@ class Lines : SampleHelper("line") { .saveSample() } + @Test + fun line_reversed_axis_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "product" to ('A'..'F').map { it.toString() }.toColumn(), + "rating" to columnOf(10, 7, 3, 5, 2, 1) + ) + + plot(dataset) { + line { + x(rating) { + scale = continuous(min = 0, max = 12) + } + y(product) { + scale = continuous(transform = Transformation.REVERSE) + } + color = Color.RED + alpha = 0.85 + } + } + // SampleEnd + .saveSample() + } + @Test fun line_reversed_axis_collections() { // SampleStart @@ -347,6 +508,31 @@ class Lines : SampleHelper("line") { .saveSample() } + @Test + fun several_lines_dataframeCompilerPlugin() { + // SampleStart + val months = listOf(1, 2, 3, 4, 5) + val salesProducts = listOf(200.0, 220.0, 180.0, 240.0, 210.0) + val salesClothes = listOf(150.0, 130.0, 160.0, 140.0, 170.0) + val salesElectronics = listOf(300.0, 320.0, 310.0, 330.0, 340.0) + + val dataset = dataFrameOf( + "month" to months + months + months, + "sales" to salesProducts + salesClothes + salesElectronics, + "category" to List(5) { "Products" } + List(5) { "Clothes" } + List(5) { "Electronics" } + ) + + dataset.groupBy { category }.plot { + line { + x(month) + y(sales) + color(category) + } + } + // SampleEnd + .saveSample() + } + @Test fun several_lines_collections() { // SampleStart @@ -445,6 +631,52 @@ class Lines : SampleHelper("line") { .saveSample(true) } + @Test + fun line_mark_dataframeCompilerPlugin() { + // SampleStart + val months = listOf( + "January", "February", + "March", "April", "May", + "June", "July", "August", + "September", "October", "November", + "December" + ) + val tempBerlin = + listOf(-0.5, 0.0, 4.8, 9.0, 14.3, 17.5, 19.2, 18.9, 14.5, 9.7, 4.7, 1.0) + val tempMadrid = + listOf(6.3, 7.9, 11.2, 12.9, 16.7, 21.1, 24.7, 24.2, 20.3, 15.4, 9.9, 6.6) + + val df = dataFrameOf( + "month" to months + months, + "temperature" to tempBerlin + tempMadrid, + "city" to List(12) { "Berlin" } + List(12) { "Madrid" } + ) + + df.plot { + line { + x(month) + y(temperature) + color(city) { scale = categorical("Berlin" to Color.PURPLE, "Madrid" to Color.ORANGE) } + width = 1.5 + } + hLine { + yIntercept.constant(tempBerlin.average()) + color = Color.PURPLE + alpha = 0.9 + type = LineType.DASHED + } + hLine { + yIntercept.constant(tempMadrid.average()) + color = Color.ORANGE + alpha = 0.9 + type = LineType.DASHED + } + layout.size = 1000 to 450 + } + // SampleEnd + .saveSample(true) + } + @Test fun line_mark_collections() { // SampleStart @@ -517,7 +749,7 @@ class Lines : SampleHelper("line") { // SampleEnd .apply { val layout = (this.features as MutableMap)[FeatureName("layout")] as? Layout - (this.features as MutableMap)[FeatureName("layout")] = layout?.copy(size = null) ?: Layout(size = null) + (this.features)[FeatureName("layout")] = layout?.copy(size = null) ?: Layout(size = null) } .saveSample() } diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/pie.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/pie.kt index 4250b0c2a..ae878a1c8 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/pie.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/pie.kt @@ -31,6 +31,24 @@ class Pie : SampleHelper("pie") { .saveSample() } + @Test + fun pie_base_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "value" to columnOf(15, 22, 40, 7, 31), + "type" to columnOf("A", "B", "C", "A", "D") + ) + + df.plot { + pie { + slice(value) + fillColor(type) + } + } + // SampleEnd + .saveSample() + } + @Test fun pie_base_collections() { // SampleStart @@ -76,6 +94,37 @@ class Pie : SampleHelper("pie") { .saveSample() } + @Test + fun pie_settings_dataframeCompilerPlugin() { + // SampleStart + val usersLanguages = dataFrameOf( + "language" to columnOf("Kotlin", "Java", "C++", "JavaScript", "C#", "Other"), + "users" to columnOf(563, 481, 202, 406, 150, 312) + ) + + usersLanguages.plot { + pie { + slice(users) + fillColor(language) { + scale = categorical( + "Kotlin" to Color.hex("#1E88E5"), + "Java" to Color.hex("#D32F2F"), + "C++" to Color.hex("#7B1FA2"), + "JavaScript" to Color.hex("#FBC02D"), + "C#" to Color.hex("#388E3C"), + "Other" to Color.hex("#757575") + ) + } + size = 33.0 + hole = 0.8 + alpha = 0.8 + } + layout.style(Style.Void) + } + // SampleEnd + .saveSample() + } + @Test fun pie_settings_collections() { // SampleStart @@ -124,6 +173,25 @@ class Pie : SampleHelper("pie") { .saveSample() } + @Test + fun pie_with_void_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "platform" to columnOf("Linux", "MacOS", "Windows"), + "count" to columnOf(30, 239, 566) + ) + + df.plot { + pie { + slice(count) + fillColor(platform) + } + layout { style(Style.Void) } + } + // SampleEnd + .saveSample() + } + @Test fun pie_with_void_collections() { // SampleStart @@ -167,6 +235,28 @@ class Pie : SampleHelper("pie") { .saveSample() } + @Test + fun pie_explode_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "range" to columnOf("0-10m", "10-20m", "20-40m", "40-100m", "100-250m", ">250m"), + "share" to columnOf(0.42, 0.23, 0.15, 0.11, 0.06, 0.03), + "explode" to columnOf(0.20, 0.0, 0.04, 0.08, 0.12, 0.16) + ) + + df.plot { + pie { + slice(share) + fillColor(range) { scale = continuous(Color.RED..Color.LIGHT_GREEN) } + explode(explode) + size = 25.0 + } + layout { style(Style.Void) } + } + // SampleEnd + .saveSample() + } + @Test fun pie_explode_collections() { // SampleStart @@ -214,6 +304,29 @@ class Pie : SampleHelper("pie") { .saveSample() } + @Test + fun nightingale_chart_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "month" to columnOf("Jan", "Feb", "Mar", "May", "Apr"), + "amount" to columnOf(34.4, 25.1, 33.6, 20.0, 15.9) + ) + + df.plot { + pie { + slice(amount) + fillColor(month) + size(amount) { + scale = continuous(10.0..25.0) + legend.type = LegendType.None + } + } + layout { style(Style.Void) } + } + // SampleEnd + .saveSample() + } + @Test fun nightingale_chart_collections() { // SampleStart @@ -262,6 +375,33 @@ class Pie : SampleHelper("pie") { .saveSample() } + @Test + fun pie_with_count_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "continent" to columnOf( + "EU", "AF", "SA", "OC", "EU", "AF", "SA", "AF", "AS", "SA", + "OC", "OC", "SA", "NA", "AF", "NA", "EU", "AF", "OC", "SA", + "AF", "SA", "OC", "EU", "AF" + ) + ) + + df.plot { + statCount(continent) { + pie { + slice(Stat.count) + fillColor(Stat.x named "continent") + size = 25.0 + } + } + layout { + style(Style.Void) + } + } + // SampleEnd + .saveSample() + } + @Test fun pie_with_count_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/points.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/points.kt index 54bca36c6..f8ab3e68e 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/points.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/points.kt @@ -47,6 +47,34 @@ class Points : SampleHelper("points") { .saveSample() } + @Test + fun basic_points_plot_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "xs" to columnOf( + 5.93, 9.15, 3.76, 5.04, 2.23, + 7.47, 2.59, 11.67, 7.90, 3.71, + 0.03, 2.73, 4.61, 5.44, 1.76, + 14.46, 1.89 + ), + "ys" to columnOf( + 14.66, 13.80, 5.37, 6.40, 6.86, + 2.98, 6.69, 5.48, 3.67, 12.36, + 0.01, 14.47, 14.56, 9.19, 12.86, + 5.37, 0.90 + ) + ) + + dataset.plot { + points { + x(xs) + y(ys) + } + } + // SampleEnd + .saveSample() + } + @Test fun basic_points_plot_collections() { // SampleStart @@ -103,6 +131,37 @@ class Points : SampleHelper("points") { .saveSample() } + @Test + fun points_settings_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "xs" to columnOf( + 5.93, 9.15, 3.76, 5.04, 2.23, + 7.47, 2.59, 11.67, 7.90, 3.71, + 0.03, 2.73, 4.61, 5.44, 1.76, + 14.46, 1.89 + ), + "ys" to columnOf( + 14.66, 13.80, 5.37, 6.40, 6.86, + 2.98, 6.69, 5.48, 3.67, 12.36, + 0.01, 14.47, 14.56, 9.19, 12.86, + 5.37, 0.90 + ) + ) + + dataset.plot { + points { + x(xs) + y(ys) + size = 10.0 + color = Color.BLUE + symbol = Symbol.DIAMOND + } + } + // SampleEnd + .saveSample() + } + @Test fun points_settings_collections() { // SampleStart @@ -162,6 +221,39 @@ class Points : SampleHelper("points") { .saveSample() } + @Test + fun points_with_abLine_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "xValues" to columnOf( + 7.13, 9.30, 7.84, 7.08, 5.51, + 8.40, 5.69, 11.59, 12.53, 4.98, + 10.29, 6.88, 7.38, 12.03, 0.92 + ), + "yValues" to columnOf( + 7.05, 8.23, 6.74, 7.95, 5.38, + 7.47, 4.88, 9.17, 9.30, 6.17, + 6.58, 5.87, 6.45, 10.53, 3.13 + ) + ) + + dataset.plot { + points { + x(xValues) + y(yValues) + size = 7.0 + color = Color.LIGHT_BLUE + } + abLine { + slope.constant(0.5) + intercept.constant(3) + color = Color.RED + } + } + // SampleEnd + .saveSample() + } + @Test fun points_with_abLine_collections() { // SampleStart @@ -252,6 +344,45 @@ class Points : SampleHelper("points") { .saveSample() } + @Test + fun points_with_color_by_category_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "xShot" to columnOf( + 4.02, 5.24, 4.41, 3.99, 3.10, 4.73, 3.20, 6.53, 7.05, 2.81, + 5.80, 3.87, 4.16, 6.78, 0.52, 0.64, 0.15, 6.09, 5.70, 6.37 + ), + "yShot" to columnOf( + 2.39, 1.95, 1.13, 1.90, 0.29, 1.56, 0.35, 2.30, 1.27, 1.01, + 0.65, 1.89, 1.11, 1.39, 0.05, 1.51, 1.49, 1.51, 2.30, 1.66 + ), + "outcome" to columnOf( + false, true, false, true, true, true, true, true, true, false, + true, true, false, false, true, false, false, true, true, false + ) + ) + + dataset.plot { + points { + x(xShot) { axis.name = "Horizontal Position (meters)" } + y(yShot) { axis.name = "Vertical Position (meters)" } + size = 8.5 + color(outcome) { + scale = categorical( + true to Color.GREEN, false to Color.RED + ) + legend { + name = "Outcome" + breaksLabeled(true to "Goal", false to "Miss") + } + } + } + layout.title = "Penalty Shot Outcomes Analysis" + } + // SampleEnd + .saveSample() + } + @Test fun points_with_color_by_category_collections() { // SampleStart @@ -352,6 +483,29 @@ class Points : SampleHelper("points") { // SampleEnd } + @Test + fun jittered_points_dataframeCompilerPlugin() { + // SampleStart + val random = kotlin.random.Random(42) + val dataset = dataFrameOf( + "type" to (List(50) { "a" } + List(50) { "b" }).toColumn(), + "value" to (List(50) { kotlin.random.Random.nextDouble(0.1, 0.6) } + + List(50) { random.nextDouble(-0.5, 0.4) } + ).toColumn() + ) + + dataset.plot { + points { + x(type) + y(value) + color(type) + position = Position.jitter() + } + } + // SampleEnd + //.saveSample() + } + @Test fun bubble_chart() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/quickstart.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/quickstart.kt index 5c54ce91f..34ea794ab 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/quickstart.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/quickstart.kt @@ -59,6 +59,47 @@ class QuickStart : SampleHelper("", "") { .saveSample() } + @Test + fun quickstart_sample_dataframeCompilerPlugin() { + // SampleStart + val weatherData = dataFrameOf( + "time" to listOf(0, 1, 2, 4, 5, 7, 8, 9), + "temperature" to listOf(12.0, 14.2, 15.1, 15.9, 17.9, 15.6, 14.2, 24.3), + "humidity" to listOf(0.5, 0.32, 0.11, 0.89, 0.68, 0.57, 0.56, 0.5) + ) + + weatherData.plot { // Begin plotting + x(time) // Set x-axis with time data + y(temperature) { // Set y-axis with temperature data + // Define scale for temperature (y-axis) + scale = continuous(0.0..25.5) + } + + bars { // Add a bar layer + fillColor(humidity) { // Customizing bar colors based on humidity + // Setting the color range + scale = continuous(range = Color.YELLOW..Color.RED) + } + borderLine.width = 0.0 // Define border line width + } + + line { + width = 3.0 // Set line width + color = Color.hex("#6e5596") // Define line color + type = LineType.DOTDASH // Specify the line type + } + + layout { // Set plot layout + title = "Simple plot with kandy-lets-plot" // Add title + // Add caption + caption = "See `examples` section for more\n complicated and interesting examples!" + size = 700 to 450 // Plot dimension settings + } + } + // SampleEnd + .saveSample() + } + @Test fun quickstart_sample_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/ribbon.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/ribbon.kt index e7d093c03..0d89858f6 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/ribbon.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/ribbon.kt @@ -40,6 +40,26 @@ class Ribbon : SampleHelper("ribbon") { .saveSample() } + @Test + fun ribbon_simple_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "xs" to columnOf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0), + "mins" to columnOf(0.2, 0.9, 0.55, 1.32, 2.2, 1.5), + "maxs" to columnOf(0.7, 1.4, 1.1, 2.1, 2.6, 2.2) + ) + + df.plot { + ribbon { + x(xs) + yMin(mins) + yMax(maxs) + } + } + // SampleEnd + .saveSample() + } + @Test fun ribbon_simple_collections() { // SampleStart @@ -87,6 +107,37 @@ class Ribbon : SampleHelper("ribbon") { .saveSample() } + @Test + fun ribbon_settings_dataframeCompilerPlugin() { + // SampleStart + val df = dataFrameOf( + "year" to columnOf("2019", "2020", "2021", "2022", "2023"), + "minCost" to columnOf(56.5, 59.9, 60.8, 78.9, 75.5), + "maxCost" to columnOf(58.1, 69.3, 66.4, 108.3, 92.2) + ) + + df.plot { + ribbon { + x(year) + y { + axis.name = "cost" + scale = continuous(55.0..110.0) + } + yMin(minCost) + yMax(maxCost) + fillColor = Color.hex(0x3f21e6) + alpha = 0.65 + borderLine { + color = Color.RED + width = 0.8 + type = LineType.DASHED + } + } + } + // SampleEnd + .saveSample() + } + @Test fun ribbon_settings_collections() { // SampleStart diff --git a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/tiles.kt b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/tiles.kt index 87f79a29b..329417b00 100644 --- a/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/tiles.kt +++ b/kandy-lets-plot/src/test/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/tiles.kt @@ -60,6 +60,38 @@ class Tiles : SampleHelper("tiles") { .saveSample() } + @Test + fun tiles_settings_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "store" to columnOf("A", "B", "C", "A", "B", "C", "A", "B", "C"), + "time" to columnOf( + "morning", "morning", "morning", + "afternoon", "afternoon", "afternoon", + "evening", "evening", "evening" + ), + "money" to columnOf(75, 64, 59, 82, 88, 91, 69, 77, 73) + ) + + dataset.plot { + tiles { + x(store) + y(time) + height = 0.7 + borderLine { + width = 0.8 + color = Color.BLACK + } + fillColor(money) { + scale = continuous(Color.RED..Color.GREEN) + } + alpha = 0.5 + } + } + // SampleEnd + .saveSample() + } + @Test fun tiles_settings_collections() { // SampleStart @@ -137,6 +169,43 @@ class Tiles : SampleHelper("tiles") { .saveSample() } + @Test + fun tiles_gradient_dataframeCompilerPlugin() { + // SampleStart + val dataset = dataFrameOf( + "xCol" to columnOf( + 1.0, 2.0, 3.0, 4.0, 5.0, + 1.0, 2.0, 3.0, 4.0, 5.0, + 1.0, 2.0, 3.0, 4.0, 5.0 + ), + "yCol" to columnOf( + 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, + 3.0, 3.0, 3.0, 3.0, 3.0 + ), + "value" to columnOf( + 6, 7, 8, 4, 2, + 7, 5, 6, 4, 3, + 8, 6, 5, 8, 4 + ) + ) + + dataset.plot { + tiles { + x(xCol) { axis.name = "x" } + y(yCol) { axis.name = "y" } + fillColor(value) { + legend.type = LegendType.None + scale = continuous(Color.hex("#E1F5FE")..Color.hex("#01579B")) + } + borderLine.width = 0.25 + } + layout.style(Style.Void) + } + // SampleEnd + .saveSample() + } + @Test fun tiles_gradient_collections() { // SampleStart @@ -200,6 +269,41 @@ class Tiles : SampleHelper("tiles") { .saveSample() } + @Test + fun tiles_color_categories_dataframeCompilerPlugin() { + // SampleStart + val cities = listOf("Yerevan", "Berlin", "Amsterdam", "Paphos") + val types = listOf("A", "B", "C") + val random = kotlin.random.Random(42) + val year22 = List(4) { types.random(random) } + val year23 = List(4) { types.random(random) } + val year24 = List(4) { types.random(random) } + + val dataset = dataFrameOf( + "city" to cities, + "2022" to year22, + "2023" to year23, + "2024" to year24 + ).gather { `2022` and `2023` and `2024` }.into("year", "value") + + plot(dataset) { + tiles { + x(city) + y(year) { + scale = categorical() + axis.breaks(format = "d") + } + width = 0.5 + height = 0.9 + fillColor(value) { + legend.breaks(types) + } + } + } + // SampleEnd + .saveSample() + } + @Test fun tiles_color_categories_collections() { // SampleStart diff --git a/util/samples-utils/src/main/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/SampleHelper.kt b/util/samples-utils/src/main/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/SampleHelper.kt index 364cb279e..b828c4ba3 100644 --- a/util/samples-utils/src/main/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/SampleHelper.kt +++ b/util/samples-utils/src/main/kotlin/org/jetbrains/kotlinx/kandy/letsplot/samples/SampleHelper.kt @@ -62,7 +62,9 @@ public abstract class SampleHelper(sampleName: String, folder: String = "samples * of the SVG files. When `true`, additional preview files are created with "preview_" prefixed to the file name. */ public fun Plot.saveSample(savePreview: Boolean = false) { - val name = testName.methodName.replace("_dataframe", "") + val name = testName.methodName + .replace("_dataframeCompilerPlugin", "") + .replace("_dataframe", "") saveAsSVG(name, savePreview) this.changeThemeToDarkMode() saveAsSVG("${name}_dark", savePreview) From df7ccf3e9646b5bde5ed35a216bdadc3e1966ab4 Mon Sep 17 00:00:00 2001 From: Nikita Klimenko Date: Fri, 21 Nov 2025 16:43:49 +0200 Subject: [PATCH 3/3] minor update plots --- .../geoms/guideLinesCompareLinePathSegmentsPlotBunch.svg | 6 +++--- .../guideLinesCompareLinePathSegmentsPlotBunch_dark.svg | 6 +++--- docs/images/guides/geoms/guidePieChartsInPlotGrid.svg | 8 ++++---- .../images/guides/geoms/guidePieChartsInPlotGrid_dark.svg | 8 ++++---- docs/images/guides/other/guideExportDensityPlot.svg | 8 ++++---- docs/images/guides/other/guideExportDensityPlot_dark.svg | 8 ++++---- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/images/guides/geoms/guideLinesCompareLinePathSegmentsPlotBunch.svg b/docs/images/guides/geoms/guideLinesCompareLinePathSegmentsPlotBunch.svg index 04abd19d2..2c6ab87f4 100644 --- a/docs/images/guides/geoms/guideLinesCompareLinePathSegmentsPlotBunch.svg +++ b/docs/images/guides/geoms/guideLinesCompareLinePathSegmentsPlotBunch.svg @@ -303,7 +303,7 @@ font-size: 13.0px; - + @@ -594,7 +594,7 @@ font-size: 13.0px; - + @@ -942,7 +942,7 @@ font-size: 13.0px; - + diff --git a/docs/images/guides/geoms/guideLinesCompareLinePathSegmentsPlotBunch_dark.svg b/docs/images/guides/geoms/guideLinesCompareLinePathSegmentsPlotBunch_dark.svg index d58acb64d..f7836b6de 100644 --- a/docs/images/guides/geoms/guideLinesCompareLinePathSegmentsPlotBunch_dark.svg +++ b/docs/images/guides/geoms/guideLinesCompareLinePathSegmentsPlotBunch_dark.svg @@ -387,7 +387,7 @@ font-size: 13.0px; - + @@ -678,7 +678,7 @@ font-size: 13.0px; - + @@ -1026,7 +1026,7 @@ font-size: 13.0px; - + diff --git a/docs/images/guides/geoms/guidePieChartsInPlotGrid.svg b/docs/images/guides/geoms/guidePieChartsInPlotGrid.svg index cefb919db..8ce4279d4 100644 --- a/docs/images/guides/geoms/guidePieChartsInPlotGrid.svg +++ b/docs/images/guides/geoms/guidePieChartsInPlotGrid.svg @@ -287,7 +287,7 @@ font-size: 13.0px; - + @@ -303,7 +303,7 @@ font-size: 13.0px; - + @@ -580,7 +580,7 @@ font-size: 13.0px; - + @@ -596,7 +596,7 @@ font-size: 13.0px; - + diff --git a/docs/images/guides/geoms/guidePieChartsInPlotGrid_dark.svg b/docs/images/guides/geoms/guidePieChartsInPlotGrid_dark.svg index 76f3758d3..cfdf5c3dd 100644 --- a/docs/images/guides/geoms/guidePieChartsInPlotGrid_dark.svg +++ b/docs/images/guides/geoms/guidePieChartsInPlotGrid_dark.svg @@ -287,7 +287,7 @@ font-size: 13.0px; - + @@ -303,7 +303,7 @@ font-size: 13.0px; - + @@ -580,7 +580,7 @@ font-size: 13.0px; - + @@ -596,7 +596,7 @@ font-size: 13.0px; - + diff --git a/docs/images/guides/other/guideExportDensityPlot.svg b/docs/images/guides/other/guideExportDensityPlot.svg index 278e74c27..885a93310 100644 --- a/docs/images/guides/other/guideExportDensityPlot.svg +++ b/docs/images/guides/other/guideExportDensityPlot.svg @@ -180,19 +180,19 @@ font-size: 13.0px; - + - + - + - + diff --git a/docs/images/guides/other/guideExportDensityPlot_dark.svg b/docs/images/guides/other/guideExportDensityPlot_dark.svg index 23ae0d335..a905235e4 100644 --- a/docs/images/guides/other/guideExportDensityPlot_dark.svg +++ b/docs/images/guides/other/guideExportDensityPlot_dark.svg @@ -314,19 +314,19 @@ font-size: 13.0px; - + - + - + - +