Kandy Kotlin Plotting Library

repository·main·Indexed 20 days ago

https://github.com/kotlin/kandy

An open-source Kotlin plotting library providing a flexible DSL for creating charts. It supports multiple engines including Lets-Plot and Apache ECharts via modules such as kandy-lets-plot and kandy-echarts. Kandy offers a wide range of geometric objects (geoms) like scatter, line, and bar plots, as well as statistical transformations including histograms, boxplots, and density plots. It is compatible with standard IntelliJ IDEA projects and interactive environments like Kotlin Notebooks, Datalore, and Jupyter.

Tokens
126.4K
Snippets
413
Records
494
Agent score
72%

What's inside Kandy

  1. Overview of Kandy modules and engines

    main

    Kandy is a plotting library that provides a unified DSL for different visualization engines. The library is split into several modules:

    • kandy-api: The core API for creating charts.
    • kandy-lets-plot: Implementation of the Lets-Plot engine, based on the Grammar of Graphics.
    • kandy-echarts: Implementation of the Apache ECharts engine, focused on interactive visualizations.
    • kandy-statistics (Experimental): Provides statistical plotting extensions like histograms and boxplots.
  2. What is Kandy?

    main

    Kandy is an open-source data visualization library for Kotlin that provides an idiomatic, type-safe, and flexible DSL for creating graphs. It uses a Plot Intermediate Representation (IR) that allows it to support multiple rendering engines.

    Key engines include:

    • kandy-lets-plot: The primary engine based on the Lets-Plot library. It supports interactive notebooks, standalone HTML files, and exports to PNG, SVG, and JPEG.
    • kandy-echarts: An experimental module utilizing echarts.js for rendering.

    Kandy integrates with:

    • Kotlin Collections: Use standard Kotlin collections as data sources.
    • Kotlin DataFrame: Seamlessly integrates with the Kotlin DataFrame library, utilizing generated extension properties for hierarchical data construction.
  3. Explore Kandy API documentation

    main

    Kandy's API is organized into several functional areas to help you build plots, manipulate data, and customize visual elements. You can find detailed documentation for each component in the following categories:

    • Plot Basics: Core functions for creating plots, managing layouts, and configuring tooltips.
    • Data Manipulation: Methods for binding data to plots (withData) and grouping data (groupBy).
    • Statistics: Built-in statistical transformations like binning, boxplots, counts, density estimation, and smoothing.
    • Layers: A wide variety of geometric layers including bars, points, line, heatmap, boxplot, area, and more.
    • Scales: Configuration for mapping data values to visual properties.
    • Export: Tools for saving plots to files or converting them to images (e.g., toBufferedImage).
    • Other: Transformations such as coordinate systems and axis reversal.
  4. Explore Kandy Geoms and Statistical Plots

    main

    Kandy provides a wide range of geometric objects (geoms) and statistical transformations for data visualization. Key categories include:

    Geoms

    • Algebraic Curve: Modeling relationships with curves.
    • ErrorBars: Visualizing uncertainty.
    • Jitter Points: Reducing overplotting in scatter plots.
    • Lines: Connecting data points.
    • Pie: Representing proportions.
    • Ribbon: Highlighting ranges (e.g., confidence intervals).
    • Scatter: Standard point-based plots.

    Statistical Plots

    • Smoothing: Applying smoothing algorithms to data.
    • Histogram: Visualizing distributions.
    • Boxplot: Showing quartiles and outliers.
    • Heatmap: Representing 2D density or values.
    • Count Plot: Visualizing frequency counts.
    • Density Plot: Showing the probability density function.
  5. What is a GeoDataFrame?

    main

    A GeoDataFrame is a specialized structure for geospatial datasets. It is a wrapper around a standard DataFrame that includes a mandatory geometry column of type org.locationtech.jts.geom.Geometry.

    Key characteristics:

    • Automatic Mapping: Unlike standard Kandy plots, you do not need to perform manual positional mapping; geometries are automatically mapped to Kandy layers.
    • CRS Support: It includes a .crs field representing the Coordinate Reference System. If not explicitly defined (as is common in GeoJSON), it defaults to WGS84.
    • JTS Integration: It uses the Java Topology Suite (JTS) for geometry types and operations.
  6. How Count Plot statistics work

    main

    A Count Plot visualizes the frequency distribution of a categorical variable. It calculates the number of observations in each category.

    Key Concepts:

    • Weighted Counts: If weights are provided, the count for each category is the sum of the weights of all elements in that category. If weights is null (default), all weights are treated as 1.0.
    • Output Statistics: When using statCount or countPlot, the resulting dataset (a StatCountFrame) contains a Stat group with the following columns:
      • Stat.x: The category (type X).
      • Stat.count: The number of observations in the category (type Int).
      • Stat.countWeighted: The sum of weights in the category (type Double).
  7. Arrange multiple plots using plotBunch()

    main

    The plotBunch() function allows you to display a collection of plots within a single figure. Unlike automatic layout engines, plotBunch provides no automatic arrangement; instead, you manually specify the location and size for each plot in the collection. This gives you full control over how plots overlap or are positioned relative to one another.

    plotBunch {
        add(plot1, x, y, width, height)
        add(plot2, x, y, width, height)
    }
  8. Customize area plot colors using categorical scales

    main

    When using fillColor mapped to a discrete variable (like a city name), you can provide a custom color scale using the categorical function within the fillColor block. This allows you to map specific data values to specific Color objects.

    Example mapping:

    fillColor("city") {
        scale = categorical("Berlin" to Color.hex("#07C3F2"), "Madrid" to Color.hex("#FDB60D"))
    }
  9. Adjust position of overlapping layers (Lets-Plot workaround)

    main

    The Lets-Plot engine does not allow customization of positions between different layers (e.g., overlapping bars or areas).

    Workarounds:

    • Series Hack: Use the series hack guide to adjust positioning.
    • Apache Echarts Engine (Experimental): This engine provides an API with flexible position adjustment for data series.
  10. How faceting works in Kandy

    main
    Faceting allows you to add new dimensions to a plot by splitting your data into subsets based on one or more variables. Instead of using standard aesthetics (like color or size) to represent every dimension, faceting creates multiple sub-panels (tiles) to allow for a more comprehensive comparative analysis of different data segments.
  11. Access statistical properties in countPlot

    main

    When using countPlot, Kandy calculates specific statistical properties that you can use for mappings, tooltips, or further customization. These properties are available within the countPlot context:

    • Stat.x: A column containing the categories.
    • Stat.count: A column of type Int containing the number of observations in each category.
    • Stat.countWeighted: A column of type Double containing the sum of weights for each category. If no weights argument was provided to countPlot, these values will match Stat.count.
  12. Create a Custom Style with CustomStyle

    main

    You can define a comprehensive visual theme using a CustomStyle lambda. This allows you to group styling configurations for various plot elements like global, axis, legend, panel, plotCanvas, and strip in one place. This style can then be applied to plots using functions like pointPlotWithStyle or within a layout { style { ... } } block.

    Key configuration areas include:

    • global: Controls general line, background, and text properties.
    • axis: Configures ticks, ticksLength, onTop, and tooltip.
    • legend: Sets position, direction, justification, and background.
    • panel: Manages background and grid (major/minor lines).
    • plotCanvas: Styles the overall canvas, including the title and background.
    val styleOrangeConstructor: CustomStyle.() -> Unit = {
        global {
            line { color = orangeNormal; width = 2.0 }
            background { fillColor = orangeLight; borderLineWidth = 2.0 }
            text { color = orangeDark }
        }
        axis {
            ticks { color = orangeNormal; width = 1.0 }
            ticksLength = 7.0
            onTop = true
        }
        legend {
            position = LegendPosition.Bottom
        }
        panel.grid {
            majorLine { color = orangeNormal; width = .5 }
            minorLine { blank = true }
        }
        plotCanvas.background { fillColor = yellowLight; borderLineWidth = 1.0 }
        axis.tooltip.background { borderLineColor = orangeDark }
    }
    
    // Usage
    pointPlotWithStyle("Scatter plot", Style.None, styleOrangeConstructor)