diff --git a/__tests__/integration/snapshots/static/alphabetIntervalSortXDomain.png b/__tests__/integration/snapshots/static/alphabetIntervalSortXDomain.png new file mode 100644 index 0000000000..b045326231 Binary files /dev/null and b/__tests__/integration/snapshots/static/alphabetIntervalSortXDomain.png differ diff --git a/__tests__/plots/static/alphabet-interval-sort-x-domain.ts b/__tests__/plots/static/alphabet-interval-sort-x-domain.ts new file mode 100644 index 0000000000..b38ec8c284 --- /dev/null +++ b/__tests__/plots/static/alphabet-interval-sort-x-domain.ts @@ -0,0 +1,18 @@ +import { G2Spec } from '../../../src'; + +export function alphabetIntervalSortXDomain(): G2Spec { + return { + type: 'interval', + data: { + type: 'fetch', + value: 'data/alphabet.csv', + }, + encode: { + x: 'letter', + y: 'frequency', + }, + transform: [{ type: 'sortX', by: 'y', reverse: true }], + scale: { x: { domain: ['A', 'B', 'C'] } }, + axis: { y: { labelFormatter: '.0%' } }, + }; +} diff --git a/__tests__/plots/static/index.ts b/__tests__/plots/static/index.ts index ebeffa8b9c..0f17109d5d 100644 --- a/__tests__/plots/static/index.ts +++ b/__tests__/plots/static/index.ts @@ -199,3 +199,4 @@ export { scoreByItemAreaRadarSize } from './score-by-item-area-radar-size'; export { mockPointLogTicks } from './mock-point-log-ticks'; export { alphabetIntervalLabelRotate } from './alphabet-interval-label-rotate'; export { aaplLineBasicTranspose } from './aapl-line-basic-transpose'; +export { alphabetIntervalSortXDomain } from './alphabet-interval-sort-x-domain'; diff --git a/src/transform/sort.ts b/src/transform/sort.ts index 2a22862b11..be5f2d731e 100644 --- a/src/transform/sort.ts +++ b/src/transform/sort.ts @@ -44,7 +44,7 @@ export type SortOptions = { }; function sortQuantitative(I, mark, options): [number[], G2Mark] { - const { reverse, slice, channel } = options; + const { reverse, channel } = options; const { encode } = mark; const [V] = columnOf(encode, channel); const sortedI = sort(I, (i: number) => V[i]); @@ -53,12 +53,21 @@ function sortQuantitative(I, mark, options): [number[], G2Mark] { return [sortedI, mark]; } +// If domain is specified, only sort data in the domain. +function filterIndex(I, values, specifiedDomain): number[] { + if (!Array.isArray(specifiedDomain)) return I; + const domain = new Set(specifiedDomain); + return I.filter((i) => domain.has(values[i])); +} + function sortOrdinal(I, mark, options): [number[], G2Mark] { const { reverse, slice, channel, ...rest } = options; - const { encode } = mark; + const { encode, scale = {} } = mark; + const domain = scale[channel]?.domain; const [T] = columnOf(encode, channel); const normalizeReducer = createReducer(channel, rest, encode); - const sortedDomain = groupSort(I, normalizeReducer, (i: number) => T[i]); + const SI = filterIndex(I, T, domain); + const sortedDomain = groupSort(SI, normalizeReducer, (i: number) => T[i]); if (reverse) sortedDomain.reverse(); const s = typeof slice === 'number' ? [0, slice] : slice; const slicedDomain = slice ? sortedDomain.slice(...s) : sortedDomain;