Line & Scatter Plots

Plotting lines and points in 2-d

Basics

A line plot requires a list of data points, (x, y) pairs, with the data type and in the coordinate system of the axes provided to the enclosing XYGraph. As an example, we want to plot the function \( y=x^2 \) with x from 1 to 10 with two Float axes:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
    val data = buildList {
        for (i in 1..10) {
            add(DefaultPoint(i.toFloat(), i * i.toFloat()))
        }
    }

    XYGraph(
        rememberFloatLinearAxisModel(data.autoScaleXRange()),
        rememberFloatLinearAxisModel(data.autoScaleYRange())
    ) {
        LinePlot(
            data,
            lineStyle = LineStyle(SolidColor(Color.Blue))
        )
    }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Line1.kt

Line1

Lines 1-5 generate the data to plot. The data for Line plots is a list of x, y coordinates provided by an implementation of the Point interface. This example uses the provided implementation, DefaultPoint.

Lines 8 and 9 provide an AxisModel for each of the x and y axes to XYChart. In this case, we are using linear axes with floating point values (other types are covered in XY Graphs) and ranges that are calculated with the calls to autoScaleXRange() and autoScaleYRange().

Lines 11 through 13 call the LineChart Composable to render the line itself, using a solid blue style.

Adding a Second Line

Now lets add a second line plotting the function \( y=e^{\sqrt{x}} \), which looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
    XYGraph(
        rememberFloatLinearAxisModel(dataSquared.autoScaleXRange()),
        rememberFloatLinearAxisModel(dataSquared.autoScaleYRange())
    ) {
        LinePlot(
            dataSquared,
            lineStyle = LineStyle(SolidColor(Color.Blue))
        )
        LinePlot(
            dataExp,
            lineStyle = LineStyle(
                SolidColor(Color(0, 200, 0)),
                2.dp,
                dashPathEffect(floatArrayOf(20f, 10f))
            )
        )
    }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Line2.kt

Line2

Scatter Plots

A scatter plot is very similar to a line plot, and uses the same LinePlot Composable function, except instead of lines connecting data points a symbol is drawn at each data point. In Koala Plot, the symbols are themselves Composables, and to make it even simpler provides the Symbol Composable to make it easy to use a Shape with any fill and outline. Beyond the standard Compose circle and rectangle shapes, Koala Plot also defines additional shapes that are common for graphs, such as the TriangleShape and DiamondShape.

The below example illustrates a scatter plot using the default RectangleShape used by Symbol.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
    val data = buildList {
        val random = Random(10)
        for (i in 1..50) {
            val x = random.nextDouble(1.0, 10.0).toFloat()
            val y = (x + (random.nextDouble() - 0.5) * 2.0).toFloat()

            add(DefaultPoint(x, y))
        }
    }

    XYGraph(
        rememberFloatLinearAxisModel(0f..12f),
        rememberFloatLinearAxisModel(0f..12f)
    ) {
        LinePlot(
            data,
            symbol = { Symbol(fillBrush = SolidColor(Color.Blue), outlineBrush = SolidColor(Color.Black)) }
        )
    }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Scatter1.kt

Scatter plot

Combining Lines & Symbols

Combining lines and symbols on a single XYGraph is as simple as repeatedly using LinePlot for each data series to be plotted. The below example illustrates the scatter plot from the previous example, together with a plot of a line.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    val data = buildList {
        val random = Random(10)
        for (i in 1..50) {
            val x = random.nextDouble(1.0, 10.0).toFloat()
            val y = (x + (random.nextDouble() - 0.5) * 2.0).toFloat()

            add(DefaultPoint(x, y))
        }
    }
    val line = buildList {
        add(DefaultPoint(-5f, -5f))
        add(DefaultPoint(15f, 15f))
    }

    XYGraph(
        rememberFloatLinearAxisModel(0f..12f),
        rememberFloatLinearAxisModel(0f..12f)
    ) {
        LinePlot(line, lineStyle = LineStyle(SolidColor(Color.Blue)))
        LinePlot(
            data,
            symbol = { Symbol(fillBrush = SolidColor(Color.Blue), outlineBrush = SolidColor(Color.Black)) }
        )
    }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Scatter2.kt

Scatter plot

The z-order of the plots corresponds to the order in which they appear in the XYGraph, so in this example the line is plotted first, and the rectangle symbols are plotted second and draw over the line.

It is also possible to plot both lines and symbols with the same LinePlot, as illustrated below, which is a modification of the previous example plotting the function \( y=x^2 \).

1
2
3
4
5
        LinePlot(
            data,
            lineStyle = LineStyle(SolidColor(Color.Blue)),
            symbol = { Symbol(fillBrush = SolidColor(Color.Blue), outlineBrush = SolidColor(Color.Black)) }
        )
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Line3.kt

Line with symbols

StairStep Plots

The StairstepPlot is a variant of a line plot that draws series as points and stairsteps between points. A simple example is shown below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
    val data = buildList {
        for (i in 1..10) {
            add(DefaultPoint(i.toFloat(), i * i.toFloat()))
        }
    }

    XYGraph(
        rememberFloatLinearAxisModel(data.autoScaleXRange()),
        rememberFloatLinearAxisModel(data.autoScaleYRange())
    ) {
        StairstepPlot(
            data,
            lineStyle = LineStyle(SolidColor(Color.Blue))
        )
    }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Stairstep1.kt

Stairstep plot

A variant of StairstepPlot lets you specify a line style for each level. This is illustrated below where the coloring of the step at each level is varied according to the y-axis value.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
    val data = buildList {
        for (i in 1..10) {
            add(DefaultPoint(i.toFloat(), i * i.toFloat()))
        }
    }

    XYGraph(
        rememberFloatLinearAxisModel(data.autoScaleXRange()),
        rememberFloatLinearAxisModel(data.autoScaleYRange())
    ) {
        StairstepPlot(
            data,
            lineStyle = LineStyle(SolidColor(Color.Transparent)),
            levelLineStyle = { y ->
                LineStyle(SolidColor(Color(red = y / 100f, green = 0f, blue = 0f)), strokeWidth = 4.dp)
            }
        )
    }
/examples/src/jvmMain/kotlin/io/github/koalaplot/example/Stairstep2.kt

Stairstep plot 2


Last modified April 23, 2024: Changes for 0.6.0 (19018a1)