# Box mark

The **box mark** summarizes one-dimensional distributions as boxplots. It is a composite mark consisting of a rule to represent the extreme values (not including outliers), a bar to represent the interquartile range (trimmed to the data), a tick to represent the median value, and a dot to represent any outliers. The group transform is used to group and aggregate data.

For example, the boxplot below shows A.A. Michelson’s experimental measurements of the speed of light. (Speed is in km/sec minus 299,000.)

Fork```
Plot.plot({
y: {
grid: true,
inset: 6
},
marks: [
Plot.boxY(morley, {x: "Expt", y: "Speed"})
]
})
```

boxY produces vertical boxplots; for horizontal boxplots, use boxX and swap **x** and **y**.

```
Plot.plot({
x: {
grid: true,
inset: 6
},
marks: [
Plot.boxX(morley, {x: "Speed", y: "Expt"})
]
})
```

As shorthand, you can pass an array of numbers for a single boxplot.

Fork`Plot.boxX([0, 3, 4.4, 4.5, 4.6, 5, 7]).plot()`

Since the box mark uses the group transform, the secondary dimension must be ordinal. To group quantitative values, bin manually, say with Math.floor; see #1330.

Fork```
Plot.plot({
marginLeft: 60,
y: {
grid: true,
label: "Price"
},
x: {
interval: 0.5,
label: "Carats",
labelAnchor: "right",
tickFormat: (x) => x.toFixed(1)
},
marks: [
Plot.ruleY([0]),
Plot.boxY(diamonds, {x: (d) => Math.floor(d.carat * 2) / 2, y: "price"})
]
})
```

This chart is slightly easier to construct with faceting using the **interval** scale option on the *fx* scale. (This technique cannot be used with the *x* scale above because the scale interval transform is applied *after* the box mark applies the group transform.)

```
Plot.plot({
marginLeft: 60,
y: {
grid: true,
label: "Price"
},
fx: {
interval: 0.5,
label: "Carats",
labelAnchor: "right",
tickFormat: (x) => x.toFixed(1)
},
marks: [
Plot.ruleY([0]),
Plot.boxY(diamonds, {fx: "carat", y: "price"})
]
})
```

## Box options

The box mark is a composite mark consisting of four marks:

- a rule representing the extreme values (not including outliers)
- a bar representing the interquartile range (trimmed to the data)
- a tick representing the median value, and
- a dot representing outliers, if any

The given *options* are passed through to these underlying marks, with the exception of the following options:

**fill**- the fill color of the bar; defaults to #ccc**fillOpacity**- the fill opacity of the bar; defaults to 1**stroke**- the stroke color of the rule, tick, and dot; defaults to*currentColor***strokeOpacity**- the stroke opacity of the rule, tick, and dot; defaults to 1**strokeWidth**- the stroke width of the tick; defaults to 1

## boxX(*data*, *options*)

`Plot.boxX(simpsons.map((d) => d.imdb_rating))`

Returns a horizontal box mark. If the **x** option is not specified, it defaults to the identity function, as when *data* is an array of numbers. If the **y** option is not specified, it defaults to null; if the **y** option is specified, it should represent an ordinal (discrete) value.

## boxY(*data*, *options*)

`Plot.boxY(simpsons.map((d) => d.imdb_rating))`

Returns a vertical box mark. If the **y** option is not specified, it defaults to the identity function, as when *data* is an array of numbers. If the **x** option is not specified, it defaults to null; if the **x** option is specified, it should represent an ordinal (discrete) value.