A marginal plot is a scatterplot (sometimes a density plot or other bivariate plot) that has histograms, boxplots, or other distribution visualization layers in the margins of the x- and y-axes.
It allows studying the relationship between 2 numeric variables.
You can use the ggmarginal()
function to add marginal layers to a plot.
%useLatestDescriptors
%use dataframe
%use lets-plot
@file:DependsOn("org.apache.commons:commons-math3:3.6.1")
import org.apache.commons.math3.distribution.MultivariateNormalDistribution
val cov0 : Array<DoubleArray> = arrayOf(doubleArrayOf(1.0, -.8),
doubleArrayOf(-.8, 1.0))
val cov1 : Array<DoubleArray> = arrayOf(doubleArrayOf(10.0, .1),
doubleArrayOf(.1, .1))
val n = 200
val means0 : DoubleArray = doubleArrayOf(-2.0, 0.0)
val means1 : DoubleArray = doubleArrayOf(0.0, 1.0)
val xy0 = MultivariateNormalDistribution(means0, cov0).sample(n)
val xy1 = MultivariateNormalDistribution(means1, cov1).sample(n)
val dat = mapOf(
"x" to (xy0.map { it[0] } + xy1.map { it[0] }).toList(),
"y" to (xy0.map { it[1] } + xy1.map { it[1] }).toList(),
"c" to List(n){"A"} + List(n){"B"},
)
// The default plot theme and palette.
LetsPlot.theme = themeLight()
val paletteColors = listOf("#394449", "#F7C443")
val palette = scaleColorManual(values = paletteColors) + scaleFillManual(values = paletteColors)
val p = letsPlot(dat.toMap()){x = "x"; y = "y"; color = "c"; fill = "c"} + geomPoint() + palette
p
// Add marginal layers to any side on the plot:
// - [l]eft
// - [r]ight
// - [t]op
// - [b]ottom
p + ggmarginal("tr", layer = geomHistogram(color = "white")) +
ggmarginal("lb", layer = geomDensity(size = 0))
// Set constant colors to disable the grouping.
val pHist = p +
ggmarginal("tr", layer=geomHistogram(fill = "gray", color = "white")) +
ggmarginal("tr", layer=geomDensity(fill = "rgba(0,0,0,0)", color = "red"))
pHist
// Add marginal boxplots.
// Make margins smaller using the parameter `size`.
pHist + ggmarginal("lb", size=0.03, layer=geomBoxplot(fill = "white", color = "black"))
// Combine marginal violin and boxplot.
// Make margins much larger.
p + ggmarginal("rb", size=0.4, layer=geomViolin(trim = false, color = "black")) +
ggmarginal("rb", layer=geomBoxplot(mapping = {group = "c"}, fill = "white", color = "white",
alpha = .25, outlierColor = "red", width = .2))
// Show marginal densities on a 2D-density plot.
letsPlot(dat) {x = "x"; y = "y"} + geomDensity2DFilled {fill = "..level.."} + coordCartesian() +
ggmarginal("tr", layer = geomArea(stat = Stat.density()))
var mpg = DataFrame.readCSV("https://raw.githubusercontent.com/JetBrains/lets-plot-kotlin/master/docs/examples/data/mpg.csv")
mpg.head(3)
DataFrame: rowsCount = 3, columnsCount = 12
untitled | manufacturer | model | displ | year | cyl | trans | drv | cty | hwy | fl | class |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | audi | a4 | 1.800000 | 1999 | 4 | auto(l5) | f | 18 | 29 | p | compact |
2 | audi | a4 | 1.800000 | 1999 | 4 | manual(m5) | f | 21 | 29 | p | compact |
3 | audi | a4 | 2.000000 | 2008 | 4 | manual(m6) | f | 20 | 31 | p | compact |
// A marginal plot with a significant number of groups on margins.
val plotSettings = ggsize(900, 700) +
theme(plotBackground = elementRect(fill = "#eaeaea"),
legendBackground = elementRect(fill = "#eaeaea"))
(letsPlot(mpg.toMap()) {x = "cty"; y = "hwy"; fill = "manufacturer"}
+ geomPoint( size = 7, shape = 21, alpha = .5, color = "black", position = positionJitter(seed = 42))
+ ggmarginal("tr", size = 0.3,
layer = geomBoxplot(width=0.5) {
fill = asDiscrete("manufacturer", orderBy = "..lower..")
})
+ plotSettings)