APB Reports
APB Reports

Reputation: 2451

Animated vega-lite charts

I started to think a bit about animated vega-lite charts after Davide (Vega Master) helped me out with my vega-lite clock a few days ago.

Vega-Lite Clock (Using a Timer in Vega-Lite)

Have a test of this see what you think. With this method I am rotating between 4 different charts every 15 seconds. This can open up for many possibilities for the vega-lite community I believe:)

Please make some comments how we can improve this.

enter image description here

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {"url": "data/weather.csv"},
  "usermeta": {"embedOptions": {"renderer": "svg"}},
  "params": [
    {
      "name": "time",
      "on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}]
    }
  ],
  "transform": [
    {"filter": "datum.location === 'Seattle'"},
    {"calculate": "toNumber(timeFormat(time, '%S'))", "as": "curr_sec"},
    {"calculate": "datum.curr_sec >= 0 && datum.curr_sec < 15 ? datum.weather : ' '", "as": "weather_1"},
    {"calculate": "datum.curr_sec >= 15 && datum.curr_sec < 30 ? datum.weather : ' '", "as": "weather_2"},
    {"calculate": "datum.curr_sec >= 30 && datum.curr_sec < 45 ? datum.weather : ' '", "as": "weather_3"},
    {"calculate": "datum.curr_sec >= 45 && datum.curr_sec < 60 ? datum.weather : ' '", "as": "weather_4"}
  ],
  "title": {"text": {"expr": "'Chart updates every 15 sec: (' + parseFloat(data('source_0')[0].curr_sec) + ')'"}},
  "layer": [
    {
      "width": {"step": 25},
      "mark": {"type": "bar"},
      "encoding": {
        "x": {
          "timeUnit": "month",
          "field": "date",
          "type": "ordinal",
          "title": "Month of the year"
        },
        "y": {"aggregate": "count", "type": "quantitative"},
        "color": {
          "field": "weather_1",
          "type": "nominal",
          "scale": {
            "domain": ["sun", "fog", "drizzle", "rain", "snow"," "],
            "range": ["#e7ba52", "#c7c7c7", "#aec7e8", "#1f77b4", "#9467bd","transparent"]
          },
          "title": "Weather type"
        }
      }
    },
      {
        "width": {"step": 25},
      "mark": {"type": "area"},
      "encoding": {
        "x": {
          "timeUnit": "month",
          "field": "date",
          "type": "ordinal",
          "title": "Month of the year"
        },
        "y": {"aggregate": "count", "type": "quantitative"},
        "color": {
          "field": "weather_2",
          "type": "nominal",
          "scale": {
            "domain": ["sun", "fog", "drizzle", "rain", "snow"," "],
            "range": ["#e7ba52", "#c7c7c7", "#aec7e8", "#1f77b4", "#9467bd","transparent"]
          },
          "title": "Weather type"
        }
      }
    },
    {
      "width": {"step": 25},
      "mark": {"type": "line"},
      "encoding": {
        "x": {
          "timeUnit": "month",
          "field": "date",
          "type": "ordinal",
          "title": "Month of the year"
        },
        "y": {"aggregate": "count", "type": "quantitative"},
        "color": {
          "field": "weather_3",
          "type": "nominal",
          "scale": {
            "domain": ["sun", "fog", "drizzle", "rain", "snow"," "],
            "range": ["#e7ba52", "#c7c7c7", "#aec7e8", "#1f77b4", "#9467bd","transparent"]
          },
          "title": "Weather type"
        }
      }
    },
     {
"width": {"step": 4},
      "mark": {"type": "bar"},
      "encoding": {
        "x": {
          "timeUnit": "month",
          "field": "date",
          "type": "ordinal",
          "title": "Month of the year",
          "sort": {"field": "weather_4"}
        },
        "y": {"aggregate": "count", "type": "quantitative"},
        "color": {
          "field": "weather_4",
          "type": "nominal",
          "scale": {
            "domain": ["sun", "fog", "drizzle", "rain", "snow"," "],
            "range": ["#e7ba52", "#c7c7c7", "#aec7e8", "#1f77b4", "#9467bd","transparent"]
          },
          "title": "Weather type"
        },
        "xOffset": {"field": "weather_4"}
      }
    }
  ]
}

Here is a second example where the chart switches from a filter of year = 2012, 2013, 2014, and finally 2015 every 15 seconds.

enter image description here

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {"url": "data/weather.csv"},
  "usermeta": {"embedOptions": {"renderer": "svg"}},
  "params": [
    {
      "name": "time",
      "on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}]
    }
  ],
  "transform": [
    {"filter": "datum.location === 'Seattle'"},
    {"calculate": "toNumber(timeFormat(time, '%S'))", "as": "curr_sec"},
    {
      "calculate": "datum.curr_sec >= 0 && datum.curr_sec < 15 ? 2012 : 0",
      "as": "year_1"
    },
    {
      "calculate": "datum.curr_sec >= 15 && datum.curr_sec < 30 ? 2013 : 0",
      "as": "year_2"
    },
    {
      "calculate": "datum.curr_sec >= 30 && datum.curr_sec < 45 ? 2014 : 0",
      "as": "year_3"
    },
    {
      "calculate": "datum.curr_sec >= 45 && datum.curr_sec < 60 ? 2015 : 0",
      "as": "year_4"
    }
  ],
  "width": {"step": 25},
  "title": {
    "text": {
      "expr": "'Seattle weather during: ' + ((data('source_0')[0].year_1 || 0) === 2012 ? '2012' : (data('source_0')[0].year_2 || 0) === 2013 ? '2013' : (data('source_0')[0].year_3 || 0) == 2014 ? '2014' : (data('source_0')[0].year_4 || 0) == 2015 ? '2015' : '2000') + ' - (Updates in: '+ (((data('source_0')[0].year_1 || 0) === 2012 ? 15 : (data('source_0')[0].year_2 || 0) === 2013 ? 30 : (data('source_0')[0].year_3 || 0) == 2014 ? 45 : (data('source_0')[0].year_4 || 0) == 2015 ? 60 : 0)- (data('source_0')[0].curr_sec)) + ')'"
    }
  },
  "layer": [
    {
      "transform": [
        {"filter": "parseFloat(timeFormat(datum.date, '%Y')) === datum.year_1"}
      ],
      "mark": {"type": "bar"},
      "encoding": {
        "x": {
          "timeUnit": "yearmonth",
          "field": "date",
          "type": "ordinal",
          "title": null,
          "axis": {
            "labelExpr": "[timeFormat(datum.value, '%b'), timeFormat(datum.value, '%m') == '01' ? timeFormat(datum.value, '%Y') : '']"
          }
        },
        "y": {"aggregate": "count", "type": "quantitative", "title": "Count"},
        "color": {
          "field": "weather",
          "type": "nominal",
          "scale": {
            "domain": ["sun", "fog", "drizzle", "rain", "snow"],
            "range": ["#e7ba52", "#c7c7c7", "#aec7e8", "#1f77b4", "#9467bd"]
          },
          "title": "weather"
        }
      }
    },
    {
      "transform": [
        {"filter": "parseFloat(timeFormat(datum.date, '%Y')) === datum.year_2"}
      ],
      "mark": {"type": "bar"},
      "encoding": {
        "x": {
          "timeUnit": "yearmonth",
          "field": "date",
          "type": "ordinal",
          "title": null,
          "axis": {
            "labelExpr": "[timeFormat(datum.value, '%b'), timeFormat(datum.value, '%m') == '01' ? timeFormat(datum.value, '%Y') : '']"
          }
        },
        "y": {"aggregate": "count", "type": "quantitative", "title": "Count"},
        "color": {
          "field": "weather",
          "type": "nominal",
          "scale": {
            "domain": ["sun", "fog", "drizzle", "rain", "snow"],
            "range": ["#e7ba52", "#c7c7c7", "#aec7e8", "#1f77b4", "#9467bd"]
          },
          "title": "weather"
        }
      }
    },
    {
      "transform": [
        {"filter": "parseFloat(timeFormat(datum.date, '%Y')) === datum.year_3"}
      ],
      "mark": {"type": "bar"},
      "encoding": {
        "x": {
          "timeUnit": "yearmonth",
          "field": "date",
          "type": "ordinal",
          "title": null,
          "axis": {
            "labelExpr": "[timeFormat(datum.value, '%b'), timeFormat(datum.value, '%m') == '01' ? timeFormat(datum.value, '%Y') : '']"
          }
        },
        "y": {"aggregate": "count", "type": "quantitative", "title": "Count"},
        "color": {
          "field": "weather",
          "type": "nominal",
          "scale": {
            "domain": ["sun", "fog", "drizzle", "rain", "snow"],
            "range": ["#e7ba52", "#c7c7c7", "#aec7e8", "#1f77b4", "#9467bd"]
          },
          "title": "weather"
        }
      }
    },
    {
      "transform": [
        {"filter": "parseFloat(timeFormat(datum.date, '%Y')) === datum.year_4"}
      ],
      "mark": {"type": "bar"},
      "encoding": {
        "x": {
          "timeUnit": "yearmonth",
          "field": "date",
          "type": "ordinal",
          "title": null,
          "axis": {
            "labelExpr": "[timeFormat(datum.value, '%b'), timeFormat(datum.value, '%m') == '01' ? timeFormat(datum.value, '%Y') : '']"
          }
        },
        "y": {"aggregate": "count", "type": "quantitative", "title": "Count"},
        "color": {
          "field": "weather",
          "type": "nominal",
          "scale": {
            "domain": ["sun", "fog", "drizzle", "rain", "snow"],
            "range": ["#e7ba52", "#c7c7c7", "#aec7e8", "#1f77b4", "#9467bd"]
          },
          "title": "weather"
        }
      }
    }
  ]
}

Here is another example where the line chart extends over a rolling 12 month window.

enter image description here

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {"url": "data/weather.csv"},
  "usermeta": {"embedOptions": {"renderer": "svg"}},
  "width": 500,
  "height": 200,
  "params": [
    {
      "name": "time",
      "on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}]
    }
  ],
  "transform": [
    {"filter": "datum.location === 'Seattle'"},
    {"filter": "datum.weather === 'rain'"},
    {"calculate": "toNumber(201200)", "as": "start_date1"},
    {"calculate": "toNumber(timeFormat(time, '%S')) % 24", "as": "sec"},
    {"calculate": "datum.sec % 24", "as": "curr_sec_temp"},
    {
      "calculate": "datum.curr_sec_temp < 12 ? (datum.curr_sec_temp) : datum.curr_sec_temp < 24 ? (datum.curr_sec_temp-12) +100 : datum.curr_sec_temp < 36 ? (datum.curr_sec_temp-24) +200 : datum.curr_sec_temp < 48 ? (datum.curr_sec_temp-36) +300 : 312",
      "as": "curr_sec_start"
    },
    {"calculate": "toNumber(datum.curr_sec_start) + 100", "as": "curr_sec_end"},
    {"calculate": "toNumber(timeFormat(datum.date, '%Y%m'))", "as": "date_num"},
    {
      "calculate": "toNumber(datum.start_date1) + toNumber(datum.curr_sec_start)",
      "as": "start_date_num"
    },
    {
      "calculate": "toNumber(datum.start_date1)+ toNumber(datum.curr_sec_end)",
      "as": "end_date_num"
    },
    {
      "filter": "datum.date_num >= datum.start_date_num && datum.date_num <= datum.end_date_num"
    },
    {"calculate": "datum.curr_sec_temp <= 24 ? 1 : 0", "as": "counter"}
  ],
  "layer": [
    {
      "mark": {"type": "area"},
      "encoding": {
        "x": {
          "timeUnit": "yearmonth",
          "field": "date",
          "type": "ordinal",
          "title": null,
          "axis": {
            "labelExpr": "[timeFormat(datum.value, '%b'), timeFormat(datum.value, '%m') == '01' ? timeFormat(datum.value, '%Y')  :'']"
          }
        },
        "y": {
          "aggregate": "sum",
          "field": "counter",
          "type": "quantitative",
          "sort": "x",
          "scale": {"domain": [0, 30]}
        },
        "size": {
          "timeUnit": "yearmonth",
          "field": "date",
          "type": "ordinal",
          "legend": null
        },
        "color": {"value": "aliceblue"}
      }
    },
    {
      "mark": {"type": "trail", "size": 2},
      "encoding": {
        "x": {
          "timeUnit": "yearmonth",
          "field": "date",
          "type": "ordinal",
          "title": null,
          "axis": {
            "labelExpr": "[timeFormat(datum.value, '%b'), timeFormat(datum.value, '%m') == '01' ? timeFormat(datum.value, '%Y')  :'']"
          }
        },
        "y": {
          "aggregate": "sum",
          "field": "counter",
          "type": "quantitative",
          "title": "Days",
          "sort": "x",
          "scale": {"domain": [0, 30]}
        },
        "size": {
          "timeUnit": "yearmonth",
          "field": "date",
          "type": "ordinal",
          "legend": null
        },
        "color": {"value": "#1f77b4"}
      }
    }
  ]
}

Happy Charting!

Adam (APB Reports)

Upvotes: 0

Views: 229

Answers (1)

APB Reports
APB Reports

Reputation: 2451

Case closed. This was a few examples for the community.

Upvotes: 0

Related Questions