Skip to content

Commit 54bf3fe

Browse files
committed
more documentation
1 parent 67b3e3b commit 54bf3fe

File tree

2 files changed

+87
-24
lines changed

2 files changed

+87
-24
lines changed

docs/marks/difference.md

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
import * as Plot from "@observablehq/plot";
44
import * as d3 from "d3";
5-
import {computed, ref, shallowRef, onMounted} from "vue";
5+
import {computed, shallowRef, onMounted} from "vue";
66

7-
const shift = ref(365);
87
const aapl = shallowRef([]);
98
const gistemp = shallowRef([]);
109
const tsa = shallowRef([{Date: new Date("2020-01-01")}]);
@@ -19,11 +18,11 @@ onMounted(() => {
1918

2019
</script>
2120

22-
# Difference mark
21+
# Difference mark <VersionBadge pr="1896" />
2322

24-
The **difference mark** compares a metric. Like the [area mark](./area.md), the region between two lines is filled; unlike the area mark, alternating color shows when the primary metric is above or below the secondary metric.
23+
The **difference mark** puts a metric in context by comparing it to something. Like the [area mark](./area.md), the region between two lines is filled; unlike the area mark, alternating color shows when the metric is above or below the comparison value.
2524

26-
In the simplest case, the difference mark compares a metric to a constant, often zero. For example, the plot below shows the [global surface temperature anomaly](https://data.giss.nasa.gov/gistemp/) from 1880–2016; 0° represents the 1951–1980 average; above-average temperatures are in <span style="border-bottom: solid var(--vp-c-red) 3px;">red</span>, while below-average temperatures are in <span style="border-bottom: solid var(--vp-c-blue) 3px;">blue</span>. (It’s getting hotter.)
25+
In the simplest case, the difference mark compares a metric to a constant. For example, the plot below shows the [global surface temperature anomaly](https://data.giss.nasa.gov/gistemp/) from 1880–2016; 0° represents the 1951–1980 average; above-average temperatures are in <span style="border-bottom: solid var(--vp-c-red) 3px;">red</span>, while below-average temperatures are in <span style="border-bottom: solid var(--vp-c-blue) 3px;">blue</span>. (It’s getting hotter.)
2726

2827
:::plot
2928
```js
@@ -37,7 +36,7 @@ Plot.differenceY(gistemp, {
3736
```
3837
:::
3938

40-
Applying a 24-month [moving average](../transforms/window.md) improves readability by smoothing the noise.
39+
A 24-month [moving average](../transforms/window.md) improves readability by smoothing out the noise.
4140

4241
:::plot
4342
```js
@@ -54,25 +53,23 @@ Plot.differenceY(
5453
```
5554
:::
5655

57-
More powerfully, the difference mark compares two metrics.
58-
59-
Comparing metrics is most convenient when the data has a column for each. For example, the plot below shows the number of daily travelers through TSA checkpoints in 2020 compared to 2019. In the first two months of 2020, there were on average <span style="border-bottom: solid #01ab63 3px;">more travelers</span> per day than 2019; yet when COVID-19 hit, there were many <span style="border-bottom: solid #4269d0 3px;">fewer travelers</span> per day, dropping almost to zero.
56+
More powerfully, the difference mark compares two metrics. For example, the plot below shows the number of travelers per day through TSA checkpoints in 2020 compared to 2019. (This in effect compares a metric against itself, but as the data represents each year as a separate column, we can think of it as two separate metrics.) In the first two months of 2020, there were on average <span style="border-bottom: solid #01ab63 3px;">more travelers</span> per day than 2019; yet when COVID-19 hit, there were many <span style="border-bottom: solid #4269d0 3px;">fewer travelers</span> per day, dropping almost to zero.
6057

6158
:::plot
6259
```js
6360
Plot.plot({
6461
x: {tickFormat: "%b"},
6562
y: {grid: true, label: "Travelers"},
6663
marks: [
67-
Plot.axisY({label: "Daily travelers (thousands, 2020 vs. 2019)", tickFormat: (d) => d / 1000}),
64+
Plot.axisY({label: "Travelers per day (thousands, 2020 vs. 2019)", tickFormat: (d) => d / 1000}),
6865
Plot.ruleY([0]),
6966
Plot.differenceY(tsa, {x: "Date", y1: "2019", y2: "2020", tip: {format: {x: "%B %-d"}}})
7067
]
7168
})
7269
```
7370
:::
7471

75-
If the data is “tall” rather than “wide” — TK explain what this means — you can use the [group transform](../transforms/group.md) with the [find reducer](../transforms/group.md#find): group the rows by date, and then for the two output columns **y1** and **y2**, find the desired corresponding row. The plot below shows daily minimum temperature for San Francisco compared to San Jose. The insulating effect of the fog keeps San Francisco warmer in winter and cooler in summer, reducing seasonal variation.
72+
If the data is “tall” rather than “wide” — that is, if the two metrics we wish to compare are represented by separate *rows* rather than separate *columns* — we can use the [group transform](../transforms/group.md) with the [find reducer](../transforms/group.md#find): group the rows by **x** (date), then find the desired **y1** and **y2** for each group. The plot below shows daily minimum temperature for San Francisco compared to San Jose. Notice how the insulating fog keeps San Francisco <span style="border-bottom: solid #01ab63 3px;">warmer</span> in winter and <span style="border-bottom: solid #4269d0 3px;">cooler</span> in summer, reducing seasonal variation.
7673

7774
:::plot
7875
```js
@@ -103,32 +100,50 @@ Plot.plot({
103100
```
104101
:::
105102

106-
The difference mark can also be used to compare a metric *to itself* using the [shift transform](../transforms/shift.md). This is especially useful for time series that exhibit [periodicity](https://en.wikipedia.org/wiki/Seasonality) — which is most of them, and certainly ones that involve human behavior. In this way a difference mark can show week-over-week or year-over-year growth.
107-
108-
<p>
109-
<label class="label-input" style="display: flex;">
110-
<span style="display: inline-block; width: 7em;">Shift:</span>
111-
<input type="range" v-model.number="shift" min="0" max="1000" step="1">
112-
<span style="font-variant-numeric: tabular-nums;">{{shift}}</span>
113-
</label>
114-
</p>
103+
The difference mark can also be used to compare a metric to itself using the [shift transform](../transforms/shift.md). The chart below shows year-over-year growth in the price of Apple stock.
115104

116105
:::plot
117106
```js
118-
Plot.differenceY(aapl, Plot.shiftX(`${shift} days`, {x: "Date", y: "Close"})).plot({y: {grid: true}})
107+
Plot.differenceY(aapl, Plot.shiftX("+1 year", {x: "Date", y: "Close"})).plot({y: {grid: true}})
119108
```
120109
:::
121110

122-
TK Something about if you sold Apple stock after holding it for a year, you’d tend to do pretty well. But if you hold it for less time, you see more blue. And even if you held it for a year, you could have still lost money if you sold in most of 2016. Even the unluckiest person would have made money if they held Apple stock for 780+ days (in 2015–2018).
111+
For most of the covered time period, you would have <span style="border-bottom: solid #01ab63 3px;">made a profit</span> by holding Apple stock for a year; however, if you bought in 2015 and sold in 2016, you would likely have <span style="border-bottom: solid #4269d0 3px;">lost money</span>.
123112

124113
## Difference options
125114

126-
TK
115+
The following channels are required:
116+
117+
* **x2** - the horizontal position of the metric; bound to the *x* scale
118+
* **y2** - the vertical position of the metric; bound to the *y* scale
119+
120+
In addition to the [standard mark options](../features/marks.md#mark-options), the following optional channels are supported:
121+
122+
* **x1** - the horizontal position of the comparison; bound to the *x* scale
123+
* **y1** - the vertical position of the comparison; bound to the *y* scale
124+
125+
If **x1** is not specified, it defaults to **x2**. If **y1** is not specified, it defaults to **y2** — TODO that’s not right, because **y1** defaults to zero for differenceY. These defaults facilitate sharing *x* or *y* coordinates between the metric and its comparison.
126+
127+
TODO
128+
129+
* **fill**
130+
* **positiveFill**
131+
* **negativeFill**
132+
* **fillOpacity**
133+
* **positiveFillOpacity**
134+
* **negativeFillOpacity**
135+
* **stroke**
136+
* **strokeOpacity**
137+
138+
TODO
139+
140+
* **z**
141+
* **clip**
127142

128143
## differenceY(*data*, *options*) {#differenceY}
129144

130145
```js
131146
Plot.differenceY(gistemp, {x: "Date", y: "Anomaly"})
132147
```
133148

134-
TK
149+
TODO

docs/transforms/shift.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<script setup>
2+
3+
import * as Plot from "@observablehq/plot";
4+
import * as d3 from "d3";
5+
import {ref, shallowRef, onMounted} from "vue";
6+
7+
const shift = ref(365);
8+
const aapl = shallowRef([]);
9+
10+
onMounted(() => {
11+
d3.csv("../data/aapl.csv", d3.autoType).then((data) => (aapl.value = data));
12+
});
13+
14+
</script>
15+
16+
# Shift transform <VersionBadge pr="1896" />
17+
18+
The **shift transform** is a specialized [map transform](./map.md) that derives an output **x1** channel by shifting the **x** channel; it can be used with the [difference mark](../marks/difference.md) to show change over time. For example, the chart below shows the price of Apple stock. The <span style="border-bottom: solid #01ab63 3px;">green region</span> shows when the price went up over the given interval, while the <span style="border-bottom: solid #4269d0 3px;">blue region</span> shows when the price went down.
19+
20+
<p>
21+
<label class="label-input" style="display: flex;">
22+
<span style="display: inline-block; width: 7em;">Shift (days):</span>
23+
<input type="range" v-model.number="shift" min="0" max="1000" step="1">
24+
<span style="font-variant-numeric: tabular-nums;">{{shift}}</span>
25+
</label>
26+
</p>
27+
28+
:::plot hidden
29+
```js
30+
Plot.differenceY(aapl, Plot.shiftX(`${shift} days`, {x: "Date", y: "Close"})).plot({y: {grid: true}})
31+
```
32+
:::
33+
34+
```js-vue
35+
Plot.differenceY(aapl, Plot.shiftX("{{shift}} days", {x: "Date", y: "Close"})).plot({y: {grid: true}})
36+
```
37+
38+
When looking at year-over-year growth, the chart is mostly green, implying that you would make a profit by holding Apple stock for a year. However, if you bought in 2015 and sold in 2016, you would likely have lost money. Try adjusting the slider to a shorter or longer interval: how does that affect the typical return?
39+
40+
## shiftX(*interval*, *options*) {#shiftX}
41+
42+
```js
43+
Plot.shiftX("7 days", {x: "Date", y: "Close"})
44+
```
45+
46+
Derives an **x1** channel from the input **x** channel by shifting values by the given *interval*. The *interval* may be specified as: a name (*second*, *minute*, *hour*, *day*, *week*, *month*, *quarter*, *half*, *year*, *monday*, *tuesday*, *wednesday*, *thursday*, *friday*, *saturday*, *sunday*) with an optional number and sign (*e.g.*, *+3 days* or *-1 year*); or as a number; or as an implementation — such as d3.utcMonth — with *interval*.floor(*value*), *interval*.offset(*value*), and *interval*.range(*start*, *stop*) methods.
47+
48+
The shiftX also transform aliases the **x** channel to **x2** and applies a domain hint to the **x2** channel such that by default the plot shows only the intersection of **x1** and **x2**. For example, if the interval is *+1 year*, the first year of the data is not shown.

0 commit comments

Comments
 (0)