ggaction 0.0.15 → 0.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +88 -0
- package/README.md +23 -2
- package/knowledge/action-cards.json +1 -1
- package/knowledge/intent-taxonomy.json +1 -1
- package/knowledge/mcp-resources.json +1 -1
- package/knowledge/task-packet.schema.json +1 -1
- package/knowledge/task-resolver.js +1 -1
- package/package.json +40 -7
- package/src/BasicChartProgram.js +3 -1
- package/src/ChartProgram.js +2 -0
- package/src/accessibility.js +157 -0
- package/src/actions/boxPlots/components.js +6 -8
- package/src/actions/boxPlots/create.js +4 -5
- package/src/actions/boxPlots/edit.js +3 -4
- package/src/actions/boxPlots/materialize.js +1 -1
- package/src/actions/canvas/actions.js +3 -3
- package/src/actions/canvas/fitting.js +1 -1
- package/src/actions/categoryOrder/index.js +6 -8
- package/src/actions/charts/area.js +1 -1
- package/src/actions/charts/bar.js +1 -1
- package/src/actions/charts/beeswarm.js +1 -1
- package/src/actions/charts/density.js +1 -1
- package/src/actions/charts/ecdf.js +2 -2
- package/src/actions/charts/endpoints.js +4 -4
- package/src/actions/charts/heatmap.js +1 -1
- package/src/actions/charts/histogram.js +1 -1
- package/src/actions/charts/horizon.js +1 -1
- package/src/actions/charts/interval-regression.js +2 -2
- package/src/actions/charts/line.js +1 -1
- package/src/actions/charts/parallel.js +1 -1
- package/src/actions/charts/pie.js +1 -1
- package/src/actions/charts/polar.js +2 -2
- package/src/actions/charts/radar.js +1 -1
- package/src/actions/charts/radial.js +2 -2
- package/src/actions/charts/raincloud.js +2 -2
- package/src/actions/charts/rug-strip.js +2 -2
- package/src/actions/charts/scatter.js +1 -1
- package/src/actions/composition/actions.js +20 -24
- package/src/actions/coordinates/actions.js +1 -1
- package/src/actions/coordinates/edit.js +1 -1
- package/src/actions/data/basicBin2d.js +4 -5
- package/src/actions/data/bin.js +3 -3
- package/src/actions/data/bin2d.js +6 -8
- package/src/actions/data/bin2dMaterialize.js +4 -5
- package/src/actions/data/box.js +4 -4
- package/src/actions/data/complete.js +2 -2
- package/src/actions/data/computed.js +2 -2
- package/src/actions/data/create.js +23 -17
- package/src/actions/data/density.js +4 -4
- package/src/actions/data/derived.js +25 -15
- package/src/actions/data/ecdf.js +2 -2
- package/src/actions/data/edit.js +54 -29
- package/src/actions/data/filter.js +29 -24
- package/src/actions/data/fold.js +2 -2
- package/src/actions/data/gradientProfile.js +2 -2
- package/src/actions/data/horizon.js +2 -2
- package/src/actions/data/impute.js +2 -2
- package/src/actions/data/index.js +58 -54
- package/src/actions/data/interval.js +4 -2
- package/src/actions/data/intervalEdit.js +26 -18
- package/src/actions/data/normalize.js +2 -2
- package/src/actions/data/regression.js +9 -7
- package/src/actions/data/revise.js +80 -0
- package/src/actions/data/revisionBindings.js +13 -33
- package/src/actions/data/shared.js +30 -2
- package/src/actions/data/sort.js +21 -0
- package/src/actions/data/stack.js +2 -2
- package/src/actions/data/summary.js +3 -3
- package/src/actions/data/timeUnit.js +2 -2
- package/src/actions/data/window.js +2 -2
- package/src/actions/encodings/angle.js +5 -2
- package/src/actions/encodings/appearance.js +10 -6
- package/src/actions/encodings/barWidth.js +1 -1
- package/src/actions/encodings/channels.js +2 -2
- package/src/actions/encodings/color/continuous.js +4 -1
- package/src/actions/encodings/color/index.js +5 -2
- package/src/actions/encodings/density.js +2 -2
- package/src/actions/encodings/histogram.js +1 -1
- package/src/actions/encodings/horizon.js +6 -8
- package/src/actions/encodings/offset.js +6 -3
- package/src/actions/encodings/parallel.js +4 -5
- package/src/actions/encodings/pathOrder.js +6 -11
- package/src/actions/encodings/position/index.js +4 -4
- package/src/actions/encodings/position/resolve.js +6 -1
- package/src/actions/encodings/ranged.js +11 -6
- package/src/actions/encodings/remove.js +4 -5
- package/src/actions/encodings/ruleAppearance.js +5 -2
- package/src/actions/encodings/seriesLayout.js +1 -1
- package/src/actions/encodings/stroke.js +5 -2
- package/src/actions/encodings/strokeDash.js +8 -3
- package/src/actions/encodings/text.js +7 -2
- package/src/actions/errorBands/create.js +11 -17
- package/src/actions/errorBands/edit.js +13 -131
- package/src/actions/errorBars/create.js +8 -13
- package/src/actions/errorBars/edit.js +10 -121
- package/src/actions/facets/actions.js +30 -16
- package/src/actions/facets/derive.js +8 -2
- package/src/actions/facets/guides.js +4 -5
- package/src/actions/facets/replay.js +4 -5
- package/src/actions/gradientPlots/components.js +5 -6
- package/src/actions/gradientPlots/create.js +4 -5
- package/src/actions/gradientPlots/edit.js +4 -5
- package/src/actions/gradientPlots/materialize.js +2 -2
- package/src/actions/gradientPlots/rebind.js +4 -5
- package/src/actions/guides/axes/axes.js +23 -4
- package/src/actions/guides/axes/axis.js +2 -2
- package/src/actions/guides/axes/edit.js +2 -2
- package/src/actions/guides/axes/labels.js +9 -9
- package/src/actions/guides/axes/lines.js +9 -7
- package/src/actions/guides/axes/parallel/lifecycle.js +13 -13
- package/src/actions/guides/axes/parallel.js +5 -5
- package/src/actions/guides/axes/remove.js +4 -4
- package/src/actions/guides/axes/tickGroups.js +4 -4
- package/src/actions/guides/axes/ticks.js +13 -4
- package/src/actions/guides/axes/titles.js +10 -10
- package/src/actions/guides/grids/grid.js +18 -29
- package/src/actions/guides/guides.js +1 -1
- package/src/actions/guides/legends/blocks.js +1 -1
- package/src/actions/guides/legends/categorical/actions.js +4 -4
- package/src/actions/guides/legends/categorical/components.js +38 -33
- package/src/actions/guides/legends/categorical/layout.js +1 -1
- package/src/actions/guides/legends/categorical/symbols.js +27 -30
- package/src/actions/guides/legends/continuous/common.js +46 -8
- package/src/actions/guides/legends/continuous/gradient.js +89 -155
- package/src/actions/guides/legends/continuous/interval.js +13 -13
- package/src/actions/guides/legends/continuous/opacity.js +30 -79
- package/src/actions/guides/legends/continuous/stroke.js +22 -322
- package/src/actions/guides/legends/edit.js +1 -1
- package/src/actions/guides/legends/focused.js +5 -5
- package/src/actions/guides/legends/lane.js +6 -6
- package/src/actions/guides/legends/remove.js +4 -5
- package/src/actions/guides/legends/size.js +21 -82
- package/src/actions/guides/legends/strokeWidth.js +17 -77
- package/src/actions/guides/polar/axes/facade.js +4 -4
- package/src/actions/guides/polar/axes/labels.js +5 -5
- package/src/actions/guides/polar/axes/lines.js +9 -15
- package/src/actions/guides/polar/axes/ticks.js +9 -15
- package/src/actions/guides/polar/axes/titles.js +5 -5
- package/src/actions/guides/polar/grids.js +11 -13
- package/src/actions/index.js +2 -0
- package/src/actions/intervals/revision.js +126 -0
- package/src/actions/marks/arc/actions.js +3 -3
- package/src/actions/marks/area/actions.js +4 -4
- package/src/actions/marks/bar/create.js +9 -2
- package/src/actions/marks/bar/edit.js +13 -6
- package/src/actions/marks/bar/materialize.js +12 -38
- package/src/actions/marks/line/actions.js +3 -3
- package/src/actions/marks/point/create.js +9 -2
- package/src/actions/marks/point/edit.js +13 -6
- package/src/actions/marks/point/jitter.js +6 -8
- package/src/actions/marks/point/materialize.js +20 -26
- package/src/actions/marks/point/packing.js +6 -8
- package/src/actions/marks/rect/actions.js +26 -11
- package/src/actions/marks/references.js +8 -10
- package/src/actions/marks/remove.js +5 -49
- package/src/actions/marks/rule/actions.js +28 -12
- package/src/actions/marks/text/actions.js +30 -11
- package/src/actions/marks/text/layout.js +12 -20
- package/src/actions/marks/text/removal.js +1 -1
- package/src/actions/marks/text/selection.js +4 -5
- package/src/actions/marks/tick/actions.js +26 -11
- package/src/actions/primitives/createGraphics.js +5 -4
- package/src/actions/primitives/editGraphics.js +5 -4
- package/src/actions/primitives/graphicProperties.js +6 -0
- package/src/actions/primitives/semantic.js +10 -3
- package/src/actions/primitives/semanticAction.js +44 -7
- package/src/actions/primitives/semanticValidation/dataset.js +14 -4
- package/src/actions/primitives/semanticValidation/layer.js +22 -2
- package/src/actions/primitives/semanticValidation/scale.js +6 -0
- package/src/actions/regression/components.js +10 -14
- package/src/actions/regression/create.js +28 -8
- package/src/actions/regression/edit.js +50 -16
- package/src/actions/regression/follow.js +22 -0
- package/src/actions/resources/remove.js +12 -11
- package/src/actions/scales/channels.js +11 -11
- package/src/actions/scales/consumers/common.js +2 -1
- package/src/actions/scales/create.js +3 -2
- package/src/actions/scales/definitions.js +1 -1
- package/src/actions/scales/edit.js +2 -2
- package/src/actions/scales/materialize.js +1 -1
- package/src/actions/scales/offset.js +2 -2
- package/src/actions/scales/parallel.js +2 -2
- package/src/actions/scales/patch.js +1 -1
- package/src/actions/scales/preview.js +28 -1
- package/src/actions/scales/quantitativeColor.js +4 -5
- package/src/actions/selection/actions.js +25 -36
- package/src/actions/textMetrics/index.js +56 -0
- package/src/actions/theme/actions.js +2 -2
- package/src/actions/theme/reconcile.js +67 -121
- package/src/actions/titles/actions.js +8 -8
- package/src/actions/titles/resolve.js +3 -3
- package/src/actions/violinPlots/create.js +1 -1
- package/src/actions/violinPlots/edit.js +1 -1
- package/src/core/action.js +109 -36
- package/src/core/diagnostics.js +16 -0
- package/src/core/extensionRegistry.js +27 -0
- package/src/core/font.js +18 -0
- package/src/core/identifiers.js +5 -4
- package/src/core/immutable.js +10 -3
- package/src/core/optionRequirements.js +8 -0
- package/src/core/programState.js +6 -2
- package/src/core/resourceReferences.js +15 -6
- package/src/core/textMetricProfile.js +28 -0
- package/src/core/textMetrics.js +24 -3
- package/src/core/validation.js +22 -10
- package/src/diagnostics.js +1 -0
- package/src/grammar/bin.js +39 -10
- package/src/grammar/datasetSchema.js +386 -0
- package/src/grammar/density.js +53 -5
- package/src/grammar/filter.js +133 -39
- package/src/grammar/impute.js +3 -2
- package/src/grammar/interval.js +32 -1
- package/src/grammar/itemMissing.js +59 -0
- package/src/grammar/regression/derive.js +57 -16
- package/src/grammar/regression/index.js +1 -0
- package/src/grammar/regression/models.js +51 -22
- package/src/grammar/regression/parameters.js +56 -4
- package/src/grammar/scales/definition.js +7 -0
- package/src/grammar/scales/types.js +8 -0
- package/src/grammar/schemas/graphicBounds.js +11 -11
- package/src/grammar/schemas/semanticPath.js +3 -2
- package/src/grammar/sort.js +88 -0
- package/src/grammar/summary.js +117 -19
- package/src/grammar/transformTopology.js +1 -0
- package/src/grammar/transforms.js +21 -11
- package/src/inspection.js +495 -0
- package/src/inspectionDescriptors.js +3 -0
- package/src/layout/labels.js +11 -10
- package/src/layout/legend.js +4 -4
- package/src/layout/legendItems.js +6 -6
- package/src/layout/text.js +10 -9
- package/src/layout/title.js +9 -9
- package/src/materialization/bars/resolve.js +4 -2
- package/src/materialization/facetGuides/placement.js +1 -1
- package/src/materialization/facetGuides/preparation.js +1 -1
- package/src/materialization/facetHeaders.js +11 -10
- package/src/materialization/guides/layout.js +3 -3
- package/src/materialization/revisionIdentity.js +19 -0
- package/src/materialization/scaleGuideDependencies.js +10 -0
- package/src/materialization/scales/resolve.js +67 -4
- package/src/materialization/selection/items/common.js +1 -1
- package/src/materialization/text.js +6 -4
- package/src/materialization/typography.js +31 -0
- package/src/mcp/cli.js +5 -3
- package/src/persistence/codec.js +65 -0
- package/src/persistence/validation.js +185 -0
- package/src/persistence.js +147 -0
- package/src/renderers/canvas/index.js +5 -4
- package/src/renderers/nativeBackend.js +10 -0
- package/src/renderers/options.js +13 -0
- package/src/renderers/pdf.js +25 -54
- package/src/renderers/png.js +22 -17
- package/src/renderers/svg.js +10 -14
- package/src/renderers/text.js +1 -11
- package/src/selectors/coordinates.js +3 -1
- package/src/selectors/datasets.js +8 -6
- package/src/selectors/layers.js +6 -4
- package/src/selectors/markOwners.js +46 -0
- package/src/selectors/scales.js +6 -4
- package/src/theme/defaults.js +2 -1
- package/src/version.js +2 -0
- package/types/accessibility.d.ts +37 -0
- package/types/basic.d.ts +4 -2
- package/types/diagnostics.d.ts +15 -0
- package/types/index.d.ts +5 -0
- package/types/inspection.d.ts +17 -0
- package/types/pdf.d.ts +9 -0
- package/types/persistence.d.ts +7 -0
- package/types/png.d.ts +9 -0
- package/types/program.d.ts +181 -28
package/src/grammar/summary.js
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
} from "./weightedStatistics.js";
|
|
17
17
|
|
|
18
18
|
const TRANSFORM_KEYS = Object.freeze([
|
|
19
|
-
"type", "groupBy", "aggregates", "members", "weight"
|
|
19
|
+
"type", "groupBy", "aggregates", "members", "weight", "missing", "empty"
|
|
20
20
|
]);
|
|
21
21
|
const AGGREGATE_KEYS = Object.freeze(["op", "field", "as"]);
|
|
22
22
|
const NOMINAL_OPERATIONS = new Set(["distinct", "valid", "missing"]);
|
|
@@ -51,7 +51,7 @@ function normalizeAggregate(value) {
|
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
export function normalizeSummaryTransform({ groupBy, aggregates, members, weight } = {}) {
|
|
54
|
+
export function normalizeSummaryTransform({ groupBy, aggregates, members, weight, missing, empty } = {}) {
|
|
55
55
|
const transform = {
|
|
56
56
|
type: "summary",
|
|
57
57
|
groupBy: normalizeGroupBy(groupBy),
|
|
@@ -61,7 +61,9 @@ export function normalizeSummaryTransform({ groupBy, aggregates, members, weight
|
|
|
61
61
|
...(members === undefined ? {} : { members }),
|
|
62
62
|
...(weight === undefined
|
|
63
63
|
? {}
|
|
64
|
-
: { weight: normalizeStatisticalWeight(weight, "Summary weight") })
|
|
64
|
+
: { weight: normalizeStatisticalWeight(weight, "Summary weight") }),
|
|
65
|
+
...(missing === undefined ? {} : { missing }),
|
|
66
|
+
...(empty === undefined ? {} : { empty })
|
|
65
67
|
};
|
|
66
68
|
validateSummaryTransform(transform);
|
|
67
69
|
return cloneAndFreeze(transform);
|
|
@@ -120,6 +122,12 @@ export function validateSummaryTransform(transform) {
|
|
|
120
122
|
if (transform.weight !== undefined) {
|
|
121
123
|
normalizeStatisticalWeight(transform.weight, "Summary weight");
|
|
122
124
|
}
|
|
125
|
+
if (transform.missing !== undefined && !["error", "drop"].includes(transform.missing)) {
|
|
126
|
+
throw new Error('Summary missing must be "error" or "drop".');
|
|
127
|
+
}
|
|
128
|
+
if (transform.empty !== undefined && !["null", "identity"].includes(transform.empty)) {
|
|
129
|
+
throw new Error('Summary empty must be "null" or "identity".');
|
|
130
|
+
}
|
|
123
131
|
return transform;
|
|
124
132
|
}
|
|
125
133
|
|
|
@@ -169,12 +177,13 @@ function validateAggregateValues(rows, aggregate) {
|
|
|
169
177
|
export function deriveSummaryRows(rows, transform) {
|
|
170
178
|
validateSummaryTransform(transform);
|
|
171
179
|
requireSourceFields(rows, transform);
|
|
180
|
+
const explicitWeighted = transform.weight !== undefined && transform.missing !== undefined;
|
|
172
181
|
let weightEntries;
|
|
173
182
|
if (transform.weight === undefined) {
|
|
174
183
|
for (const aggregate of transform.aggregates) {
|
|
175
184
|
validateAggregateValues(rows, aggregate);
|
|
176
185
|
}
|
|
177
|
-
} else {
|
|
186
|
+
} else if (!explicitWeighted) {
|
|
178
187
|
weightEntries = readStatisticalWeights(rows, transform.weight, "Summary").entries;
|
|
179
188
|
validateWeightedNumericFields(
|
|
180
189
|
weightEntries,
|
|
@@ -183,6 +192,37 @@ export function deriveSummaryRows(rows, transform) {
|
|
|
183
192
|
))],
|
|
184
193
|
"Summary"
|
|
185
194
|
);
|
|
195
|
+
} else {
|
|
196
|
+
// Explicit missing policy is evaluated per measure. Validate every
|
|
197
|
+
// nonmissing value now, while leaving nullish value/weight pairs for the
|
|
198
|
+
// reason-priority accounting below.
|
|
199
|
+
readStatisticalWeights(
|
|
200
|
+
rows.filter(row => row[transform.weight.field] !== null && row[transform.weight.field] !== undefined),
|
|
201
|
+
transform.weight,
|
|
202
|
+
"Summary"
|
|
203
|
+
);
|
|
204
|
+
for (const aggregate of transform.aggregates) {
|
|
205
|
+
if (aggregate.field === undefined) continue;
|
|
206
|
+
validateAggregateValues(
|
|
207
|
+
rows.filter(row => row[aggregate.field] !== null && row[aggregate.field] !== undefined),
|
|
208
|
+
aggregate
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (transform.missing === "error") {
|
|
213
|
+
if (transform.weight !== undefined) {
|
|
214
|
+
const weightIndex = rows.findIndex(row =>
|
|
215
|
+
row[transform.weight.field] === null || row[transform.weight.field] === undefined
|
|
216
|
+
);
|
|
217
|
+
if (weightIndex !== -1) {
|
|
218
|
+
throw new TypeError(`Summary weight "${transform.weight.field}" is missing at row ${weightIndex}.`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
for (const aggregate of transform.aggregates) {
|
|
222
|
+
if (aggregate.field === undefined) continue;
|
|
223
|
+
const index = rows.findIndex(row => row[aggregate.field] === null || row[aggregate.field] === undefined);
|
|
224
|
+
if (index !== -1) throw new TypeError(`Summary field "${aggregate.field}" is missing at row ${index}.`);
|
|
225
|
+
}
|
|
186
226
|
}
|
|
187
227
|
|
|
188
228
|
const groups = new Map();
|
|
@@ -212,34 +252,92 @@ export function deriveSummaryRows(rows, transform) {
|
|
|
212
252
|
throw new RangeError(`Summary output cannot exceed ${MAX_OUTPUT_ROWS} groups.`);
|
|
213
253
|
}
|
|
214
254
|
|
|
215
|
-
|
|
216
|
-
|
|
255
|
+
const units = [];
|
|
256
|
+
const values = [...groups.values()].map(group => {
|
|
257
|
+
const sharedWeightSummary = transform.weight === undefined || explicitWeighted
|
|
217
258
|
? undefined
|
|
218
259
|
: summarizeStatisticalWeights(
|
|
219
260
|
group.entries,
|
|
220
261
|
transform.weight.kind,
|
|
221
262
|
"Summary group"
|
|
222
263
|
);
|
|
264
|
+
const aggregated = Object.fromEntries(transform.aggregates.map(aggregate => {
|
|
265
|
+
let missingValue = 0;
|
|
266
|
+
let missingWeight = 0;
|
|
267
|
+
let zeroWeightRows = 0;
|
|
268
|
+
let measureWeightSummary = sharedWeightSummary;
|
|
269
|
+
if (explicitWeighted) {
|
|
270
|
+
const eligible = group.rows.filter(row => {
|
|
271
|
+
if (aggregate.field !== undefined &&
|
|
272
|
+
(row[aggregate.field] === null || row[aggregate.field] === undefined)) {
|
|
273
|
+
missingValue += 1;
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
if (row[transform.weight.field] === null || row[transform.weight.field] === undefined) {
|
|
277
|
+
missingWeight += 1;
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
return true;
|
|
281
|
+
});
|
|
282
|
+
const entries = readStatisticalWeights(eligible, transform.weight, "Summary").entries;
|
|
283
|
+
zeroWeightRows = entries.filter(entry => entry.weight === 0).length;
|
|
284
|
+
measureWeightSummary = summarizeStatisticalWeights(
|
|
285
|
+
entries,
|
|
286
|
+
transform.weight.kind,
|
|
287
|
+
"Summary group"
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
let value = measureWeightSummary === undefined
|
|
291
|
+
? aggregateRows(group.rows, aggregate.field ?? "__row", aggregate.op)
|
|
292
|
+
: calculateWeightedAggregate(
|
|
293
|
+
measureWeightSummary,
|
|
294
|
+
aggregate.field,
|
|
295
|
+
aggregate.op,
|
|
296
|
+
`Summary aggregate "${aggregate.as}"`
|
|
297
|
+
);
|
|
298
|
+
if (value === undefined && transform.empty !== undefined) {
|
|
299
|
+
const op = typeof aggregate.op === "string" ? aggregate.op : aggregate.op.op;
|
|
300
|
+
value = transform.empty === "identity" && op === "sum" ? 0 : null;
|
|
301
|
+
}
|
|
302
|
+
if (transform.missing !== undefined || transform.empty !== undefined) {
|
|
303
|
+
const missing = explicitWeighted
|
|
304
|
+
? missingValue + missingWeight
|
|
305
|
+
: aggregate.field === undefined ? 0 : group.rows.filter(row => row[aggregate.field] === null || row[aggregate.field] === undefined).length;
|
|
306
|
+
units.push({
|
|
307
|
+
role: aggregate.as,
|
|
308
|
+
group: group.values,
|
|
309
|
+
inputRows: group.rows.length,
|
|
310
|
+
usedRows: group.rows.length - missing,
|
|
311
|
+
excludedRows: missing,
|
|
312
|
+
excludedByReason: missing === 0 ? {} : {
|
|
313
|
+
...(missingValue === 0 && explicitWeighted ? {} : { "missing-value": explicitWeighted ? missingValue : missing }),
|
|
314
|
+
...(missingWeight === 0 ? {} : { "missing-weight": missingWeight })
|
|
315
|
+
},
|
|
316
|
+
...(explicitWeighted ? { zeroWeightRows } : {})
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
return [aggregate.as, value];
|
|
320
|
+
}));
|
|
223
321
|
return {
|
|
224
322
|
...group.values,
|
|
225
|
-
...
|
|
226
|
-
aggregate.as,
|
|
227
|
-
weightSummary === undefined
|
|
228
|
-
? aggregateRows(group.rows, aggregate.field ?? "__row", aggregate.op)
|
|
229
|
-
: calculateWeightedAggregate(
|
|
230
|
-
weightSummary,
|
|
231
|
-
aggregate.field,
|
|
232
|
-
aggregate.op,
|
|
233
|
-
`Summary aggregate "${aggregate.as}"`
|
|
234
|
-
)
|
|
235
|
-
])),
|
|
323
|
+
...aggregated,
|
|
236
324
|
...(transform.members === undefined
|
|
237
325
|
? {}
|
|
238
326
|
: {
|
|
239
|
-
[transform.members]:
|
|
327
|
+
[transform.members]: sharedWeightSummary === undefined
|
|
240
328
|
? group.rows
|
|
241
|
-
: weightedRows(
|
|
329
|
+
: weightedRows(sharedWeightSummary)
|
|
242
330
|
})
|
|
243
331
|
};
|
|
244
332
|
});
|
|
333
|
+
if (transform.missing === undefined && transform.empty === undefined) return values;
|
|
334
|
+
return {
|
|
335
|
+
values,
|
|
336
|
+
report: cloneAndFreeze({
|
|
337
|
+
version: 1,
|
|
338
|
+
owner: { kind: "data", id: "pending" },
|
|
339
|
+
inputs: [],
|
|
340
|
+
units
|
|
341
|
+
})
|
|
342
|
+
};
|
|
245
343
|
}
|
|
@@ -16,6 +16,7 @@ const TRANSFORM_TOPOLOGY = Object.freeze({
|
|
|
16
16
|
markFilter: Object.freeze({ provenanceTransparent: true }),
|
|
17
17
|
normalize: Object.freeze({ facetTopology: "statistical" }),
|
|
18
18
|
regression: Object.freeze({ facetTopology: "statistical" }),
|
|
19
|
+
sort: Object.freeze({ facetTopology: "statistical" }),
|
|
19
20
|
summary: Object.freeze({ facetTopology: "statistical" }),
|
|
20
21
|
stack: Object.freeze({ facetTopology: "statistical" }),
|
|
21
22
|
statisticalReference: Object.freeze({ facetTopology: "statistical" }),
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
validateCompleteTransform
|
|
24
24
|
} from "./complete.js";
|
|
25
25
|
import {
|
|
26
|
+
normalizeFilterTransformEdit,
|
|
26
27
|
normalizeFilterTransform,
|
|
27
28
|
validateFilterTransform
|
|
28
29
|
} from "./filter.js";
|
|
@@ -62,6 +63,7 @@ import {
|
|
|
62
63
|
validateSummaryTransform
|
|
63
64
|
} from "./summary.js";
|
|
64
65
|
import { normalizeStackTransform, validateStackTransform } from "./stack.js";
|
|
66
|
+
import { normalizeSortTransform, validateSortTransform } from "./sort.js";
|
|
65
67
|
import { validateStatisticalReferenceTransform } from
|
|
66
68
|
"./statisticalReference.js";
|
|
67
69
|
import { findTransformTopology } from "./transformTopology.js";
|
|
@@ -102,15 +104,6 @@ function normalizeSimple(normalize) {
|
|
|
102
104
|
return (transform, patch) => normalize(mergedOptions(transform, patch));
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
function normalizeFilterEdit(transform, patch) {
|
|
106
|
-
const base = replaceExclusive(
|
|
107
|
-
requestedOptions(transform),
|
|
108
|
-
patch,
|
|
109
|
-
["oneOf", "predicate", "range"]
|
|
110
|
-
);
|
|
111
|
-
return normalizeFilterTransform({ ...base, ...patch });
|
|
112
|
-
}
|
|
113
|
-
|
|
114
107
|
function normalizeBinEdit(transform, patch) {
|
|
115
108
|
const prior = requestedOptions(transform);
|
|
116
109
|
const base = replaceExclusive(
|
|
@@ -202,6 +195,7 @@ function normalizeNormalizeEdit(transform, patch) {
|
|
|
202
195
|
|
|
203
196
|
function normalizeRegressionEdit(transform, patch) {
|
|
204
197
|
const base = { ...requestedOptions(transform) };
|
|
198
|
+
if (patch.predict === false) delete base.predict;
|
|
205
199
|
const method = patch.method ?? base.method;
|
|
206
200
|
if (method !== base.method) {
|
|
207
201
|
if (method !== "polynomial") delete base.degree;
|
|
@@ -212,7 +206,14 @@ function normalizeRegressionEdit(transform, patch) {
|
|
|
212
206
|
]) delete base[key];
|
|
213
207
|
}
|
|
214
208
|
}
|
|
215
|
-
|
|
209
|
+
if (patch.interval === false) {
|
|
210
|
+
for (const key of ["confidenceMethod", "level", "confidence"]) delete base[key];
|
|
211
|
+
}
|
|
212
|
+
return normalizeRegressionTransform({
|
|
213
|
+
...base,
|
|
214
|
+
...Object.fromEntries(Object.entries(patch).filter(([key, value]) => !(key === "predict" && value === false))),
|
|
215
|
+
method
|
|
216
|
+
});
|
|
216
217
|
}
|
|
217
218
|
|
|
218
219
|
function normalizeTimeUnitEdit(transform, patch) {
|
|
@@ -373,7 +374,7 @@ const TRANSFORM_POLICIES = Object.freeze({
|
|
|
373
374
|
materializeOp: "materializeFilteredData",
|
|
374
375
|
replayTransform: requestedTransform,
|
|
375
376
|
editable: true,
|
|
376
|
-
normalizeEdit:
|
|
377
|
+
normalizeEdit: normalizeFilterTransformEdit,
|
|
377
378
|
outputRoles: () => ({})
|
|
378
379
|
}),
|
|
379
380
|
fold: Object.freeze({
|
|
@@ -442,6 +443,15 @@ const TRANSFORM_POLICIES = Object.freeze({
|
|
|
442
443
|
normalizeEdit: normalizeRegressionEdit,
|
|
443
444
|
outputRoles: () => ({})
|
|
444
445
|
}),
|
|
446
|
+
sort: Object.freeze({
|
|
447
|
+
...findTransformTopology("sort"),
|
|
448
|
+
validate: validateSortTransform,
|
|
449
|
+
materializeOp: "materializeSortedData",
|
|
450
|
+
replayTransform: requestedTransform,
|
|
451
|
+
editable: true,
|
|
452
|
+
normalizeEdit: normalizeSimple(normalizeSortTransform),
|
|
453
|
+
outputRoles: () => ({})
|
|
454
|
+
}),
|
|
445
455
|
summary: Object.freeze({
|
|
446
456
|
...findTransformTopology("summary"),
|
|
447
457
|
validate: validateSummaryTransform,
|