# Normalize transform

The **normalize transform** is a specialized map transform that normalizes series values relative to some basis, say to convert absolute values into relative values. For example, here is an index chart — a type of multi-series line chart — showing the return of several stocks relative to their closing price on a particular date.

```
Plot.plot({
y: {
type: "log",
grid: true,
label: "Change in price (%)",
tickFormat: ((f) => (x) => f((x - 1) * 100))(d3.format("+d"))
},
marks: [
Plot.ruleY([1]),
Plot.line(stocks, Plot.normalizeY({
x: "Date",
y: "Close",
stroke: "Symbol"
})),
Plot.text(stocks, Plot.selectLast(Plot.normalizeY({
x: "Date",
y: "Close",
z: "Symbol",
text: "Symbol",
textAnchor: "start",
dx: 3
})))
]
})
```

TIP

The select transform is used to label the endpoints of each line.

INFO

This example uses an immediately-invoked function expression (IIFE) for the **tickFormat** option so that the d3.format only needs to be constructed once.

The normalize transform converts absolute values into relative ones. So, if **y** is [*y₀*, *y₁*, *y₂*, …] and the *first* basis is used with normalizeY, the resulting output **y** channel is [*y₀* / *y₀*, *y₁* / *y₀*, *y₂* / *y₀*, …]. But it’s a bit more complicated than this in practice since **y** is first grouped by **z**, **fill**, or **stroke** into separate series.

As another example, the normalize transform can be used to compute proportional demographics from absolute populations. The plot below compares the demographics of U.S. states: color represents age group, **y** represents the state, and **x** represents the proportion of the state’s population in that age group.

```
Plot.plot({
height: 660,
axis: null,
grid: true,
x: {
axis: "top",
label: "Population (%)",
percent: true
},
color: {
scheme: "spectral",
domain: stateage.ages, // in age order
legend: true
},
marks: [
Plot.ruleX([0]),
Plot.ruleY(stateage, Plot.groupY({x1: "min", x2: "max"}, {...xy, sort: {y: "x1"}})),
Plot.dot(stateage, {...xy, fill: "age", title: "age"}),
Plot.text(stateage, Plot.selectMinX({...xy, textAnchor: "end", dx: -6, text: "state"}))
]
})
```

`xy = Plot.normalizeX("sum", {z: "state", x: "population", y: "state"})`

TIP

To reduce code duplication, pull shared options out into an object (here `xy`

) and then merge them into each mark’s options using the spread operator (`...`

).

## Normalize options

The **basis** option specifies how to normalize the series values; it is one of:

*first*- the first value, as in an index chart; the default*last*- the last value*min*- the minimum value*max*- the maximum value*mean*- the mean value (average)*median*- the median value*pXX*- the percentile value, where XX is a number in [00,99]*sum*- the sum of values*extent*- the minimum is mapped to zero, and the maximum to one*deviation*- subtract the mean, then divide by the standard deviation- a function to be passed an array of values, returning the desired basis
- a function to be passed an index and channel value array, returning the desired basis

## normalize(*basis*) ^0.2.3

`Plot.map({y: Plot.normalize("first")}, {x: "Date", y: "Close", stroke: "Symbol"})`

Returns a normalize map method for the given *basis*, suitable for use with the map transform.

## normalizeX(*basis*, *options*)

`Plot.normalizeX("first", {y: "Date", x: "Close", stroke: "Symbol"})`

Like mapX, but applies the normalize map method with the given *basis*. The **basis** option can also be mixed into the specified *options* like so:

`Plot.normalizeX({basis: "first", y: "Date", x: "Close", stroke: "Symbol"})`

If not specified, the *basis* defaults to *first*.

## normalizeY(*basis*, *options*)

`Plot.normalizeY("first", {x: "Date", y: "Close", stroke: "Symbol"})`

Like mapY, but applies the normalize map method with the given *basis*. The **basis** option can also be mixed into the specified *options* like so:

`Plot.normalizeY({basis: "first", x: "Date", y: "Close", stroke: "Symbol"})`

If not specified, the *basis* defaults to *first*.