Skip to content

Commit 6c76b8b

Browse files
authored
Polish area and ribbon layers (#97)
* ribbon translates ymin/ymax * translate linetype linewidth * forgot name change * add linewidth aesthetic * implement area stacking * add some docs * streamline geom specifics * extract logic to functions * add tests for area stacking and ribbon translation - Add render_ribbon tests for ymin/ymax to y/y2 translation - Add render_area tests for all stacking parameter values (on/off/fill/default) - Add render_area test for invalid stacking values - Fix render_ribbon bug: ymin should map to y2 not y - Update test_variant_aesthetics to use errorbar instead of ribbon * cargo fmt * remove colour as aesthetic
1 parent 41846fe commit 6c76b8b

6 files changed

Lines changed: 332 additions & 44 deletions

File tree

doc/syntax/index.qmd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ There are many different layers to choose from when visualising your data. Some
1818
- [`point`](layer/point.qmd) is used to create a scatterplot layer
1919
- [`line`](layer/line.qmd) is used to produce lineplots with the data sorted along the x axis
2020
- [`path`](layer/path.qmd) is like `line` above but does not sort the data but plot it according to its own order
21+
- [`area`](layer/area.qmd) is used to display series as an area chart.
22+
- [`ribbon`](layer/ribbon.qmd) is used to display series extrema.
2123
- [`bar`](layer/bar.qmd) creates a bar chart, optionally calculating y from the number of records in each bar
2224
- [`histogram`](layer/histogram.qmd) bins the data along the x axis and produces a bar for each bin showing the number of records in it
2325
- [`boxplot`](layer/boxplot.qmd) displays continuous variables as 5-number summaries

doc/syntax/layer/area.qmd

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
title: "Area"
3+
---
4+
5+
> Layers are declared with the [`DRAW` clause](../clause/draw.qmd). Read the documentation for this clause for a thorough description of how to use it.
6+
7+
The area layer is used to display absolute amounts over a sorted x-axis. It can be seen as a [ribbon layer](ribbon.qmd) where the `ymin` is anchored at zero.
8+
9+
## Aesthetics
10+
The following aesthetics are recognised by the area layer.
11+
12+
### Required
13+
* `x`: Position along the x-axis.
14+
* `y`: Position along the y-axis.
15+
16+
### Optional
17+
* `stroke`: The colour of the contour lines.
18+
* `fill`: The colour of the inner area.
19+
* `colour`: Shorthand for setting `stroke` and `fill` simultaneously.
20+
* `opacity`: The opacity of the colours.
21+
* `linewidth`: The width of the contour lines.
22+
23+
## Settings
24+
* `stacking`: Determines how multiple groups are displayed. One of the following:
25+
* `'off'`: The groups `y`-values are displayed as-is (default).
26+
* `'on'`: The `y`-values are stacked per `x` position, accumulating over groups.
27+
* `'fill'`: Like `'on'` but displayed as a fraction of the total per `x` position.
28+
29+
## Data transformation
30+
The area layer does not transform its data but passes it through unchanged.
31+
32+
## Examples
33+
34+
Create a typical area chart
35+
36+
```{ggsql}
37+
VISUALISE FROM ggsql:airquality
38+
DRAW area
39+
MAPPING Date AS x, Wind AS y
40+
```
41+
42+
We can reshape the data to 'long format' from our wide format.
43+
44+
```{ggsql}
45+
CREATE TABLE long_airquality AS
46+
SELECT * FROM ggsql:airquality
47+
UNPIVOT(
48+
Value FOR Series IN (Temp, Wind)
49+
) AS u;
50+
```
51+
52+
Which means we can display multiple series at once, by mapping the identifier to an aesthetic.
53+
54+
```{ggsql}
55+
VISUALISE Date AS x, Value AS y FROM long_airquality
56+
DRAW area MAPPING Series AS colour
57+
```
58+
59+
We can stack the series by using `stacking => 'on'`. The line serves as a reference for 'unstacked' data.
60+
61+
```{ggsql}
62+
VISUALISE Date AS x, Value AS y, Series AS colour FROM long_airquality
63+
DRAW area SETTING stacking => 'on', opacity => 0.5
64+
DRAW line
65+
```
66+
67+
When `stacking => 'fill'` we're plotting stacked proportions. These only make sense if every series is measured in the same absolute unit. (Wind and temperature have different units and the temperature is not absolute.)
68+
69+
```{ggsql}
70+
VISUALISE Date AS x, Value AS y, Series AS colour FROM long_airquality
71+
DRAW area SETTING stacking => 'fill'
72+
```

doc/syntax/layer/ribbon.qmd

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
---
2+
title: "Ribbon"
3+
---
4+
5+
> Layers are declared with the [`DRAW` clause](../clause/draw.qmd). Read the documentation for this clause for a thorough description of how to use it.
6+
7+
The ribbon layer is used to display extrema over a sorted x-axis. It can be seen as an [area chart](area.qmd) that is unanchored from zero.
8+
9+
## Aesthetics
10+
The following aesthetics are recognised by the ribbon layer.
11+
12+
### Required
13+
* `x`: Position along the x-axis
14+
* `ymin`: Lower position along the y-axis.
15+
* `ymax`: Upper position along the y-axis.
16+
17+
### Optional
18+
* `stroke`: The colour of the contour lines.
19+
* `fill`: The colour of the inner area.
20+
* `colour`: Shorthand for setting `stroke` and `fill` simultaneously.
21+
* `opacity`: The opacity of the colours.
22+
* `linewidth`: The width of the contour lines.
23+
24+
## Settings
25+
The ribbon layer has no additional settings.
26+
27+
## Data transformation
28+
The ribbon layer does not transform its data but passes it through unchanged.
29+
30+
## Examples
31+
32+
A ribbon plot with arbitrary values as minima/maxima
33+
34+
```{ggsql}
35+
VISUALISE FROM ggsql:airquality
36+
DRAW ribbon
37+
MAPPING Date AS x, Wind AS ymin, Temp AS ymax
38+
```
39+
40+
Ribbon plots are great for showing the range of some aggregation.
41+
42+
```{ggsql}
43+
// Weekly aggregation of temperature
44+
SELECT
45+
WEEKOFYEAR(Date) AS Week,
46+
MAX(Temp) AS MaxTemp,
47+
MEAN(Temp) AS MeanTemp,
48+
MIN(Temp) AS MinTemp
49+
FROM ggsql:airquality
50+
GROUP BY WEEKOFYEAR(Date)
51+
52+
VISUALISE Week AS x
53+
DRAW ribbon
54+
MAPPING MinTemp AS ymin, MaxTemp AS ymax
55+
SETTING opacity => 0.5
56+
DRAW line
57+
MAPPING MeanTemp AS y
58+
```

src/plot/layer/geom/area.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! Area geom implementation
22
3+
use crate::plot::{DefaultParam, DefaultParamValue};
4+
35
use super::{GeomAesthetics, GeomTrait, GeomType};
46

57
/// Area geom - filled area charts
@@ -13,11 +15,26 @@ impl GeomTrait for Area {
1315

1416
fn aesthetics(&self) -> GeomAesthetics {
1517
GeomAesthetics {
16-
supported: &["x", "y", "color", "colour", "fill", "stroke", "opacity"],
18+
supported: &[
19+
"x",
20+
"y",
21+
"fill",
22+
"stroke",
23+
"opacity",
24+
"linewidth",
25+
// "linetype", // vegalite doesn't support strokeDash
26+
],
1727
required: &["x", "y"],
1828
hidden: &[],
1929
}
2030
}
31+
32+
fn default_params(&self) -> &'static [DefaultParam] {
33+
&[DefaultParam {
34+
name: "stacking",
35+
default: DefaultParamValue::String("off"),
36+
}]
37+
}
2138
}
2239

2340
impl std::fmt::Display for Area {

src/plot/layer/geom/ribbon.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@ impl GeomTrait for Ribbon {
1414
fn aesthetics(&self) -> GeomAesthetics {
1515
GeomAesthetics {
1616
supported: &[
17-
"x", "ymin", "ymax", "color", "colour", "fill", "stroke", "opacity",
17+
"x",
18+
"ymin",
19+
"ymax",
20+
"fill",
21+
"stroke",
22+
"opacity",
23+
"linewidth",
24+
// "linetype" // vegalite doesn't support strokeDash
1825
],
1926
required: &["x", "ymin", "ymax"],
2027
hidden: &[],

0 commit comments

Comments
 (0)