A concise grammar of interactive graphics, built on Vega.

Overview

Vega-Lite

npm version Build Status codecov code style: prettier JSDevlivr

Teaser

Vega-Lite provides a higher-level grammar for visual analysis that generates complete Vega specifications.

You can find more details, documentation, examples, usage instructions, and tutorials on the Vega-Lite website.

Try using Vega-Lite in the online Vega Editor.

Contributions are also welcome. Please see CONTRIBUTING.md for contribution and development guidelines and our Code of Conduct.

Read about future plans in our roadmap.

Team

The development of Vega-Lite is led by the alumni and members of the University of Washington Interactive Data Lab (UW IDL), including Kanit "Ham" Wongsuphasawat (now at Databricks), Dominik Moritz (now at CMU and Apple), Arvind Satyanarayan (now at MIT), and Jeffrey Heer (UW IDL).

Vega-Lite gets significant contributions from its community--in particular Will Strimling, Yuhan (Zoe) Lu, Souvik Sen, Chanwut Kittivorawong, Matthew Chun, Akshat Shrivastava, Saba Noorassa, Sira Horradarn, Donghao Ren, and Halden Lin. Please see the contributors page for the full list of contributors.

Citing Vega-Lite

@article{2017-vega-lite,
  doi = {10.1109/tvcg.2016.2599030},
  year = {2017},
  author = {Arvind Satyanarayan and Dominik Moritz and Kanit Wongsuphasawat and Jeffrey Heer},
  title = {Vega-Lite: A Grammar of Interactive Graphics},
  journal = {{IEEE} Transactions on Visualization \& Computer Graphics (Proc. InfoVis)},
  url = {http://idl.cs.washington.edu/papers/vega-lite},
}
Comments
  • Wrapped facet & wrapped concat / repeat

    Wrapped facet & wrapped concat / repeat

    Current vegalite supports small multiples only on one axis (with row/col similar to Tableau)

    However, it's useful to create wrapped small mutliples (similar to lattice in r / ggplot) http://codealamode.blogspot.com/2012/02/trellis-graphs-in-ggplot2.html

    or this example

    Area - View Composition 
    opened by kanitw 48
  • Reduce redundancy in generated schema

    Reduce redundancy in generated schema

    Some structures in the generated vega-lite-schema.json are repeated multiple times. For example, the timeUnit enumeration is repeated verbatim 13 times throughout the schema. Detecting this redundancy and emitting repeated structures to a shared defs section of the schema would make it much more compact.

    TODO:

    • [x] add enum support to typescript-json-schema
    • [ ] change build process to generate schema using new typescript-json-schema
    • [ ] remove old schema generation process
    opened by marcprux 33
  • Signals in Vega-Lite

    Signals in Vega-Lite

    It would be great to have basic support for signals in Vega-Lite. This could be used to implement a rotating earth as in https://beta.observablehq.com/@domoritz/rotating-earth. Another example would be to define the colors of marks via a signal.

    To implement this, we need to add signal support to the types and fix resulting bugs. Also, as we parse the spec, we need to collect signals and create definitions at the top.

    While this is exciting, we want to be very careful about the design. We don't want to break abstractions or introduce multiple ways to do the same thing. @arvind suggest that we look into how we can extend single selections to support this use case.

    Area - Interaction 
    opened by domoritz 32
  • Support expression for formatting axis

    Support expression for formatting axis

    We already have format types for number and time. We could introduce a flexible expression formatter. This would resolve https://github.com/vega/vega-lite-api/issues/12.

    Related issue: https://github.com/vega/vega/issues/608

    cc @curran

    RFC / Discussion :speech_balloon: Area - Visual Encoding 
    opened by domoritz 31
  • Error bar macro for value + error

    Error bar macro for value + error

    Commonly users come with data of the form value, error. Our errorbar macro should support this use case and not require users to create a transform.

    mark: "errorbar",
    encoding: {
      y: {field: value, type: "quantitative"},
      yError: {field: error, type: "quantitative"}
    }
    
    {
      "data": {
        "values": [
          {
            "yield_error": 3,
            "yield": 32.4,
            "variety": "Glabron"
          },
          {
            "yield_error": 3.2,
            "yield": 30.96667,
            "variety": "Manchuria"
          },
          {
            "yield_error": 1.2,
            "center": 33.966665,
            "variety": "No. 457"
          },
          {
            "yield_error": 2,
            "yield": 30.45,
            "variety": "No. 462"
          }
        ]
      },
      "layer": [
        {
          "mark": "errorbar",
          "encoding": {
            "x": {
              "field": "yield",
              "type": "quantitative",
              "scale": {"zero": false},
              "title": "yield"
            },
            "xError": {"field": "yield_error", "type": "quantitative"},
            "y": {"field": "variety", "type": "ordinal"}
          }
        },
        {
          "mark": {
            "type": "point",
            "filled": true,
            "color": "black"
          },
          "encoding": {
            "x": {
              "field": "yield",
              "type": "quantitative"
            },
            "y": {"field": "variety", "type": "ordinal"}
          }
        }
      ]
    }
    
    Enhancement :tada: RFC / Discussion :speech_balloon: 
    opened by domoritz 31
  • Layers with shared encodings

    Layers with shared encodings

    From reading the documentation it seems like there's not an easy way to have multiple marks share the same encodings without repeating them. For example in this example from the docs:

    {
      "data": {"url": "data/stocks.csv"},
      "layer": [
        {
          "mark": "line",
          "encoding": {
            "x": {"field": "date", "type": "temporal"},
            "y": {"field": "price", "type": "quantitative"},
            "color": {"field": "symbol", "type": "nominal"}
          }
        },
        {
          "mark": "rule",
          "encoding": {
            "y": {
              "field": "price",
              "type": "quantitative",
              "aggregate": "mean"
            },
            "size": {"value": 2},
            "color": {"field": "symbol", "type": "nominal"}
          }
        }
      ]
    }
    

    the color scale is identical between the two layers, and most of the y scale is the same too. To avoid this kind of repetition it would be nice if the layers could "inherit" encodings from the top level, possibly augmenting them along the way:

    {
      "data": {"url": "data/stocks.csv"},
      "encoding": {
        "y": {"field": "price", "type": "quantitative"},
        "color": {"field": "symbol", "type": "nominal"}
      },
      "layer": [
        {
          "mark": "line",
          "encoding": {
            "x": {"field": "date", "type": "temporal"}
          }
        },
        {
          "mark": "rule",
          "encoding": {
            "y": { "aggregate": "mean" },
            "size": {"value": 2}
          }
        }
      ]
    }
    
    Help Wanted Area - Macro / Composite Mark 
    opened by pelotom 27
  • Setting only `width` when using `autosize: fit` should not use default height in compiled Vega

    Setting only `width` when using `autosize: fit` should not use default height in compiled Vega

    See the compiled Vega from this example. The height is set the default config.view.height of 200, but I'd expect this chart to only "fit" the width (since that is all I specified).

    To solve this, I imagine there are two options:

    1. We should not apply the config's height or width when using "autosize": "fit" with one of the dimensions specified.
    2. We allow for some value of "autosize" that specifies only to "fit" along one dimension.
    Bug :bug: Enhancement :tada: Area - Visual Encoding 
    opened by willium 25
  • Consider supporting Filter Object

    Consider supporting Filter Object

    @jheer @domoritz

    Currently our filter is using Vega Expression, which is easy for compilation and manual writing, but not easy for static analysis / enumeration. This will make implementing UI in Polestar / Enumerating in Compass(QL) much easier.

    Should we bring back the support for filter in an object form? I remember we briefly discuss about this in a meeting with @jheer (like in two sentences).

    Now that I think more about CompassQL syntax (and Polestar UI) ... maybe it makes sense to consider it even more closely.

    For example, the following filter

    transform: {
      filter: {
        operator: '<',
        operand1:  {field: 'horsepower'}   // alternative names left / x1/ l
        operand2: {value: 9}               // alternative names right / x2 / r
      }
    } 
    

    might get compiled into transform: {filter: 'datum.horsepower < 9'}.

    In some sense, this syntax proposed syntax is more consistent with how we design FieldDefs.

    If we want to, we can support 'and' and 'or' like this:
    (This is useful for Polestar, but I don't think we really need it for CompassQL and our new UI prototype.)

    transform: {
      filter: {
        and/or: [
           filter1,  // same syntax as above
           filter2
        ] 
      }
    } 
    

    Basically here are the TS interfaces.

    interface BinaryPredicate {
      operator: '<' | '>' | '==' | ...,
      operand1: FieldDef,
      operand2: FieldDef
    }
    
    interface UnaryPredicate {
      operator: ...,   // do we need any unary predicate?
      operand: FieldDef
    }
    
    interface And/OrFilter { // there are two separate interfaces
      and/or: Filter[]
    }
    
    interface NotFilter {
      not: Filter
    }
    
    type Filter = UnaryPredicate | BinaryPredicate | And/OrFilter | NotFilter | string;  // string = expression
    
    RFC / Discussion :speech_balloon: 
    opened by kanitw 24
  • Post aggregation calculation & filter

    Post aggregation calculation & filter

    I'd like to use transform > calculate feature with aggregated fields.

    For example,
    I'm using a simple data set which includes "Status", "Gender", "Department", "Count". What I want to do is calculating "Acceptance Rate" of each "Gender" and "Department".

    The query will looks like below

    SELECT Gender
        , Department
        , sum( case when Status = 'Admit' then Count else 0 end)*1.0  / sum( Count ) * 100 Acceptance_Rate
    FROM admission 
    GROUP BY Gender,  Department
    

    If I can use some aggregated fields to express calculate I can substitute the above query like the below.

    {
      "transform": {
        "calculate": [
          {
            "field": "Acceptance_Rate",
            "expr": "datum.Count / aggregated.sum(datum.Count).by(datum.Department, datum.Gender)"
          }
        ]
      }
    ...
    }
    
    

    (I talked about this issue with @kanitw and it seems not supporting currently.)

    opened by yhoonkim 24
  • Support pre-binned data

    Support pre-binned data

    From an earlier conversation with @domoritz, supporting pre-binned data would be useful for connecting with database. I think this would be useful for @leibatt as well.

    From the conversation, the tricky part is how to know the bin step.

    I wonder if we should just let users input the step in such case?

    opened by kanitw 22
  • JavaScript Syntax for Vega-Lite (similar to Altair)

    JavaScript Syntax for Vega-Lite (similar to Altair)

    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

    opened by domoritz 22
  • Custom formatters with temporal type

    Custom formatters with temporal type

    Issue Custom formatters with type temporal renders unexpectedly. Warn: "Infinite extent for field '__count': [Infinity, -Infinity]"

    Example Codepen

    Versions vega 5.22.1 vega-lite 5.5.0 vega-embed 6.21.0

    Spec

    {
      "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
      "config": {
        "customFormatTypes": true,
      },
      "width": 600,
      "height": 100,
      "data": {
        "values": [
          { "date": "2022-03-16" },
          { "date": "2022-04-16" },
          { "date": "2022-05-16" },
        ]
      },
      "mark": "bar",
      "encoding": {
        "x": {
          "field": "date",
          "type": "temporal",
          "axis": {
            "formatType": "customFormatter",
          },
        },
        "y": {
          "aggregate": "count",
        },
      },
    }
    

    Context: Should work fine if temporal data is epoch time

    Bug :bug: 
    opened by danielmalaton 0
  • Bug: chart seems to incorrectly label single data entry value with a decimal point

    Bug: chart seems to incorrectly label single data entry value with a decimal point

    Please:

    • [x] Check for duplicate issues. Please file separate requests as separate issues.
    • [x] Describe how to reproduce the bug.
    • [x] Use the latest versions of Vega and Vega-Lite. - using latest version of altair
    • [x] Provide an minimal, reproducible example spec in JSON, wrapped by triple backticks like this:
    {
      "$schema": "https://vega.github.io/schema/vega-lite/v4.17.0.json",
      "data": {"name": "data-0c37a591ceae41251602063922514f84"},
      "datasets": {
        "data-0c37a591ceae41251602063922514f84": [
          {
            "day": "2022-04-01T00:00:00",
            "metric": "Nodulation of legumes",
            "sample": "Arch Field: Hedge",
            "value_float": 0.5
          },
          {
            "day": "2022-07-27T00:00:00",
            "metric": "Nodulation of legumes",
            "sample": "Arch Field: Hedge",
            "value_float": 0.5
          }
        ]
      },
      "layer": [
        {
          "encoding": {
            "detail": {"field": "sample", "type": "nominal"},
            "opacity": {
              "condition": {"selection": "selector001", "value": 1},
              "value": 0.1
            },
            "x": {
              "axis": {"format": "%b %d", "title": null},
              "field": "day",
              "type": "temporal"
            },
            "y": {
              "axis": {"title": "Nodulation of legumes"},
              "field": "value_float",
              "scale": {"zero": false},
              "type": "quantitative"
            }
          },
          "mark": "line",
          "selection": {
            "selector001": {
              "bind": "legend",
              "fields": ["sample"],
              "toggle": "true",
              "type": "multi"
            }
          }
        },
        {
          "encoding": {
            "color": {"field": "sample", "type": "nominal"},
            "detail": {"field": "sample", "type": "nominal"},
            "opacity": {
              "condition": {"selection": "selector001", "value": 1},
              "value": 0.1
            },
            "tooltip": [
              {"field": "sample", "title": "Soil sample", "type": "nominal"},
              {"field": "day", "title": "Date", "type": "temporal"},
              {"field": "value_float", "title": "Value", "type": "quantitative"}
            ],
            "x": {"field": "day", "type": "temporal"},
            "y": {
              "field": "value_float",
              "scale": {"zero": false},
              "type": "quantitative"
            }
          },
          "mark": {"opacity": 1, "size": 50, "type": "circle"}
        }
      ],
      "title": "",
      "width": "container"
    }
    

    Hello! I have found some strange behaviour when representing a small dataset that includes a single data entry with a decimal point value. Here is a simplified version of the code I have to reproduce the bug:

    
    def get_chart(df, dt_format, y_title):
    	chart_base = alt.Chart(df)
    	
    	line_chart = chart_base.mark_line().encode(
    	    x=alt.X("day", axis=alt.Axis(title=None, format=dt_format)),
    	    y=alt.Y(
    	        "value_float",
    	        axis=alt.Axis(title=y_title),
    	        scale=alt.Scale(zero=False),
    	    ),
    	)
    	
    	chart = alt.layer(line_chart).properties(width="container", title="")
    	
    	return chart.to_json()
    

    The df is:

      day         metric             	sample  				value_float
    0 2022-04-01  Nodulation of legumes  Arch Field: Hedge          0.5
    1 2022-07-27  Nodulation of legumes  Arch Field: Hedge          0.5
    

    And the chart looks like this:

    image

    I would expect the scale on the y axis to be labeled 0.5 rather than 1!

    If we try the same code with a slightly bigger dataset, it works as expected.

    df
      day              metric              	sample                value_float
    0 2022-05-06  Nodulation of legumes  Mud Mead: Sample 1          1.5
    1 2022-07-29  Nodulation of legumes  Mud Mead: Sample 1          0.5
    2 2022-08-12  Nodulation of legumes  Mud Mead: Sample 1          0.5
    3 2022-09-28  Nodulation of legumes  Mud Mead: Sample 1          1.5
    4 2022-11-28  Nodulation of legumes  Mud Mead: Sample 1          1.5
    

    image

    I'm not sure if it's relevant to the issue, but I am using a django template the display the chart. Here is the code from the template in case it is relevant:

    <div id="chart" class="vega-plot col-12"></div>
    <script type="text/javascript">
    	window.addEventListener('DOMContentLoaded', function() {
    	  vegaEmbed('#chart', {{ chart|safe }}, {renderer: 'svg'})
    	})
    </script>
    

    Where chart is the chart.to_json() returned above.

    Thanks for your help! Let me know if you need any more information.

    • [] If applicable, include error messages and screenshots, GIF videos (e.g. using https://www.cockos.com/licecap/), or working examples (e.g. by clicking share in the Vega-Editor or https://bit.ly/vega-lite-blocks)
    Bug :bug: 
    opened by taosharma 0
  • chore(deps-dev): bump puppeteer from 15.5.0 to 19.4.1

    chore(deps-dev): bump puppeteer from 15.5.0 to 19.4.1

    Bumps puppeteer from 15.5.0 to 19.4.1.

    Release notes

    Sourced from puppeteer's releases.

    puppeteer-core: v19.4.1

    19.4.1 (2022-12-16)

    Bug Fixes

    • improve a11y snapshot handling if the tree is not correct (#9405) (02fe501), closes #9404
    • remove oopif expectations and fix oopif flakiness (#9375) (810e0cd)

    puppeteer: v19.4.1

    19.4.1 (2022-12-16)

    Miscellaneous Chores

    • puppeteer: Synchronize puppeteer versions

    Dependencies

    • The following workspace dependencies were updated
      • dependencies
        • puppeteer-core bumped from 19.4.0 to 19.4.1

    puppeteer-core: v19.4.0

    19.4.0 (2022-12-07)

    Features

    • ability to send headers via ws connection to browser in node.js environment (#9314) (937fffa), closes #7218
    • chromium: roll to Chromium 109.0.5412.0 (r1069273) (#9364) (1875da6), closes #9233
    • puppeteer-core: keydown supports commands (#9357) (b7ebc5d)

    Bug Fixes

    puppeteer: v19.4.0

    19.4.0 (2022-12-07)

    Features

    Dependencies

    ... (truncated)

    Commits
    • 848c849 chore: release main (#9395)
    • fe986c6 chore: trigger reindexing on doc deployment (#9425)
    • f0951aa docs: use a number of documented versions for indexing (#9424)
    • 68c53df chore(deps): Bump loader-utils from 2.0.2 to 2.0.4 in /website (#9423)
    • 69b03df chore(deps): Bump @​angular-devkit/schematics from 15.0.3 to 15.0.4 (#9420)
    • fa05a1c chore(deps): Bump @​angular-devkit/core from 15.0.3 to 15.0.4 (#9414)
    • 0f0e717 chore(deps): Bump @​angular-devkit/architect from 0.1402.10 to 0.1500.4 (#9415)
    • cd073ab chore(deps): Bump ws from 8.10.0 to 8.11.0 (#9412)
    • cd8eec3 chore(deps): Bump @​angular-devkit/schematics from 14.2.8 to 15.0.3 (#9413)
    • 28cedac chore: Revert Dependabot config (#9411)
    • Additional commits viewable in compare view
    Maintainer changes

    This version was pushed to npm by google-wombot, a new releaser for puppeteer since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    Dependencies :robot: javascript 
    opened by dependabot[bot] 0
  • chore(deps-dev): bump typescript from 4.8.4 to 4.9.4

    chore(deps-dev): bump typescript from 4.8.4 to 4.9.4

    Bumps typescript from 4.8.4 to 4.9.4.

    Release notes

    Sourced from typescript's releases.

    TypeScript 4.9.4

    For release notes, check out the release announcement.

    For the complete list of fixed issues, check out the

    Downloads are available on:

    Changes:

    • e2868216f637e875a74c675845625eb15dcfe9a2 Bump version to 4.9.4 and LKG.
    • eb5419fc8d980859b98553586dfb5f40d811a745 Cherry-pick #51704 to release 4.9 (#51712)
    • b4d382b9b12460adf2da4cc0d1429cf19f8dc8be Cherry-pick changes for narrowing to tagged literal types.
    • e7a02f43fce47e1a39259ada5460bcc33c8e98b5 Port of #51626 and #51689 to release-4.9 (#51627)
    • 1727912f0437a7f367d90040fc4b0b4f3efd017a Cherry-pick fix around visitEachChild to release-4.9. (#51544)

    This list of changes was auto generated.

    TypeScript 4.9

    For release notes, check out the release announcement.

    Downloads are available on:

    Changes:

    • 93bd577458d55cd720b2677705feab5c91eb12ce Bump version to 4.9.3 and LKG.
    • 107f832b80df2dc97748021cb00af2b6813db75b Update LKG.
    • 31bee5682df130a14ffdd5742f994dbe7313dd0e Cherry-pick PR #50977 into release-4.9 (#51363) [ #50872 ]
    • 1e2fa7ae15f8530910fef8b916ec8a4ed0b59c45 Update version to 4.9.2-rc and LKG.
    • 7ab89e5c6e401d161f31f28a6c555a3ba530910e Merge remote-tracking branch 'origin/main' into release-4.9
    • e5cd686defb1a4cbdb36bd012357ba5bed28f371 Update package-lock.json
    • 8d40dc15d1b9945837e7860320fdccfe27c40cad Update package-lock.json
    • 5cfb3a2fe344a5350734305193e6cc99516285ca Only call return() for an abrupt completion in user code (#51297)
    • a7a9d158e817fcb0e94dc1c24e0a401b21be0cc9 Fix for broken baseline in yieldInForInInDownlevelGenerator (#51345)
    • 7f8426f4df0d0a7dd8b72079dafc3e60164a23b1 fix for-in enumeration containing yield in generator (#51295)
    • 3d2b4017eb6b9a2b94bc673291e56ae95e8beddd Fix assertion functions accessed via wildcard imports (#51324)
    • 64d0d5ae140b7b26a09e75114517b418d6bcaa9f fix(51301): Fixing an unused import at the end of a line removes the newline (#51320)
    • 754eeb2986bde30d5926e0fa99c87dda9266d01b Update CodeQL workflow and configuration, fix found bugs (#51263)
    • d8aad262006ad2d2c91aa7a0e4449b4b83c57f7b Update package-lock.json
    • d4f26c840b1db76c0b25a405c8e73830a2b45cbc fix(51245): Class with parameter decorator in arrow function causes "convert to default export" refactoring failure (#51256)
    • 16faf45682173ea437a50330feb4785578923d7f Update package-lock.json
    • 8b1ecdb701e2a2e19e9f8bcdd6b2beac087eabee fix(50654): "Move to a new file" breaks the declaration of referenced variable (#50681)
    • 170a17fad57eae619c5ef2b7bdb3ac00d6c32c47 Dom update 2022-10-25 (#51300)

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    Dependencies :robot: javascript 
    opened by dependabot[bot] 0
  • Order of layering affect bar bandwidth

    Order of layering affect bar bandwidth

    I want to use multiple aggregated tooltips with a box plot, but https://github.com/vega/vega-lite/issues/7918 is preventing me from using the boxplot mark for this so I am building the chart from scratch. I noticed that the order of layering objects changes the bar bandwidth in an unfortunate way. If I put the line under the bar (as desired), there are not spaces between the bars:

    Open the Chart in the Vega Editor

    image

    If the line goes on top, the spaces are there as intended:

    Open the Chart in the Vega Editor

    image

    It feels like a bug to me that this is changed depending on the order of the charts in the layering. Looking at the vega spec, we can see that the first chart has "update": "bandspace(domain('x').length, 0, 0) * x_step"} and the second one has "update": "bandspace(domain('x').length, 0.1, 0.05) * x_step". A workaround is to set "mark": {"type": "bar", "width": {"band": 0.8}},

    Bug :bug: 
    opened by joelostblom 0
Releases(v5.6.1-next.0)
Owner
Vega
Data Visualization Languages & Tools
Vega
Interactive plotting for Pandas using Vega-Lite

pdvega: Vega-Lite plotting for Pandas Dataframes pdvega is a library that allows you to quickly create interactive Vega-Lite plots from Pandas datafra

Altair 342 Oct 26, 2022
Interactive plotting for Pandas using Vega-Lite

pdvega: Vega-Lite plotting for Pandas Dataframes pdvega is a library that allows you to quickly create interactive Vega-Lite plots from Pandas datafra

Altair 340 Feb 1, 2021
A grammar of graphics for Python

plotnine Latest Release License DOI Build Status Coverage Documentation plotnine is an implementation of a grammar of graphics in Python, it is based

Hassan Kibirige 3.3k Jan 1, 2023
A grammar of graphics for Python

plotnine Latest Release License DOI Build Status Coverage Documentation plotnine is an implementation of a grammar of graphics in Python, it is based

Hassan Kibirige 2.6k Feb 12, 2021
A grammar of graphics for Python

plotnine Latest Release License DOI Build Status Coverage Documentation plotnine is an implementation of a grammar of graphics in Python, it is based

Hassan Kibirige 2.6k Feb 18, 2021
An interactive dashboard built with python that enables you to visualise how rent prices differ across Sweden.

sweden-rent-dashboard An interactive dashboard built with python that enables you to visualise how rent prices differ across Sweden. The dashboard/web

Rory Crean 5 Dec 19, 2021
A dashboard built using Plotly-Dash for interactive visualization of Dex-connected individuals across the country.

Dashboard For The DexConnect Platform of Dexterity Global Working prototype submission for internship at Dexterity Global Group. Dashboard for real ti

Yashasvi Misra 2 Jun 15, 2021
Interactive Data Visualization in the browser, from Python

Bokeh is an interactive visualization library for modern web browsers. It provides elegant, concise construction of versatile graphics, and affords hi

Bokeh 17.1k Dec 31, 2022
An interactive GUI for WhiteboxTools in a Jupyter-based environment

whiteboxgui An interactive GUI for WhiteboxTools in a Jupyter-based environment GitHub repo: https://github.com/giswqs/whiteboxgui Documentation: http

Qiusheng Wu 105 Dec 15, 2022
The interactive graphing library for Python (includes Plotly Express) :sparkles:

plotly.py Latest Release User forum PyPI Downloads License Data Science Workspaces Our recommended IDE for Plotly’s Python graphing library is Dash En

Plotly 12.7k Jan 5, 2023
Interactive Data Visualization in the browser, from Python

Bokeh is an interactive visualization library for modern web browsers. It provides elegant, concise construction of versatile graphics, and affords hi

Bokeh 14.7k Feb 13, 2021
Draw interactive NetworkX graphs with Altair

nx_altair Draw NetworkX graphs with Altair nx_altair offers a similar draw API to NetworkX but returns Altair Charts instead. If you'd like to contrib

Zachary Sailer 206 Dec 12, 2022
The interactive graphing library for Python (includes Plotly Express) :sparkles:

plotly.py Latest Release User forum PyPI Downloads License Data Science Workspaces Our recommended IDE for Plotly’s Python graphing library is Dash En

Plotly 8.9k Feb 18, 2021
Interactive Data Visualization in the browser, from Python

Bokeh is an interactive visualization library for modern web browsers. It provides elegant, concise construction of versatile graphics, and affords hi

Bokeh 14.7k Feb 18, 2021
Draw interactive NetworkX graphs with Altair

nx_altair Draw NetworkX graphs with Altair nx_altair offers a similar draw API to NetworkX but returns Altair Charts instead. If you'd like to contrib

Zachary Sailer 156 Feb 6, 2021
Easily convert matplotlib plots from Python into interactive Leaflet web maps.

mplleaflet mplleaflet is a Python library that converts a matplotlib plot into a webpage containing a pannable, zoomable Leaflet map. It can also embe

Jacob Wasserman 502 Dec 28, 2022
SummVis is an interactive visualization tool for text summarization.

SummVis is an interactive visualization tool for analyzing abstractive summarization model outputs and datasets.

Robustness Gym 246 Dec 8, 2022
nvitop, an interactive NVIDIA-GPU process viewer, the one-stop solution for GPU process management

An interactive NVIDIA-GPU process viewer, the one-stop solution for GPU process management.

Xuehai Pan 1.3k Jan 2, 2023
ICS-Visualizer is an interactive Industrial Control Systems (ICS) network graph that contains up-to-date ICS metadata

ICS-Visualizer is an interactive Industrial Control Systems (ICS) network graph that contains up-to-date ICS metadata (Name, company, port, user manua

QeeqBox 2 Dec 13, 2021