From d0bf9b4cdff5e7bf713d713bd84a12f697062541 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 19 May 2023 10:36:03 -0700 Subject: [PATCH 1/3] descending shorthand --- docs/features/facets.md | 4 ++-- docs/features/scales.md | 4 ++-- docs/marks/bar.md | 2 +- docs/transforms/group.md | 2 +- docs/transforms/sort.md | 4 ++-- src/channel.d.ts | 5 ++++- src/channel.js | 3 +++ src/mark.d.ts | 2 +- src/marks/dot.js | 4 +--- src/transforms/basic.d.ts | 2 +- src/transforms/basic.js | 12 ++++++++++++ src/transforms/dodge.js | 2 +- src/transforms/stack.js | 2 +- test/plots/athletes-nationality.ts | 12 +++--------- test/plots/ballot-status-race.ts | 3 +-- test/plots/d3-survey-2015.ts | 2 +- test/plots/fruit-sales.ts | 10 ++-------- test/plots/industry-unemployment-track.ts | 2 +- test/plots/learning-poverty.ts | 2 +- test/plots/metro-unemployment-ridgeline.ts | 2 +- test/plots/movies-profit-by-genre.ts | 2 +- test/plots/movies-rating-by-genre.ts | 5 ++--- test/plots/penguin-annotated.ts | 5 +---- test/plots/us-population-state-age-dots.ts | 2 +- test/plots/us-population-state-age.ts | 2 +- 25 files changed, 48 insertions(+), 49 deletions(-) diff --git a/docs/features/facets.md b/docs/features/facets.md index 31fd211820..ff8fd962c4 100644 --- a/docs/features/facets.md +++ b/docs/features/facets.md @@ -42,7 +42,7 @@ Plot.plot({ y: "variety", fy: "site", stroke: "year", - sort: {y: "x", fy: "x", reduce: "median", reverse: true} + sort: {y: "-x", fy: "-x", reduce: "median"} }) ] }) @@ -81,7 +81,7 @@ Plot.plot({ fy: "site", stroke: "yield", strokeWidth: 2, - sort: {y: "x1", fy: "x1", reduce: "median", reverse: true} + sort: {y: "-x1", fy: "-x1", reduce: "median"} })) ] }) diff --git a/docs/features/scales.md b/docs/features/scales.md index 52845cf646..75b82b2e7a 100644 --- a/docs/features/scales.md +++ b/docs/features/scales.md @@ -977,10 +977,10 @@ Plot.barY(alphabet, {x: "letter", y: "frequency", sort: {x: "y", reduce: "max"}} Generally speaking, a reducer only needs to be specified when there are multiple secondary values for a given primary value. See the [group transform](../transforms/group.md) for the list of supported reducers. -For descending rather than ascending order, use the *reverse* option: +For descending rather than ascending order, use the *reverse* option, or *-name* when referring to a channel: ```js -Plot.barY(alphabet, {x: "letter", y: "frequency", sort: {x: "y", reverse: true}}) +Plot.barY(alphabet, {x: "letter", y: "frequency", sort: {x: "-y"}}) ``` An additional *limit* option truncates the domain to the first *n* values after sorting. If *limit* is negative, the last *n* values are used instead. Hence, a positive *limit* with *reverse* = true will return the top *n* values in descending order. If *limit* is an array [*lo*, *hi*], the *i*th values with *lo* ≤ *i* < *hi* will be selected. (Note that like the [basic filter transform](../transforms/filter.md), limiting the *x* domain here does not affect the computation of the *y* domain, which is computed independently without respect to filtering.) diff --git a/docs/marks/bar.md b/docs/marks/bar.md index 4b0397f73c..b00b722f92 100644 --- a/docs/marks/bar.md +++ b/docs/marks/bar.md @@ -41,7 +41,7 @@ Ordinal domains are sorted naturally (alphabetically) by default. Either set the :::plot https://observablehq.com/@observablehq/plot-vertical-bars ```js -Plot.barY(alphabet, {x: "letter", y: "frequency", sort: {x: "y", reverse: true}}).plot() +Plot.barY(alphabet, {x: "letter", y: "frequency", sort: {x: "-y"}}).plot() ``` ::: diff --git a/docs/transforms/group.md b/docs/transforms/group.md index dd11175ceb..df85aea289 100644 --- a/docs/transforms/group.md +++ b/docs/transforms/group.md @@ -52,7 +52,7 @@ Plot.plot({ x: {label: null, tickRotate: 90}, y: {grid: true}, marks: [ - Plot.barY(olympians, Plot.groupX({y: "count"}, {x: "sport", sort: {x: "y", reverse: true}})), + Plot.barY(olympians, Plot.groupX({y: "count"}, {x: "sport", sort: {x: "-y"}})), Plot.ruleY([0]) ] }) diff --git a/docs/transforms/sort.md b/docs/transforms/sort.md index d015f0ff28..02032dd4fc 100644 --- a/docs/transforms/sort.md +++ b/docs/transforms/sort.md @@ -49,7 +49,7 @@ Plot.plot({ fill: "currentColor", stroke: "var(--vp-c-bg)", strokeWidth: 1, - sort: sorted ? {channel: "r", order: "descending"} : null + sort: sorted ? {channel: "-r"} : null })) ] }) @@ -134,7 +134,7 @@ Sorts the data by the specified *order*, which is one of: - a field name - a {*channel*, *order*} object -In the object case, the **channel** option specifies the name of the channel, while the **order** option specifies *ascending* (the default) or *descending* order. For example, `sort: {channel: "r", order: "descending"}` will sort by descending radius (**r**). +In the object case, the **channel** option specifies the name of the channel, while the **order** option specifies *ascending* (the default) or *descending* order. You can also use the shorthand *-name* to sort by descending order of the channel with the given *name*. For example, `sort: {channel: "-r"}` will sort by descending radius (**r**). In the function case, if the sort function does not take exactly one argument, it is interpreted as a comparator function; otherwise it is interpreted as an accessor function. diff --git a/src/channel.d.ts b/src/channel.d.ts index 1b10f889ec..cd6e0178fa 100644 --- a/src/channel.d.ts +++ b/src/channel.d.ts @@ -161,6 +161,9 @@ export type ChannelValueBinSpec = ChannelValue | ({value: ChannelValue} & BinOpt */ export type ChannelValueDenseBinSpec = ChannelValue | ({value: ChannelValue; scale?: Channel["scale"]} & Omit); // prettier-ignore +/** A channel name, or an implied one for domain sorting. */ +type ChannelDomainName = ChannelName | "data" | "width" | "height"; + /** * The available inputs for imputing scale domains. In addition to a named * channel, an input may be specified as: @@ -176,7 +179,7 @@ export type ChannelValueDenseBinSpec = ChannelValue | ({value: ChannelValue; sca * custom **reduce** function, as when the built-in single-channel reducers are * insufficient. */ -export type ChannelDomainValue = ChannelName | "data" | "width" | "height" | null; +export type ChannelDomainValue = ChannelDomainName | `-${ChannelDomainName}` | null; /** Options for imputing scale domains from channel values. */ export interface ChannelDomainOptions { diff --git a/src/channel.js b/src/channel.js index 100688908f..cdee13a69e 100644 --- a/src/channel.js +++ b/src/channel.js @@ -82,7 +82,10 @@ export function channelDomain(data, facets, channels, facetChannels, options) { for (const x in options) { if (!registry.has(x)) continue; // ignore unknown scale keys (including generic options) let {value: y, reverse = defaultReverse, reduce = defaultReduce, limit = defaultLimit} = maybeValue(options[x]); + const negate = y?.startsWith("-"); + if (negate) y = y.slice(1); if (reverse === undefined) reverse = y === "width" || y === "height"; // default to descending for lengths + if (negate) reverse = !reverse; if (reduce == null || reduce === false) continue; // disabled reducer const X = x === "fx" || x === "fy" ? reindexFacetChannel(facets, facetChannels[x]) : findScaleChannel(channels, x); if (!X) throw new Error(`missing channel for scale: ${x}`); diff --git a/src/mark.d.ts b/src/mark.d.ts index 6061501e78..21921fdd79 100644 --- a/src/mark.d.ts +++ b/src/mark.d.ts @@ -102,7 +102,7 @@ export interface MarkOptions { * with a *value* object and per-scale options: * * ```js - * sort: {y: {value: "x", reverse: true}} + * sort: {y: {value: "-x"}} * ``` * * When sorting the mark’s index, the **sort** option is instead one of: diff --git a/src/marks/dot.js b/src/marks/dot.js index 1080e48f68..2d969444c6 100644 --- a/src/marks/dot.js +++ b/src/marks/dot.js @@ -23,9 +23,7 @@ const defaults = { }; export function withDefaultSort(options) { - return options.sort === undefined && options.reverse === undefined - ? sort({channel: "r", order: "descending"}, options) - : options; + return options.sort === undefined && options.reverse === undefined ? sort({channel: "-r"}, options) : options; } export class Dot extends Mark { diff --git a/src/transforms/basic.d.ts b/src/transforms/basic.d.ts index cfc7c988b2..fddc507801 100644 --- a/src/transforms/basic.d.ts +++ b/src/transforms/basic.d.ts @@ -149,7 +149,7 @@ export type SortOrder = | CompareFunction | ChannelValue | {value?: ChannelValue; order?: CompareFunction | "ascending" | "descending"} - | {channel?: ChannelName; order?: CompareFunction | "ascending" | "descending"}; + | {channel?: ChannelName | `-${ChannelName}`; order?: CompareFunction | "ascending" | "descending"}; /** * Applies a transform to *options* to sort the mark’s index by the specified diff --git a/src/transforms/basic.js b/src/transforms/basic.js index 3b4fd032a5..ab6e90ddfe 100644 --- a/src/transforms/basic.js +++ b/src/transforms/basic.js @@ -121,6 +121,10 @@ function sortValue(value) { throw new Error(`invalid order: ${order}`); } } + if (channel?.startsWith("-")) { + channel = channel.slice(1); + order = reverseOrder(order); + } return (data, facets, channels) => { let V; if (channel === undefined) { @@ -135,3 +139,11 @@ function sortValue(value) { return {data, facets: facets.map((I) => I.slice().sort(compareValue))}; }; } + +function reverseOrder(order) { + return order === ascendingDefined + ? descendingDefined + : order === descendingDefined + ? ascendingDefined + : (i, j) => order(j, i); +} diff --git a/src/transforms/dodge.js b/src/transforms/dodge.js index 3f9b6a267a..23c20bd807 100644 --- a/src/transforms/dodge.js +++ b/src/transforms/dodge.js @@ -64,7 +64,7 @@ function dodge(y, x, anchor, padding, r, options) { let {channels, sort, reverse} = options; channels = maybeNamed(channels); if (channels?.r === undefined) options = {...options, channels: {...channels, r: {value: r, scale: "r"}}}; - if (sort === undefined && reverse === undefined) options.sort = {channel: "r", order: "descending"}; + if (sort === undefined && reverse === undefined) options.sort = {channel: "-r"}; } return initializer(options, function (data, facets, channels, scales, dimensions, context) { let {[x]: X, r: R} = channels; diff --git a/src/transforms/stack.js b/src/transforms/stack.js index 1550d20e81..cad3675c54 100644 --- a/src/transforms/stack.js +++ b/src/transforms/stack.js @@ -81,7 +81,7 @@ function stack(x, y = one, kx, ky, {offset, order, reverse}, options) { const [Y2, setY2] = column(y); Y1.hint = Y2.hint = lengthy; offset = maybeOffset(offset); - order = maybeOrder(order, offset, ky); + order = maybeOrder(order, offset, ky); // TODO shorthand -order with reverse? return [ basic(options, (data, facets, plotOptions) => { const X = x == null ? undefined : setX(maybeApplyInterval(valueof(data, x), plotOptions?.[kx])); diff --git a/test/plots/athletes-nationality.ts b/test/plots/athletes-nationality.ts index b5ea9a40fd..a3da9e658f 100644 --- a/test/plots/athletes-nationality.ts +++ b/test/plots/athletes-nationality.ts @@ -4,14 +4,8 @@ import * as d3 from "d3"; export async function athletesNationality() { const athletes = await d3.csv("data/athletes.csv", d3.autoType); return Plot.plot({ - x: { - grid: true - }, - y: { - label: null - }, - marks: [ - Plot.barX(athletes, Plot.groupY({x: "count"}, {y: "nationality", sort: {y: "x", reverse: true, limit: 20}})) - ] + x: {grid: true}, + y: {label: null}, + marks: [Plot.barX(athletes, Plot.groupY({x: "count"}, {y: "nationality", sort: {y: "-x", limit: 20}}))] }); } diff --git a/test/plots/ballot-status-race.ts b/test/plots/ballot-status-race.ts index d546871fc0..8a5b314c27 100644 --- a/test/plots/ballot-status-race.ts +++ b/test/plots/ballot-status-race.ts @@ -81,8 +81,7 @@ export async function ballotStatusRace() { title: (d) => `${d.percent.toFixed(1)}%`, sort: { fy: "data", - reduce: (data) => data.find((d) => d.status === "ACCEPTED").percent, - reverse: true + reduce: (data) => -data.find((d) => d.status === "ACCEPTED").percent } }), Plot.ruleX([0]) diff --git a/test/plots/d3-survey-2015.ts b/test/plots/d3-survey-2015.ts index 1abb8a3bc1..3525910c6c 100644 --- a/test/plots/d3-survey-2015.ts +++ b/test/plots/d3-survey-2015.ts @@ -43,7 +43,7 @@ function bars(groups, title) { y: ([key]) => key, fill: "steelblue", insetTop: 1, - sort: {y: "x", reverse: true} + sort: {y: "-x"} }), Plot.ruleX([0]) ] diff --git a/test/plots/fruit-sales.ts b/test/plots/fruit-sales.ts index 0c3b0dd085..f79235ab2a 100644 --- a/test/plots/fruit-sales.ts +++ b/test/plots/fruit-sales.ts @@ -5,13 +5,7 @@ export async function fruitSales() { const sales = await d3.csv("data/fruit-sales.csv", d3.autoType); return Plot.plot({ marginLeft: 50, - y: { - label: null, - reverse: true - }, - marks: [ - Plot.barX(sales, Plot.groupY({x: "sum"}, {x: "units", y: "fruit", sort: {y: "x", reverse: true}})), - Plot.ruleX([0]) - ] + y: {label: null, reverse: true}, + marks: [Plot.barX(sales, Plot.groupY({x: "sum"}, {x: "units", y: "fruit", sort: {y: "-x"}})), Plot.ruleX([0])] }); } diff --git a/test/plots/industry-unemployment-track.ts b/test/plots/industry-unemployment-track.ts index 6221f60832..0baa29c288 100644 --- a/test/plots/industry-unemployment-track.ts +++ b/test/plots/industry-unemployment-track.ts @@ -12,7 +12,7 @@ export async function industryUnemploymentTrack() { interval: "month", fill: "unemployed", title: "unemployed", - sort: {fy: "fill", reverse: true}, + sort: {fy: "-fill"}, inset: 0 }), Plot.dotX( diff --git a/test/plots/learning-poverty.ts b/test/plots/learning-poverty.ts index 266e3bd8f3..d3714f6ba7 100644 --- a/test/plots/learning-poverty.ts +++ b/test/plots/learning-poverty.ts @@ -30,7 +30,7 @@ export async function learningPoverty() { x: (d) => (d.type === "ok" ? -1 : 1) * d.share, // diverging bars y: "Country Name", fill: "type", - sort: {y: "x", reverse: true} + sort: {y: "-x"} }), Plot.ruleX([0]) ] diff --git a/test/plots/metro-unemployment-ridgeline.ts b/test/plots/metro-unemployment-ridgeline.ts index cbeea3191c..4eef1335be 100644 --- a/test/plots/metro-unemployment-ridgeline.ts +++ b/test/plots/metro-unemployment-ridgeline.ts @@ -21,7 +21,7 @@ export async function metroUnemploymentRidgeline() { }, marks: [ Plot.areaY(data, {x: "date", y: "unemployment", fill: "#eee"}), - Plot.line(data, {x: "date", y: "unemployment", sort: {fy: "y", reverse: true}}), + Plot.line(data, {x: "date", y: "unemployment", sort: {fy: "-y"}}), Plot.ruleY([0]) ] }); diff --git a/test/plots/movies-profit-by-genre.ts b/test/plots/movies-profit-by-genre.ts index f407be6c3f..f403f9973f 100644 --- a/test/plots/movies-profit-by-genre.ts +++ b/test/plots/movies-profit-by-genre.ts @@ -40,7 +40,7 @@ export async function moviesProfitByGenre() { x: Profit, stroke: "red", strokeWidth: 2, - sort: {y: "x", reverse: true} + sort: {y: "-x"} } ) ) diff --git a/test/plots/movies-rating-by-genre.ts b/test/plots/movies-rating-by-genre.ts index 97f0256413..4709bb5cb6 100644 --- a/test/plots/movies-rating-by-genre.ts +++ b/test/plots/movies-rating-by-genre.ts @@ -35,9 +35,8 @@ export async function moviesRatingByGenre() { stroke: "Major Genre", r: 2.5, sort: { - fy: "x", - reduce: "median", - reverse: true + fy: "-x", + reduce: "median" } } ) diff --git a/test/plots/penguin-annotated.ts b/test/plots/penguin-annotated.ts index 3fa24ba587..2b06a872e6 100644 --- a/test/plots/penguin-annotated.ts +++ b/test/plots/penguin-annotated.ts @@ -8,10 +8,7 @@ export async function penguinAnnotated() { x: {insetRight: 10}, marks: [ Plot.frame(), - Plot.barX( - penguins, - Plot.groupY({x: "count"}, {y: "species", fill: "sex", title: "sex", sort: {y: "x", reverse: true}}) - ), + Plot.barX(penguins, Plot.groupY({x: "count"}, {y: "species", fill: "sex", title: "sex", sort: {y: "-x"}})), Plot.text(["Count of penguins\ngrouped by species\n and colored by sex"], { frameAnchor: "bottom-right", dx: -3, diff --git a/test/plots/us-population-state-age-dots.ts b/test/plots/us-population-state-age-dots.ts index 978ce5d365..4ee923d675 100644 --- a/test/plots/us-population-state-age-dots.ts +++ b/test/plots/us-population-state-age-dots.ts @@ -32,7 +32,7 @@ export async function usPopulationStateAgeDots() { textAnchor: "end", dx: -6, text: "state", - sort: {y: "x", reduce: "min", reverse: true} + sort: {y: "-x", reduce: "min"} }) ) ] diff --git a/test/plots/us-population-state-age.ts b/test/plots/us-population-state-age.ts index 501b0a12a9..d9a3b91c5d 100644 --- a/test/plots/us-population-state-age.ts +++ b/test/plots/us-population-state-age.ts @@ -49,7 +49,7 @@ export async function usPopulationStateAgeGrouped() { y: "population", fill: "age", title: "age", - sort: {fx: "y", reverse: true, limit: 6} + sort: {fx: "-y", limit: 6} }), Plot.ruleY([0]) ] From bef0ec98085669f0eb1a979af8bdaf534087aaad Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 19 May 2023 10:42:12 -0700 Subject: [PATCH 2/3] no double reverse --- test/plots/fruit-sales.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/plots/fruit-sales.ts b/test/plots/fruit-sales.ts index f79235ab2a..482ac61b5c 100644 --- a/test/plots/fruit-sales.ts +++ b/test/plots/fruit-sales.ts @@ -5,7 +5,7 @@ export async function fruitSales() { const sales = await d3.csv("data/fruit-sales.csv", d3.autoType); return Plot.plot({ marginLeft: 50, - y: {label: null, reverse: true}, - marks: [Plot.barX(sales, Plot.groupY({x: "sum"}, {x: "units", y: "fruit", sort: {y: "-x"}})), Plot.ruleX([0])] + y: {label: null}, + marks: [Plot.barX(sales, Plot.groupY({x: "sum"}, {x: "units", y: "fruit", sort: {y: "x"}})), Plot.ruleX([0])] }); } From a05f6fd3c2205c9eae48fe763bbd3a96fbedb93e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Sun, 21 May 2023 20:13:54 +0200 Subject: [PATCH 3/3] more descending shorthand --- src/reducer.d.ts | 9 +++++++++ src/transforms/basic.js | 4 ++++ src/transforms/bin.js | 4 ++++ src/transforms/group.d.ts | 4 ++-- src/transforms/group.js | 4 ++++ src/transforms/stack.js | 6 +++++- test/plots/music-revenue.ts | 3 +-- test/plots/penguin-sex-mass-culmen-species.ts | 3 +-- 8 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/reducer.d.ts b/src/reducer.d.ts index f567a77a5b..b869efa47f 100644 --- a/src/reducer.d.ts +++ b/src/reducer.d.ts @@ -80,3 +80,12 @@ export interface ReducerImplementation { * - an object that implements the *reduceIndex* method */ export type Reducer = ReducerName | ReducerFunction | ReducerImplementation; + +/** + * How to reduce aggregated (binned or grouped) values for sorting; one of: + * + * - a named reducer implementation such as *count* or *sum* + * - a function that takes an array of values and returns the reduced value + * - an object that implements the *reduceIndex* method + */ +export type ReducerSort = `-${ReducerName}` | Reducer; diff --git a/src/transforms/basic.js b/src/transforms/basic.js index ab6e90ddfe..0fd61cb5e1 100644 --- a/src/transforms/basic.js +++ b/src/transforms/basic.js @@ -125,6 +125,10 @@ function sortValue(value) { channel = channel.slice(1); order = reverseOrder(order); } + if (typeof value === "string" && value?.startsWith("-")) { + value = value.slice(1); + order = reverseOrder(order); + } return (data, facets, channels) => { let V; if (channel === undefined) { diff --git a/src/transforms/bin.js b/src/transforms/bin.js index f929abfedf..75a1316c38 100644 --- a/src/transforms/bin.js +++ b/src/transforms/bin.js @@ -98,6 +98,10 @@ function binn( // Compute the outputs. outputs = maybeBinOutputs(outputs, inputs); reduceData = maybeBinReduce(reduceData, identity); + if (typeof sort === "string" && sort.startsWith("-")) { + sort = sort.slice(1); + reverse = !reverse; + } sort = sort == null ? undefined : maybeBinOutput("sort", sort, inputs); filter = filter == null ? undefined : maybeBinEvaluator("filter", filter, inputs); diff --git a/src/transforms/group.d.ts b/src/transforms/group.d.ts index 24b422aa40..50d661b115 100644 --- a/src/transforms/group.d.ts +++ b/src/transforms/group.d.ts @@ -1,5 +1,5 @@ import type {ChannelReducers, ChannelValue} from "../channel.js"; -import type {Reducer} from "../reducer.js"; +import type {ReducerSort, Reducer} from "../reducer.js"; import type {Transformed} from "./basic.js"; /** Options for outputs of the group (and bin) transform. */ @@ -29,7 +29,7 @@ export interface GroupOutputOptions { * Plot.groupX({y: "count", sort: "count"}, {fill: "sex", x: "sport"}) * ``` */ - sort?: T | null; + sort?: ReducerSort | null; /** If true, reverse the order of generated groups; defaults to false. */ reverse?: boolean; diff --git a/src/transforms/group.js b/src/transforms/group.js index 390a711620..8159ed844e 100644 --- a/src/transforms/group.js +++ b/src/transforms/group.js @@ -78,6 +78,10 @@ function groupn( // Compute the outputs. outputs = maybeOutputs(outputs, inputs); reduceData = maybeReduce(reduceData, identity); + if (typeof sort === "string" && sort.startsWith("-")) { + sort = sort.slice(1); + reverse = !reverse; + } sort = sort == null ? undefined : maybeOutput("sort", sort, inputs); filter = filter == null ? undefined : maybeEvaluator("filter", filter, inputs); diff --git a/src/transforms/stack.js b/src/transforms/stack.js index cad3675c54..7366c57fb1 100644 --- a/src/transforms/stack.js +++ b/src/transforms/stack.js @@ -81,7 +81,11 @@ function stack(x, y = one, kx, ky, {offset, order, reverse}, options) { const [Y2, setY2] = column(y); Y1.hint = Y2.hint = lengthy; offset = maybeOffset(offset); - order = maybeOrder(order, offset, ky); // TODO shorthand -order with reverse? + if (typeof order === "string" && order.startsWith("-")) { + order = order.slice(1); + reverse = !reverse; + } + order = maybeOrder(order, offset, ky); return [ basic(options, (data, facets, plotOptions) => { const X = x == null ? undefined : setX(maybeApplyInterval(valueof(data, x), plotOptions?.[kx])); diff --git a/test/plots/music-revenue.ts b/test/plots/music-revenue.ts index 7bd9dc8230..c3eb49e64f 100644 --- a/test/plots/music-revenue.ts +++ b/test/plots/music-revenue.ts @@ -7,8 +7,7 @@ export async function musicRevenue() { x: "year", y: "revenue", z: "format", - order: "appearance", - reverse: true + order: "-appearance" }; return Plot.plot({ y: { diff --git a/test/plots/penguin-sex-mass-culmen-species.ts b/test/plots/penguin-sex-mass-culmen-species.ts index 86a0db7c97..f2cc9294e7 100644 --- a/test/plots/penguin-sex-mass-culmen-species.ts +++ b/test/plots/penguin-sex-mass-culmen-species.ts @@ -25,8 +25,7 @@ export async function penguinSexMassCulmenSpecies() { Plot.bin( { r: "count", - sort: "count", - reverse: true + sort: "-count" }, { x: "body_mass_g",