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.