Plot.valueof may return input array without copying
Plot.valueof is not guaranteed to return a new array. When a transform method is used, or when the given value is an array compatible with the requested type, the array may be returned as-is without making a copy.
Plot.valueof function for extracting data columns
Plot.valueof(data, value, type) returns an array (column) of the specified type with the corresponding value of each element in the data. The value accessor can be: a string (field accessor), an accessor function called as type.from(data, value), a number/Date/boolean (uniformly fills array with that value), an object with a transform method (called as value.transform(data)), an array of values (returned as-is), or null/undefined (returned as-is). If type is Array or a typed array class, the return value will be an instance of that type. For Float64Array, Float32Array, or subclasses, null values are implicitly replaced with NaN.
Custom transform overrides basic transforms
If a custom transform function is specified via the transform option, it supersedes any basic transforms. This means the filter, sort, and reverse options are ignored when a custom transform is present. However, built-in transforms automatically compose with the basic filter, sort, and reverse transforms.
Transforms are composable
Multiple transforms can be composed together by passing options through more than one transform before passing it to a mark. For example, binX and normalizeY can be combined.
Custom initializers can declare additional channels
If an initializer desires a channel that is not supported by the downstream mark, additional channels can be declared using the mark channels option.
Transform function signature and return value
A custom transform function is passed three arguments: data, facets, and options. It must return an object with two properties: data (the transformed data array) and facets (a nested array of arrays representing zero-based indexes of elements in data that belong to each facet). The facets structure is [[0, 1, 3, …], [2, 5, 10, …], …] where each element specifies the indexes of data elements in a given facet (those with distinct values in the associated fx or fy dimension).
Marks provide implicit transforms
Many of Plot's marks provide implicit transforms. For example, the rectY mark applies an implicit stackY transform if the y option is used, and the dot mark applies an implicit sort transform to mitigate occlusion by drawing the smallest dots on top.
Transforms can derive channels and modify defaults
Transforms can derive new channels (such as creating a y channel from a bin transform) as well as changing the default options for marks. For example, the bin transform sets default insets for a one-pixel gap between adjacent rects.
Transform structure: options object pairs
Plot's transforms typically take two options objects as arguments. The first object contains transform options (e.g., {y: 'count'}), while the second contains mark options to be passed through to the mark (e.g., {x: 'weight', fill: 'sex'}). The transform returns a new options object representing the transformed mark options.
Plot.initializer function for composing initializers
Plot.initializer(options, initializer) composes an initializer function with any other transforms present in the options object and returns a new options object. It is used internally by Plot's built-in initializer transforms.
Built-in transforms for Plot
Plot's built-in transforms include: bin, centroid, dodge, filter, group, hexbin, interval, map, normalize, reverse, select, shuffle, sort, stack, tree, and window.
Plot.transform function for composing basic transforms
Plot.transform(options, transform) composes a transform function with any basic transforms (filter, sort, or reverse) specified in the options object. If a custom transform function is present in options, any basic transforms are ignored. Returns a new options object with the composed transforms. This method facilitates applying basic transforms prior to applying a custom transform.
Plot.identity channel helper
Plot.identity is a channel helper that returns a source array as-is, avoiding an extra copy when defining a channel as being equal to the data.
Initializer function signature and return value
A custom initializer function is called after scales have been computed and receives as inputs: the data array, the facets index, the input channels object, the scales, and the dimensions. The mark itself is the this context. The initializer must return an object with data, facets, and new channels properties. Any new channels are merged with existing channels, replacing channels of the same name.
Plot.column helper for derived columns
Plot.column(source) returns a [column, setColumn] array. The column object implements column.transform, returning whatever value was most recently passed to setColumn. If setColumn is not called, column.transform returns undefined. If a source is specified, column.label exposes the source's label: if source is a string (field name), column.label is that string; otherwise column.label propagates source.label. This allows derived columns to propagate human-readable axis or legend labels.
Initializer transforms operate in screen space
Initializers are a special class of transform that operate in screen space (pixel coordinates and colors) rather than abstract data space. They are invoked after the initial scales are constructed and can modify channels or derive new channels. Plot's hexbin and dodge transforms are initializers.
Transform functions should not mutate inputs
Custom transform functions should not mutate the input data or facets. Similarly, options transforms should not mutate the input options object.
Plot.indexOf channel helper
Plot.indexOf is a channel helper that returns an array of numbers [0, 1, 2, 3, …]. It is used internally by marks with zero-based index defaults for channels.
Custom transforms must be compatible with faceting
When implementing a custom transform for generic usage, keep in mind that it needs to be compatible with Plot's faceting system, which partitions the original dataset into discrete subsets.
areaX interval option and binY transform
If the interval option is specified in areaX, the binY transform is implicitly applied. The reducer of the output x channel may be specified via the reduce option, which defaults to first. To default to zero instead of showing gaps when the value represents a quantity, use the sum reducer.
geoCentroid transform computes spherical centroids before projection
The geoCentroid transform derives x and y channels representing the longitudes and latitudes of the centroids of given GeoJSON geometries before projection. It expects geometries to be specified in spherical coordinates. The spherical centroid always represents the center of mass of the original shape and will be rotated exactly in line with the projection's rotate argument. It might land outside the frame if only part of the land mass is visible, and might be clipped by the projection.
centroid transform computes planar centroids after projection
The centroid transform operates as an initializer after geometries have been projected to screen coordinates. It derives x and y channels representing the pixel coordinates of the planar centroid of the projected shapes. No assumption is made about the geometries — they can be in any coordinate system. The resulting value is in the frame as long as the projected geometry returns at least one visible point.
centroid with pointer transform for interactive tips
Plot.tip(states, Plot.pointer(Plot.centroid({title: (d) => d.properties.name}))) combines the pointer transform with the centroid transform to add interactive tips on a map.
geoCentroid with hexbin for density mapping
Plot.dot(counties, Plot.hexbin({r:"count"}, Plot.geoCentroid())).plot({projection: "albers"}) combines a hexbin transform with geoCentroid to show density on a map.
centroid with dot mark for geometry centroids
Plot.dot(counties, Plot.centroid()).plot({projection: "albers-usa"}) combines a dot mark with the centroid transform to plot planar centroids of projected geometries.
geoCentroid with voronoi mark for county visualization
Plot.voronoi(counties, Plot.centroid()).plot({projection: "albers"}) combines a voronoi mark with the centroid transform to visualize county data.
centroid with text mark for state labels
Plot.text(states, Plot.centroid({text: (d) => d.properties.name, fill: "currentColor", stroke: "var(--vp-c-bg)"})) combines a text mark with the centroid transform to label U.S. states at their centroid positions.
geoCentroid is faster than centroid initializer
The geoCentroid transform is slightly faster than the centroid initializer, which might be useful if you have tens of thousands of features.
geoCentroid() API signature
Plot.geoCentroid({geometry: Plot.identity}). The geoCentroid transform derives x and y channels representing the spherical centroids for the given GeoJSON geometry. If the geometry option is not specified, the mark's data is assumed to be GeoJSON objects.
centroid() API signature
Plot.centroid({geometry: Plot.identity}). The centroid initializer derives x and y channels representing the planar (projected) centroids for the given GeoJSON geometry. If the geometry option is not specified, the mark's data is assumed to be GeoJSON objects.
dodge plot height and width requirements
When using dodgeY, you must typically specify the plot's height to create suitable space for the layout. The dodge transform is not currently able to set the height automatically. For dodgeX, the default width of 640 is often sufficient, though you may need to adjust it depending on your data.
dodgeY with faceting example
The dodge transform works with Plot's faceting system. Example: Plot.dot(penguins, Plot.dodgeY("middle", {fx: "species", y: "body_mass_g", fill: "sex"})) creates independent beeswarm plots for each species value, with dots colored by sex and positioned by body mass.
dodge transform with variable radius example
When r is a channel, the dodge transform can position circles of varying radius. Example: Plot.dodgeY({x: "date", r: "rMVOP", title: (d) => `${d.NAME}\n${(d.rMVOP / 1e3).toFixed(1)}B`, fill: "currentColor"}) creates dots sized proportionally to the rMVOP field.
dodgeX function signature
The dodgeX function is called as Plot.dodgeX(dodgeOptions, options) or Plot.dodgeX({y: "value"}). It accepts dodge options (padding, anchor) and mark options (y, fill, title, sort, reverse, etc.), and produces a new x position channel while leaving the y position channel unchanged.
dodge layout depends on input order
The dodge transform places dots sequentially using a greedy algorithm, each time finding the closest position to the baseline that avoids intersection with previously-placed dots. The resulting layout depends on the input order. When r is a channel, dots are sorted by descending radius by default. Otherwise, dots are placed in input order by default. To adjust the dodge layout, use the sort transform.
dodge transform sort option usage
To adjust the dodge layout, use the sort transform. If the sort option uses the same column as the position channel, the dots are arranged in piles leaning in the direction of the sort. For example, sort: "weight (lb)" with reverse: true produces piles leaning left, while sort: "weight (lb)" alone produces piles leaning right.
dodge r option for dot radius
The dodge transform respects the radius r of each dot. The r option can be a fixed number or a channel that varies by data point. When r is a channel, the dodge transform will position circles of varying radius. Dots are sorted by descending radius by default when r is a channel, such that the largest dots are placed closest to the baseline.
dodge padding option
The dodge transform supports a padding option that specifies the minimum separating distance between dots in pixels, with a default value of 1. The padding is a number added to the radius of the mark to estimate its size. Increasing padding provides more breathing room between dots.
dodge anchor option for dodgeY
For the dodgeY transform, the supported anchor options are: bottom (default), middle, and top. With the middle anchor, dots are placed symmetrically around the baseline. With bottom (default), piles grow from bottom towards top. With top, piles grow from top towards bottom.
dodge anchor option for dodgeX
For the dodgeX transform, the supported anchor options are: left (default), middle, and right. With the middle anchor, dots are placed symmetrically around the baseline. With left (default), piles grow from left towards right. With right, piles grow from right towards left.
dodgeY transform definition and purpose
The dodgeY transform computes the y position given an x position, such that dots are packed densely without overlapping. It is commonly used to produce beeswarm plots, a way of showing a one-dimensional distribution that preserves the visual identity of individual data points. The dodgeY transform works with Plot's faceting system, allowing independent beeswarm plots on discrete partitions of the data.
dodgeX transform definition and purpose
The dodgeX transform computes the x position given a y position, such that dots are packed densely without overlapping. It is equivalent to dodgeY but piles horizontally instead of vertically, creating a new x position channel that avoids overlapping while leaving the y position channel unchanged.
dodge vs stack transform difference
The dodge transform differs from the stack transform in that dots do not need the exact same input position to avoid overlap; the dodge transform respects the radius r of each dot and provides more flexibility in positioning.
bin cumulative option
The cumulative option produces a cumulative distribution. When cumulative is positive (1 by convention), each bin represents the number of items with the given value or less. To have each bin represent the number of items with the given value or more, set cumulative to −1.
bin implicit stackY transform opt-out
You can opt-out of the implicit stackY transform by having binX generate y1 or y2 instead of y (and similarly x1 or x2 for stackX and binY). When overlapping marks, use either opacity or blending to make the overlap visible.
bin z partitioning default behavior
You can partition bins using z. If z is undefined, it defaults to fill or stroke, if any. In conjunction with the rectY mark's implicit stackY transform, this will produce a stacked histogram.
bin transform three orientations
The bin transform comes in three orientations: binX bins on x and often outputs y as in a histogram with vertical rects; binY bins on y and often outputs x as in a histogram with horizontal rects; and bin bins on both x and y and often outputs to fill or r as in a heatmap.
bin custom reducer as object with reduceIndex
A reducer may be specified as an object with a reduceIndex method and optionally a scope property. The reduceIndex method is repeatedly passed three arguments: the index for each bin (an array of integers), the input channel's array of values, and the extent of the bin (an object {data, x1, x2, y1, y2}). It must return the corresponding aggregate value for the bin.
binX transform input and output
The binX transform takes x as input and outputs x1 and x2 representing the extent of each bin in x. The outputs argument declares additional output channels and the associated reducer. For example, {y: "count"} declares that the y channel should output the count of items in each bin.
bin transform purpose and use cases
The bin transform groups quantitative or temporal data—continuous measurements such as heights, weights, or temperatures—into discrete bins. You can then compute summary statistics for each bin, such as a count, sum, or proportion. The bin transform is most often used to make histograms or heatmaps with the rect mark. For ordinal or nominal data, use the group transform instead.
bin custom reducer as function
A reducer may be specified as a function to be passed the array of values for each bin and the extent of the bin.
bin reducer scope property
If the reducer object's scope is "data", then the reduceIndex method is first invoked for the full data, with the return value made available as a third argument (making the extent the fourth argument). If scope is "facet", the reduceIndex method is invoked for each facet, and the resulting reduce value is made available while reducing the facet's bins. This scope is used by the proportion and proportion-facet reducers.
bin output channels x1/x2 and y1/y2 defaults
The x1 and x2 outputs default to undefined if x is explicitly defined; similarly, y1 and y2 outputs default to undefined if y is explicitly defined.
bin named reducers complete list
The following named reducers are supported by bin transforms: first, last, count, distinct, sum, proportion, proportion-facet, min, min-index, max, max-index, mean, median, mode, pXX (percentile where XX is 00-99), deviation, variance, identity, x (middle of bin's x extent when binning on x), x1 (lower bound), x2 (upper bound), y (middle of bin's y extent when binning on y), y1 (lower bound), y2 (upper bound), and z (bin's z value).
bin default insets
The bin transform sets default insets for a one-pixel gap between rects. You can set explicit insets if you prefer, such as inset: 0 to make rects touch. When rects touch, it is recommended to use round: true on the scale to avoid antialiasing artifacts.
bin faceting support
The bin transform works with Plot's faceting system, partitioning bins by facet. The proportion-facet reducer computes the sum proportional to the facet total.
bin output channels automatically computed
In addition to data, the following channels are automatically output by bin transforms: x1 (starting horizontal position), x2 (ending horizontal position), x (horizontal center), y1 (starting vertical position), y2 (ending vertical position), y (vertical center), z (first value of z channel if any), fill (first value of fill channel if any), and stroke (first value of stroke channel if any). The x1, x2, and x outputs are only computed by binX and bin; y1, y2, and y are only computed by binY and bin. The x and y outputs are lazy—only computed if needed downstream.
bin filter option for continuous marks
When using continuous marks such as area and line with bin transform, set the bin transform's filter option to null so that empty bins are included in the output. Otherwise, the area or line would mislead by interpolating over missing bins.
bin channel computation before or after binning
You can control whether a channel is computed before or after binning. If a channel is declared only in options (and it is not a special group-eligible channel such as x, y, z, fill, or stroke), it will be computed after binning and be passed the binned data—each datum is the array of input data corresponding to the current bin. If a channel is declared in both outputs and options, then the channel in options is computed before binning and can be aggregated using any built-in reducer during the bin transform.
bin thresholds option
To control how quantitative dimensions x and y are divided into bins, the thresholds option specifies the threshold values. The thresholds option may be specified as: "auto" (default, Scott's rule capped at 200), "freedman-diaconis", "scott", "sturges", a count (hint for desired number of bins), an array of n threshold values for n-1 bins, an interval or time interval, or a function that returns an array, count, or time interval.