Last modified: Tue Aug 29 2017 12:07:53 GMT+0800 (Malay Peninsula Standard Time)

Chapter 9. Plotting A Chart

One way of presenting data in an interactive way is to use chart. Chartkick is a gem that can take in your data and plot it into an interactive chat providing that you are sending in the correct format that it takes.

Chartkick’s website shows a great example on how to implement the chart and sample code are also included in the website. In this example, instead of using the example from the website, data conversion from array of hash to array of array will be discussed. The example of charts will be discussed in this chapter are bar chart and pie chart.

9.1 Initial Setup

To begin, add the gem chartkick to your gemfile as shown in Table 9.1.1.

Table 9.1.1: Code to add to gemfile

#MyApp/gemfile

gem ‘chartkick’

Then, add the following code as shown in Table 9.1.2 to your application layout. This is to include the required library for chartkick.

Table 9.1.2: Code to add to view

#MyApp/views/layouts/application.html.erb

<%= javascript_include_tag "http://www.google.com/jsapi", "chartkick" %>  
<%= javascript_include_tag "application", "chartkick" %>

If you are going to use more features, you may have to refer to the website to include more required libraries.

9.2 Hash and Array Explanation

Before we can begin implementing, we have to understand the difference between array and hash. The code below is an example of array of hash.

array_of_hash = [{"name"=>"aa", "job"=>"a", "pay"=> 2, ... },   
                 {"name"=>"bb", "job"=>"a", "pay"=> 4, ... },   
                 {"name"=>"cc", "job"=>"a", "pay"=> 6, ... },   
                 {"name"=>"dd", "job"=>"a", "pay"=> 8, ... },  
                 {"name"=>"ee", "job"=>"b", "pay"=> 2, ... },   
                 {"name"=>"ff", "job"=>"b", "pay"=> 4, ... },   
                 {"name"=>"gg", "job"=>"b", "pay"=> 6, ... },   
                 {"name"=>"hh", "job"=>"b", "pay"=> 9, ... }]

The code below is an example of array of array.

array_of_array = [["a", 2], ["a", 4], ["a", 6], ["a", 8],  
                  ["b", 2], ["b", 4], ["b", 6], ["b", 10]]

According to Charkick’s documentation, you are able to pass data as hash or array. However, I was unable to get array of hash to work while I was experimenting with one Web Application I wrote. You may need to do some research if you are planning to use array of hash instead of array of array that I am going to discuss.

9.3 Array of Hash to Array of Array

Based on the Daru Gem that we used in Chapter 8, we can decode the data, @output, from the Daru table and turns it into JSON format by using .to_json method. To achieve that, we can use the code below. The above be

@array_of_hash = ActiveSupport::JSON.decode(@output.to_json)

If you are not using Daru Gem and simply want to use the chart feature, the code below shows an array of hash. @array_of_hash contains all the keys and values of the hash and in the form of array.

@array_of_hash = [{"name"=>"aa", "job"=>"a", "pay"=> 2, ... },   
                  {"name"=>"bb", "job"=>"a", "pay"=> 4, ... },   
                  {"name"=>"cc", "job"=>"a", "pay"=> 6, ... },   
                  {"name"=>"dd", "job"=>"a", "pay"=> 8, ... },  
                  {"name"=>"ee", "job"=>"b", "pay"=> 2, ... },   
                  {"name"=>"ff", "job"=>"b", "pay"=> 4, ... },   
                  {"name"=>"gg", "job"=>"b", "pay"=> 6, ... },   
                  {"name"=>"hh", "job"=>"b", "pay"=> 9, ... }]

9.4 Bar Chart

The solution discussed may not be the most optimized and efficient solution. You may have an even optimal solution that can perform the same task.

We can see that there are multiple keys in the array of hash: name, job, pays, ... in @array_of_hash from Chapter 9.3. Since we are plotting bar chart we have limited options for x axis (keys). The keys that we can use as an example for x axis will be name and job (job title) while data such as pay can be used for y axis data representation. We can use the code below to extract the keys and values we want.

@array_of_hash.each { |h|   
    @sliced << [h[“name”], h[“pay”]]  
}

For Daru users, we can also choose to turn it into a single operation by using the @output we have earlier.

ActiveSupport::JSON.decode(@array_of_hash.to_json).each { |h|   
    @sliced << [h[“name”], h[“pay”]]  
}

The result of both the above operations will give us the same result. The result is shown as below.

@sliced = [["a", 2], ["a", 4], ["a", 6], ["a", 8],  
           ["b", 2], ["b", 4], ["b", 6], ["b", 10]]

The array of array @sliced now contains two keys, a key for x axis and y axis. We can now pass our data @sliced into the chart input as shown in the code below. The chart input will take care of grouping the data and show the average value based on the key you provide. The height, 1000px, can changed by replacing ti with a different value.

<%= bar_chart @sliced, height: “1000px” %>

The result of the bar chart is shown in Figure 9.4.1.


Figure 9.4.1: Bar Chart of Average Total Pay & Benefits against Job Title

9.5 Pie Chart

The solution discussed may not be the most optimized and efficient solution. You may have an even optimal solution that can perform the same task.

We can see that there are multiple keys in the array of hash: name, job, pays, ... in @array_of_hash from Chapter 9.3. We have to group the data based on the key in order to represent it in the form of pie chart. The keys that we can use as data representation of each sector will be name and job (job title) while data such as pay can be used for y axis data representation. We can use the code below to extract the keys and values we want.

@array_of_hash.each { |h|   
    @sliced << [h[“name”], h[“pay”]]  
}

For Daru users, we can also choose to turn it into a single operation by using the @output we have earlier.

ActiveSupport::JSON.decode(@array_of_hash.to_json).each { |h|   
    @sliced << [h[“name”], h[“pay”]]  
}

The result of both the above operations will give us the same result. The result is shown as below.

@sliced = [["a", 2], ["a", 4], ["a", 6], ["a", 8],  
           ["b", 2], ["b", 4], ["b", 6], ["b", 10]]

The array of array @sliced now contains two keys, a key for x axis and y axis. Then, before we can put it in the form of pie chart. There are two methods that we can use to represent the data. The first method will be get the total based on the key and the second method will be get the average based on the key.

For the first method, we can use the code below to sum up the values based on the key. The total value of each key will be computed.

@res =  @sliced.inject({}) { |h,(name, data)| h[name] ||= 0; h[name] += data; h }.to_a

The result of the operation above is shown below.

@res = [["a", 20], ["b", 22]]

Now, we can put our data into the pie chart.

<%= pie_chart @res, height: “1000px” %>

Figure 9.5.1 shows one of the example that we can obtained based on the above operation.


Figure 9.5.1: Pie Chart of Total Total Pay & Benefits by Job Title

For the second method, we have to group each of the values based the key and find the average value based on each key. This is because we are trying to show the average of each key and pie chart does not take care of it.

To group and get the average, we can use the code below.

@res = @sliced.group_by { |key, _value| key }.map do |key, list|  
                          [key, list.map(&:last).reduce(:+) / list.size.to_f]  
                        end

We first group by the value where key is what the value will be group based on. Then, .reduce(:+) is an accumulator method. The accumulator method will sum up all the values and divide the value returned by the method list.size.to_f, where the total size of the element based on each key is obtained.

The result of the operation above is shown below.

@res = [["a", 5], ["b", 5.5]]

Now, we can put our data into the pie chart.

<%= pie_chart @res, height: “1000px” %>

Figure 9.5.2 shows one of the example that we can obtained based on the above operation.


Figure 9.5.2: Pie Chart of Average Total Pay & Benefits by Job Title

results matching ""

    No results matching ""