Rubyvis - Example: Parallel Coordinates

Parallel coordinates is a popular method of visualizing high-dimensional data using dynamic queries.
On static setting, you could choose an attribute and colour each datum which belongs to an attribute differently. On this example, we choose to color :cylinders attribute and highlight the cars with 8 cylinders

require 'rubyvis'
load(File.dirname(__FILE__)+"/cars_data.rb")
attr_to_color=:cylinders
highlighted=lambda {|d|
  d[:cylinders].to_i==8
}

dims = [
  :cylinders,
  :displacement,
  :weight,
  :horsepower,
  :acceleration,
  :mpg,
  :year,
  :origin
];

# Sizing and scales. */
w = 840
h = 420
color = Rubyvis.Colors.category10()
car_color = Rubyvis.Colors.category10()
x = Rubyvis.Scale.ordinal(dims).split_flush(0, w)
y = Rubyvis.dict(dims, lambda {|t|
    Rubyvis.Scale.linear().
      domain($cars.find_all {|d| !d[t].nil?} ,
        lambda {|d| d[t]}).range(0, h)
    })

#/* The root panel. */
vis=Rubyvis::Panel.new do 
  width w 
  height h 
  margin 20 
  bottom 40 
  # Rule and labels per dimension
  rule do 
    data(dims)
    left(x)
    stroke_style(lambda {|d| color.scale(index)})
    line_width(2)
    # Min value
    label(:anchor=>'bottom') do
      text {|t|
        y[t].tick_format.call(y[t].domain()[0])
      }
    end
    # Max value
    label(:anchor=>'top') do
      text {
        |t| y[t].tick_format.call(y[t].domain()[1])
      }
    end
    # Dim name
    label(:anchor=>'bottom') do
      text_style {color.scale(index).darker}
      text_margin 14
    end
  end
  # Parallel coordinates.
  panel do
    # Each car generate a panel
    data($cars)
    line do
      # Inside each car, every dimension generate a point
      data(dims)
      left {|t, d| x.scale(t)}
      bottom {|t, d|  y[t].scale(d[t])}
      line_width {|t,d| 
        highlighted.call(d) ? 4 : 1
      }
      stroke_style {|t,d|
        # Highlighted items will be opaquer
        alpha=highlighted.call(d) ? 0.4 : 0.1
        car_color.scale(d[attr_to_color]).alpha(alpha)
      }
      line_width(1)
    end
  end
end


vis.render()
puts vis.to_svg