Cross-filter with quantitative and nominal attributes based on vega lite API

Viewed 107

I would like to create a general cross-filter based on the vega lite API. Quantitative attributes should be shown binned as histograms and nominal/ordinal attributes as bar charts.

In this observable (https://observablehq.com/@ee2dev/exploring-a-csv-file-with-vega-lite) I have tried to implement it (see cell vis3 - next to last visualization).

Here is the code:

vis3 = {
  vl.vega.timeFormatLocale(locale); // show dates in German 
  vl.vega.formatLocale(locale); // show numbers with German groupings/ separators
  const brush = vl.selectInterval().encodings('x').resolve('intersect');

  // 1 histograms for quantitative data
  const hist1 = vl.markBar({tooltip: true}).encode(
    vl.x().fieldQ(vl.repeat('row'))
      //.bin({maxbins: 100, minstep: 1}) // up to 100 bins, but no smaller than 1 unit
      .bin({maxbins: 100}) 
      //.axis({format: 'd', titleAnchor: 'start'}), // integer format, left-aligned title
      .axis({titleAnchor: 'start'}), 
    vl.y().count().title(null) // no y-axis title
  );
  
  const hist1r = vl.layer(
      hist1.select(brush).encode(vl.color().value('lightgrey')),
      hist1.transform(vl.filter(brush))
    )
    .width(800).height(100)
    .repeat({row: Object.keys(attributes).filter(d => attributes[d] === "quantitative")});

  // 2 bars for non-quantitative data
  const hist2 = vl.markBar({tooltip: true}).encode(
    vl.x().field(vl.repeat('row'))
      .axis({titleAnchor: 'start'}), // left-aligned title
    vl.y().count().title(null) // no y-axis title
  );
  const hist2r = vl.layer(
      hist2.select(brush).encode(vl.color().value('lightgrey')),
      hist2.transform(vl.filter(brush))
    )
    .width(800).height(100)
    .repeat({row: Object.keys(attributes).filter(d => (attributes[d] !== "quantitative") && (cardinality[d] < 30) )});

  const plot = vl
    .data(processedData)
    .config({view: {stroke: null}}) // no outline
    .vconcat(hist1r, hist2r);
  
  return plot.render();
  // return html`<pre>${JSON.stringify(plot.toObject(), 0, 2)}</pre>`; // format JSON data
} 

However the code has at least two drawbacks:

  • the brush selection is always selectInterval(). I would like it to be selectInterval() for quantitative attributes, and selectMulti() otherwise

  • what is a more efficient way to get this done? I created two different charts for quantitative and for the remaining attributes solely because the latter doesn't need binning.

Any help would be greatly appreciated!

0 Answers
Related