Plot.contour() constructor
Plot.contour(data, options) returns a new contour mark with the given optional data and options. The data parameter is optional; it represents discrete samples in abstract coordinates x and y. If data is not provided, the value channel must be a continuous function.
Contour grid bounds defaults
If width is specified, x1 defaults to 0 and x2 defaults to width. If height is specified, y1 defaults to 0 and y2 defaults to height. If data is specified but width/height are not, x1, y1, x2, and y2 respectively default to the frame's left, top, right, and bottom coordinates. If data is not specified and value is a function of x and y, you must specify all of x1, x2, y1, and y2 to define the raster domain.
Contour grid resolution options
The resolution of the raster grid may be specified with width (the number of pixels on each horizontal line) and height (the number of lines; a positive integer). Alternatively, raster dimensions may be imputed from x1, x2, y1, y2, and pixelSize (the screen size of a raster pixel; defaults to 1).
Contour value as continuous function
The value channel may be specified as a continuous function f(x,y) to be evaluated at each pixel centroid of the raster grid without interpolation. When faceting, the function f(x,y) is passed a third argument of the facet values {fx, fy}.
Contour smooth option
The smooth option specifies whether to apply linear interpolation after marching squares when computing contour polygons. Default is true.
Contour interpolate option
The interpolate option controls spatial interpolation. It is ignored when the value channel is a continuous function of x and y, and otherwise defaults to nearest.
Contour blur option
The blur option applies a Gaussian blur to the underlying raster grid, resulting in smoother contours. It specifies a non-negative pixel radius for smoothing prior to applying marching squares. Default is 0.
Contour mark with arbitrary point positions
The contour mark works with samples in arbitrary positions and arbitrary order, not just strictly gridded data. Pass x, y, and value channels for spatial interpolation to produce contours from irregular samples.
Contour levels with interval or thresholds
Contour levels can be specified either with the interval option (a contour at each multiple of the specified value) or with the thresholds option (either a count of thresholds or an explicit array of values), similar to the bin transform.
Contour channel evaluation
With the exception of x, y, x1, y1, x2, y2, and value channels, the contour mark's channels are not evaluated on the initial data but rather on the contour multipolygons generated in the initializer.
Contour grid row-major order
The grid is a list of numbers in row-major order. The first number is the value of the bottom-left corner. Elevations of the first row are followed by the second row, then the third, and so on. Grid points represent the middle of each pixel rather than the corner.
Contour drawing order and overlap
Contours are drawn in ascending value order, with the highest value on top. Filled contour polygons overlap. For isobands, see GitHub issue #1420.
Contour filled vs stroked
The value option produces isolines suitable for stroking. The fill option produces filled contours. Setting fill to Plot.identity applies a color encoding to the contour values, allowing the contour values to be read via a color legend.
Contour mark overview
The contour mark draws isolines to delineate regions above and below a particular continuous value. Contours are computed by applying the marching squares algorithm to a discrete grid. The grid can be constructed either by interpolating spatial samples (arbitrary points in x and y) or by sampling a continuous function f(x,y) along the grid.
Delaunay marks work with projections
The Delaunay marks including voronoi, voronoiMesh, delaunayLink, delaunayMesh, and hull work with Plot's projection system, allowing them to be used with geographic data.
hull draws convex hull around points
Plot.hull(data, options) draws a convex hull around the points given by x and y channels. The stroke option defaults to currentColor and the fill option defaults to none. When an aesthetic channel is specified, the hull inherits the channel value from one of its constituent points arbitrarily.
Delaunay marks one-dimensional support
The Delaunay marks can be one-dimensional by specifying only the x channel without y, which creates one-dimensional Voronoi tessellations.
delaunay marks introduced in version 0.5.1
The Delaunay marks were introduced in Observable Plot version 0.5.1.
delaunayLink color driven by endpoint arbitrarily
In delaunayLink, when stroke color is specified, the link color is driven by one arbitrary extremity of each edge and this might change in the future.
Planar vs spherical Voronoi warning
Distances between projected points are not exactly proportional to corresponding distances on the sphere, creating a discrepancy between the planar Voronoi diagram and its spherical counterpart. For greater accuracy with geographic data, use d3-geo-voronoi with the geo mark.
voronoiMesh z channel for grouping
If a z channel is specified in voronoiMesh, the input points are grouped by z, and separate Voronoi tessellations are constructed for each group.
voronoiMesh stroke and fill defaults
In voronoiMesh, the stroke option defaults to currentColor, strokeOpacity defaults to 0.2, and fill is not supported.
voronoiMesh draws cell boundaries only once
Plot.voronoiMesh(data, options) draws a mesh for the cell boundaries of the Voronoi tessellation of points given by x and y channels. Unlike voronoi which draws shared cell boundaries twice, voronoiMesh draws them only once.
voronoi supports aesthetic channels like stroke and fill
The voronoi mark supports aesthetic channels such as stroke, fill, fillOpacity, strokeOpacity, and href, which work the same way as on other marks like dots.
voronoi draws Voronoi tessellation cells
Plot.voronoi(data, options) draws polygons for each cell of the Voronoi tessellation of the points given by x and y channels. Each cell represents the region closest to its associated point.
hull z channel for grouping and defaults
If a z channel is specified in hull, the input points are grouped by z, and separate convex hulls are constructed for each group. If z is not specified, it defaults to either the fill channel if any, or the stroke channel if any.
delaunayMesh z channel for grouping
If a z channel is specified in delaunayMesh, the input points are grouped by z, and separate Delaunay triangulations are constructed for each group.
delaunayMesh draws mesh of Delaunay triangulation
Plot.delaunayMesh(data, options) draws a mesh of the Delaunay triangulation of points given by x and y channels. The stroke option defaults to currentColor and strokeOpacity defaults to 0.2. The fill option is not supported. When an aesthetic channel is specified, the mesh inherits the channel value from one of its constituent points arbitrarily.
delaunayLink draws edges from Delaunay triangulation
Plot.delaunayLink(data, options) draws links for each edge of the Delaunay triangulation of points given by x and y channels. It supports the same options as the link mark, except x1, y1, x2, and y2 are derived automatically from x and y. When an aesthetic channel like stroke or strokeWidth is specified, the link inherits the channel value from one of its two endpoints arbitrarily.
differenceY stroke options
The differenceY mark supports stroke (the metric line's stroke color, defaults to currentColor) and strokeOpacity (the metric line's opacity, defaults to 1).
differenceY with shift transform example
A differenceY mark can compare a metric to itself using the shift transform: Plot.differenceY(aapl, Plot.shiftX("+1 year", {x: "Date", y: "Close"})), which shows year-over-year changes.
differenceY with group and find example
To compare two metrics from tall data (separate rows), use Plot.differenceY(temperature, Plot.windowY(14, Plot.groupX({y1: Plot.find((d) => d.station === "SJ"), y2: Plot.find((d) => d.station === "SF")}, {x: "date", y: "tmin", tip: true}))).
differenceY comparing two separate metrics example
A differenceY mark can compare two separate metrics using y1 and y2 channels: Plot.differenceY(tsa, {x: "Date", y1: "2019", y2: "2020", tip: {format: {x: "%B %-d"}}}).
differenceY with window transform example
A differenceY mark can use the window transform to smooth data, such as Plot.differenceY(gistemp, Plot.windowY(24, {x: "Date", y: "Anomaly", positiveFill: "red", negativeFill: "blue", tip: true})), which applies a 24-month moving average.
differenceX mark
The differenceX mark is a horizontal difference mark that compares a metric to a comparison value by filling the region between two lines horizontally. It uses the same options and behavior as differenceY, but with x and y channels reversed. The signature is Plot.differenceX(data, {y: fieldName, x: fieldName}).
differenceY channel-based styling and z channel
When fill, stroke, or opacity options are defined as a channel in differenceY, the underlying marks are broken into contiguous overlapping segments when the values change. When any of these channels are used, setting an explicit z channel (possibly to null) is strongly recommended.
differenceY fill color options
The differenceY mark supports positiveFill (the color for when the metric is greater, defaults to green #01ab63), negativeFill (the color for when the comparison is greater, defaults to blue #4269d0), fillOpacity (the areas' opacity, defaults to 1), positiveFillOpacity (the positive area's opacity, defaults to opacity), and negativeFillOpacity (the negative area's opacity, defaults to opacity). The standard fill option is ignored.
differenceY mark optional channels
The differenceY mark supports optional channels x1 (the horizontal position of the comparison, bound to the x scale) and y1 (the vertical position of the comparison, bound to the y scale). If x1 is not specified, it defaults to x2. If y1 is not specified, it defaults to 0 if x1 and x2 are equal, and to y2 otherwise.
differenceY mark required channels
The differenceY mark requires two channels: x2 (the horizontal position of the metric, bound to the x scale) and y2 (the vertical position of the metric, bound to the y scale).
Difference mark purpose and use
The difference mark compares a metric to a comparison value by filling the region between two lines with alternating colors based on whether the metric is above or below the comparison. Like the area mark, it fills the region between two lines, but uses different colors for positive and negative differences. The difference mark can compare a metric to a constant, compare two separate metrics, or compare a metric to itself using transforms.
differenceY composition and clipping
The differenceY mark is a composite of a positive area, negative area, and line. The positive area extends from the bottom of the frame to the line and is clipped by the area extending from the comparison to the top of the frame. The negative area conversely extends from the top of the frame to the line and is clipped by the area extending from the comparison to the bottom of the frame.
density mark example with weight channel
Plot.plot({
inset: 10,
color: {legend: true},
marks: [
Plot.density(penguins.filter((d) => d.sex), {
weight: (d) => d.sex === "FEMALE" ? 1 - skew : 1 + skew,
x: "flipper_length_mm",
y: "culmen_length_mm",
strokeOpacity: 0.5,
clip: true
}),
Plot.dot(penguins.filter((d) => d.sex), {
x: "flipper_length_mm",
y: "culmen_length_mm",
stroke: "sex",
strokeOpacity: (d) => d.sex === "FEMALE" ? 1 - skew : 1 + skew
}),
Plot.frame()
]
})
This example shows weighted density estimation where the weight varies dynamically based on a skew parameter.
density mark example with projection
Plot.plot({
projection: "albers",
color: {scheme: "YlGnBu"},
marks: [
Plot.density(walmarts, {x: "longitude", y: "latitude", bandwidth: 10, fill: "density"}),
Plot.geo(statemesh, {strokeOpacity: 0.3}),
Plot.geo(nation),
Plot.dot(walmarts, {x: "longitude", y: "latitude", r: 1, fill: "currentColor"})
]
})
This example shows density estimation on geographic data using an equal-area projection.
density mark example one-dimensional
Plot.plot({
height: 100,
inset: 10,
marks: [
Plot.density(faithful, {x: "waiting", stroke: "blue", strokeWidth: 0.25, bandwidth: 10}),
Plot.density(faithful, {x: "waiting", stroke: "blue", thresholds: 4, bandwidth: 10}),
Plot.dot(faithful, {x: "waiting", fill: "currentColor", r: 1.5})
]
})
This example shows density estimation along a single axis.
density mark example basic two-dimensional
Plot.plot({
inset: 10,
marks: [
Plot.density(faithful, {x: "waiting", y: "eruptions", stroke: "blue", strokeWidth: 0.25}),
Plot.density(faithful, {x: "waiting", y: "eruptions", stroke: "blue", thresholds: 4}),
Plot.dot(faithful, {x: "waiting", y: "eruptions", fill: "currentColor", r: 1.5})
]
})
This example shows density contours overlaid with a point cloud.
density function signature
The density mark is created using Plot.density(data, options), which returns a new density mark for the given data and options.
density mark series grouping
If a z, stroke, or fill channel is specified, the input points are grouped by series, and separate sets of contours are generated for each series.
density mark frameAnchor option
If either the x or y channel is not specified, the corresponding position is controlled by the frameAnchor option.
density mark channels
The density mark supports the following optional channels: x (horizontal position, bound to the x scale), y (vertical position, bound to the y scale), and weight (contribution to the estimated density).
density mark negative weight
You can specify a negative weight for points that the density contours should avoid, resulting in regions of influence that do not overlap.
density weight channel
The weight channel specifies the contribution of each data point to the estimated density. It defaults to 1, weighing each point equally. This can be used to give some points more influence than others.
density mark fill or stroke as density color encoding
By using the density keyword as a fill or stroke color, you can draw regions with a sequential color encoding representing the density values.
density mark one-dimensional support
The density mark works with one-dimensional values, allowing density estimation along a single axis by specifying only x or only y.
density thresholds option
The thresholds option specifies the number of contour lines (minus one) to be computed, or an explicit array of threshold values. It defaults to 20. For example, with 4 thresholds and a maximum density of 10, contour lines would be drawn for the values 2.5, 5, and 7.5. When specified as an array or iterable, explicit density values can be provided.
density bandwidth option
The bandwidth option specifies the radius of the Gaussian kernel describing the influence of each point as a function of distance. It defaults to 20 and is measured in pixels.
density mark how it works
The density mark uses a Gaussian kernel centered on each point with a radius specified by the bandwidth option. This kernel is summed over a discrete grid covering the plot, and then contours (isolines) are derived for values between 0 (exclusive) and the maximum density (exclusive) using the marching squares algorithm.
density mark definition
The density mark shows the estimated density of two-dimensional point clouds using contours that guide the eye towards local peaks of concentration. This is especially useful for handling overplotting in dense datasets.
density mark example with color encoding
Plot.plot({
inset: 10,
grid: true,
x: {type: "log"},
y: {type: "log"},
marks: [
Plot.density(diamonds, {x: "carat", y: "price", stroke: "density"})
]
})
This example shows density contours with stroke color sequential encoding based on density values.
density mark example with negative weight
Plot.plot({
inset: 10,
color: {legend: true},
marks: [
d3.groups(penguins, (d) => d.species).map(([s]) =>
Plot.density(penguins, {
x: "flipper_length_mm",
y: "culmen_length_mm",
weight: (d) => d.species === s ? 1 : -1,
fill: () => s,
fillOpacity: 0.2,
thresholds: [0.05]
})
),
Plot.dot(penguins, {
x: "flipper_length_mm",
y: "culmen_length_mm",
stroke: "species"
}),
Plot.frame()
]
})
This example shows non-overlapping density regions created by using negative weights for points that should be avoided.
Frame mark equivalent to rect mark
A frame mark is equivalent to Plot.rect({length: 1}, {fill: 0}).