PageSourceSearch

https://data-science.wifo.ac.at/observable/fg5-en/[email protected]

js wifo.ac.at collected 2026-10-01 10:25:54 UTC 14,947 bytes, 421 lines download raw bytes

1import define1 from "./[email protected]";
2
3function _1(md){return(
4md`# Vega-Lite API v5`
5)}
6
7function _2(md){return(
8md`The [Vega-Lite JavaScript API](https://github.com/vega/vega-lite-api/) provides a convenient way to write [Vega-Lite](https://vega.github.io/vega-lite) specifications in a programmatic fashion. Scroll down for some usage examples, or browse the [Vega-Lite API example collection](https://observablehq.com/collection/@vega/vega-lite-api)! 
9
10_This notebook uses **version 5** of Vega-Lite and the corresponding Vega-Lite API v5._ To see what's new in version 5, [have a look at the changelog](https://github.com/vega/vega-lite/releases/tag/v5.0.0). To use Vega-Lite version 4, see the [Vega-Lite API v4 notebook](https://observablehq.com/@vega/vega-lite-api) instead.
11
12Want to learn more about data visualization and how to use the Vega-Lite API? Read the [introduction to Vega-Lite](https://observablehq.com/@uwdata/introduction-to-vega-lite) and the [data visualization curriculum](https://observablehq.com/@uwdata/data-visualization-curriculum?collection=@uwdata/visualization-curriculum).`
13)}
14
15function _3(md){return(
16md`
17The cell below imports the Vega-Lite API and registers the desired versions of Vega and Vega-Lite, along with default [Vega View options](https://vega.github.io/vega/docs/api/view/#view) and [Vega-Lite configuration](https://vega.github.io/vega-lite/docs/config.html):
18`
19)}
20
21async function _vl(vegaVersion,vlVersion,apiVersion,tooltipVersion,require)
22{
23  const [vega, vegalite, api, tooltip] = await Promise.all([
24    `vega@${vegaVersion}`,
25    `vega-lite@${vlVersion}`,
26    `vega-lite-api@${apiVersion}`,
27    `vega-tooltip@${tooltipVersion}`
28  ].map(module => require(module)));
29
30  const options = {
31    config: {
32      // vega-lite default configuration
33      config: {
34        view: {continuousWidth: 400, continuousHeight: 300},
35        mark: {tooltip: null}
36      }
37    },
38    init: view => {
39      // initialize tooltip handler
40      view.tooltip(new tooltip.Handler().call);
41      // enable horizontal scrolling for large plots
42      if (view.container()) view.container().style['overflow-x'] = 'auto';
43    },
44    view: {
45      // view constructor options
46      loader: vega.loader({baseURL: 'https://cdn.jsdelivr.net/npm/vega-datasets@2/'}),
47      renderer: 'canvas'
48    }
49  };
50  
51  return api.register(vega, vegalite, options);
52}
53
54
55function _apiVersion(){return(
56'5.0.0'
57)}
58
59function _vlVersion(){return(
60'5.0.0'
61)}
62
63function _vegaVersion(){return(
64'5.20.2'
65)}
66
67function _tooltipVersion(){return(
68'0.25.1'
69)}
70
71function _9(md){return(
72md`To use the same setup in your own notebooks, add a cell with the following code:
73~~~ js
74import {vl} from '@vega/vega-lite-api-v5'
75~~~
76To use the API outside of Observable, see the [stand-alone usage instructions](#standalone_use) below.
77`
78)}
79
80function _zip_codes(md){return(
81md`<hr/>
82## Zip Codes
83
84A dot for each zip code in the United States, colored by the first digit.
85`
86)}
87
88function _11(vl,width){return(
89vl.markSquare({size: 2, opacity: 1})
90  .data('data/zipcodes.csv')
91  .transform(vl.calculate('substring(datum.zip_code, 0, 1)').as('digit'))
92  .project(
93    vl.projection('albersUsa')
94  )
95  .encode(
96    vl.longitude().fieldQ('longitude'),
97    vl.latitude().fieldQ('latitude'),
98    vl.color().fieldN('digit')
99  )
100  .width(width)
101  .height(Math.floor(width / 1.75))
102  .autosize({type: 'fit-x', contains: 'padding'})
103  .config({view: {stroke: null}})
104  .render()
105)}
106
107function _interactive_weather(md){return(
108md`<hr/>
109## Interactive Seattle Weather 2012-2015
110
111A scatter plot and summary histogram with linked selections between plots to perform cross-filtering and configure conditional color encodings.
112`
113)}
114
115function _13(vl,width)
116{
117  const brush = vl.selectInterval().encodings('x');
118  const click = vl.selectPoint().encodings('color');
119
120  const scale = {
121    domain: ['sun', 'fog', 'drizzle', 'rain', 'snow'],
122    range: ['#e7ba52', '#a7a7a7', '#aec7e8', '#1f77b4', '#9467bd']
123  };
124
125  const plot1 = vl.markPoint({filled: true})
126    .encode(
127      vl.color().value('lightgray')
128        .if(brush, vl.color().fieldN('weather').scale(scale).title('Weather')),
129      vl.size().fieldQ('precipitation').scale({domain: [-1, 50], range: [10, 500]}).title('Precipitation'),
130      vl.order().fieldQ('precipitation').sort('descending'),
131      vl.x().timeMD('date').axis({title: 'Date', format: '%b'}),
132      vl.y().fieldQ('temp_max').scale({domain: [-5, 40]}).axis({title: 'Maximum Daily Temperature (°C)'})
133    )
134    .width(width)
135    .height(300)
136    .params(brush)
137    .transform(vl.filter(click));
138
139  const plot2 = vl.markBar()
140    .encode(
141      vl.color().if(click, vl.color().fieldN('weather')).value('lightgray')
142        .scale(scale).title('Weather'),
143      vl.x().count(),
144      vl.y().fieldN('weather').scale({domain: scale.domain}).title('Weather')
145    )
146    .width(width)
147    .params(click)
148    .transform(vl.filter(brush));
149
150  return vl.vconcat(plot1, plot2)
151    .data('data/seattle-weather.csv')
152    .autosize({type: 'fit-x', contains: 'padding'})
153    .render();
154}
155
156
157function _population_pyramid(md){return(
158md`<hr/>
159## Population Pyramid
160
161A [population pyramid](https://en.wikipedia.org/wiki/Population_pyramid) shows the distribution of age groups in a population. Drag the slider to see the U.S. change over time, but watch out for [missing data in 1890!](https://www.census.gov/
161history/www/faqs/genealogy_faqs/why_cant_i_find_1890_census_records.html) The slider is generated internally by binding the \`Year\` parameter using \`vl.slider()\`.`
162)}
163
164function _15(vl){return(
165vl.markBar({ opacity: 0.4 })
166  .params(
167    vl.param('Year').value(2000).bind(vl.slider(1850, 2000, 10))
168  )
169  .data('data/population.json')
170  .transform(
171    vl.calculate('datum.sex === 1 ? "Male" : "Female"').as('sex'),
172    vl.filter('datum.year === Year')
173  )
174  .encode(
175    vl.x().sum('people').scale({ domain: [0, 12e6] }).stack(null).title('People'),
176    vl.y().fieldO('age').sort('descending').title('Age'),
177    vl.color().fieldN('sex').scale({ range: ['#675193', '#ca8861'] }).title('Sex')
178  )
179  .height(300) // fix the height to keep stability over missing data
180  .render()
181)}
182
183function _bind_external(md){return(
184md`### Bind Parameters to External Inputs
185
186As an alternative to having Vega-Lite generate its own input widgets (as with \`vl.slider()\` above), we can also directly bind a Vega-Lite parameter to an existing widget, such as Observable's \`Range\` component:`
187)}
188
189function _year(Range){return(
190Range([1850, 2000], { step: 10, value: 2000 })
191)}
192
193function _19(vl,$0){return(
194vl.markBar({ opacity: 0.4 })
195  .params(
196    // use viewof to bind to the input element (the view), not the numeric year value
197    vl.param('Year').bind($0)
198  )
199  .data('data/population.json')
200  .transform(
201    vl.calculate('datum.sex === 1 ? "Male" : "Female"').as('sex'),
202    vl.filter('datum.year === Year')
203  )
204  .encode(
205    vl.x().sum('people').scale({ domain: [0, 12e6] }).stack(null).title('People'),
206    vl.y().fieldO('age').sort('descending').title('Age'),
207    vl.color().fieldN('sex').scale({ range: ['#675193', '#ca8861'] }).title('Sex')
208  )
209  .height(300)
210  .render()
211)}
212
213function _dynamic_scatter(md){return(
214md`<hr/>
215## Dynamic Query Scatter Plot
216
217A scatter plot of automobile mileage and horsepower. (Shift-)Click the legend and drag the slider to filter by Origin and Year.`
218)}
219
220function _21(vl)
221{
222  const isOrigin = vl.selectPoint('isOrigin')
223    .fields('Origin')
224    .bind('legend'); // bind to legend interactions
225 
226  const isYear = vl.selectPoint('isYear')
227    .fields('Year').value(1970)
228    .bind(vl.slider(1970, 1980, 1).name('Year')); // bind to slider
229  
230  const show = vl.and(isOrigin, isYear); // combine selections
231
232  return vl.markCircle()
233    .data('data/cars.json')
234    .transform(
235      vl.calculate('year(datum.Year)').as('Year')
236    )
237    .params(isOrigin, isYear) // add selections to plot
238    .encode(
239      vl.x().fieldQ('Horsepower'),
240      vl.y().fieldQ('Miles_per_Gallon'),
241      vl.color().if(show, vl.color().fieldN('Origin')).value('grey'),
242      vl.opacity().if(show, vl.value(1.0)).value(0.2)
243    )
244    .render();
245}
246
247
248function _parallel_coordinats(md){return(
249md`<hr/>
250## Parallel Coordinates
251
252A [parallel coordinates plot](https://en.wikipedia.org/wiki/Parallel_coordinates) that uses \`window\` and \`fold\` transforms to convert the four dimensions of penguin measurements into normalized coordinates that can be visualized as \`line\` marks. The graphic includes an additional layer with custom \`text\` mark labels for the parallel axis grid lines. We render the plot as SVG by passing \`{renderer:'svg'}\` to the \`render\` method.
253`
254)}
255
256function _23(vl,width)
257{
258  const domain = [
259    'Beak Length (mm)',
260    'Beak Depth (mm)',
261    'Flipper Length (mm)',
262    'Body Mass (g)'
263  ];
264
265  const scale = {
266    type: 'point',
267    padding: 0
268  };
269  
270  const axis = {
271    domain: false,
272    ticks: false,
273    title: false,
274    grid: true,
275    gridColor: '#888',
276    labelAngle: 0,
277    labelPadding: 8,
278    labelFontWeight: 'bold'
279  };
280
281  const lines = vl.markLine({
282      strokeWidth: 1.5,
283      opacity: 0.5
284    })
285    .encode(
286      vl.color().fieldN('Species').sort('descending'),
287      vl.detail().fieldN('index'),
288      vl.x().fieldO('key').scale(scale).axis(axis),
289      vl.y().fieldQ('fraction').axis(null)
290    );
291
292  const labels = vl.markText({
293      dx: -2,
294      align: 'right',
295      baseline: 'middle'
296    })
297    .transform(
298      vl.groupby('key').aggregate(vl.min('value').as('min'), vl.max('value').as('max')),
299      vl.fold('min', 'max').as('op', 'value'),
300      vl.groupby('key').window(vl.percent_rank('value').as('fraction'))
301    )
302    .encode(
303      vl.x().fieldN('key'),
304      vl.y().fieldQ('fraction').axis(null),
305      vl.text().field('value').format(',')
306    );
307
308  const plot = vl.layer(lines, labels)
309    .data('data/penguins.json')
310    .transform(
311      vl.filter('datum["Beak Length (mm)"] != null'),
312      vl.window(vl.row_number().as('index')),
313      vl.fold(domain).as('key', 'value'),
314      vl.groupby('key').join(vl.min('value').as('min'), vl.max('value').as('max')),
315      vl.calculate('(datum.value - datum.min) / (datum.max - datum.min)').as('fraction')
316    )
317    .width(width)
318    .height(300)
319    .autosize({type: 'fit-x', contains: 'padding'})
320
321  return plot.render({renderer: 'svg'});
322}
323
324
325function _standalone_use(md,apiVersion){return(
326md`<hr/>
327## Stand-Alone Usage in a Web Browser
328
329To use the Vega-Lite API in the browser outside of Observable, you need to include all the dependencies, set the default configuration, and then register the Vega libraries. Here is some starting code to build from:
330
331~~~html
332<!DOCTYPE html>
333<html lang="en">
334  <head>
335    <meta charset="UTF-8" />
336    <script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
337    <script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
338    <script src="https://cdn.jsdelivr.net/npm/vega-lite-api@${apiVersion}"></script>
339    <script src="https://cdn.jsdelivr.net/npm/vega-tooltip"></script>
340  </head>
341  <body>
342    <div id="view"></div>
343
344    <script>
345      // setup API options
346      const options = {
347        config: {
348          // Vega-Lite default configuration
349        },
350        init: (view) => {
351          // initialize tooltip handler
352          view.tooltip(new vegaTooltip.Handler().call);
353        },
354        view: {
355          // view constructor options
356          // remove the loader if you don't want to default to vega-datasets!
357          loader: vega.loader({
358            baseURL: "https://cdn.jsdelivr.net/npm/vega-datasets@2/",
359          }),
360          renderer: "canvas",
361        },
362      };
363
364      // register vega and vega-lite with the API
365      vl.register(vega, vegaLite, options);
366
367      // now you can use the API!
368      vl.markBar({ tooltip: true })
369        .data([
370          { a: "A", b: 28 }, { a: "B", b: 55 }, { a: "C", b: 43 },
371          { a: "D", b: 91 }, { a: "E", b: 81 }, { a: "F", b: 53 },
372          { a: "G", b: 19 }, { a: "H", b: 87 }, { a: "I", b: 52 },
373        ])
374        .encode(
375          vl.x().fieldQ("b"),
376          vl.y().fieldN("a"),
377          vl.tooltip([vl.fieldQ("b"), vl.fieldN("a")])
378        )
379        .render()
380        .then(viewElement => {
381          // render returns a promise to a DOM element containing the chart
382          // viewElement.value contains the Vega View object instance
383          document.getElementById('view').appendChild(viewElement);
384        });
385    </script>
386  </body>
387</html>
388
389~~~`
390)}
391
392export default function define(runtime, observer) {
393  const main = runtime.module();
394  main.variable(observer()).define(["md"], _1);
395  main.variable(observer()).define(["md"], _2);
396  main.variable(observer()).define(["md"], _3);
397  main.variable(observer("vl")).define("vl", ["vegaVersion","vlVersion","apiVersion","tooltipVersion","require"], _vl);
398  main.variable(observer("apiVersion")).define("apiVersion", _apiVersion);
399  main.variable(observer("vlVersion")).define("vlVersion", _vlVersion);
400  main.variable(observer("vegaVersion")).define("vegaVersion", _vegaVersion);
401  main.variable(observer("tooltipVersion")).define("tooltipVersion", _tooltipVersion);
402  main.variable(observer()).define(["md"], _9);
403  main.variable(observer("zip_codes")).define("zip_codes", ["md"], _zip_codes);
404  main.variable(observer()).define(["vl","width"], _11);
405  main.variable(observer("interactive_weather")).define("interactive_weather", ["md"], _interactive_weather);
406  main.variable(observer()).define(["vl","width"], _13);
407  main.variable(observer("population_pyramid")).define("population_pyramid", ["md"], _population_pyramid);
408  main.variable(observer()).define(["vl"], _15);
409  main.variable(observer("bind_external")).define("bind_external", ["md"], _bind_external);
410  const child1 = runtime.module(define1);
411  main.import("Range", child1);
412  main.variable(observer("viewof year")).define("viewof year", ["Range"], _year);
413  main.variable(observer("year")).define("year", ["Generators", "viewof year"], (G, _) => G.input(_));
414  main.variable(observer()).define(["vl","viewof year"], _19);
415  main.variable(observer("dynamic_scatter")).define("dynamic_scatter", ["md"], _dynamic_scatter);
416  main.variable(observer()).define(["vl"], _21);
417  main.variable(observer("parallel_coordinats")).define("parallel_coordinats", ["md"], _parallel_coordinats);
418  main.variable(observer()).define(["vl","width"], _23);
419  main.variable(observer("standalone_use")).define("standalone_use", ["md","apiVersion"], _standalone_use);
420  return main;
421}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.