Overriding Default Grouping with the group Aesthetic¶

How Grouping Works in Lets-Plot-Kotlin¶

Default Grouping Behavior:

  • Lets-Plot-Kotlin automatically groups data by discrete variables mapped to aesthetics like color, shape, linetype, etc.
  • This creates separate visual elements (lines, paths, polygons) for each unique combination of these variables

Explicit Group Control:

  • Use group = "var" to group only by that specific variable, overriding default grouping
  • Use group = listOf(var1, var2, ...) to group by the interaction of multiple variables
  • Use group = emptyList<String> to disable all grouping completely
In [1]:
%useLatestDescriptors
%use dataframe
%use lets-plot(output="js, png")
In [2]:
LetsPlot.getInfo()
Out[2]:
Lets-Plot Kotlin API v.4.12.0. Frontend: Notebook with dynamically loaded JS. Lets-Plot JS v.4.8.1.
Outputs: Web (HTML+JS), Static PNG (hidden)
In [3]:
val df = DataFrame.readCSV("https://raw.githubusercontent.com/JetBrains/lets-plot-docs/refs/heads/master/data/mpg.csv")
val mtcars = df.toMap()
df.head()
Out[3]:

DataFrame: rowsCount = 5, columnsCount = 12

untitledmanufacturermodeldisplyearcyltransdrvctyhwyflclass
1audia41,80000019994auto(l5)f1829pcompact
2audia41,80000019994manual(m5)f2129pcompact
3audia42,00000020084manual(m6)f2031pcompact
4audia42,00000020084auto(av)f2130pcompact
5audia42,80000019996auto(l5)f1626pcompact

1. Highway MPG by Drive Type¶

In [4]:
val seed = 21
letsPlot(mtcars) { x = "drv"; y = "hwy" } +
    geomViolin(tooltips = tooltipsNone) +
    geomSina(seed = seed)
Out[4]:
image

2. Add More Information - color¶

In [5]:
letsPlot(mtcars) { x = "drv"; y = "hwy" } +
    geomViolin(tooltips = tooltipsNone) +
    geomSina(seed = seed) {
        color = "cyl"
    }
Out[5]:
image

3. Discrete color: Default Grouping Creates Unwanted Separation¶

Let's add discrete colors by marking the cyl variable as discrete.

When we map color=asDiscrete("cyl"), Lets-Plot automatically groups the data by the discrete color variable.
This means:

  • Automatic grouping: Each combination of drv (x-axis) and cyl (color) becomes a separate group
  • Position adjustment: The geomSina() uses "dodge" positioning by default, which separates overlapping groups horizontally
  • Result: Instead of one sina plot per drive type, we get 4 separate sina plots (one for each cylinder count) within each drive type category
In [6]:
letsPlot(mtcars) { x = "drv"; y = "hwy" } +
    geomViolin(tooltips = tooltipsNone) +
    geomSina(seed = seed) {
        color = asDiscrete("cyl")
    }
Out[6]:
image

4. Fix with Explicit Grouping by Drive Type¶

In [7]:
letsPlot(mtcars) { x = "drv"; y = "hwy" } +
    geomViolin(tooltips = tooltipsNone) +
    geomSina(seed = seed) {
        color = asDiscrete("cyl")
        
        group = "drv"      // <-- group only by drive type (ignoring the color variable for grouping)
    }
Out[7]:
image

5. Cleaner Fix: Disable All Grouping¶

In [8]:
letsPlot(mtcars) { x = "drv"; y = "hwy" } +
    geomViolin(tooltips = tooltipsNone) +
    geomSina(seed = seed) {
        color = asDiscrete("cyl")
        
        group = emptyList<String>()     // <-- disable all grouping entirely
    }
Out[8]:
image