diff --git a/examples/compiled/arc_ordinal_theta.vg.json b/examples/compiled/arc_ordinal_theta.vg.json index eda82aec99..b1e44cd834 100644 --- a/examples/compiled/arc_ordinal_theta.vg.json +++ b/examples/compiled/arc_ordinal_theta.vg.json @@ -23,6 +23,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["dir"], + "field": "strength", + "sort": {"field": [], "order": []}, + "as": ["strength_start", "strength_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"strength\"]) && isFinite(+datum[\"strength\"])" @@ -44,8 +52,8 @@ }, "x": {"signal": "width", "mult": 0.5}, "y": {"signal": "height", "mult": 0.5}, - "outerRadius": {"scale": "radius", "field": "strength"}, - "innerRadius": {"scale": "radius", "value": 0}, + "outerRadius": {"scale": "radius", "field": "strength_end"}, + "innerRadius": {"scale": "radius", "field": "strength_start"}, "startAngle": {"scale": "theta", "field": "dir"}, "endAngle": { "scale": "theta", @@ -66,7 +74,10 @@ { "name": "radius", "type": "linear", - "domain": {"data": "data_0", "field": "strength"}, + "domain": { + "data": "data_0", + "fields": ["strength_start", "strength_end"] + }, "range": [0, {"signal": "min(width,height)/2"}], "zero": true }, diff --git a/examples/compiled/area_gradient.vg.json b/examples/compiled/area_gradient.vg.json index 6c9e22dc1d..ad480764d8 100644 --- a/examples/compiled/area_gradient.vg.json +++ b/examples/compiled/area_gradient.vg.json @@ -11,7 +11,25 @@ "name": "source_0", "url": "data/stocks.csv", "format": {"type": "csv", "parse": {"date": "date"}}, - "transform": [{"type": "filter", "expr": "datum.symbol==='GOOG'"}] + "transform": [ + {"type": "filter", "expr": "datum.symbol==='GOOG'"}, + { + "type": "impute", + "field": "price", + "groupby": [], + "key": "date", + "method": "value", + "value": 0 + }, + { + "type": "stack", + "groupby": ["date"], + "field": "price", + "sort": {"field": [], "order": []}, + "as": ["price_start", "price_end"], + "offset": "zero" + } + ] } ], "marks": [ @@ -42,8 +60,8 @@ "signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))" }, "x": {"scale": "x", "field": "date"}, - "y": {"scale": "y", "field": "price"}, - "y2": {"scale": "y", "value": 0}, + "y": {"scale": "y", "field": "price_end"}, + "y2": {"scale": "y", "field": "price_start"}, "defined": { "signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" } @@ -63,7 +81,7 @@ "signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))" }, "x": {"scale": "x", "field": "date"}, - "y": {"scale": "y", "field": "price"}, + "y": {"scale": "y", "field": "price_end"}, "defined": { "signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" } @@ -81,7 +99,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "source_0", "field": "price"}, + "domain": {"data": "source_0", "fields": ["price_start", "price_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/area_overlay.vg.json b/examples/compiled/area_overlay.vg.json index 77f5607300..aec203dc4b 100644 --- a/examples/compiled/area_overlay.vg.json +++ b/examples/compiled/area_overlay.vg.json @@ -17,6 +17,36 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "impute", + "field": "price", + "groupby": [], + "key": "date", + "method": "value", + "value": 0 + }, + { + "type": "stack", + "groupby": ["date"], + "field": "price", + "sort": {"field": [], "order": []}, + "as": ["price_start", "price_end"], + "offset": "zero" + } + ] + }, + { + "name": "data_1", + "source": "source_0", + "transform": [ + { + "type": "stack", + "groupby": ["date"], + "field": "price", + "sort": {"field": [], "order": []}, + "as": ["price_start", "price_end"], + "offset": "zero" + }, { "type": "filter", "expr": "(isDate(datum[\"date\"]) || (isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]))) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" @@ -30,7 +60,7 @@ "type": "area", "style": ["area"], "sort": {"field": "datum[\"date\"]"}, - "from": {"data": "source_0"}, + "from": {"data": "data_0"}, "encode": { "update": { "opacity": {"value": 0.7}, @@ -40,8 +70,8 @@ "signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))" }, "x": {"scale": "x", "field": "date"}, - "y": {"scale": "y", "field": "price"}, - "y2": {"scale": "y", "value": 0}, + "y": {"scale": "y", "field": "price_end"}, + "y2": {"scale": "y", "field": "price_start"}, "defined": { "signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" } @@ -53,7 +83,7 @@ "type": "line", "style": ["line"], "sort": {"field": "datum[\"date\"]"}, - "from": {"data": "source_0"}, + "from": {"data": "data_0"}, "encode": { "update": { "stroke": {"value": "#4c78a8"}, @@ -61,7 +91,7 @@ "signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))" }, "x": {"scale": "x", "field": "date"}, - "y": {"scale": "y", "field": "price"}, + "y": {"scale": "y", "field": "price_end"}, "defined": { "signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" } @@ -72,7 +102,7 @@ "name": "layer_2_marks", "type": "symbol", "style": ["point"], - "from": {"data": "data_0"}, + "from": {"data": "data_1"}, "encode": { "update": { "opacity": {"value": 1}, @@ -82,7 +112,7 @@ "signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))" }, "x": {"scale": "x", "field": "date"}, - "y": {"scale": "y", "field": "price"} + "y": {"scale": "y", "field": "price_end"} } } } @@ -93,8 +123,8 @@ "type": "time", "domain": { "fields": [ - {"data": "source_0", "field": "date"}, - {"data": "data_0", "field": "date"} + {"data": "data_0", "field": "date"}, + {"data": "data_1", "field": "date"} ] }, "range": [0, {"signal": "width"}] @@ -104,8 +134,10 @@ "type": "linear", "domain": { "fields": [ - {"data": "source_0", "field": "price"}, - {"data": "data_0", "field": "price"} + {"data": "data_0", "field": "price_start"}, + {"data": "data_0", "field": "price_end"}, + {"data": "data_1", "field": "price_start"}, + {"data": "data_1", "field": "price_end"} ] }, "range": [{"signal": "height"}, 0], diff --git a/examples/compiled/bar.vg.json b/examples/compiled/bar.vg.json index 2840f2d51e..cf7d1e2bbc 100644 --- a/examples/compiled/bar.vg.json +++ b/examples/compiled/bar.vg.json @@ -24,6 +24,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -53,8 +61,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -71,7 +79,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_aggregate_transform.vg.json b/examples/compiled/bar_aggregate_transform.vg.json index 22f7da095b..47ed9786bf 100644 --- a/examples/compiled/bar_aggregate_transform.vg.json +++ b/examples/compiled/bar_aggregate_transform.vg.json @@ -17,6 +17,14 @@ "fields": ["Acceleration"], "as": ["mean_acc"] }, + { + "type": "stack", + "groupby": ["Cylinders"], + "field": "mean_acc", + "sort": {"field": [], "order": []}, + "as": ["mean_acc_start", "mean_acc_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"mean_acc\"]) && isFinite(+datum[\"mean_acc\"])" @@ -46,8 +54,8 @@ }, "x": {"scale": "x", "field": "Cylinders"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "mean_acc"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "mean_acc_end"}, + "y2": {"scale": "y", "field": "mean_acc_start"} } } } @@ -64,7 +72,10 @@ { "name": "y", "type": "linear", - "domain": {"data": "source_0", "field": "mean_acc"}, + "domain": { + "data": "source_0", + "fields": ["mean_acc_start", "mean_acc_end"] + }, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_argmax_transform.vg.json b/examples/compiled/bar_argmax_transform.vg.json index d985a8d0a1..87a4afbed9 100644 --- a/examples/compiled/bar_argmax_transform.vg.json +++ b/examples/compiled/bar_argmax_transform.vg.json @@ -23,6 +23,17 @@ "expr": "datum[\"argmax_US_Gross\"] && datum[\"argmax_US_Gross\"][\"Production Budget\"]", "as": "argmax_US_Gross.Production Budget" }, + { + "type": "stack", + "groupby": ["Major Genre"], + "field": "argmax_US_Gross\\.Production Budget", + "sort": {"field": [], "order": []}, + "as": [ + "argmax_US_Gross.Production Budget._start", + "argmax_US_Gross.Production Budget._end" + ], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"argmax_US_Gross.Production Budget\"]) && isFinite(+datum[\"argmax_US_Gross.Production Budget\"])" @@ -50,8 +61,14 @@ "description": { "signal": "\"argmax_US_Gross['Production Budget']: \" + (format(datum[\"argmax_US_Gross.Production Budget\"], \"\")) + \"; Major Genre: \" + (isValid(datum[\"Major Genre\"]) ? datum[\"Major Genre\"] : \"\"+datum[\"Major Genre\"])" }, - "x": {"scale": "x", "field": "argmax_US_Gross\\.Production Budget"}, - "x2": {"scale": "x", "value": 0}, + "x": { + "scale": "x", + "field": "argmax_US_Gross\\.Production Budget\\._end" + }, + "x2": { + "scale": "x", + "field": "argmax_US_Gross\\.Production Budget\\._start" + }, "y": {"scale": "y", "field": "Major Genre"}, "height": {"scale": "y", "band": 1} } @@ -64,7 +81,10 @@ "type": "linear", "domain": { "data": "source_0", - "field": "argmax_US_Gross\\.Production Budget" + "fields": [ + "argmax_US_Gross\\.Production Budget\\._start", + "argmax_US_Gross\\.Production Budget\\._end" + ] }, "range": [0, {"signal": "width"}], "nice": true, diff --git a/examples/compiled/bar_axis_orient_signal_future.vg.json b/examples/compiled/bar_axis_orient_signal_future.vg.json index 5631559ac5..552dcbeb94 100644 --- a/examples/compiled/bar_axis_orient_signal_future.vg.json +++ b/examples/compiled/bar_axis_orient_signal_future.vg.json @@ -25,6 +25,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -54,8 +62,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -72,7 +80,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_color_disabled_scale.vg.json b/examples/compiled/bar_color_disabled_scale.vg.json index c63876568c..68c3a29ad3 100644 --- a/examples/compiled/bar_color_disabled_scale.vg.json +++ b/examples/compiled/bar_color_disabled_scale.vg.json @@ -18,6 +18,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["color"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -47,8 +55,8 @@ }, "x": {"scale": "x", "field": "color"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -65,7 +73,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_column_fold.vg.json b/examples/compiled/bar_column_fold.vg.json index 2eec0646da..f197b99d3d 100644 --- a/examples/compiled/bar_column_fold.vg.json +++ b/examples/compiled/bar_column_fold.vg.json @@ -15,6 +15,14 @@ "source": "source_0", "transform": [ {"type": "fold", "fields": ["gold", "silver"], "as": ["key", "value"]}, + { + "type": "stack", + "groupby": ["country", "key"], + "field": "value", + "sort": {"field": [], "order": []}, + "as": ["value_start", "value_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"value\"]) && isFinite(+datum[\"value\"])" @@ -131,8 +139,8 @@ }, "x": {"scale": "x", "field": "country"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "value"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "value_end"}, + "y2": {"scale": "y", "field": "value_start"} } } } @@ -167,7 +175,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "value"}, + "domain": {"data": "data_0", "fields": ["value_start", "value_end"]}, "range": [{"signal": "child_height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_column_pivot.vg.json b/examples/compiled/bar_column_pivot.vg.json index ad450b0681..3e69682af4 100644 --- a/examples/compiled/bar_column_pivot.vg.json +++ b/examples/compiled/bar_column_pivot.vg.json @@ -29,6 +29,14 @@ "value": "count", "groupby": ["country"] }, + { + "type": "stack", + "groupby": ["country"], + "field": "gold", + "sort": {"field": [], "order": []}, + "as": ["gold_start", "gold_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"gold\"]) && isFinite(+datum[\"gold\"])" @@ -58,8 +66,8 @@ }, "x": {"scale": "x", "field": "country"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "gold"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "gold_end"}, + "y2": {"scale": "y", "field": "gold_start"} } } } @@ -76,7 +84,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "gold"}, + "domain": {"data": "data_0", "fields": ["gold_start", "gold_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_corner_radius_end.svg b/examples/compiled/bar_corner_radius_end.svg index 1b6fd00d71..ec6bc8107a 100644 --- a/examples/compiled/bar_corner_radius_end.svg +++ b/examples/compiled/bar_corner_radius_end.svg @@ -1 +1 @@ -ABCDEFGHIa020406080100b \ No newline at end of file +ABCDEFGHIa020406080100b \ No newline at end of file diff --git a/examples/compiled/bar_corner_radius_end.vg.json b/examples/compiled/bar_corner_radius_end.vg.json index 14dc2f0740..64a6015a4f 100644 --- a/examples/compiled/bar_corner_radius_end.vg.json +++ b/examples/compiled/bar_corner_radius_end.vg.json @@ -24,6 +24,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -40,25 +48,64 @@ ], "marks": [ { - "name": "marks", - "type": "rect", - "style": ["bar"], - "from": {"data": "data_0"}, + "type": "group", + "from": { + "facet": { + "data": "data_0", + "name": "stack_group_main", + "groupby": ["a"], + "aggregate": { + "fields": ["b_start", "b_start", "b_end", "b_end"], + "ops": ["min", "max", "min", "max"] + } + } + }, "encode": { "update": { - "cornerRadiusTopLeft": {"value": 4}, - "cornerRadiusTopRight": {"value": 4}, - "fill": {"value": "#4c78a8"}, - "ariaRoleDescription": {"value": "bar"}, - "description": { - "signal": "\"a: \" + (isValid(datum[\"a\"]) ? datum[\"a\"] : \"\"+datum[\"a\"]) + \"; b: \" + (format(datum[\"b\"], \"\"))" - }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": { + "signal": "min(scale('y',datum[\"min_b_start\"]),scale('y',datum[\"max_b_start\"]),scale('y',datum[\"min_b_end\"]),scale('y',datum[\"max_b_end\"]))" + }, + "y2": { + "signal": "max(scale('y',datum[\"min_b_start\"]),scale('y',datum[\"max_b_start\"]),scale('y',datum[\"min_b_end\"]),scale('y',datum[\"max_b_end\"]))" + }, + "clip": {"value": true}, + "cornerRadiusTopLeft": {"value": 4}, + "cornerRadiusTopRight": {"value": 4} } - } + }, + "marks": [ + { + "type": "group", + "encode": { + "update": { + "y": {"field": {"group": "y"}, "mult": -1}, + "width": {"field": {"group": "width"}} + } + }, + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["bar"], + "from": {"data": "stack_group_main"}, + "encode": { + "update": { + "fill": {"value": "#4c78a8"}, + "ariaRoleDescription": {"value": "bar"}, + "description": { + "signal": "\"a: \" + (isValid(datum[\"a\"]) ? datum[\"a\"] : \"\"+datum[\"a\"]) + \"; b: \" + (format(datum[\"b\"], \"\"))" + }, + "width": {"field": {"group": "width"}}, + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} + } + } + } + ] + } + ] } ], "scales": [ @@ -73,7 +120,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_custom_sort_full.vg.json b/examples/compiled/bar_custom_sort_full.vg.json index be87e67c82..4cfa00cbdc 100644 --- a/examples/compiled/bar_custom_sort_full.vg.json +++ b/examples/compiled/bar_custom_sort_full.vg.json @@ -24,6 +24,14 @@ "name": "data_1", "source": "data_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -53,8 +61,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -75,7 +83,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_1", "field": "b"}, + "domain": {"data": "data_1", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_custom_sort_partial.vg.json b/examples/compiled/bar_custom_sort_partial.vg.json index 7a9c1c59e7..cc37703181 100644 --- a/examples/compiled/bar_custom_sort_partial.vg.json +++ b/examples/compiled/bar_custom_sort_partial.vg.json @@ -31,6 +31,14 @@ "name": "data_1", "source": "data_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -60,8 +68,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -82,7 +90,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_1", "field": "b"}, + "domain": {"data": "data_1", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_custom_time_domain.vg.json b/examples/compiled/bar_custom_time_domain.vg.json index 3b3a710947..fef5727456 100644 --- a/examples/compiled/bar_custom_time_domain.vg.json +++ b/examples/compiled/bar_custom_time_domain.vg.json @@ -26,6 +26,14 @@ "units": ["hours"], "as": ["hours_a", "hours_a_end"] }, + { + "type": "stack", + "groupby": ["hours_a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "(isDate(datum[\"hours_a\"]) || (isValid(datum[\"hours_a\"]) && isFinite(+datum[\"hours_a\"]))) && isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -60,8 +68,8 @@ }, {"scale": "x", "field": "hours_a_end"} ], - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -81,7 +89,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_default_tooltip_title_null.vg.json b/examples/compiled/bar_default_tooltip_title_null.vg.json index 2be9384556..414e5a232d 100644 --- a/examples/compiled/bar_default_tooltip_title_null.vg.json +++ b/examples/compiled/bar_default_tooltip_title_null.vg.json @@ -24,6 +24,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -56,8 +64,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -74,7 +82,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_filter_calc.vg.json b/examples/compiled/bar_filter_calc.vg.json index 57fa80f133..961077ae0d 100644 --- a/examples/compiled/bar_filter_calc.vg.json +++ b/examples/compiled/bar_filter_calc.vg.json @@ -26,6 +26,14 @@ "transform": [ {"type": "formula", "expr": "2*datum.b", "as": "b2"}, {"type": "filter", "expr": "datum.b2 > 60"}, + { + "type": "stack", + "groupby": ["a"], + "field": "b2", + "sort": {"field": [], "order": []}, + "as": ["b2_start", "b2_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b2\"]) && isFinite(+datum[\"b2\"])" @@ -55,8 +63,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b2"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b2_end"}, + "y2": {"scale": "y", "field": "b2_start"} } } } @@ -73,7 +81,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b2"}, + "domain": {"data": "data_0", "fields": ["b2_start", "b2_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_fit.vg.json b/examples/compiled/bar_fit.vg.json index c72e3e8817..6abf452be9 100644 --- a/examples/compiled/bar_fit.vg.json +++ b/examples/compiled/bar_fit.vg.json @@ -26,6 +26,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -48,8 +56,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -66,7 +74,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_negative.vg.json b/examples/compiled/bar_negative.vg.json index ec64412589..8f9e76b9f9 100644 --- a/examples/compiled/bar_negative.vg.json +++ b/examples/compiled/bar_negative.vg.json @@ -24,6 +24,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -53,8 +61,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -71,7 +79,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_params.svg b/examples/compiled/bar_params.svg index 9e458ba525..1fbef27891 100644 --- a/examples/compiled/bar_params.svg +++ b/examples/compiled/bar_params.svg @@ -1 +1 @@ -ABCDEFGHIa020406080100b \ No newline at end of file +ABCDEFGHIa020406080100b \ No newline at end of file diff --git a/examples/compiled/bar_params.vg.json b/examples/compiled/bar_params.vg.json index 69deed03e2..e34db33fa3 100644 --- a/examples/compiled/bar_params.vg.json +++ b/examples/compiled/bar_params.vg.json @@ -24,6 +24,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -50,26 +58,65 @@ ], "marks": [ { - "name": "marks", - "type": "rect", - "style": ["bar"], - "from": {"data": "data_0"}, + "type": "group", + "from": { + "facet": { + "data": "data_0", + "name": "stack_group_main", + "groupby": ["a"], + "aggregate": { + "fields": ["b_start", "b_start", "b_end", "b_end"], + "ops": ["min", "max", "min", "max"] + } + } + }, "encode": { "update": { + "x": {"scale": "x", "field": "a"}, + "width": {"scale": "x", "band": 1}, + "y": { + "signal": "min(scale('y',datum[\"min_b_start\"]),scale('y',datum[\"max_b_start\"]),scale('y',datum[\"min_b_end\"]),scale('y',datum[\"max_b_end\"]))" + }, + "y2": { + "signal": "max(scale('y',datum[\"min_b_start\"]),scale('y',datum[\"max_b_start\"]),scale('y',datum[\"min_b_end\"]),scale('y',datum[\"max_b_end\"]))" + }, + "clip": {"value": true}, "cornerRadius": {"signal": "cornerRadius"}, "cornerRadiusTopLeft": {"signal": "cornerRadiusEnd"}, - "cornerRadiusTopRight": {"signal": "cornerRadiusEnd"}, - "fill": {"value": "#4c78a8"}, - "ariaRoleDescription": {"value": "bar"}, - "description": { - "signal": "\"a: \" + (isValid(datum[\"a\"]) ? datum[\"a\"] : \"\"+datum[\"a\"]) + \"; b: \" + (format(datum[\"b\"], \"\"))" + "cornerRadiusTopRight": {"signal": "cornerRadiusEnd"} + } + }, + "marks": [ + { + "type": "group", + "encode": { + "update": { + "y": {"field": {"group": "y"}, "mult": -1}, + "width": {"field": {"group": "width"}} + } }, - "x": {"scale": "x", "field": "a"}, - "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "marks": [ + { + "name": "marks", + "type": "rect", + "style": ["bar"], + "from": {"data": "stack_group_main"}, + "encode": { + "update": { + "fill": {"value": "#4c78a8"}, + "ariaRoleDescription": {"value": "bar"}, + "description": { + "signal": "\"a: \" + (isValid(datum[\"a\"]) ? datum[\"a\"] : \"\"+datum[\"a\"]) + \"; b: \" + (format(datum[\"b\"], \"\"))" + }, + "width": {"field": {"group": "width"}}, + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} + } + } + } + ] } - } + ] } ], "scales": [ @@ -84,7 +131,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_title.vg.json b/examples/compiled/bar_title.vg.json index 61abeede99..cac465ad90 100644 --- a/examples/compiled/bar_title.vg.json +++ b/examples/compiled/bar_title.vg.json @@ -24,6 +24,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -53,8 +61,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -71,7 +79,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_title_start.vg.json b/examples/compiled/bar_title_start.vg.json index 37ce30bca4..060cdc9c87 100644 --- a/examples/compiled/bar_title_start.vg.json +++ b/examples/compiled/bar_title_start.vg.json @@ -24,6 +24,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -53,8 +61,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -71,7 +79,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_tooltip.vg.json b/examples/compiled/bar_tooltip.vg.json index 8d8747c756..2ab3ef1e59 100644 --- a/examples/compiled/bar_tooltip.vg.json +++ b/examples/compiled/bar_tooltip.vg.json @@ -24,6 +24,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -54,8 +62,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -72,7 +80,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_tooltip_multi.vg.json b/examples/compiled/bar_tooltip_multi.vg.json index 369dfaf67d..a1b3f4e40a 100644 --- a/examples/compiled/bar_tooltip_multi.vg.json +++ b/examples/compiled/bar_tooltip_multi.vg.json @@ -23,6 +23,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -55,8 +63,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -73,7 +81,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/bar_tooltip_title.vg.json b/examples/compiled/bar_tooltip_title.vg.json index fc6e2d176d..78c257643f 100644 --- a/examples/compiled/bar_tooltip_title.vg.json +++ b/examples/compiled/bar_tooltip_title.vg.json @@ -23,6 +23,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -55,8 +63,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -73,7 +81,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/facet_bullet.vg.json b/examples/compiled/facet_bullet.vg.json index 465fd35351..1080a96e24 100644 --- a/examples/compiled/facet_bullet.vg.json +++ b/examples/compiled/facet_bullet.vg.json @@ -83,6 +83,14 @@ "name": "data_1", "source": "data_0", "transform": [ + { + "type": "stack", + "groupby": ["title"], + "field": "ranges\\.2", + "sort": {"field": [], "order": []}, + "as": ["ranges.2._start", "ranges.2._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"ranges.2\"]) && isFinite(+datum[\"ranges.2\"])" @@ -93,6 +101,14 @@ "name": "data_2", "source": "data_0", "transform": [ + { + "type": "stack", + "groupby": ["title"], + "field": "ranges\\.1", + "sort": {"field": [], "order": []}, + "as": ["ranges.1._start", "ranges.1._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"ranges.1\"]) && isFinite(+datum[\"ranges.1\"])" @@ -103,6 +119,14 @@ "name": "data_3", "source": "data_0", "transform": [ + { + "type": "stack", + "groupby": ["title"], + "field": "ranges\\.0", + "sort": {"field": [], "order": []}, + "as": ["ranges.0._start", "ranges.0._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"ranges.0\"]) && isFinite(+datum[\"ranges.0\"])" @@ -113,6 +137,14 @@ "name": "data_4", "source": "data_0", "transform": [ + { + "type": "stack", + "groupby": ["title"], + "field": "measures\\.1", + "sort": {"field": [], "order": []}, + "as": ["measures.1._start", "measures.1._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"measures.1\"]) && isFinite(+datum[\"measures.1\"])" @@ -123,6 +155,14 @@ "name": "data_5", "source": "data_0", "transform": [ + { + "type": "stack", + "groupby": ["title"], + "field": "measures\\.0", + "sort": {"field": [], "order": []}, + "as": ["measures.0._start", "measures.0._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"measures.0\"]) && isFinite(+datum[\"measures.0\"])" @@ -184,6 +224,14 @@ "source": "facet", "name": "data_0", "transform": [ + { + "type": "stack", + "groupby": [], + "field": "ranges\\.2", + "sort": {"field": [], "order": []}, + "as": ["ranges.2._start", "ranges.2._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"ranges.2\"]) && isFinite(+datum[\"ranges.2\"])" @@ -194,6 +242,14 @@ "source": "facet", "name": "data_1", "transform": [ + { + "type": "stack", + "groupby": [], + "field": "ranges\\.1", + "sort": {"field": [], "order": []}, + "as": ["ranges.1._start", "ranges.1._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"ranges.1\"]) && isFinite(+datum[\"ranges.1\"])" @@ -204,6 +260,14 @@ "source": "facet", "name": "data_2", "transform": [ + { + "type": "stack", + "groupby": [], + "field": "ranges\\.0", + "sort": {"field": [], "order": []}, + "as": ["ranges.0._start", "ranges.0._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"ranges.0\"]) && isFinite(+datum[\"ranges.0\"])" @@ -214,6 +278,14 @@ "source": "facet", "name": "data_3", "transform": [ + { + "type": "stack", + "groupby": [], + "field": "measures\\.1", + "sort": {"field": [], "order": []}, + "as": ["measures.1._start", "measures.1._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"measures.1\"]) && isFinite(+datum[\"measures.1\"])" @@ -224,6 +296,14 @@ "source": "facet", "name": "data_4", "transform": [ + { + "type": "stack", + "groupby": [], + "field": "measures\\.0", + "sort": {"field": [], "order": []}, + "as": ["measures.0._start", "measures.0._end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"measures.0\"]) && isFinite(+datum[\"measures.0\"])" @@ -261,8 +341,8 @@ "description": { "signal": "\"ranges[2]: \" + (format(datum[\"ranges.2\"], \"\"))" }, - "x": {"scale": "child_x", "field": "ranges\\.2"}, - "x2": {"scale": "child_x", "value": 0}, + "x": {"scale": "child_x", "field": "ranges\\.2\\._end"}, + "x2": {"scale": "child_x", "field": "ranges\\.2\\._start"}, "yc": {"signal": "child_height", "mult": 0.5}, "height": {"value": 18} } @@ -280,8 +360,8 @@ "description": { "signal": "\"ranges[1]: \" + (format(datum[\"ranges.1\"], \"\"))" }, - "x": {"scale": "child_x", "field": "ranges\\.1"}, - "x2": {"scale": "child_x", "value": 0}, + "x": {"scale": "child_x", "field": "ranges\\.1\\._end"}, + "x2": {"scale": "child_x", "field": "ranges\\.1\\._start"}, "yc": {"signal": "child_height", "mult": 0.5}, "height": {"value": 18} } @@ -299,8 +379,8 @@ "description": { "signal": "\"ranges[0]: \" + (format(datum[\"ranges.0\"], \"\"))" }, - "x": {"scale": "child_x", "field": "ranges\\.0"}, - "x2": {"scale": "child_x", "value": 0}, + "x": {"scale": "child_x", "field": "ranges\\.0\\._end"}, + "x2": {"scale": "child_x", "field": "ranges\\.0\\._start"}, "yc": {"signal": "child_height", "mult": 0.5}, "height": {"value": 18} } @@ -318,8 +398,8 @@ "description": { "signal": "\"measures[1]: \" + (format(datum[\"measures.1\"], \"\"))" }, - "x": {"scale": "child_x", "field": "measures\\.1"}, - "x2": {"scale": "child_x", "value": 0}, + "x": {"scale": "child_x", "field": "measures\\.1\\._end"}, + "x2": {"scale": "child_x", "field": "measures\\.1\\._start"}, "yc": {"signal": "child_height", "mult": 0.5}, "height": {"value": 10} } @@ -337,8 +417,8 @@ "description": { "signal": "\"measures[0]: \" + (format(datum[\"measures.0\"], \"\"))" }, - "x": {"scale": "child_x", "field": "measures\\.0"}, - "x2": {"scale": "child_x", "value": 0}, + "x": {"scale": "child_x", "field": "measures\\.0\\._end"}, + "x2": {"scale": "child_x", "field": "measures\\.0\\._start"}, "yc": {"signal": "child_height", "mult": 0.5}, "height": {"value": 10} } @@ -371,11 +451,16 @@ "type": "linear", "domain": { "fields": [ - {"data": "data_0", "field": "ranges\\.2"}, - {"data": "data_1", "field": "ranges\\.1"}, - {"data": "data_2", "field": "ranges\\.0"}, - {"data": "data_3", "field": "measures\\.1"}, - {"data": "data_4", "field": "measures\\.0"}, + {"data": "data_0", "field": "ranges\\.2\\._start"}, + {"data": "data_0", "field": "ranges\\.2\\._end"}, + {"data": "data_1", "field": "ranges\\.1\\._start"}, + {"data": "data_1", "field": "ranges\\.1\\._end"}, + {"data": "data_2", "field": "ranges\\.0\\._start"}, + {"data": "data_2", "field": "ranges\\.0\\._end"}, + {"data": "data_3", "field": "measures\\.1\\._start"}, + {"data": "data_3", "field": "measures\\.1\\._end"}, + {"data": "data_4", "field": "measures\\.0\\._start"}, + {"data": "data_4", "field": "measures\\.0\\._end"}, {"data": "data_5", "field": "markers\\.0"} ] }, diff --git a/examples/compiled/facet_grid_bar.vg.json b/examples/compiled/facet_grid_bar.vg.json index 2297ec3331..2d3696ae45 100644 --- a/examples/compiled/facet_grid_bar.vg.json +++ b/examples/compiled/facet_grid_bar.vg.json @@ -40,6 +40,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["c", "a", "b"], + "field": "p", + "sort": {"field": [], "order": []}, + "as": ["p_start", "p_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"p\"]) && isFinite(+datum[\"p\"])" @@ -181,8 +189,8 @@ "description": { "signal": "\"c: \" + (isValid(datum[\"c\"]) ? datum[\"c\"] : \"\"+datum[\"c\"]) + \"; p: \" + (format(datum[\"p\"], \"%\")) + \"; settings: \" + (isValid(datum[\"c\"]) ? datum[\"c\"] : \"\"+datum[\"c\"])" }, - "x": {"scale": "x", "field": "p"}, - "x2": {"scale": "x", "value": 0}, + "x": {"scale": "x", "field": "p_end"}, + "x2": {"scale": "x", "field": "p_start"}, "y": {"scale": "y", "field": "c"}, "height": {"scale": "y", "band": 1} } @@ -211,7 +219,7 @@ { "name": "x", "type": "linear", - "domain": {"data": "data_0", "field": "p"}, + "domain": {"data": "data_0", "fields": ["p_start", "p_end"]}, "range": [0, {"signal": "child_width"}], "nice": true, "zero": true diff --git a/examples/compiled/interactive_bar_select_highlight.vg.json b/examples/compiled/interactive_bar_select_highlight.vg.json index 3fbbfd62e1..1a588a2169 100644 --- a/examples/compiled/interactive_bar_select_highlight.vg.json +++ b/examples/compiled/interactive_bar_select_highlight.vg.json @@ -27,6 +27,14 @@ "source": "source_0", "transform": [ {"type": "identifier", "as": "_vgsid_"}, + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -151,8 +159,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } } @@ -169,7 +177,7 @@ { "name": "y", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": {"data": "data_0", "fields": ["b_start", "b_end"]}, "range": [{"signal": "height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/interactive_dashboard_europe_pop.vg.json b/examples/compiled/interactive_dashboard_europe_pop.vg.json index 70eeaff7e0..9a9fc3c4fc 100644 --- a/examples/compiled/interactive_dashboard_europe_pop.vg.json +++ b/examples/compiled/interactive_dashboard_europe_pop.vg.json @@ -313,6 +313,17 @@ "name": "data_1", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["Country"], + "field": "Population_ages_15_64_of_total", + "sort": {"field": [], "order": []}, + "as": [ + "Population_ages_15_64_of_total_start", + "Population_ages_15_64_of_total_end" + ], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"Population_ages_15_64_of_total\"]) && isFinite(+datum[\"Population_ages_15_64_of_total\"])" @@ -323,6 +334,17 @@ "name": "data_2", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["Country"], + "field": "Population_ages_65_and_above_of_total", + "sort": {"field": [], "order": []}, + "as": [ + "Population_ages_65_and_above_of_total_start", + "Population_ages_65_and_above_of_total_end" + ], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"Population_ages_65_and_above_of_total\"]) && isFinite(+datum[\"Population_ages_65_and_above_of_total\"])" @@ -597,9 +619,12 @@ }, "x": { "scale": "concat_0_x", - "field": "Population_ages_15_64_of_total" + "field": "Population_ages_15_64_of_total_end" + }, + "x2": { + "scale": "concat_0_x", + "field": "Population_ages_15_64_of_total_start" }, - "x2": {"scale": "concat_0_x", "value": 0}, "y": {"scale": "concat_0_y", "field": "Country"}, "height": {"scale": "concat_0_y", "band": 1} } @@ -918,9 +943,12 @@ }, "x": { "scale": "concat_1_x", - "field": "Population_ages_65_and_above_of_total" + "field": "Population_ages_65_and_above_of_total_end" + }, + "x2": { + "scale": "concat_1_x", + "field": "Population_ages_65_and_above_of_total_start" }, - "x2": {"scale": "concat_1_x", "value": 0}, "y": {"scale": "concat_1_y", "field": "Country"}, "height": {"scale": "concat_1_y", "band": 1} } @@ -1440,7 +1468,13 @@ { "name": "concat_0_x", "type": "linear", - "domain": {"data": "data_1", "field": "Population_ages_15_64_of_total"}, + "domain": { + "data": "data_1", + "fields": [ + "Population_ages_15_64_of_total_start", + "Population_ages_15_64_of_total_end" + ] + }, "range": [0, {"signal": "concat_0_width"}], "nice": true, "zero": true @@ -1452,7 +1486,7 @@ "data": "source_0", "field": "Country", "sort": { - "op": "min", + "op": "sum", "field": "Population_ages_15_64_of_total", "order": "descending" } @@ -1466,7 +1500,10 @@ "type": "linear", "domain": { "data": "data_2", - "field": "Population_ages_65_and_above_of_total" + "fields": [ + "Population_ages_65_and_above_of_total_start", + "Population_ages_65_and_above_of_total_end" + ] }, "range": [0, {"signal": "concat_1_width"}], "nice": true, @@ -1479,7 +1516,7 @@ "data": "source_0", "field": "Country", "sort": { - "op": "min", + "op": "sum", "field": "Population_ages_65_and_above_of_total", "order": "descending" } diff --git a/examples/compiled/interactive_overview_detail.vg.json b/examples/compiled/interactive_overview_detail.vg.json index 540c13e867..b0aea67264 100644 --- a/examples/compiled/interactive_overview_detail.vg.json +++ b/examples/compiled/interactive_overview_detail.vg.json @@ -9,6 +9,50 @@ "name": "source_0", "url": "data/sp500.csv", "format": {"type": "csv", "parse": {"date": "date"}} + }, + { + "name": "data_0", + "source": "source_0", + "transform": [ + { + "type": "impute", + "field": "price", + "groupby": [], + "key": "date", + "method": "value", + "value": 0 + }, + { + "type": "stack", + "groupby": ["date"], + "field": "price", + "sort": {"field": [], "order": []}, + "as": ["price_start", "price_end"], + "offset": "zero" + } + ] + }, + { + "name": "data_1", + "source": "source_0", + "transform": [ + { + "type": "impute", + "field": "price", + "groupby": [], + "key": "date", + "method": "value", + "value": 0 + }, + { + "type": "stack", + "groupby": ["date"], + "field": "price", + "sort": {"field": [], "order": []}, + "as": ["price_start", "price_end"], + "offset": "zero" + } + ] } ], "signals": [ @@ -46,7 +90,7 @@ "style": ["area"], "sort": {"field": "datum[\"date\"]"}, "interactive": false, - "from": {"data": "source_0"}, + "from": {"data": "data_0"}, "encode": { "update": { "orient": {"value": "vertical"}, @@ -55,8 +99,8 @@ "signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))" }, "x": {"scale": "concat_0_x", "field": "date"}, - "y": {"scale": "concat_0_y", "field": "price"}, - "y2": {"scale": "concat_0_y", "value": 0}, + "y": {"scale": "concat_0_y", "field": "price_end"}, + "y2": {"scale": "concat_0_y", "field": "price_start"}, "defined": { "signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" } @@ -337,7 +381,7 @@ "style": ["area"], "sort": {"field": "datum[\"date\"]"}, "interactive": true, - "from": {"data": "source_0"}, + "from": {"data": "data_1"}, "encode": { "update": { "orient": {"value": "vertical"}, @@ -346,8 +390,8 @@ "signal": "\"date: \" + (timeFormat(datum[\"date\"], '%b %d, %Y')) + \"; price: \" + (format(datum[\"price\"], \"\"))" }, "x": {"scale": "concat_1_x", "field": "date"}, - "y": {"scale": "concat_1_y", "field": "price"}, - "y2": {"scale": "concat_1_y", "value": 0}, + "y": {"scale": "concat_1_y", "field": "price_end"}, + "y2": {"scale": "concat_1_y", "field": "price_start"}, "defined": { "signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"price\"]) && isFinite(+datum[\"price\"])" } @@ -438,14 +482,14 @@ { "name": "concat_0_x", "type": "time", - "domain": {"data": "source_0", "field": "date"}, + "domain": {"data": "data_0", "field": "date"}, "domainRaw": {"signal": "brush[\"date\"]"}, "range": [0, {"signal": "width"}] }, { "name": "concat_0_y", "type": "linear", - "domain": {"data": "source_0", "field": "price"}, + "domain": {"data": "data_0", "fields": ["price_start", "price_end"]}, "range": [{"signal": "concat_0_height"}, 0], "nice": true, "zero": true @@ -453,13 +497,13 @@ { "name": "concat_1_x", "type": "time", - "domain": {"data": "source_0", "field": "date"}, + "domain": {"data": "data_1", "field": "date"}, "range": [0, {"signal": "width"}] }, { "name": "concat_1_y", "type": "linear", - "domain": {"data": "source_0", "field": "price"}, + "domain": {"data": "data_1", "fields": ["price_start", "price_end"]}, "range": [{"signal": "concat_1_height"}, 0], "nice": true, "zero": true diff --git a/examples/compiled/joinaggregate_mean_difference.vg.json b/examples/compiled/joinaggregate_mean_difference.vg.json index c04717e4c8..ae63ba42e2 100644 --- a/examples/compiled/joinaggregate_mean_difference.vg.json +++ b/examples/compiled/joinaggregate_mean_difference.vg.json @@ -27,6 +27,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["Title"], + "field": "IMDB Rating", + "sort": {"field": [], "order": []}, + "as": ["IMDB Rating_start", "IMDB Rating_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"IMDB Rating\"]) && isFinite(+datum[\"IMDB Rating\"])" @@ -71,8 +79,8 @@ "description": { "signal": "\"IMDB Rating: \" + (format(datum[\"IMDB Rating\"], \"\")) + \"; Title: \" + (isValid(datum[\"Title\"]) ? datum[\"Title\"] : \"\"+datum[\"Title\"])" }, - "x": {"scale": "x", "field": "IMDB Rating"}, - "x2": {"scale": "x", "value": 0}, + "x": {"scale": "x", "field": "IMDB Rating_end"}, + "x2": {"scale": "x", "field": "IMDB Rating_start"}, "y": {"scale": "y", "field": "Title"}, "height": {"scale": "y", "band": 1} } @@ -102,7 +110,8 @@ "type": "linear", "domain": { "fields": [ - {"data": "data_0", "field": "IMDB Rating"}, + {"data": "data_0", "field": "IMDB Rating_start"}, + {"data": "data_0", "field": "IMDB Rating_end"}, {"data": "data_1", "field": "average_AverageRating"} ] }, diff --git a/examples/compiled/joinaggregate_mean_difference_by_year.vg.json b/examples/compiled/joinaggregate_mean_difference_by_year.vg.json index 6febd7fb52..476b0af3f3 100644 --- a/examples/compiled/joinaggregate_mean_difference_by_year.vg.json +++ b/examples/compiled/joinaggregate_mean_difference_by_year.vg.json @@ -35,6 +35,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["Title"], + "field": "IMDB Rating", + "sort": {"field": [], "order": []}, + "as": ["IMDB Rating_start", "IMDB Rating_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"IMDB Rating\"]) && isFinite(+datum[\"IMDB Rating\"])" @@ -73,8 +81,8 @@ "description": { "signal": "\"IMDB Rating: \" + (format(datum[\"IMDB Rating\"], \"\")) + \"; Title: \" + (isValid(datum[\"Title\"]) ? datum[\"Title\"] : \"\"+datum[\"Title\"])" }, - "x": {"scale": "x", "field": "IMDB Rating"}, - "x2": {"scale": "x", "value": 0}, + "x": {"scale": "x", "field": "IMDB Rating_end"}, + "x2": {"scale": "x", "field": "IMDB Rating_start"}, "y": {"scale": "y", "field": "Title"}, "height": {"scale": "y", "band": 1} } @@ -107,7 +115,8 @@ "type": "linear", "domain": { "fields": [ - {"data": "data_0", "field": "IMDB Rating"}, + {"data": "data_0", "field": "IMDB Rating_start"}, + {"data": "data_0", "field": "IMDB Rating_end"}, {"data": "data_1", "field": "AverageYearRating"} ] }, diff --git a/examples/compiled/joinaggregate_percent_of_total.vg.json b/examples/compiled/joinaggregate_percent_of_total.vg.json index f5e9c1b4ce..ed7365cc58 100644 --- a/examples/compiled/joinaggregate_percent_of_total.vg.json +++ b/examples/compiled/joinaggregate_percent_of_total.vg.json @@ -31,6 +31,14 @@ "expr": "datum.Time/datum.TotalTime * 100", "as": "PercentOfTotal" }, + { + "type": "stack", + "groupby": ["Activity"], + "field": "PercentOfTotal", + "sort": {"field": [], "order": []}, + "as": ["PercentOfTotal_start", "PercentOfTotal_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"PercentOfTotal\"]) && isFinite(+datum[\"PercentOfTotal\"])" @@ -58,8 +66,8 @@ "description": { "signal": "\"% of total Time: \" + (format(datum[\"PercentOfTotal\"], \"\")) + \"; Activity: \" + (isValid(datum[\"Activity\"]) ? datum[\"Activity\"] : \"\"+datum[\"Activity\"])" }, - "x": {"scale": "x", "field": "PercentOfTotal"}, - "x2": {"scale": "x", "value": 0}, + "x": {"scale": "x", "field": "PercentOfTotal_end"}, + "x2": {"scale": "x", "field": "PercentOfTotal_start"}, "y": {"scale": "y", "field": "Activity"}, "height": {"scale": "y", "band": 1} } @@ -70,7 +78,10 @@ { "name": "x", "type": "linear", - "domain": {"data": "data_0", "field": "PercentOfTotal"}, + "domain": { + "data": "data_0", + "fields": ["PercentOfTotal_start", "PercentOfTotal_end"] + }, "range": [0, {"signal": "width"}], "nice": true, "zero": true diff --git a/examples/compiled/layer_bar_annotations.vg.json b/examples/compiled/layer_bar_annotations.vg.json index 588bd49c3d..481e8c5c7b 100644 --- a/examples/compiled/layer_bar_annotations.vg.json +++ b/examples/compiled/layer_bar_annotations.vg.json @@ -31,6 +31,14 @@ "name": "data_1", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["Day"], + "field": "Value", + "sort": {"field": [], "order": []}, + "as": ["Value_start", "Value_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"Value\"]) && isFinite(+datum[\"Value\"])" @@ -72,8 +80,8 @@ }, "x": {"scale": "x", "field": "Day"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "Value"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "Value_end"}, + "y2": {"scale": "y", "field": "Value_start"} } } }, @@ -149,7 +157,8 @@ "type": "linear", "domain": { "fields": [ - {"data": "data_1", "field": "Value"}, + {"data": "data_1", "field": "Value_start"}, + {"data": "data_1", "field": "Value_end"}, {"data": "data_2", "field": "baseline"}, {"data": "data_2", "field": "Value"}, [300] diff --git a/examples/compiled/layer_bar_labels.vg.json b/examples/compiled/layer_bar_labels.vg.json index e8ba556f8e..a1213323b3 100644 --- a/examples/compiled/layer_bar_labels.vg.json +++ b/examples/compiled/layer_bar_labels.vg.json @@ -1,6 +1,6 @@ { "$schema": "https://vega.github.io/schema/vega/v5.json", - "description": "Bar chart with text labels. Apply scale padding to make the frame cover the labels.", + "description": "Bar chart with text labels. Set domain to make the frame cover the labels.", "background": "white", "padding": 5, "width": 200, @@ -11,7 +11,25 @@ "values": [{"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43}] }, { - "name": "data_0", + "name": "data_1", + "source": "source_0", + "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, + { + "type": "filter", + "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" + } + ] + }, + { + "name": "data_2", "source": "source_0", "transform": [ { @@ -33,7 +51,7 @@ "name": "layer_0_marks", "type": "rect", "style": ["bar"], - "from": {"data": "data_0"}, + "from": {"data": "data_1"}, "encode": { "update": { "fill": {"value": "#4c78a8"}, @@ -41,8 +59,8 @@ "description": { "signal": "\"a: \" + (isValid(datum[\"a\"]) ? datum[\"a\"] : \"\"+datum[\"a\"]) + \"; b: \" + (format(datum[\"b\"], \"\"))" }, - "x": {"scale": "x", "field": "b"}, - "x2": {"scale": "x", "value": 0}, + "x": {"scale": "x", "field": "b_end"}, + "x2": {"scale": "x", "field": "b_start"}, "y": {"scale": "y", "field": "a"}, "height": {"scale": "y", "band": 1} } @@ -52,7 +70,7 @@ "name": "layer_1_marks", "type": "text", "style": ["text"], - "from": {"data": "data_0"}, + "from": {"data": "data_2"}, "encode": { "update": { "align": {"value": "left"}, @@ -73,16 +91,21 @@ { "name": "x", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": [0, 60], "range": [0, {"signal": "width"}], - "padding": 10, "nice": true, "zero": true }, { "name": "y", "type": "band", - "domain": {"data": "data_0", "field": "a", "sort": true}, + "domain": { + "fields": [ + {"data": "data_1", "field": "a"}, + {"data": "data_2", "field": "a"} + ], + "sort": true + }, "range": {"step": {"signal": "y_step"}}, "paddingInner": 0.1, "paddingOuter": 0.05 diff --git a/examples/compiled/layer_bar_labels_style.vg.json b/examples/compiled/layer_bar_labels_style.vg.json index da34ff423a..96e3a868b5 100644 --- a/examples/compiled/layer_bar_labels_style.vg.json +++ b/examples/compiled/layer_bar_labels_style.vg.json @@ -10,7 +10,25 @@ "values": [{"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43}] }, { - "name": "data_0", + "name": "data_1", + "source": "source_0", + "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, + { + "type": "filter", + "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" + } + ] + }, + { + "name": "data_2", "source": "source_0", "transform": [ { @@ -32,7 +50,7 @@ "name": "layer_0_marks", "type": "rect", "style": ["bar"], - "from": {"data": "data_0"}, + "from": {"data": "data_1"}, "encode": { "update": { "fill": {"value": "#4c78a8"}, @@ -40,8 +58,8 @@ "description": { "signal": "\"a: \" + (isValid(datum[\"a\"]) ? datum[\"a\"] : \"\"+datum[\"a\"]) + \"; b: \" + (format(datum[\"b\"], \"\"))" }, - "x": {"scale": "x", "field": "b"}, - "x2": {"scale": "x", "value": 0}, + "x": {"scale": "x", "field": "b_end"}, + "x2": {"scale": "x", "field": "b_start"}, "y": {"scale": "y", "field": "a"}, "height": {"scale": "y", "band": 1} } @@ -51,7 +69,7 @@ "name": "layer_1_marks", "type": "text", "style": ["text", "label"], - "from": {"data": "data_0"}, + "from": {"data": "data_2"}, "encode": { "update": { "fill": {"value": "black"}, @@ -69,7 +87,13 @@ { "name": "x", "type": "linear", - "domain": {"data": "data_0", "field": "b"}, + "domain": { + "fields": [ + {"data": "data_1", "field": "b_start"}, + {"data": "data_1", "field": "b_end"}, + {"data": "data_2", "field": "b"} + ] + }, "range": [0, {"signal": "width"}], "nice": true, "zero": true @@ -77,7 +101,13 @@ { "name": "y", "type": "band", - "domain": {"data": "data_0", "field": "a", "sort": true}, + "domain": { + "fields": [ + {"data": "data_1", "field": "a"}, + {"data": "data_2", "field": "a"} + ], + "sort": true + }, "range": {"step": {"signal": "y_step"}}, "paddingInner": 0.1, "paddingOuter": 0.05 diff --git a/examples/compiled/layer_bar_line.vg.json b/examples/compiled/layer_bar_line.vg.json index 53b3391873..eec6e7a17b 100644 --- a/examples/compiled/layer_bar_line.vg.json +++ b/examples/compiled/layer_bar_line.vg.json @@ -23,6 +23,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "b", + "sort": {"field": [], "order": []}, + "as": ["b_start", "b_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"b\"]) && isFinite(+datum[\"b\"])" @@ -52,8 +60,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "b"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "b_end"}, + "y2": {"scale": "y", "field": "b_start"} } } }, @@ -98,7 +106,8 @@ "type": "linear", "domain": { "fields": [ - {"data": "data_0", "field": "b"}, + {"data": "data_0", "field": "b_start"}, + {"data": "data_0", "field": "b_end"}, {"data": "source_0", "field": "b"} ] }, diff --git a/examples/compiled/layer_bar_line_union.vg.json b/examples/compiled/layer_bar_line_union.vg.json index 09bdf36657..ea1feef68a 100644 --- a/examples/compiled/layer_bar_line_union.vg.json +++ b/examples/compiled/layer_bar_line_union.vg.json @@ -23,6 +23,14 @@ "name": "data_0", "source": "source_0", "transform": [ + { + "type": "stack", + "groupby": ["a"], + "field": "c", + "sort": {"field": [], "order": []}, + "as": ["c_start", "c_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"c\"]) && isFinite(+datum[\"c\"])" @@ -52,8 +60,8 @@ }, "x": {"scale": "x", "field": "a"}, "width": {"scale": "x", "band": 1}, - "y": {"scale": "y", "field": "c"}, - "y2": {"scale": "y", "value": 0} + "y": {"scale": "y", "field": "c_end"}, + "y2": {"scale": "y", "field": "c_start"} } } }, @@ -98,7 +106,8 @@ "type": "linear", "domain": { "fields": [ - {"data": "data_0", "field": "c"}, + {"data": "data_0", "field": "c_start"}, + {"data": "data_0", "field": "c_end"}, {"data": "source_0", "field": "c"} ] }, diff --git a/examples/compiled/trellis_area_seattle.png b/examples/compiled/trellis_area_seattle.png index 01ee80d2e9..25ff23c931 100644 Binary files a/examples/compiled/trellis_area_seattle.png and b/examples/compiled/trellis_area_seattle.png differ diff --git a/examples/compiled/trellis_area_seattle.svg b/examples/compiled/trellis_area_seattle.svg index 2d2ec8d6d4..67f2fa26be 100644 --- a/examples/compiled/trellis_area_seattle.svg +++ b/examples/compiled/trellis_area_seattle.svg @@ -1 +1 @@ -date (hours)06:00 AM07:00 AM08:00 AM09:00 AM10:00 AM11:00 AMNoon01:00 PM02:00 PM03:00 PM04:00 PM05:00 PM06:00 PM07:00 PM08:00 PM09:00 PM10:00 PM11:00 PMMidnight01:00 AM02:00 AM03:00 AM04:00 AM05:00 AMFebMarAprMayJunJulAugSepOctNovDecMonthSeattle Temperature Normals \ No newline at end of file +date (hours)01:00 AM02:00 AM03:00 AM04:00 AM05:00 AM06:00 AM07:00 AM08:00 AM09:00 AM10:00 AM11:00 AMNoon01:00 PM02:00 PM03:00 PM04:00 PM05:00 PM06:00 PM07:00 PM08:00 PM09:00 PM10:00 PM11:00 PMMidnightJanFebMarAprMayJunJulAugSepOctNovDecMonthSeattle Temperature Normals \ No newline at end of file diff --git a/examples/compiled/trellis_area_seattle.vg.json b/examples/compiled/trellis_area_seattle.vg.json index 84f727bda9..95353fa85c 100644 --- a/examples/compiled/trellis_area_seattle.vg.json +++ b/examples/compiled/trellis_area_seattle.vg.json @@ -20,6 +20,19 @@ "type": "timeunit", "units": ["hours"], "as": ["hours_date", "hours_date_end"] + }, + { + "field": "date", + "type": "timeunit", + "units": ["month", "date"], + "as": ["monthdate_date", "monthdate_date_end"] + }, + { + "type": "aggregate", + "groupby": ["monthdate_date", "hours_date"], + "ops": ["mean"], + "fields": ["temperature"], + "as": ["mean_temperature"] } ] }, @@ -143,20 +156,20 @@ "name": "child_marks", "type": "area", "style": ["area"], - "sort": {"field": "datum[\"date\"]"}, + "sort": {"field": "datum[\"monthdate_date\"]"}, "from": {"data": "facet"}, "encode": { "update": { "orient": {"value": "vertical"}, "fill": {"value": "#4c78a8"}, "description": { - "signal": "\"Month: \" + (timeFormat(datum[\"date\"], '%b')) + \"; temperature: \" + (format(datum[\"temperature\"], \"\"))" + "signal": "\"Month: \" + (timeFormat(datum[\"monthdate_date\"], '%b')) + \"; Mean of temperature: \" + (format(datum[\"mean_temperature\"], \"\"))" }, - "x": {"scale": "x", "field": "date"}, - "y": {"scale": "y", "field": "temperature"}, + "x": {"scale": "x", "field": "monthdate_date"}, + "y": {"scale": "y", "field": "mean_temperature"}, "y2": {"field": {"group": "height"}}, "defined": { - "signal": "isValid(datum[\"date\"]) && isFinite(+datum[\"date\"]) && isValid(datum[\"temperature\"]) && isFinite(+datum[\"temperature\"])" + "signal": "isValid(datum[\"monthdate_date\"]) && isFinite(+datum[\"monthdate_date\"]) && isValid(datum[\"mean_temperature\"]) && isFinite(+datum[\"mean_temperature\"])" } } } @@ -168,13 +181,13 @@ { "name": "x", "type": "time", - "domain": {"data": "source_0", "field": "date"}, + "domain": {"data": "source_0", "field": "monthdate_date"}, "range": [0, {"signal": "child_width"}] }, { "name": "y", "type": "linear", - "domain": {"data": "source_0", "field": "temperature"}, + "domain": {"data": "source_0", "field": "mean_temperature"}, "range": [{"signal": "child_height"}, 0], "zero": false, "nice": true diff --git a/examples/compiled/window_percent_of_total.vg.json b/examples/compiled/window_percent_of_total.vg.json index f5e9c1b4ce..ed7365cc58 100644 --- a/examples/compiled/window_percent_of_total.vg.json +++ b/examples/compiled/window_percent_of_total.vg.json @@ -31,6 +31,14 @@ "expr": "datum.Time/datum.TotalTime * 100", "as": "PercentOfTotal" }, + { + "type": "stack", + "groupby": ["Activity"], + "field": "PercentOfTotal", + "sort": {"field": [], "order": []}, + "as": ["PercentOfTotal_start", "PercentOfTotal_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"PercentOfTotal\"]) && isFinite(+datum[\"PercentOfTotal\"])" @@ -58,8 +66,8 @@ "description": { "signal": "\"% of total Time: \" + (format(datum[\"PercentOfTotal\"], \"\")) + \"; Activity: \" + (isValid(datum[\"Activity\"]) ? datum[\"Activity\"] : \"\"+datum[\"Activity\"])" }, - "x": {"scale": "x", "field": "PercentOfTotal"}, - "x2": {"scale": "x", "value": 0}, + "x": {"scale": "x", "field": "PercentOfTotal_end"}, + "x2": {"scale": "x", "field": "PercentOfTotal_start"}, "y": {"scale": "y", "field": "Activity"}, "height": {"scale": "y", "band": 1} } @@ -70,7 +78,10 @@ { "name": "x", "type": "linear", - "domain": {"data": "data_0", "field": "PercentOfTotal"}, + "domain": { + "data": "data_0", + "fields": ["PercentOfTotal_start", "PercentOfTotal_end"] + }, "range": [0, {"signal": "width"}], "nice": true, "zero": true diff --git a/examples/compiled/window_top_k.vg.json b/examples/compiled/window_top_k.vg.json index 38e3ce1077..37d343a85f 100644 --- a/examples/compiled/window_top_k.vg.json +++ b/examples/compiled/window_top_k.vg.json @@ -52,6 +52,14 @@ "name": "data_1", "source": "data_0", "transform": [ + { + "type": "stack", + "groupby": ["student"], + "field": "score", + "sort": {"field": [], "order": []}, + "as": ["score_start", "score_end"], + "offset": "zero" + }, { "type": "filter", "expr": "isValid(datum[\"score\"]) && isFinite(+datum[\"score\"])" @@ -79,8 +87,8 @@ "description": { "signal": "\"score: \" + (format(datum[\"score\"], \"\")) + \"; student: \" + (isValid(datum[\"student\"]) ? datum[\"student\"] : \"\"+datum[\"student\"])" }, - "x": {"scale": "x", "field": "score"}, - "x2": {"scale": "x", "value": 0}, + "x": {"scale": "x", "field": "score_end"}, + "x2": {"scale": "x", "field": "score_start"}, "y": {"scale": "y", "field": "student"}, "height": {"scale": "y", "band": 1} } @@ -91,7 +99,7 @@ { "name": "x", "type": "linear", - "domain": {"data": "data_1", "field": "score"}, + "domain": {"data": "data_1", "fields": ["score_start", "score_end"]}, "range": [0, {"signal": "width"}], "nice": true, "zero": true diff --git a/examples/specs/layer_bar_labels.vl.json b/examples/specs/layer_bar_labels.vl.json index 0eb5167f30..ec3fbf2df5 100644 --- a/examples/specs/layer_bar_labels.vl.json +++ b/examples/specs/layer_bar_labels.vl.json @@ -1,6 +1,6 @@ { "$schema": "https://vega.github.io/schema/vega-lite/v4.json", - "description": "Bar chart with text labels. Apply scale padding to make the frame cover the labels.", + "description": "Bar chart with text labels. Set domain to make the frame cover the labels.", "data": { "values": [ {"a": "A", "b": 28}, @@ -10,7 +10,7 @@ }, "encoding": { "y": {"field": "a", "type": "nominal"}, - "x": {"field": "b", "type": "quantitative", "scale": {"padding": 10}} + "x": {"field": "b", "type": "quantitative", "scale": {"domain": [0, 60]}} }, "layer": [{ "mark": "bar" diff --git a/examples/specs/normalized/area_gradient_normalized.vl.json b/examples/specs/normalized/area_gradient_normalized.vl.json index f5da76f809..70175e869e 100644 --- a/examples/specs/normalized/area_gradient_normalized.vl.json +++ b/examples/specs/normalized/area_gradient_normalized.vl.json @@ -29,7 +29,7 @@ "mark": {"type": "line", "color": "darkgreen"}, "encoding": { "x": {"field": "date", "type": "temporal"}, - "y": {"field": "price", "type": "quantitative"} + "y": {"field": "price", "type": "quantitative", "stack": "zero"} } } ] diff --git a/examples/specs/normalized/area_overlay_normalized.vl.json b/examples/specs/normalized/area_overlay_normalized.vl.json index 89ebb61ff1..d1a136396f 100644 --- a/examples/specs/normalized/area_overlay_normalized.vl.json +++ b/examples/specs/normalized/area_overlay_normalized.vl.json @@ -15,14 +15,14 @@ "mark": {"type": "line"}, "encoding": { "x": {"field": "date", "type": "temporal"}, - "y": {"field": "price", "type": "quantitative"} + "y": {"field": "price", "type": "quantitative", "stack": "zero"} } }, { "mark": {"type": "point", "opacity": 1, "filled": true}, "encoding": { "x": {"field": "date", "type": "temporal"}, - "y": {"field": "price", "type": "quantitative"} + "y": {"field": "price", "type": "quantitative", "stack": "zero"} } } ] diff --git a/examples/specs/normalized/layer_bar_labels_normalized.vl.json b/examples/specs/normalized/layer_bar_labels_normalized.vl.json index 7a4afb8180..5c0aeab0f4 100644 --- a/examples/specs/normalized/layer_bar_labels_normalized.vl.json +++ b/examples/specs/normalized/layer_bar_labels_normalized.vl.json @@ -1,6 +1,6 @@ { "$schema": "https://vega.github.io/schema/vega-lite/v4.json", - "description": "Bar chart with text labels. Apply scale padding to make the frame cover the labels.", + "description": "Bar chart with text labels. Set domain to make the frame cover the labels.", "data": { "values": [{"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43}] }, @@ -9,14 +9,22 @@ "mark": "bar", "encoding": { "y": {"field": "a", "type": "nominal"}, - "x": {"field": "b", "type": "quantitative", "scale": {"padding": 10}} + "x": { + "field": "b", + "type": "quantitative", + "scale": {"domain": [0, 60]} + } } }, { "mark": {"type": "text", "align": "left", "baseline": "middle", "dx": 3}, "encoding": { "y": {"field": "a", "type": "nominal"}, - "x": {"field": "b", "type": "quantitative", "scale": {"padding": 10}}, + "x": { + "field": "b", + "type": "quantitative", + "scale": {"domain": [0, 60]} + }, "text": {"field": "b", "type": "quantitative"} } } diff --git a/examples/specs/trellis_area_seattle.vl.json b/examples/specs/trellis_area_seattle.vl.json index 146cac4aef..d685070b85 100644 --- a/examples/specs/trellis_area_seattle.vl.json +++ b/examples/specs/trellis_area_seattle.vl.json @@ -32,11 +32,13 @@ "field": "date", "type": "temporal", "title": "Month", + "timeUnit": "monthdate", "axis": {"format": "%b"} }, "y": { "field": "temperature", "type": "quantitative", + "aggregate": "mean", "scale": {"zero": false}, "axis": {"title": null, "labels": false, "ticks": false} } diff --git a/src/compile/mark/mark.ts b/src/compile/mark/mark.ts index 957e8afe19..4e092c7942 100644 --- a/src/compile/mark/mark.ts +++ b/src/compile/mark/mark.ts @@ -167,12 +167,19 @@ function getGroupsForStackedBarWithCornerRadius(model: UnitModel) { } } - // For bin and time unit, we have to add bin/timeunit -end channels. - const groupByField = model.fieldDef(model.stack.groupbyChannel); - const groupby: string[] = vgField(groupByField) ? [vgField(groupByField)] : []; + const groupby: string[] = []; - if (groupByField?.bin || groupByField?.timeUnit) { - groupby.push(vgField(groupByField, {binSuffix: 'end'})); + if (model.stack.groupbyChannel) { + // For bin and time unit, we have to add bin/timeunit -end channels. + const groupByField = model.fieldDef(model.stack.groupbyChannel); + const field = vgField(groupByField); + if (field) { + groupby.push(field); + } + + if (groupByField?.bin || groupByField?.timeUnit) { + groupby.push(vgField(groupByField, {binSuffix: 'end'})); + } } const strokeProperties = [ diff --git a/src/stack.ts b/src/stack.ts index 83128bb39e..d3d971fbcf 100644 --- a/src/stack.ts +++ b/src/stack.ts @@ -207,8 +207,7 @@ export function stack( } else { offset = stackedFieldDef.stack; } - } else if (stackBy.length > 0 && STACK_BY_DEFAULT_MARKS.has(mark)) { - // Bar and Area with sum ops are automatically stacked by default + } else if (STACK_BY_DEFAULT_MARKS.has(mark)) { offset = 'zero'; } @@ -221,7 +220,7 @@ export function stack( } // warn when stacking non-linear - if (stackedFieldDef.scale && stackedFieldDef.scale.type && stackedFieldDef.scale.type !== ScaleType.LINEAR) { + if (stackedFieldDef?.scale?.type && stackedFieldDef?.scale?.type !== ScaleType.LINEAR) { if (opt.disallowNonLinearStack) { return null; } else { diff --git a/test/compile/mark/mark.test.ts b/test/compile/mark/mark.test.ts index 11eb1d3ba9..2d27057c7d 100644 --- a/test/compile/mark/mark.test.ts +++ b/test/compile/mark/mark.test.ts @@ -217,7 +217,7 @@ describe('Mark', () => { }); const markGroup = parseMarkGroups(model); - expect(markGroup[0].aria).toBe(false); + expect(markGroup[0].marks[0].marks[0].aria).toBe(false); }); it('should set aria to false for line mark', () => { @@ -235,6 +235,22 @@ describe('Mark', () => { expect(markGroup[0].aria).toBe(false); }); + it('should group mark with corder radius by nominal field', () => { + const model = parseUnitModelWithScaleAndLayoutSize({ + mark: { + type: 'bar', + cornerRadius: 2 + }, + encoding: { + x: {type: 'quantitative', field: 'foo'}, + y: {type: 'nominal', field: 'bar'} + } + }); + + const markGroup = parseMarkGroups(model); + expect(markGroup[0].from.facet.groupby).toEqual(['bar']); + }); + describe('interactiveFlag', () => { it('should not contain flag if no selections', () => { const model = parseUnitModelWithScaleAndSelection({ diff --git a/test/normalize/pathoverlay.test.ts b/test/normalize/pathoverlay.test.ts index 9aee9be07a..5d84259af2 100644 --- a/test/normalize/pathoverlay.test.ts +++ b/test/normalize/pathoverlay.test.ts @@ -170,14 +170,14 @@ describe('PathOverlayNormalizer', () => { mark: {type: 'line'}, encoding: { x: {field: 'date', type: 'temporal'}, - y: {field: 'price', type: 'quantitative'} + y: {field: 'price', type: 'quantitative', stack: 'zero'} } }, { mark: {type: 'point', opacity: 1, filled: true}, encoding: { x: {field: 'date', type: 'temporal'}, - y: {field: 'price', type: 'quantitative'} + y: {field: 'price', type: 'quantitative', stack: 'zero'} } } ], @@ -210,7 +210,7 @@ describe('PathOverlayNormalizer', () => { mark: {type: 'line', interpolate: 'monotone'}, encoding: { x: {field: 'date', type: 'temporal'}, - y: {field: 'price', type: 'quantitative'} + y: {field: 'price', type: 'quantitative', stack: 'zero'} } } ], @@ -349,7 +349,7 @@ describe('PathOverlayNormalizer', () => { mark: {type: 'line'}, encoding: { x: {field: 'date', type: 'temporal'}, - y: {field: 'price', type: 'quantitative'} + y: {field: 'price', type: 'quantitative', stack: 'zero'} } } ] diff --git a/test/stack.test.ts b/test/stack.test.ts index 895aab7c4a..8cb0e872f3 100644 --- a/test/stack.test.ts +++ b/test/stack.test.ts @@ -38,7 +38,7 @@ describe('stack', () => { } }; const stackProps = stack(spec.mark, spec.encoding, undefined); - expect(stackProps.fieldChannel).toBe('x'); + expect(stackProps.fieldChannel).toBe(X); } }); @@ -58,6 +58,21 @@ describe('stack', () => { } }); + it('should stack default stack marks', () => { + for (const mark of STACK_BY_DEFAULT_MARKS) { + const spec: TopLevel = { + data: {url: 'data/barley.json'}, + mark: mark, + encoding: { + x: {field: 'yield', type: 'quantitative'}, + y: {field: 'variety', type: 'nominal'} + } + }; + const stackProps = stack(spec.mark, spec.encoding, undefined); + expect(stackProps.fieldChannel).toBe(X); + } + }); + it('should prioritize axis with stack', () => { for (const mark of STACKABLE_NON_POLAR_MARKS) { const spec: TopLevel = { @@ -70,7 +85,7 @@ describe('stack', () => { } }; const stackProps = stack(spec.mark, spec.encoding, undefined); - expect(stackProps.fieldChannel).toBe('x'); + expect(stackProps.fieldChannel).toBe(X); } });