CSC/ECE 517 Spring 2015 E1522 Visualization: Difference between revisions
(51 intermediate revisions by 4 users not shown) | |||
Line 1: | Line 1: | ||
<font size="6"><b> Expertiza - Visualization </b></font> | <font size="6"><b> Expertiza - Visualization </b></font> | ||
=Project Description= | |||
The goal of this project is to present the the data in Expertiza in a more convenient way. Through the use of charts and graphs to enhance certain pages, such as the student's scores page and the instructor's scores page, and allow for the users to get an at-a-glance analysis of the data without having to dive into the tables. | |||
Our project video https://www.youtube.com/watch?v=26jVUAyF6TA | |||
==Purpose== | ==Purpose== | ||
The purpose of this project is to add a visualization element to some of the data collected in expertiza. The aim of this is to provide a more intuitive “at-a-glance” idea of the data, some examples would be: how a student is doing on his/her assignments, or how their work compares to that of their classmates. On a less functional angle, it also enhances the aesthetics of the pages, taking the drab tables and giving them a more appealing look. | |||
=Overview of Approach= | |||
There are quite a few gems available to visualize data in Ruby on Rails, like Goolgecharts <ref>http://googlecharts.rubyforge.org/</ref> and GoogleVisualr <ref>http://googlevisualr.herokuapp.com/</ref>. These gems makes use of Google Visualization API and wrap it to let users write ruby codes to present nice charts in their web pages instead of using Javascript. | There are quite a few gems available to visualize data in Ruby on Rails, like Goolgecharts <ref>http://googlecharts.rubyforge.org/</ref> and GoogleVisualr <ref>http://googlevisualr.herokuapp.com/</ref>. These gems makes use of Google Visualization API and wrap it to let users write ruby codes to present nice charts in their web pages instead of using Javascript. | ||
===GoogleVisualr=== | ===GoogleVisualr=== | ||
GoogleVisualr is a a wrapper around the Google Chart Tools<ref>https://developers.google.com/chart/</ref> which allows users to create beautiful charts with just Ruby, instead of writing JavaScript if using the Google Chart Tools directly. | GoogleVisualr is a a wrapper around the Google Chart Tools<ref>https://developers.google.com/chart/</ref> which allows users to create beautiful charts with just Ruby, instead of writing JavaScript if using the Google Chart Tools directly. | ||
====Installing==== | |||
Installing GoogleVisualr is pretty simple. Just include the following gem in the Gemfile. | |||
<pre> | |||
gem "google_visualr", "~> 2.1.0" | |||
</pre> | |||
And in the Rails layout, load Google Ajax API in the head tag, at the very top. | |||
<pre> | |||
<script src='http://www.google.com/jsapi'></script>; | |||
</pre> | |||
====Work Flow==== | ====Work Flow==== | ||
*In your model or controller, write Ruby code to create your chart (e.g. Area Chart, Bar Chart, even Spark Lines etc). | *In your model or controller, write Ruby code to create your chart (e.g. Area Chart, Bar Chart, even Spark Lines etc). | ||
<pre> | |||
# Add Column Headers | |||
data_table.new_column('string', 'Year' ) | |||
data_table.new_column('number', 'Sales') | |||
data_table.new_column('number', 'Expenses') | |||
# Add Rows and Values | |||
data_table.add_rows([ | |||
['2004', 1000, 400], | |||
['2005', 1170, 460], | |||
['2006', 660, 1120], | |||
['2007', 1030, 540] | |||
]) | |||
</pre> | |||
*Configure your chart with any of the options as listed in Google Chart Tools' API Docs. | *Configure your chart with any of the options as listed in Google Chart Tools' API Docs. | ||
<pre> | |||
option = { width: 400, height: 240, title: 'Company Performance' }<br/> | |||
@chart = GoogleVisualr::Interactive::AreaChart.new(data_table, option) | |||
</pre> | |||
*In your view, invoke a chart.to_js(div_id) method and that will magically generate and insert JavaScript into the final HTML output. | *In your view, invoke a chart.to_js(div_id) method and that will magically generate and insert JavaScript into the final HTML output. | ||
<pre> | |||
<div id='chart'></div> | |||
<%= render_chart @chart, 'chart' %> | |||
</pre> | |||
====Chart Examples==== | |||
=====Area Chart<ref>http://googlevisualr.herokuapp.com/examples/interactive/area_chart</ref>===== | |||
The following code presents the example of area chart. | |||
<pre> | |||
# http://code.google.com/apis/chart/interactive/docs/gallery/areachart.html#Example | |||
def area_chart | |||
data_table = GoogleVisualr::DataTable.new | |||
data_table.new_column('string', 'Year') | |||
data_table.new_column('number', 'Sales') | |||
data_table.new_column('number', 'Expenses') | |||
data_table.add_rows( [ | |||
['2004', 1000, 400], | |||
['2005', 1170, 460], | |||
['2006', 660, 1120], | |||
['2007', 1030, 540] | |||
]) | |||
opts = { width: 400, height: 240, title: 'Company Performance', hAxis: {title: 'Year', titleTextStyle: {color: '#FF0000'}} } | |||
@chart = GoogleVisualr::Interactive::AreaChart.new(data_table, opts) | |||
end | |||
</pre> | |||
=====Bar Chart<ref>http://googlevisualr.herokuapp.com/examples/interactive/bar_chart</ref>===== | |||
The following code presents the example of area chart. | |||
<pre> | |||
# http://code.google.com/apis/chart/interactive/docs/gallery/barchart.html#Example | |||
def bar_chart | |||
data_table = GoogleVisualr::DataTable.new | |||
data_table.new_column('string', 'Year') | |||
data_table.new_column('number', 'Sales') | |||
data_table.new_column('number', 'Expenses') | |||
data_table.add_rows(4) | |||
data_table.set_cell(0, 0, '2004') | |||
data_table.set_cell(0, 1, 1000) | |||
data_table.set_cell(0, 2, 400) | |||
data_table.set_cell(1, 0, '2005') | |||
data_table.set_cell(1, 1, 1170) | |||
data_table.set_cell(1, 2, 460) | |||
data_table.set_cell(2, 0, '2006') | |||
data_table.set_cell(2, 1, 660) | |||
data_table.set_cell(2, 2, 1120) | |||
data_table.set_cell(3, 0, '2007') | |||
data_table.set_cell(3, 1, 1030) | |||
data_table.set_cell(3, 2, 540) | |||
opts = { :width => 400, :height => 240, :title => 'Company Performance', vAxis: {title: 'Year', titleTextStyle: {color: 'red'}} } | |||
@chart = GoogleVisualr::Interactive::BarChart.new(data_table, opts) | |||
end | |||
</pre> | |||
=====Bubble Chart<ref>http://googlevisualr.herokuapp.com/examples/interactive/bubble_chart</ref>===== | |||
The following code presents the example of area chart. | |||
<pre> | <pre> | ||
# http://code.google.com/apis/chart/interactive/docs/gallery/bubblechart.html | |||
def bubble_chart | |||
data_table = GoogleVisualr::DataTable.new | |||
data_table.new_column('string', 'ID') | |||
data_table.new_column('number', 'Life Expectancy') | |||
data_table.new_column('number', 'Fertility Rate') | |||
data_table.new_column('string', 'Region') | |||
data_table.new_column('number', 'Population') | |||
data_table.add_rows( [ | |||
['CAN', 80.66, 1.67, 'North America', 33739900], | |||
['DEU', 79.84, 1.36, 'Europe', 81902307], | |||
['DNK', 78.6, 1.84, 'Europe', 5523095], | |||
['EGY', 72.73, 2.78, 'Middle East', 79716203], | |||
['GBR', 80.05, 2, 'Europe', 61801570], | |||
['IRN', 72.49, 1.7, 'Middle East', 73137148], | |||
['IRQ', 68.09, 4.77, 'Middle East', 31090763], | |||
['ISR', 81.55, 2.96, 'Middle East', 7485600], | |||
['RUS', 68.6, 1.54, 'Europe', 141850000], | |||
['USA', 78.09, 2.05, 'North America', 307007000] | |||
]) | |||
opts = { | |||
:width => 800, :height => 500, | |||
:title => 'Correlation between life expectancy, fertility rate and population of some world countries (2010)', | |||
:hAxis => { :title => 'Life Expectancy' }, | |||
:vAxis => { :title => 'Fertility Rate' }, | |||
:bubble => { :textStyle => { :fontSize => 11 } } | |||
} | |||
@chart = GoogleVisualr::Interactive::BubbleChart.new(data_table, opts) | |||
end | |||
</pre> | </pre> | ||
The resulting chart looks like below. | |||
[[File:BubbleChart.png|center]] | |||
===GoogleCharts=== | ===GoogleCharts=== | ||
Line 52: | Line 178: | ||
=====Detail Usages===== | =====Detail Usages===== | ||
---- | ---- | ||
simple line chart: | |||
<pre> | |||
Gchart.line(:data => [0, 40, 10, 70, 20]) | |||
</pre> | |||
[[File:Simplechart.png]] | |||
bar chart: | |||
<pre> | |||
Gchart.bar(:data => [300, 100, 30, 200]) | |||
</pre> | |||
[[File:Barchart.png]] | |||
multiple bars chart: | |||
<pre> | |||
Gchart.bar(:data => [[300, 100, 30, 200], [100, 200, 300, 10]], :bar_colors => ['FF0000', '00FF00']) | |||
</pre> | |||
[[File:Multbarschart.png]] | |||
pie chart: | |||
<pre> | |||
Gchart.pie(:data => [20, 35, 45]) | |||
</pre> | |||
[[File:Piechart.png]] | |||
These usages come from http://googlecharts.rubyforge.org/. If you want to see more usages, go and visit this site. | |||
===gchartrb=== | |||
gchartrb<ref>http://code.google.com/p/gchartrb/</ref> is a Ruby wrapper around the Google chart API<ref>http://code.google.com/apis/chart/</ref>. In our project, we use gchartrb to generate all the bar charts in the visualization. | |||
====installing==== | |||
Installing gchartrb is simple, just include the gem in the Gemfile. | |||
<pre> | |||
gem 'gchartrb', :require => 'google_chart' | |||
</pre> | |||
====Examples==== | |||
=====Bar Chart===== | |||
The following example code would generate a bar chart. | |||
<pre> | |||
# Bar Chart | |||
GoogleChart::BarChart.new('800x200', "Bar Chart", :vertical, false) do |bc| | |||
bc.data "Trend 1", [5,4,3,1,3,5], '0000ff' | |||
bc.data "Trend 2", [1,2,3,4,5,6], 'ff0000' | |||
bc.data "Trend 3", [6,5,4,4,5,6], '00ff00' | |||
puts "\nBar Chart" | |||
puts bc.to_url | |||
end | |||
</pre> | |||
The bar chart would look like below. | |||
[[File:BarChart.png|center]] | |||
=====Line Chart===== | |||
The following example code would generate a line chart. | |||
<pre> | |||
# Line Chart | |||
GoogleChart::LineChart.new('320x200', "Line Chart", false) do |lc| | |||
lc.data "Trend 1", [5,4,3,1,3,5,6], '0000ff' | |||
lc.show_legend = true | |||
lc.data "Trend 2", [1,2,3,4,5,6], '00ff00' | |||
lc.data "Trend 3", [6,5,4,3,2,1], 'ff0000' | |||
lc.axis :y, :range => [0,6], :color => 'ff00ff', :font_size => 16, :alignment => :center | |||
lc.axis :x, :range => [0,6], :color => '00ffff', :font_size => 16, :alignment => :center | |||
lc.grid :x_step => 100.0/6.0, :y_step => 100.0/6.0, :length_segment => 1, :length_blank => 0 | |||
puts "\nLine Chart" | |||
puts lc.to_url | |||
end | |||
</pre> | |||
The bar chart would look like below. | |||
[[File:AeraChart.png|center]] | |||
===Circles=== | |||
---- | |||
We use the Circles lightweight JavaScript library generating circular graphs to represent the average scores expressed as percentage with animation. | |||
Here is an example of the circles we use. | |||
[[File:Circles.png|center]] | |||
For more details about the circles.js, you can refer to https://github.com/lugolabs/circles | |||
====Usage==== | |||
---- | |||
Include the circles.js or circles.min.js file in your HTML file. There are no dependencies. | |||
And create a placeholder div in your HTML: | |||
<pre> | |||
<div class="circle" id="circles-1"></div> | |||
</pre> | |||
Create a graph by calling, the id should match id of the placeholder div: | |||
<pre> | |||
var myCircle = Circles.create({ | |||
id: 'circles-1', | |||
radius: 60, | |||
value: 43, | |||
maxValue: 100, | |||
width: 10, | |||
text: function(value){return value + '%';}, | |||
colors: ['#D3B6C6', '#4B253A'], | |||
duration: 400, | |||
wrpClass: 'circles-wrp', | |||
textClass: 'circles-text' | |||
styleWrapper: true, | |||
styleText: true | |||
}); | |||
</pre> | |||
where | |||
* `id` - the DOM element that will hold the graph | |||
* `radius` - the radius of the circles | |||
* `value` - init value of the circle (optional, defaults to 0) | |||
* `maxValue` - maximum value of the circle (optional, defaults to 100) | |||
* `width` - the width of the ring (optional, has value 10, if not specified) | |||
* `colors` - an array of colors, with the first item coloring the full circle (optional, it will be `['#EEE', '#F00']` if not specified) | |||
* `duration` - value in ms of animation's duration; defaults to 500; if 0 or `null` is passed, the animation will not run. | |||
* `wrpClass` - class name to apply on the generated element wrapping the whole circle. | |||
* `textClass` - class name to apply on the generated element wrapping the text content. | |||
* `styleWrapper' - whether or not to add inline styles to the wrapper element (defaults to true) | |||
* `styleText` - whether or not to add inline styles to the text (defaults to true) | |||
* `text` - the text to display at the center of the graph (optional, the current "htmlified" value will be shown). If `null` or an empty string, no text will be displayed. | |||
API | |||
---- | |||
<pre> | |||
myCircle.updateRadius(Number radius) | |||
</pre> | |||
Regenerates the circle with the given `radius` (see `spec/responsive.html` for an example on how to create a responsive circle). | |||
<pre> | |||
myCircle.updateWidth(Number width) | |||
</pre> | |||
Regenerates the circle with the given `width` | |||
<pre> | |||
myCircle.updateColors(Array colors) | |||
</pre> | |||
Change `colors` used to draw the circle. | |||
<pre> | |||
myCircle.update(Number value [, Number duration]) | |||
</pre> | |||
Set the value of the circle to `value`. | |||
Animation will take `duration` ms to execute. If no `duration` is given, default duration set in constructor will be used. | |||
If you don't want animation, set `duration` to 0. | |||
<pre> | |||
myCircle.update(Boolean force) | |||
</pre> | |||
Force the redrawing of the circle if `force` is set to **true**. Do nothing otherwise. | |||
<pre> | |||
myCircle.getPercent() | |||
</pre> | |||
Returns the percentage value of the circle, based on its current value and its max value. | |||
<pre> | |||
myCircle.getValue() | |||
</pre> | |||
Returns the value of the circle. | |||
<pre> | |||
myCircle.getMaxValue() | |||
</pre> | |||
Returns the max value of the circle. | |||
<pre> | |||
myCircle.getValueFromPercent(Number percentage) | |||
</pre> | |||
Returns the corresponding value of the circle based on its max value and given `percentage`. | |||
<pre> | |||
myCircle.htmlifyNumber(Number number[, integerPartClass, decimalPartClass]) | |||
</pre> | |||
=Visualization in Expertiza= | |||
This section describes where in Expertiza we can use these visualizations to provide a better user experience. | |||
The 'Review Score' view of the assignments can be enhanced using these visualization. | |||
We can see by the image below that currently the scores views includes only a large table. From a user experience perspective having a more prioritized view of the scores would be beneficial. Having all the data available for the user to peruse in a table is informative, but when the user wants only to get a quick idea of how they did in an assignment, it would be helpful to have some sort of visualization. | |||
[[File:score_view.png.jpeg]] | |||
The above scoring which is in tabular form can be enhanced with charts. | |||
=Graphical Score Dashboard= | |||
The scores page was augmented with bar graphs displaying the distributions of each column, as well as a circle icon for the average score for that column. This will allow for easily determining what the reviewers thought of the work, as well as what the range of scores given. The circle graphs with the averages provide a visual for the quality of the work in each of the categories. | |||
[[File:Score_chart.png]] | |||
==New View== | |||
We created a new view under the grades views, called participant_charts. This view is included as a partial in the grades/view_my_scores view. This allows us to not modify any of the existing views and keep the code modular. | |||
==Bar Charts== | |||
For the bar charts we constructed a method that, given the score and the type of bar chart, populates an instance variable that contains the charts. The code was included in the grades controller (grades_controller.rb file) and is shown below | |||
def bar_chart(scores, type) | |||
GoogleChart::BarChart.new("100x100", " ", :vertical, false) do |bc| | |||
data = scores | |||
bc.data "Line green", data, '990000' | |||
#bc.axis :x, :positions => [0, data.size], :range => [0,100] | |||
bc.axis :y, :range => [0, data.max] ,:positions => [data.min, data.max] | |||
bc.show_legend = false | |||
bc.stacked = false | |||
bc.width_spacing_options({:bar_width => 70/(data.size+1),:bar_spacing => 1, :group_spacing => 1}) | |||
bc.data_encoding = :extended | |||
@grades_bar_charts[type.to_sym] = (bc.to_url) | |||
end | |||
end | |||
The width of the bars is dependent on the number of scores to show. Assignments with many reviews to show, require smaller bars. This is accomplished by tying the bar_width parameter, to the size of the data. | |||
==Circle Charts== | |||
For the circle charts showing the averages of the columns we used a javascript library, circle.js. By simply passing the scores to the .js code in the grades view as shown in the code below. The circle is then rendered automatically in a div block elsewhere in the view named the same as the id: tag below | |||
<script type="text/javascript"> | |||
<% ['review', 'metareview', 'feedback', 'teammate'].each do |type| %> | |||
<% if @pscore[type.to_sym][:scores][:avg]%> | |||
var myCircle = Circles.create({ | |||
id: '<%= "#{type}-circle" %>', | |||
radius: 25, | |||
value: <%= @pscore[type.to_sym][:scores][:avg].to_i %>, | |||
maxValue: 100, | |||
width: 7, | |||
text: '<%=@pscore[type.to_sym][:scores][:avg].to_i%>', | |||
colors: ['#FFEB99', '#FFCC00'], | |||
duration: 700, | |||
textClass: 'circles-text' | |||
}); | |||
==Show / Hide stats== | |||
The user might want to hide the stats, with that in mind we included a button to toggle the visibility of the charts. Making use of an existing function, toggleElement, we added a link above the charts table that when clicked hides/shows the charts. The code to accomplish this is shown below | |||
<a href="#" name='score-chartLink' onClick="toggleElement('score-chart', 'stats');return false;">hide stats</a> | |||
=Reliability Metric= | |||
Based on the uniformity of the review scores, we compiled a reliability metric. This metric encapsulates the level of agreement between the reviews, and should provide a quick at a glance notion of whether reviewers agree on the scoring for the particular assignment, or whether there is a high variance in the scores given. A good reliability score indicates that the grade given to the assignment by the reviewers is to be trusted, whereas a poor reliability score indicates that there was a high level of disagreement in the reviewers and the instructors should perhaps take a closer look at the participant's assignment. | |||
This reliability score is computed from the standard deviation of the review scores. A standard deviation that's less than 10 will award a good reliability score. A standard deviation between 10 and 20 will award a medium reliability score, whereas a standard deviation greater than 20 will give a poor reliability score. | |||
===Different Icon colors=== | |||
[[File:Green_icon.png]] | |||
The color of the three bars Icon, and the number of filled bars is representative of the reliability of the reviews. | |||
Take the case of the green sample icon in the image above, the reviews mostly all agree. Whereas in the following two images, the icon is yellow and red respectively to signify increasingly worrying levels of disparity in review scores. | |||
[[File:Yellow_icon.png]] | |||
[[File:Red_icon.png]] | |||
A similar method to the one used for the bar charts was used. In this case, a horizontal bar chart was created, and the data was dictated by the qualitative score that was passed into the method. This score could be 'good', 'medium' or 'bad'. Based on this string argument the graph is created with the correct number of bars and the correct color. | |||
def reliability_chart(score,type) | |||
GoogleChart::BarChart.new("25x20", " ", :horizontal, false) do |bc| | |||
if score == 'good' | |||
data = [1,1,1] | |||
color = '00ff00' | |||
elsif score == 'medium' | |||
data = [1,1] | |||
color = 'FFCC00' | |||
else | |||
data = [1] | |||
color = '990000' | |||
end | |||
bc.data "Reliability Symbol", data, color | |||
bc.show_legend = false | |||
bc.stacked = false | |||
bc.width_spacing_options({:bar_width => 5,:bar_spacing => 10, :group_spacing => 1}) | |||
bc.data_encoding = :extended | |||
@grades_bar_charts[type.to_sym] = (bc.to_url) | |||
end | |||
end | |||
=Instructor View= | |||
In the instructor view of the assignment scores we added similar charts to the one shown for students. | |||
In this case we include a class average in the form of a circle chart, and a class distribution in the form of a bar chart. An example of this is shown below | |||
[[File:Instructor_viz.png]] | |||
==Reference== | ==Reference== | ||
<references/> | <references/> |
Latest revision as of 04:13, 5 May 2015
Expertiza - Visualization
Project Description
The goal of this project is to present the the data in Expertiza in a more convenient way. Through the use of charts and graphs to enhance certain pages, such as the student's scores page and the instructor's scores page, and allow for the users to get an at-a-glance analysis of the data without having to dive into the tables.
Our project video https://www.youtube.com/watch?v=26jVUAyF6TA
Purpose
The purpose of this project is to add a visualization element to some of the data collected in expertiza. The aim of this is to provide a more intuitive “at-a-glance” idea of the data, some examples would be: how a student is doing on his/her assignments, or how their work compares to that of their classmates. On a less functional angle, it also enhances the aesthetics of the pages, taking the drab tables and giving them a more appealing look.
Overview of Approach
There are quite a few gems available to visualize data in Ruby on Rails, like Goolgecharts <ref>http://googlecharts.rubyforge.org/</ref> and GoogleVisualr <ref>http://googlevisualr.herokuapp.com/</ref>. These gems makes use of Google Visualization API and wrap it to let users write ruby codes to present nice charts in their web pages instead of using Javascript.
GoogleVisualr
GoogleVisualr is a a wrapper around the Google Chart Tools<ref>https://developers.google.com/chart/</ref> which allows users to create beautiful charts with just Ruby, instead of writing JavaScript if using the Google Chart Tools directly.
Installing
Installing GoogleVisualr is pretty simple. Just include the following gem in the Gemfile.
gem "google_visualr", "~> 2.1.0"
And in the Rails layout, load Google Ajax API in the head tag, at the very top.
<script src='http://www.google.com/jsapi'></script>;
Work Flow
- In your model or controller, write Ruby code to create your chart (e.g. Area Chart, Bar Chart, even Spark Lines etc).
# Add Column Headers data_table.new_column('string', 'Year' ) data_table.new_column('number', 'Sales') data_table.new_column('number', 'Expenses') # Add Rows and Values data_table.add_rows([ ['2004', 1000, 400], ['2005', 1170, 460], ['2006', 660, 1120], ['2007', 1030, 540] ])
- Configure your chart with any of the options as listed in Google Chart Tools' API Docs.
option = { width: 400, height: 240, title: 'Company Performance' }<br/> @chart = GoogleVisualr::Interactive::AreaChart.new(data_table, option)
- In your view, invoke a chart.to_js(div_id) method and that will magically generate and insert JavaScript into the final HTML output.
<div id='chart'></div> <%= render_chart @chart, 'chart' %>
Chart Examples
Area Chart<ref>http://googlevisualr.herokuapp.com/examples/interactive/area_chart</ref>
The following code presents the example of area chart.
# http://code.google.com/apis/chart/interactive/docs/gallery/areachart.html#Example def area_chart data_table = GoogleVisualr::DataTable.new data_table.new_column('string', 'Year') data_table.new_column('number', 'Sales') data_table.new_column('number', 'Expenses') data_table.add_rows( [ ['2004', 1000, 400], ['2005', 1170, 460], ['2006', 660, 1120], ['2007', 1030, 540] ]) opts = { width: 400, height: 240, title: 'Company Performance', hAxis: {title: 'Year', titleTextStyle: {color: '#FF0000'}} } @chart = GoogleVisualr::Interactive::AreaChart.new(data_table, opts) end
Bar Chart<ref>http://googlevisualr.herokuapp.com/examples/interactive/bar_chart</ref>
The following code presents the example of area chart.
# http://code.google.com/apis/chart/interactive/docs/gallery/barchart.html#Example def bar_chart data_table = GoogleVisualr::DataTable.new data_table.new_column('string', 'Year') data_table.new_column('number', 'Sales') data_table.new_column('number', 'Expenses') data_table.add_rows(4) data_table.set_cell(0, 0, '2004') data_table.set_cell(0, 1, 1000) data_table.set_cell(0, 2, 400) data_table.set_cell(1, 0, '2005') data_table.set_cell(1, 1, 1170) data_table.set_cell(1, 2, 460) data_table.set_cell(2, 0, '2006') data_table.set_cell(2, 1, 660) data_table.set_cell(2, 2, 1120) data_table.set_cell(3, 0, '2007') data_table.set_cell(3, 1, 1030) data_table.set_cell(3, 2, 540) opts = { :width => 400, :height => 240, :title => 'Company Performance', vAxis: {title: 'Year', titleTextStyle: {color: 'red'}} } @chart = GoogleVisualr::Interactive::BarChart.new(data_table, opts) end
Bubble Chart<ref>http://googlevisualr.herokuapp.com/examples/interactive/bubble_chart</ref>
The following code presents the example of area chart.
# http://code.google.com/apis/chart/interactive/docs/gallery/bubblechart.html def bubble_chart data_table = GoogleVisualr::DataTable.new data_table.new_column('string', 'ID') data_table.new_column('number', 'Life Expectancy') data_table.new_column('number', 'Fertility Rate') data_table.new_column('string', 'Region') data_table.new_column('number', 'Population') data_table.add_rows( [ ['CAN', 80.66, 1.67, 'North America', 33739900], ['DEU', 79.84, 1.36, 'Europe', 81902307], ['DNK', 78.6, 1.84, 'Europe', 5523095], ['EGY', 72.73, 2.78, 'Middle East', 79716203], ['GBR', 80.05, 2, 'Europe', 61801570], ['IRN', 72.49, 1.7, 'Middle East', 73137148], ['IRQ', 68.09, 4.77, 'Middle East', 31090763], ['ISR', 81.55, 2.96, 'Middle East', 7485600], ['RUS', 68.6, 1.54, 'Europe', 141850000], ['USA', 78.09, 2.05, 'North America', 307007000] ]) opts = { :width => 800, :height => 500, :title => 'Correlation between life expectancy, fertility rate and population of some world countries (2010)', :hAxis => { :title => 'Life Expectancy' }, :vAxis => { :title => 'Fertility Rate' }, :bubble => { :textStyle => { :fontSize => 11 } } } @chart = GoogleVisualr::Interactive::BubbleChart.new(data_table, opts) end
The resulting chart looks like below.
GoogleCharts
Googlecharts is a ruby gem implements a wrapper for Google Chart API. It is fully tested using RSpec.
Usage
Installing
gem install googlecharts
Example in Ruby on Rails
Controller:
@line_chart = Gchart.line(:data => [1, 2, 3, 4, 5])
View:
<%= image_tag(@line_chart) %>
Basic Usages
require ‘gchart’
Gchart.line(:size => ‘200*200’, :title => “title”, :bg => ‘efefef’, :legend => :data => [1, 2, 3, 4, 5])
Detail Usages
simple line chart:
Gchart.line(:data => [0, 40, 10, 70, 20])
bar chart:
Gchart.bar(:data => [300, 100, 30, 200])
multiple bars chart:
Gchart.bar(:data => [[300, 100, 30, 200], [100, 200, 300, 10]], :bar_colors => ['FF0000', '00FF00'])
pie chart:
Gchart.pie(:data => [20, 35, 45])
These usages come from http://googlecharts.rubyforge.org/. If you want to see more usages, go and visit this site.
gchartrb
gchartrb<ref>http://code.google.com/p/gchartrb/</ref> is a Ruby wrapper around the Google chart API<ref>http://code.google.com/apis/chart/</ref>. In our project, we use gchartrb to generate all the bar charts in the visualization.
installing
Installing gchartrb is simple, just include the gem in the Gemfile.
gem 'gchartrb', :require => 'google_chart'
Examples
Bar Chart
The following example code would generate a bar chart.
# Bar Chart GoogleChart::BarChart.new('800x200', "Bar Chart", :vertical, false) do |bc| bc.data "Trend 1", [5,4,3,1,3,5], '0000ff' bc.data "Trend 2", [1,2,3,4,5,6], 'ff0000' bc.data "Trend 3", [6,5,4,4,5,6], '00ff00' puts "\nBar Chart" puts bc.to_url end
The bar chart would look like below.
Line Chart
The following example code would generate a line chart.
# Line Chart GoogleChart::LineChart.new('320x200', "Line Chart", false) do |lc| lc.data "Trend 1", [5,4,3,1,3,5,6], '0000ff' lc.show_legend = true lc.data "Trend 2", [1,2,3,4,5,6], '00ff00' lc.data "Trend 3", [6,5,4,3,2,1], 'ff0000' lc.axis :y, :range => [0,6], :color => 'ff00ff', :font_size => 16, :alignment => :center lc.axis :x, :range => [0,6], :color => '00ffff', :font_size => 16, :alignment => :center lc.grid :x_step => 100.0/6.0, :y_step => 100.0/6.0, :length_segment => 1, :length_blank => 0 puts "\nLine Chart" puts lc.to_url end
The bar chart would look like below.
Circles
We use the Circles lightweight JavaScript library generating circular graphs to represent the average scores expressed as percentage with animation.
Here is an example of the circles we use.
For more details about the circles.js, you can refer to https://github.com/lugolabs/circles
Usage
Include the circles.js or circles.min.js file in your HTML file. There are no dependencies.
And create a placeholder div in your HTML:
<div class="circle" id="circles-1"></div>
Create a graph by calling, the id should match id of the placeholder div:
var myCircle = Circles.create({ id: 'circles-1', radius: 60, value: 43, maxValue: 100, width: 10, text: function(value){return value + '%';}, colors: ['#D3B6C6', '#4B253A'], duration: 400, wrpClass: 'circles-wrp', textClass: 'circles-text' styleWrapper: true, styleText: true });
where
- `id` - the DOM element that will hold the graph
- `radius` - the radius of the circles
- `value` - init value of the circle (optional, defaults to 0)
- `maxValue` - maximum value of the circle (optional, defaults to 100)
- `width` - the width of the ring (optional, has value 10, if not specified)
- `colors` - an array of colors, with the first item coloring the full circle (optional, it will be `['#EEE', '#F00']` if not specified)
- `duration` - value in ms of animation's duration; defaults to 500; if 0 or `null` is passed, the animation will not run.
- `wrpClass` - class name to apply on the generated element wrapping the whole circle.
- `textClass` - class name to apply on the generated element wrapping the text content.
- `styleWrapper' - whether or not to add inline styles to the wrapper element (defaults to true)
- `styleText` - whether or not to add inline styles to the text (defaults to true)
- `text` - the text to display at the center of the graph (optional, the current "htmlified" value will be shown). If `null` or an empty string, no text will be displayed.
API
myCircle.updateRadius(Number radius)
Regenerates the circle with the given `radius` (see `spec/responsive.html` for an example on how to create a responsive circle).
myCircle.updateWidth(Number width)
Regenerates the circle with the given `width`
myCircle.updateColors(Array colors)
Change `colors` used to draw the circle.
myCircle.update(Number value [, Number duration])
Set the value of the circle to `value`. Animation will take `duration` ms to execute. If no `duration` is given, default duration set in constructor will be used. If you don't want animation, set `duration` to 0.
myCircle.update(Boolean force)
Force the redrawing of the circle if `force` is set to **true**. Do nothing otherwise.
myCircle.getPercent()
Returns the percentage value of the circle, based on its current value and its max value.
myCircle.getValue()
Returns the value of the circle.
myCircle.getMaxValue()
Returns the max value of the circle.
myCircle.getValueFromPercent(Number percentage)
Returns the corresponding value of the circle based on its max value and given `percentage`.
myCircle.htmlifyNumber(Number number[, integerPartClass, decimalPartClass])
Visualization in Expertiza
This section describes where in Expertiza we can use these visualizations to provide a better user experience. The 'Review Score' view of the assignments can be enhanced using these visualization.
We can see by the image below that currently the scores views includes only a large table. From a user experience perspective having a more prioritized view of the scores would be beneficial. Having all the data available for the user to peruse in a table is informative, but when the user wants only to get a quick idea of how they did in an assignment, it would be helpful to have some sort of visualization.
The above scoring which is in tabular form can be enhanced with charts.
Graphical Score Dashboard
The scores page was augmented with bar graphs displaying the distributions of each column, as well as a circle icon for the average score for that column. This will allow for easily determining what the reviewers thought of the work, as well as what the range of scores given. The circle graphs with the averages provide a visual for the quality of the work in each of the categories.
New View
We created a new view under the grades views, called participant_charts. This view is included as a partial in the grades/view_my_scores view. This allows us to not modify any of the existing views and keep the code modular.
Bar Charts
For the bar charts we constructed a method that, given the score and the type of bar chart, populates an instance variable that contains the charts. The code was included in the grades controller (grades_controller.rb file) and is shown below
def bar_chart(scores, type) GoogleChart::BarChart.new("100x100", " ", :vertical, false) do |bc| data = scores bc.data "Line green", data, '990000' #bc.axis :x, :positions => [0, data.size], :range => [0,100] bc.axis :y, :range => [0, data.max] ,:positions => [data.min, data.max] bc.show_legend = false bc.stacked = false bc.width_spacing_options({:bar_width => 70/(data.size+1),:bar_spacing => 1, :group_spacing => 1}) bc.data_encoding = :extended @grades_bar_charts[type.to_sym] = (bc.to_url) end end
The width of the bars is dependent on the number of scores to show. Assignments with many reviews to show, require smaller bars. This is accomplished by tying the bar_width parameter, to the size of the data.
Circle Charts
For the circle charts showing the averages of the columns we used a javascript library, circle.js. By simply passing the scores to the .js code in the grades view as shown in the code below. The circle is then rendered automatically in a div block elsewhere in the view named the same as the id: tag below
<script type="text/javascript"> <% ['review', 'metareview', 'feedback', 'teammate'].each do |type| %> <% if @pscore[type.to_sym][:scores][:avg]%> var myCircle = Circles.create({ id: '<%= "#{type}-circle" %>', radius: 25, value: <%= @pscore[type.to_sym][:scores][:avg].to_i %>, maxValue: 100, width: 7, text: '<%=@pscore[type.to_sym][:scores][:avg].to_i%>', colors: ['#FFEB99', '#FFCC00'], duration: 700, textClass: 'circles-text' });
Show / Hide stats
The user might want to hide the stats, with that in mind we included a button to toggle the visibility of the charts. Making use of an existing function, toggleElement, we added a link above the charts table that when clicked hides/shows the charts. The code to accomplish this is shown below
<a href="#" name='score-chartLink' onClick="toggleElement('score-chart', 'stats');return false;">hide stats</a>
Reliability Metric
Based on the uniformity of the review scores, we compiled a reliability metric. This metric encapsulates the level of agreement between the reviews, and should provide a quick at a glance notion of whether reviewers agree on the scoring for the particular assignment, or whether there is a high variance in the scores given. A good reliability score indicates that the grade given to the assignment by the reviewers is to be trusted, whereas a poor reliability score indicates that there was a high level of disagreement in the reviewers and the instructors should perhaps take a closer look at the participant's assignment. This reliability score is computed from the standard deviation of the review scores. A standard deviation that's less than 10 will award a good reliability score. A standard deviation between 10 and 20 will award a medium reliability score, whereas a standard deviation greater than 20 will give a poor reliability score.
Different Icon colors
The color of the three bars Icon, and the number of filled bars is representative of the reliability of the reviews. Take the case of the green sample icon in the image above, the reviews mostly all agree. Whereas in the following two images, the icon is yellow and red respectively to signify increasingly worrying levels of disparity in review scores.
A similar method to the one used for the bar charts was used. In this case, a horizontal bar chart was created, and the data was dictated by the qualitative score that was passed into the method. This score could be 'good', 'medium' or 'bad'. Based on this string argument the graph is created with the correct number of bars and the correct color.
def reliability_chart(score,type) GoogleChart::BarChart.new("25x20", " ", :horizontal, false) do |bc| if score == 'good' data = [1,1,1] color = '00ff00' elsif score == 'medium' data = [1,1] color = 'FFCC00' else data = [1] color = '990000' end bc.data "Reliability Symbol", data, color bc.show_legend = false bc.stacked = false bc.width_spacing_options({:bar_width => 5,:bar_spacing => 10, :group_spacing => 1}) bc.data_encoding = :extended @grades_bar_charts[type.to_sym] = (bc.to_url) end end
Instructor View
In the instructor view of the assignment scores we added similar charts to the one shown for students. In this case we include a class average in the form of a circle chart, and a class distribution in the form of a bar chart. An example of this is shown below
Reference
<references/>