Skip to content

Sketch Aggregates ​

Brush the height histogram to update the median weight and the number of distinct nationalities per sport. Exact medians and distinct counts can not be pre-aggregated, so by default each update queries the filtered rows. With sketch aggregates enabled, Mosaic instead pre-aggregates approximate results using mergeable sketches. Without sketches, the example works the same and shows exact results; sketches trade a small error for faster updates on large data.

Loading Example... ⏳

Specification ​

js
import * as vg from "@uwdata/vgplot";

await vg.coordinator().exec([
  vg.loadParquet("athletes", "data/athletes.parquet")
]);

const $brush = vg.Selection.intersect();

export default vg.vconcat(
  vg.plot(
    vg.rectY(
      vg.from("athletes"),
      {x: vg.bin("height"), y: vg.count(), fill: "steelblue", inset: 0.5}
    ),
    vg.intervalX({as: $brush}),
    vg.xLabel("Height (m) →"),
    vg.yLabel("↑ Athletes"),
    vg.width(700),
    vg.height(150)
  ),
  vg.hconcat(
    vg.plot(
      vg.barX(
        vg.from("athletes", {filterBy: $brush}),
        {x: vg.median("weight"), y: "sport", fill: "steelblue", sort: {y: "-x"}}
      ),
      vg.xLabel("Median weight (kg) →"),
      vg.yLabel(null),
      vg.marginLeft(110),
      vg.width(350),
      vg.height(500)
    ),
    vg.plot(
      vg.barX(
        vg.from("athletes", {filterBy: $brush}),
        {
          x: vg.count("nationality").distinct(),
          y: "sport",
          fill: "steelblue",
          sort: {y: "-x"}
        }
      ),
      vg.xLabel("Distinct nationalities →"),
      vg.yLabel(null),
      vg.marginLeft(110),
      vg.width(350),
      vg.height(500)
    )
  )
);
yaml
meta:
  title: Sketch Aggregates
  description: >
    Brush the height histogram to update the median weight and the number of
    distinct nationalities per sport. Exact medians and distinct counts can
    not be pre-aggregated, so by default each update queries the filtered
    rows. With [sketch aggregates](https://idl.uw.edu/mosaic/api/core/coordinator#sketch-aggregates)
    enabled, Mosaic instead pre-aggregates approximate results using
    mergeable sketches. Without sketches, the example works the same and
    shows exact results; sketches trade a small error for faster updates on
    large data.
data:
  athletes: { file: data/athletes.parquet }
params:
  brush: { select: intersect }
vconcat:
- plot:
  - mark: rectY
    data: { from: athletes }
    x: { bin: height }
    y: { count: }
    fill: steelblue
    inset: 0.5
  - select: intervalX
    as: $brush
  xLabel: Height (m) →
  yLabel: ↑ Athletes
  width: 700
  height: 150
- hconcat:
  - plot:
    - mark: barX
      data: { from: athletes, filterBy: $brush }
      x: { median: weight }
      y: sport
      fill: steelblue
      sort: { y: -x }
    xLabel: Median weight (kg) →
    yLabel: null
    marginLeft: 110
    width: 350
    height: 500
  - plot:
    - mark: barX
      data: { from: athletes, filterBy: $brush }
      x: { count: nationality, distinct: true }
      y: sport
      fill: steelblue
      sort: { y: -x }
    xLabel: Distinct nationalities →
    yLabel: null
    marginLeft: 110
    width: 350
    height: 500
json
{
  "meta": {
    "title": "Sketch Aggregates",
    "description": "Brush the height histogram to update the median weight and the number of distinct nationalities per sport. Exact medians and distinct counts can not be pre-aggregated, so by default each update queries the filtered rows. With [sketch aggregates](https://idl.uw.edu/mosaic/api/core/coordinator#sketch-aggregates) enabled, Mosaic instead pre-aggregates approximate results using mergeable sketches. Without sketches, the example works the same and shows exact results; sketches trade a small error for faster updates on large data.\n"
  },
  "data": {
    "athletes": {
      "file": "data/athletes.parquet"
    }
  },
  "params": {
    "brush": {
      "select": "intersect"
    }
  },
  "vconcat": [
    {
      "plot": [
        {
          "mark": "rectY",
          "data": {
            "from": "athletes"
          },
          "x": {
            "bin": "height"
          },
          "y": {
            "count": null
          },
          "fill": "steelblue",
          "inset": 0.5
        },
        {
          "select": "intervalX",
          "as": "$brush"
        }
      ],
      "xLabel": "Height (m) →",
      "yLabel": "↑ Athletes",
      "width": 700,
      "height": 150
    },
    {
      "hconcat": [
        {
          "plot": [
            {
              "mark": "barX",
              "data": {
                "from": "athletes",
                "filterBy": "$brush"
              },
              "x": {
                "median": "weight"
              },
              "y": "sport",
              "fill": "steelblue",
              "sort": {
                "y": "-x"
              }
            }
          ],
          "xLabel": "Median weight (kg) →",
          "yLabel": null,
          "marginLeft": 110,
          "width": 350,
          "height": 500
        },
        {
          "plot": [
            {
              "mark": "barX",
              "data": {
                "from": "athletes",
                "filterBy": "$brush"
              },
              "x": {
                "count": "nationality",
                "distinct": true
              },
              "y": "sport",
              "fill": "steelblue",
              "sort": {
                "y": "-x"
              }
            }
          ],
          "xLabel": "Distinct nationalities →",
          "yLabel": null,
          "marginLeft": 110,
          "width": 350,
          "height": 500
        }
      ]
    }
  ]
}
py
import vgplot as vg

athletes = vg.parquet("data/athletes.parquet")

brush = vg.selection.intersect()

view = vg.vconcat(
    vg.plot(
        vg.rect_y(
            athletes, x=vg.bin("height"), y=vg.count(), fill="steelblue", inset=0.5
        ),
        vg.interval_x(bind=brush),
        vg.x_label("Height (m) →"),
        vg.y_label("↑ Athletes"),
        vg.width(700),
        vg.height(150),
    ),
    vg.hconcat(
        vg.plot(
            vg.bar_x(
                data=athletes,
                filter_by=brush,
                x=vg.median("weight"),
                y="sport",
                fill="steelblue",
                sort=vg.sort(y="-x"),
            ),
            vg.x_label("Median weight (kg) →"),
            vg.y_label(None),
            vg.margin_left(110),
            vg.width(350),
            vg.height(500),
        ),
        vg.plot(
            vg.bar_x(
                data=athletes,
                filter_by=brush,
                x=vg.count("nationality", distinct=True),
                y="sport",
                fill="steelblue",
                sort=vg.sort(y="-x"),
            ),
            vg.x_label("Distinct nationalities →"),
            vg.y_label(None),
            vg.margin_left(110),
            vg.width(350),
            vg.height(500),
        ),
    ),
)