Shared on slack by @jheer.
The refereneces are with regard to the Vega-Lite Infovis paper.
/// FIGURE 2
var weather = vl.data()
.url('data/weather.csv')
.format('csv');
// Line chart with aggregation
var fig2a = vl.line()
.data(weather)
.x(vl.month('date'))
.y(vl.mean('temp_max'))
.color(vl.field('location').type(vl.Nominal));
// fig2a.toJSON() --> generate Vega-Lite JSON
// Correlation between wind and temperature
var fig2b = vl.point()
.data(weather)
.x(vl.bin('temp_max'))
.y(vl.bin('wind'))
.size(vl.count())
.color(vl.field('location').type(vl.Nominal));
// Stacked bar chart of weather types
var fig2c = vl.bar()
.data(weather)
.x(vl.field('location').type(vl.Nominal));
.y(vl.count())
.color(vl.field('weather').type(vl.Nominal));
/// FIGURE 3
var seattleWeather = vl.data()
.url('data/weather.csv')
.format('csv')
.filter('datum.location === "Seattle"');
var noGrid = vl.axis().grid(false);
// Dual axis layered chart
var fig3a = vl.layers()
.add(vl.bar()
.data(seattleWeather)
.x(vl.month('date'))
.y(vl.mean('precipitation').axis(noGrid))
.color(vl.value('#77b2c7')))
.add(vl.line()
.data(seattleWeather)
.x(vl.month('date'))
.y(vl.mean('temp_max').axis(noGrid))
.color(vl.value('#ce323c"}')))
.resolve(vl.resolve().y('independent'));
var fig3b = vl.vconcat()
.add(fig2a)
.add(vl.point()
.data(weather.copy()
.filter('datum.precipitation > 0'))
.x(vl.count())
.y(vl.field('location').type(vl.Nominal))
.color(vl.year('date')));
/// FIGURE 4
// Faceted charts
var fig4a = vl.facet(fig2a)
.column(vl.field('location'));
var fig4a = vl.facet()
.column(vl.field('location'))
.spec(fig2a);
// Repeated charts
var fig4b = vl.repeat(fig2a.copy().y(vl.mean(vl.column)))
.column(['temp_max', 'precipitation']);
var fig4b = vl.repeat()
.column(['temp_max', 'precipitation'])
.spec(fig2a.copy().y(vl.mean(vl.column)));
/// FIGURE 5
var cars = vl.data().url('data/cars.json');
var scatter = vl.circle()
.x(vl.field('Horsepower').type(vl.Q))
.y(vl.field('MPG').type(vl.Q))
.color(vl.rule()
.if('id', vl.field('Origin').type(vl.N))
.else(vl.value('grey')))
.size(vl.value(100));
// Highlight a single point on click
var fig5a = scetter.copy()
.select('id', vl.single());
// Highlight a list of individual points
var fig5b = scatter.copy()
.select('id', vl.multi().toggle(true));
// "Paintbrush": highlight multiple points on hover
var fig5c = scatter.copy()
.select('id', vl.multi().on('mouseover').toggle(true));
// Highlight a single Origin
var fig5d = scatter.copy()
.select('id', vl.single().fields('Origin'));
// Highlight a list of Origins
var fig5e = scatter.copy()
.select('id', vl.multi().toggle(true).fields('Origin'));
/// FIGURE 6
// Rectangular brush
var fig6a = vl.circle()
.x(vl.field('Horsepower').type(vl.Q))
.y(vl.field('MPG').type(vl.Q))
.color(vl.rule()
.if('region', vl.field('Origin').type(vl.N))
.else(vl.value('grey')))
.size(vl.value(100))
.select('region', vl.interval());
// Moving the brush
var fig6b = fig6a.copy()
.select('region', vl.interval().translate(true));
// Single-dimension brush
var fig6c = fig6a.copy()
.select('region', vl.interval().translate(true).channels('x'));
/// FIGURE 7
var fig7 = fig6a.copy()
.select('region', vl.interval()
.on('[mousedown[event.shiftKey], mouseup] > mousemove'))
.select('grid', vl.interval()
.scales(true)
.zoom(true)
.translate('[mousedown[!event.shiftKey], mouseup] > mousemove'));
/// FIGURE 8
// A Single Brush, and Panning & Zooming in a Scatterplot Matri
var fig8a = vl.repeat()
.row(['Displacement', 'Miles_per_Gallon'])
.column(['Displacement', 'Miles_per_Gallon'])
.spec(vl.circle()
.data(cars)
.x(vl.field(vl.column).type(vl.Q))
.y(vl.field(vl.row).type(vl.Q))
.color(vl.rule()
.if('region', vl.field('Origin').type(vl.N))
.else(vl.value('grey')))
.size(vl.value(100))
.select('region', vl.interval()
.translate(true).zoom(true).resolve('single')
.on('[mousedown[event.shiftKey], mouseup] > mousemove'))
.select('grid', vl.interval()
.scales(true).zoom(true).resolve('single')
.on('[mousedown[!event.shiftKey], mouseup] > mousemove')));
// Independent Brushes
var fig8b = fig8a.copy();
fig8b.spec().select('region').resolve('independent');
fig8b.spec().select('grid').resolve('independent');
// Unioned Brushes
var fig8c = fig8a.copy();
fig8c.spec().select('region').resolve('union');
fig8c.spec().select('grid').resolve('union');
// Intersected Brushes
var fig8d = fig8a.copy();
fig8d.spec().select('region').resolve('intersect');
fig8d.spec().select('grid').resolve('intersect');
/// FIGURE 9
var stocks = vl.data.url('data/sp500.csv').format('csv');
// Overview + Detail
var fig9a = vl.vconcat([
vl.area()
.x(vl.field('date').type(vl.T))
.y(vl.field('price').type(vl.Q))
.select('region', vl.interval().channels('x'))
.height(100),
vl.area()
.x(vl.field('date').type(vl.T))
.y(vl.field('price').type(vl.Q)
.scale(vl.scale().domain(vl.selection('region'))))
.height(300)
]);
// Index Chart
var fig9b = vl.layers([
vl.line()
.data(stocks.copy()
.lookup('index', vl.selection('indexPt').keys('symbol'))
.calculate('field', 'indexed_price')
.calculate('expr', '(datum.price - datum.index.price) / datum.index.price'))
.x(vl.field('date').type(vl.Temporal))
.y(vl.field('indexed_price').type(vl.Quantitative))
.color(vl.field('symbol').type(vl.Nominal))
.select('indexPt', vl.single()
.on('mousemove').fields('date').nearest(true)),
vl.rule()
.x(vl.selection('indexPt.date').type(vl.T))
.color(vl.value('red'))
]);
/// FIGURE 10
var flights = vl.data().url('data/flights-2k.json');
var fig10 = vl.repeat()
.column(['hour', 'delay', 'distance'])
.spec(vl.bar()
.data(flights.copy().filter(vl.selection('region')))
.x(vl.bin(vl.column))
.y(vl.count())
.color(vl.value('steelblue'))
.select('region', vl.interval()
.channels('x').resolve('intersect_others')));
/// FIGURE 11
// Single-Point Layered Cross Filtering
var fig11a = vl.repeat()
.column(['hour', 'delay', 'distance'])
.spec(vl.layers([
vl.bar()
.data(flights)
.x(vl.bin(vl.column))
.y(vl.count())
.color(vl.value('steelblue'))
.select('selectedBins', vl.single().on('mousemove').channels('x')),
vl.bar()
.data(flights.copy().filter(vl.selection('selectedBins')))
.x(vl.bin(vl.column))
.y(vl.count())
.color(vl.value('goldenrod'))
]);
// Multi-Point Layered Cross Filtering
var fig11b = vl.repeat()
.column(['hour', 'delay', 'distance'])
.spec(vl.layers([
vl.bar()
.data(flights)
.x(vl.bin(vl.column))
.y(vl.count())
.color(vl.value('steelblue'))
.select('selectedBins', vl.multi().on('click').channels('x')),
vl.bar()
.data(flights.copy().filter(vl.selection('selectedBins')))
.x(vl.bin(vl.column))
.y(vl.count())
.color(vl.value('goldenrod'))
]);
// Continuous Layered Cross Filtering
var fig11b = vl.repeat()
.column(['hour', 'delay', 'distance'])
.spec(vl.layers([
vl.bar()
.data(flights)
.x(vl.bin(vl.column))
.y(vl.count())
.color(vl.value('steelblue'))
.select('selectedBins', vl.interval().channels('x')),
vl.bar()
.data(flights.copy().filter(vl.selection('selectedBins')))
.x(vl.bin(vl.column))
.y(vl.count())
.color(vl.value('goldenrod'))
]);
cc @mbostock
From a type-safety & conciseness perspective, one question I have is whether you can declare typed fields for your dataset symbolically, rather than repeating string identifiers. So for example rather than this:
line.x(vl.field("date").type(vl.Temporal));
You would first declare the typed field like this:
var date = vl.field("date").type(vl.Temporal);
Or in slightly shorter form:
var date = vl.Temporal("date");
And then later use it:
line.x(date);
It looks like this is mostly possible already, but there appear to be a few places where you must refer to a field again by name, rather than by symbol; for example with calculated fields or the repeat operator.
Likewise, could there be a more symbolic approach to derived fields? Like instead of this:
var temp_mean = vl.mean("temp_max");
You could say something like this?
var temp_max = vl.Quantitative("temp_max"),
temp_mean = vl.mean(temp_max);
Or maybe this?
var temp_max = vl.Quantitative("temp_max"),
temp_mean = temp_max.mean();
Also, it would be great to “autobox” constant values rather than requiring vl.value. For example, instead of this:
bar.color(vl.value("steelblue"));
You could say this:
bar.color("steelblue");
I don’t know if these things are possible but these are first impressions. Thanks for inviting me to the discussion.
Would love to see this happen
I think it's nice that we have this issue documenting this idea and it could be nice if someone try doing it. However, the JSON syntax is already pretty convenient for Javascript users and they can already get free typing with Typescripts and get free autocompletion like we do in the editor.
Implementing this would require a lot of efforts and even more maintenance. Both @domoritz and I think that it's not worth the efforts for us to do this ourselves. So I will close this for now.
https://github.com/gjmcn/to-vega does a great job implementing this idea, and recently has been updated to vega-lite v3 schema
@kanitw I'd like to revisit this. The issue with just JSON and typescript is that you don't get errors where they are happening (see below). Moreover, Observable will add support for runtime autocomplete and this won't support Typescript. I think there is value in a JS API even if we don't implement it soon.

The issue with just JSON and typescript is that you don't get errors where they are happening (see below).
It seems like this would provide better error for TS users as the underline will show if a parameter doesn't matching type. However, in pure JS, you won't get a red underline in your method call either? If so, this might only benefit TS users.
In any case, for small specs like this, the error message for which part is breaking the type isn't too bad. For bigger spec like multi-views, people can declare subpart of the specs and get error specific to each subpart.
Overall, I agree that a TS/JS API (rather than JSON) provide benefits for showing errors, but maybe not so big?
Observable will add support for runtime autocomplete and this won't support Typescript.
This is an important point. However, we better understand how they generate the autocompletion and make sure that adding the JS APIs will really solve the task.
They will just autocomplete the properties that are available on an object.
Object or function?
On Fri, Dec 21, 2018 at 6:27 PM Dominik Moritz notifications@github.com
wrote:
They will just autocomplete the properties that are available on an object.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/vega/vega-lite/issues/2280#issuecomment-449538661,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAGypWHGEcNWFIeLgQGRif4Di0uO0Ha7ks5u7ZhygaJpZM4NJU-e
.
Either. But a function with properties is an object in disguise to me.
related: is this vega lite json schema up to date?
http://json.schemastore.org/vega-lite
I am planning to use it for vl.json validation in the vscode viewer I am working on
Always use https://github.com/vega/schema.
You should always just follow the URL in the spec. I don't understand why you need separate validation from what vscode already does without a plugin.
Dom,
It's mostly for the vg/vl json lang. dialect hookup in vscode ext for file matching and validation for me to open vega viewer preview and add explorer/contexts Vega Preview contributes (vscode hookup specific), not for the editor or authoring of that json that is accomplished via default vscode json schema reference, validation and hints as you point out.
that former part is typically done with the following json block in package.json vscode ext, or somewhat along those lines:
"languages": [
{
"id": "json",
"aliases": ["VegaJSON"],
"extensions": [".vg.json"]
},
{
"id": "json",
"aliases": ["VegaLightJSON"],
"extensions": [".vl.json"]
}
],
"jsonValidation": [
{
"fileMatch": "*.vg.json",
"url": "https://vega.github.io/schema/vega/v4.json"
},
{
"fileMatch": "*.vl.json",
"url": "https://vega.github.io/schema/vega-lite/v3.json"
}
]
I am hoping to push an alpha v. for preview soon. I think it will be clearer in context then.
btw, vega embed is no go for that plugin since vscode webview panel dosn't allow iframe sandbox="allow-popus" to open content in browser due to sandboxing, but I'll have options to save as svg or png. I did get an interactive vega chart working in my local prototype, with tooltips etc. unlike that vega-preview plugin. Just finishing up the IDE dressing parts now.
another option would be to generate typed JS and TS apis and JSON spec converters from vega JSON schemas using quicktype lib:
https://github.com/quicktype/quicktype
Worth a look for api driven vega spec creation.
Quicktype is cool but is there a way to compile ts interfaces to js?
I just created a quick test repo to see what quicktype does:
https://github.com/RandomFractals/vega-lite-api
It does give us quick spec json validation, to/from, and auto-complete for TS, as expected. See main.ts and src/spec.ts.
Not sure if this is worth considering since you already have your types defined in vega-typings repo.
However, it could be a quick way to gen. vega-lite spec api for C#, GO and other langs if you don't have it already and want to create vega-lite spec programmatically on the server side... :)
I want ts to js, not json to ts or json to js.
You can gen js from ts types, but I think your typings might need some cleanup for that to work with quicktype.
Personally, I am more excited about creating json types interfaces with quicktype for C#, Go and Java, where there is no library for generating vega specs. I've tried it locally, but there are some objects that will need to be cleaned up in your types and schemas.
So, for those reasons, I'd pick the schema json as the one source of truth for vega grammar.
Also, I believe I've seen some issues logged and closed regarding vega types being added to
https://github.com/DefinitelyTyped/DefinitelyTyped
I think it would be benefitial to the dev community to have them posted there to make them more accessible since most JS devs are familiar with how to add types via @types
Vega comes with types. I deleted them from definitely typed.
ok. getting back to other langs and typed interfaces:
I generated CS vega types from your schema in case you guys want to explore that route later:
https://github.com/RandomFractals/vega-lite-api/blob/master/src/Spec.cs
A simple CS demo app with spec gen on the server side could be an intersting project to explore since you don't have any api or support in CS or other server side langs and real world projects do do that all the time, based on my expi with data viz libs and dashboards.
Thinks about it...
Feel free to open new epic issue for this topic discussion
I think there are multiple APIs already. Jeff has also started https://github.com/vega/vega-lite-api.
I think it's time to close this issue. (Feel free to keep commenting here to discuss, but I'll close the issue since there is no actionable item specific to this repository anymore.
Most helpful comment
I think there are multiple APIs already. Jeff has also started https://github.com/vega/vega-lite-api.
I think it's time to close this issue. (Feel free to keep commenting here to discuss, but I'll close the issue since there is no actionable item specific to this repository anymore.