Dynamic Queries (Part 2)

An introduction to details-on-demand.

Kris Sankaran (UW Madison)
02-11-2021

Reading, Recording, Notebook, Rmarkdown

  1. One common type of dynamic query is to ask the identity of a particular observation. A generalization of this query is the details-on-demand class of interactions. We will see examples of both in these notes.
  2. To reveal the identity of an observation, we can reveal a label on hover. This is essentially a tooltip, but we have re-implemented it manually using a selection. The reason is that this allows additional customization in the structure of the interaction and visual update.
{
  /* Define behavior of hover and click selections */
  const hover = vl.selectSingle()
    .on('mouseover') // select on mouseover
    .nearest(true)   // select nearest point to mouse cursor
    .empty('none');  // empty selection should match nothing
  
  const click = vl.selectMulti()
    .empty('none');  // empty selection matches no points
  
  /* Define encodings for full and filtered data */
  const all_points = vl.markCircle().encode(
    vl.x().fieldQ('Rotten_Tomatoes_Rating'),
    vl.y().fieldQ('IMDB_Rating')
  )
  
  const filter = vl.filter(vl.or(hover, click)),
        subset_points = all_points.transform(filter);

  // mark properties for new layers
  const halo = {size: 100, stroke: 'firebrick', strokeWidth: 3},
        label = {dx: 4, dy: -8, align: 'right'},
        white = {stroke: 'white', strokeWidth: 2};

  // layer scatter plot points, halo annotations, and title labels
  return vl.data(movies)
    .layer(
      all_points.select(hover, click),
      subset_points.markPoint(halo),
      subset_points.markText(label, white).encode(vl.text().fieldN('Title')),
      subset_points.markText(label).encode(vl.text().fieldN('Title'))
    )
    .width(600)
    .height(450)
    .render();
}
robservable("@krisrs1128/week-3-3", include = 4, height = 480)
  1. This kind of labeling is a good middle ground between overloading the user with all details (putting all labels in the plot) and hiding the information completely (no labels). This is one of the benefits of interactive visualization — we can adapt the complexity of a visualization based on user inputs.

  2. Aside: Notice that we didn’t need to directly hover over a point in order for the label to be revealed. Behind the scenes, a the nearest-neighbor (Voronoi) tessellation has been computed, and the labels change as soon as you transition from one cell to another. This article provides a detailed description, if you are curious (we won’t refer to this again, though).

  1. Another example of details-on-demand is overview + detail1 time series visualization. The fine-grained structure in the time series might not be visible in the overview, but the user can zoom into features of interest using the selector. We can understand detail without losing our orientation in the overall time series.
{
  const selector = vl.selectInterval().encodings('x');
  const x = vl.x().fieldT('date').title(null);
  
  // reusable time series encoding
  const base = vl.markArea()
    .encode(x, vl.y().fieldQ('price'))
    .width(700);
  
  const overview = base.select(selector).height(60);
  const detail = base.encode(
    x.scale({domain: selector})
  );

  // return layered view
  return vl.vconcat(detail, overview)
    .data(sp500)
    .render();
}
robservable("@krisrs1128/week-3-3", include = 5, height = 475)
  1. The visualization is implemented by re-using the same base visual encoding (markArea time series) and (a) binding a selector to a smaller (60 pixel high) full time series and (b) adapting the scale of the larger time series, so that it only displays years within the current selection interval.

  2. Finally, we note that dynamic queries can be chained together in a sequence. They allow the user to navigate between static visualizations that display information across subsets and at different resolution.

  3. These visualizations are more complex to implement, but it’s worth sharing an example. One of the earliest examples of details on demand was the film finder app.

It let’s you transition between an overview of all movies and details about selected ones. The key is that the transition is effortless — we can focus in on a few movies without losing our bearings in the broader context.

You can watch a whole (delightfully retro) video about this visualization here.


  1. Visualization people really like abstract compound words↩︎