This page is available as an executable or viewable Jupyter Notebook:

In [1]:
%useLatestDescriptors
%use lets-plot

@file:DependsOn("org.apache.commons:commons-math3:3.6.1")

In [2]:
import org.apache.commons.math3.distribution.MultivariateNormalDistribution

In [3]:
val cov0 : Array<DoubleArray> = arrayOf(doubleArrayOf(1.0, -.8),
doubleArrayOf(-.8, 1.0))

val cov1 : Array<DoubleArray> = arrayOf(doubleArrayOf(1.0, .8),
doubleArrayOf(.8, 1.0))

val cov2 : Array<DoubleArray> = arrayOf(doubleArrayOf(10.0, .1),
doubleArrayOf(.1, .1))

In [4]:
val n = 400

val means0 : DoubleArray = doubleArrayOf(-2.0, 0.0)
val means1 : DoubleArray = doubleArrayOf(2.0, 0.0)
val means2 : DoubleArray = doubleArrayOf(0.0, 1.0)

val xy0 = MultivariateNormalDistribution(means0, cov0).sample(n)
val xy1 = MultivariateNormalDistribution(means1, cov1).sample(n)
val xy2 = MultivariateNormalDistribution(means2, cov2).sample(n)

In [5]:
val data = mapOf(
"x" to (xy0.map { it[0] } + xy1.map { it[0] } + xy2.map { it[0] }).toList(),
"y" to (xy0.map { it[1] } + xy1.map { it[1] } + xy2.map { it[1] }).toList()
)

In [6]:
val p = letsPlot(data) {x="x"; y="y"} + ggsize(600,300) +
geomPoint(color="black", alpha=.1)
p

Out[6]:
In [7]:
// Basic density
p + geomDensity2D(color="red")

Out[7]:
In [8]:
// Set contour color by level
//  - change defailt position and size of colorbar
p + geomDensity2D {color="..level.."} +
scaleColorGradient(low="dark_green", high="yellow", guide=guideColorbar(barHeight=10, barWidth=300)) +
theme().legendPosition_bottom()

Out[8]:

### Filling contours by level¶

In [9]:
val p1 = letsPlot(data) {x="x"; y="y"} + ggsize(600,300)

// Filled polygons are not always working well - note missing polygons in the middle.
p1 + geomPolygon(stat=Stat.density2D()) {fill="..level.."} + coordFixed()

Out[9]: