Giter Club home page Giter Club logo

vega-ruby's Introduction

Vega.rb

Interactive charts for Ruby, powered by Vega and Vega-Lite

See it in action

Works with Rails, iRuby, and other frameworks

Build Status

Installation

Add this line to your application’s Gemfile:

gem "vega"

Then follow the instructions for how you plan to use it:

Importmap

Add to config/importmap.rb:

pin "vega", to: "vega.js"
pin "vega-lite", to: "vega-lite.js"
pin "vega-embed", to: "vega-embed.js"

And add to app/javascript/application.js:

import "vega"
import "vega-lite"
import "vega-embed"

window.dispatchEvent(new Event("vega:load"))

esbuild or Webpack

Run:

yarn add vega vega-lite vega-embed

And add to app/javascript/application.js:

import embed from "vega-embed"

window.vegaEmbed = embed
window.dispatchEvent(new Event("vega:load"))

Webpacker

Run:

yarn add vega vega-lite vega-embed

And add to app/javascript/packs/application.js:

window.vegaEmbed = require("vega-embed").default

Sprockets

Add to app/assets/javascripts/application.js:

//= require vega
//= require vega-lite
//= require vega-embed

iRuby

No additional set up is needed.

Other

For Sinatra and other web frameworks, download Vega, Vega-Lite, and Vega-Embed and include them on pages with charts:

<script src="vega.js"></script>
<script src="vega-lite.js"></script>
<script src="vega-embed.js"></script>

Getting Started

Vega is a visualization grammar, and Vega-Lite is a high-level grammar built on top of it. We recommend using Vega-Lite by default and moving to Vega for advanced use cases.

Create visualizations by chaining together methods:

Vega.lite.data(data).mark("bar").height(200)

There are methods for each of the top-level properties. The docs are a great source of examples:

Example

Create a bar chart

Vega.lite
  .data([{city: "A", sales: 28}, {city: "B", sales: 55}, {city: "C", sales: 43}])
  .mark(type: "bar", tooltip: true)
  .encoding(
    x: {field: "city", type: "nominal"},
    y: {field: "sales", type: "quantitative"}
  )

The chart will automatically render in iRuby. For Rails, render it in your view:

<%= Vega.lite.data(...) %>

Vega-Lite

Start a Vega-Lite chart with:

Vega.lite

Data

Docs

Data can be an array

data([{x: "A", y: 1}, {x: "B", y: 2}])

Or a URL

data("https://www.example.com/data.json")

Or a Rover data frame

data(df)

Or a data generator

data(sequence: {start: 0, stop: 10, step: 1, as: "x"})

Transforms

Docs

transform(bin: true, field: "a", as: "binned a")

Marks

Docs

Bar chart

mark("bar")

Line chart

mark("line")

Pie chart

mark("pie")

Area chart

mark("area")

Enable tooltips

mark(type: "bar", tooltip: true)

Encoding

Docs

encoding(x: {field: "a", type: "ordinal"})

Projection

Docs

projection(type: "albersUsa")

View Composition

Docs

Faceting

facet(row: {field: "x"})

Layering

layer(view)

Concatenation

hconcat(view)
vconcat(view)
concat(view)

Repeating

repeat(row: ["a", "b", "c"])

Resolving

resolve(scale: {color: "independent"})

Selections

Docs

selection(x: {type: "single"})

Parameters

Docs

params(name: "cornerRadius", value: 5)

Config

Docs

Set the font

config(font: "Helvetica")

Top-Level Properties

Docs

Set width and height

width(500).height(300)

Set the background color

background("#000")

Set padding

padding(5)
# or
padding(left: 5, top: 5, right: 5, bottom: 5)

Embed Options

Docs

Set embed options

embed_options(actions: true)

Vega

You can also use Vega directly. In this case, you don’t need to include Vega-Lite in the JavaScript files.

Start a Vega chart with:

Vega.start

Spec

You can also create a specification by hand

spec = {
  "$schema" => "https://vega.github.io/schema/vega-lite/v5.json",
  "data" => {"url" => "https://www.example.com"},
  # ...
}

And render it in Rails

<%= vega_chart spec %>

Or display it in iRuby

Vega.display(spec)

Get the spec for a chart

chart.spec

Exporting Charts (experimental)

Export charts to PNG, SVG, or PDF. This requires Node.js and npm 7+. Run:

yarn add vega-cli vega-lite

For PNG, use:

File.binwrite("chart.png", chart.to_png)

For SVG, use:

File.binwrite("chart.svg", chart.to_svg)

For PDF, use:

File.binwrite("chart.pdf", chart.to_pdf)

Content Security Policy (CSP)

Styles and Frames

Enable unsafe inline styles and blob frames on actions that have charts

class ChartsController < ApplicationController
  content_security_policy only: :index do |policy|
    policy.style_src :self, :unsafe_inline
    policy.frame_src :blob
  end
end

Nonce

Automatically add a nonce when configured in Rails with:

<%= vega_chart chart %>

Interpreter

By default, the Vega parser uses the Function constructor, which can cause issues with CSP.

For Importmap, add to config/importmap.rb:

pin "vega-interpreter", to: "vega-interpreter.js"

And add to app/javascript/application.js:

import "vega-interpreter"

For Webpacker, run:

yarn add vega-interpreter

For Sprockets, add to app/assets/javascripts/application.js:

//= require vega-interpreter

And set embed options for your charts

embed_options(ast: true)

History

View the changelog

Contributing

Everyone is encouraged to help improve this project. Here are a few ways you can help:

To get started with development:

git clone https://github.com/ankane/vega-ruby.git
cd vega-ruby
bundle install
bundle exec rake test

Resources for contributors:

vega-ruby's People

Contributors

ankane avatar dorianmariecom avatar sebastianszturo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

vega-ruby's Issues

Error trying to create the example Vega.lite bar chart in IRuby Jupyter notebook

Notebook command:

Vega.lite
  .data([{city: "A", sales: 28}, {city: "B", sales: 55}, {city: "C", sales: 43}])
  .mark(type: "bar", tooltip: true)
  .encoding(
    x: {field: "city", type: "nominal"},
    y: {field: "sales", type: "quantitative"}
  )

Error in notebook:

RuntimeError: Command failed: npm ERR! canceled

npm ERR! A complete log of this run can be found in:
npm ERR!     ~/.npm/_logs/2021-12-21T01_46_21_620Z-debug.log

~/.rvm/gems/ruby-2.6.6/gems/vega-0.2.3/lib/vega/base_chart.rb:65:in `export'
~/.rvm/gems/ruby-2.6.6/gems/vega-0.2.3/lib/vega/lite_chart.rb:38:in `to_svg'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/display.rb:279:in `block in <module:Registry>'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/display.rb:105:in `render'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/display.rb:61:in `block in render'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/display.rb:60:in `each'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/display.rb:60:in `render'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/display.rb:23:in `display'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/kernel.rb:100:in `execute_request'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/kernel.rb:49:in `dispatch'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/kernel.rb:38:in `run'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/command.rb:110:in `run_kernel'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/lib/iruby/command.rb:40:in `run'
~/.rvm/gems/ruby-2.6.6/gems/iruby-0.4.0/bin/iruby:5:in `<top (required)>'
~/.rvm/gems/ruby-2.6.6/bin/iruby:23:in `load'
~/.rvm/gems/ruby-2.6.6/bin/iruby:23:in `<main>'
~/.rvm/gems/ruby-2.6.6/bin/ruby_executable_hooks:24:in `eval'
~/.rvm/gems/ruby-2.6.6/bin/ruby_executable_hooks:24:in `<main>'

Contents of '2021-12-21T01_46_21_620Z-debug.log':

0 verbose cli [
0 verbose cli   '/usr/local/Cellar/node/17.2.0/bin/node',
0 verbose cli   '/usr/local/bin/npm',
0 verbose cli   'exec',
0 verbose cli   '--no',
0 verbose cli   '--package=vega-lite',
0 verbose cli   '--',
0 verbose cli   'vl2svg'
0 verbose cli ]
1 info using [email protected]
2 info using [email protected]
3 timing npm:load:whichnode Completed in 0ms
4 timing config:load:defaults Completed in 1ms
5 timing config:load:file:/usr/local/lib/node_modules/npm/npmrc Completed in 1ms
6 timing config:load:builtin Completed in 1ms
7 timing config:load:cli Completed in 2ms
8 timing config:load:env Completed in 0ms
9 timing config:load:file:~/repos/app/.npmrc Completed in 1ms
10 timing config:load:project Completed in 2ms
11 timing config:load:file:~/.npmrc Completed in 0ms
12 timing config:load:user Completed in 0ms
13 timing config:load:file:/usr/local/etc/npmrc Completed in 0ms
14 timing config:load:global Completed in 0ms
15 timing config:load:validate Completed in 0ms
16 timing config:load:credentials Completed in 1ms
17 timing config:load:setEnvs Completed in 1ms
18 timing config:load Completed in 8ms
19 timing npm:load:configload Completed in 8ms
20 timing npm:load:setTitle Completed in 2ms
21 timing npm:load:setupLog Completed in 1ms
22 timing config:load:flatten Completed in 2ms
23 timing npm:load:cleanupLog Completed in 2ms
24 timing npm:load:configScope Completed in 0ms
25 timing npm:load:projectScope Completed in 0ms
26 timing npm:load Completed in 16ms
27 http fetch GET 200 https://registry.npmjs.org/vega-lite 126ms (cache revalidated)
28 timing arborist:ctor Completed in 1ms
29 timing arborist:ctor Completed in 0ms
30 timing command:exec Completed in 884ms
31 verbose stack Error: canceled
31 verbose stack     at exec (/usr/local/lib/node_modules/npm/node_modules/libnpmexec/lib/index.js:154:17)
31 verbose stack     at async module.exports (/usr/local/lib/node_modules/npm/lib/cli.js:65:5)
32 verbose cwd ~/repos/app/console
33 verbose Darwin 20.6.0
34 verbose argv "/usr/local/Cellar/node/17.2.0/bin/node" "/usr/local/bin/npm" "exec" "--no" "--package=vega-lite" "--" "vl2svg"
35 verbose node v17.2.0
36 verbose npm  v8.1.4
37 error canceled
38 verbose exit 1

Example Vega.lite bar chart does not render in IRuby Jupyter notebook

iruby 0.7.4
ruby 3.0.4
vega-ruby 0.2.6
jupyter lab 3.3.2

Notebook command:

Vega.lite
  .data([{city: "A", sales: 28}, {city: "B", sales: 55}, {city: "C", sales: 43}])
  .mark(type: "bar", tooltip: true)
  .encoding(
    x: {field: "city", type: "nominal"},
    y: {field: "sales", type: "quantitative"}
  )

vega-ruby creates html code

Bildschirmfoto 2022-06-20 um 23 16 34

html code is not rendered in jupyter lab

Bildschirmfoto 2022-06-20 um 23 16 46

This might be an issue of jupyterlab? Daruview with googlecharts renders fine.

Ideas

Ideas

  • Add support for importmap-rails - importmap branch (need to handle async loading)
  • Add support for exporting charts to PNG, SVG, and PDF
  • Support JupyterLab
  • Support data from Groupdate (use x and y for names?)
  • (probably not) Add default options for each chart type
    Vega.lite.default_options = Vega.lite.config(...).embed_options(...).background(...)

layer usage example

Hi,
first of all, thanks for the Gem, really clean and useful.

I am trying to use =layer=s and I am a bit lost on what to pass as argument. I tried to look at the code, to no avail.

Consider the following excerpt (from the Vega Light website):

  "layer": [{
    "mark": "bar"
    },
   {
    "mark": {
      "type": "text",
      "align": "left",
      "baseline": "middle",
      "dx": 3
    },
    "encoding": {
      "text": {"field": "b", "type": "quantitative"}
    }
  }]
}

when representing in Ruby, I thought I could do something like:

.layer([
   Vega.lite.mark( { type: "bar" }),
   Vega.lite.mark
   ...
])

but it does not work.

Any help really appreciated it.
Thanks again!

`Uncaught ReferenceError: vegaEmbed is not defined` (even though Vega's js is loaded)

Screenshot 2021-10-23 at 12 30 15

Screenshot 2021-10-23 at 12 29 36

Maybe related to Turbo, not sure, it happens when navigating to the page with charts from the homepage

= javascript_include_tag "admin", "data-turbo-track": "reload"

h1= t(".attendances")

= raw Stl.plot(Attendance.before_today.group_by_day(:created_at).count, Stl.decompose(Attendance.before_today.group_by_day(:created_at).count, period: 7))

h1(style="margin-top: 280px")= t(".users")

= raw Stl.plot(User.before_today.after_import.group_by_day(:created_at).count, Stl.decompose(User.before_today.after_import.group_by_day(:created_at).count, period: 7))

and in admin.js

//= require vega
//= require vega-lite
//= require vega-embed

How to configure a spec and data separately?

The docs describe how to make API calls to set the data and then build up the chart configuration. Separately a whole chart can be configured using a Vega spec, which includes a data location.

Is there a way to configure a chart using a Vega spec, but make an API call to independently set the data?

Thanks!

Add instruction to include to bridgetown

The gem works wonderful! Thanks for building it.

I just included it into a (static) Bridgetown-page.

Its worth to include the steps in the description

  • include gem 'vega' in Gemfile
  • include require 'vega' in config/initializers. No plugin needed.
  • use the instructions for rails7/esconfig and implement in frontend/javascript/config.js
  • vega-Objects can be defined in frontmatter

Example for the frontmatter-approach

~~~ruby
{ 
  layout:  :home,
  title:  'Übersicht',
  vega:  Vega.lite .data([{city: "A", sales: 28}, {city: "B", sales: 55}, {city: "C", sales: 43}])
                   .mark(type: "bar", tooltip: true)
                   .encoding( x: {field: "city", type: "nominal"},
                   y: {field: "sales", type: "quantitative"}) 
}
~~~

# title
<%=  data.vega %>

In my impression, this is the easiest way to setup an example-page.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.