Create a Chart.js Bar Chart Directly From a CSV File

Use Chart.js with CSV files

Javascript Charts Using CSV

Creating charts for your website or web app today is easier than ever. There are a number of great Javascript charting libraries out there which provide good documentation and many examples, such as Chart.js, D3.js, Highcharts, Plotly.js, Chartist and Victory.

However, almost all of these charts are created using a JSON object for configuration as well as the dataset. This is fine as long as your data is stored in local JSON files or available as a JSON object from a REST API, but what if your data is stored externally in a tabular format, such as a CSV file?

Thankfully, there is a solution. This tutorial will provide you with a quick example of how to utilize the Flex.io API to grab a CSV file, convert it to JSON and pipe it to use with Chart.js.

Demonstration: Live Example and Code

Before jumping into the tutorial, here is a live demonstration of what we’re about to build:

View a Live Demonstration | Source Data | Fork the Source Code

Summary: This example is hosted on GitHub Pages and uses a Chart.js bar chart to visualize the mobile phone operating system market share over time. Charts.js requires JSON, but the market share data was in a CSV file. It utilizes the Flex.io API to pull the CSV file and convert it to JSON to be utilized by the chart.

Let’s Start Building

In this tutorial, we’ll do the following:

  1. Create a Chart. Build the initial scaffolding with chart.js.
  2. Build a Data Feed. Use the Flex.io API to access the remote CSV file.
  3. Convert and Format the Data. Use the Flex.io to convert the file to JSON and Lodash to format as required by Chart.js.
  4. Pull it all together. Combine the front-end component with the data feed to display the live bar chart.

 

To get started, you’ll need the following:

 

OK, let’s build the example above and show you how you can pull data from a CSV and render it using Chart.js. When we’re done, we should have a chart that looks like the one in the header of this page.

Step 1: Create a Basic Chart with Chart.js

First, let’s get a basic chart up-and-running. To do this, create an index.html file with a single canvas element:

<html>
<body>
<div id="chart">
<canvas id="canvas"></canvas>
</div>
</body>
</html>

Next, include a script tag to include the Chart.js library:

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.bundle.min.js"></script>

Finally, add the code for to display a vertical bar chart using some inline data:

<script>
(function(window, document, undefined) {

var chart_data = {
labels: ['Year1', 'Year 2', 'Year 3', 'Year 4', 'Year 5'],
datasets: [
{
label: 'A',
data: [2,4,8,14,22],
backgroundColor: 'rgba(255,0,0,0.5)'
},
{
label: 'B',
data: [3,5,9,17,33],
backgroundColor: 'rgba(0,0,255,0.5)'
}
]
}

var ctx = document.getElementById('canvas').getContext('2d')
window.my_chart = new Chart(ctx, {
type: 'bar',
data: chart_data,
options: {
responsive: true,
legend: {
position: 'top'
},
title: {
display: true,
text: 'Basic Yearly Comparison'
}
}
})
})(window, document)
</script>

Step 2: Build a Feed to Pull Data from a CSV

Now that we have a basic chart example up-and-running, we want to hook it up to a CSV. First, let’s simply pull data from a CSV; then we’ll add formatting logic in the next step. To pull data from a CSV, we’ll be using Flex.io and the Flex.io JS SDK.

First, let’s include the Flex.io SDK library in the code by adding the following script tag right after the html body and before the link for Chart.js:

<script src="https://cdn.jsdelivr.net/npm/flexio-sdk-js@latest"></script>

Next, let’s move the logic that creates a chart to a separate render function to help keep this functionality disctinct from the logic that we’ll be adding to pull the data:

(function(window, document, undefined) {

function render()
{
var chart_data = {
labels: ['Year1', 'Year 2', 'Year 3', 'Year 4', 'Year 5'],
datasets: [
{
label: 'A',
data: [2,4,8,14,22],
backgroundColor: 'rgba(255,0,0,0.5)'
},
{
label: 'B',
data: [3,5,9,17,33],
backgroundColor: 'rgba(0,0,255,0.5)'
}
]
}

var ctx = document.getElementById('canvas').getContext('2d')
window.my_chart = new Chart(ctx, {
type: 'bar',
data: chart_data,
options: {
responsive: true,
legend: {
position: 'top'
},
title: {
display: true,
text: 'Basic Yearly Comparison'
}
}
})
}
})(window, document)

Now, let’s add the code to pull the data from the CSV inside the (function(window, document, undefined) body. To do this, we’ll add a ‘Flexio’ parameter to the function and then create a pipe inside the function to requests data from the CSV and runs the pipe with an alert showing the results of the call:

(function(window, document, Flexio, undefined) {
Flexio.setup('YOUR_API_KEY')
Flexio.pipe()
.request('https://raw.githubusercontent.com/flexiodata/data/master/phone-market-share/phone-market-share.csv')
.run(function(err, response) {
alert(response.text)
})

})(window, document, Flexio)

To run the code inside this function, you’ll need an API key. To get an API key, sign up, and when you log in, you’ll see your API key on the dashboard. Copy it and paste it into the code; for the example, we’ll use an example API key, but you’ll want to use your own for your own data.

Once you’ve added your API key, your code should look like:

(function(window, document, Flexio, undefined) {
Flexio.setup('bbphhkgvrfkgdskssrcb')
Flexio.pipe()
.request('https://raw.githubusercontent.com/flexiodata/data/master/phone-market-share/phone-market-share.csv')
.run(function(err, response) {
alert(response.text)
})

})(window, document, Flexio)

To see the output of the CSV, simply refresh the webpage displaying the index.html file, and you’ll see an alert message box showing the contents of the CSV.

Here’s what’s happening: when the page refreshes, the anonymous function defined as ‘(function(window, document, Flexio, undefined)’ is being called. When this function is called, the Flex.io pipe is configured with the specified API key with the call to ‘Flexio.setup()’. Next, a pipe is defined with the call to Flexio.pipe(); this pipe begins with a ‘request’ function that requests the data from a link pointing to a CSV, and then the pipe ends with a ‘run’ function that runs the steps in the pipe, which in this case is the ‘request’ command. When the pipe finishes running, the callback in the run() function is called and the results of the pipe passed in the ‘response’ object, which is displayed in this case with the alert() function.

Of course, we want the CSV in a format we can use in the chart.

Step 3: Convert and Format the CSV Data

Now that we’re pulling data from the CSV, we want to format it in a form used by the chart.

Looking at the results from the CSV, we see the data looks like the following:

OS,2009,2010,2011,2012,2013,2014,2015,2016,2017
Android,1.6,9.6,36.4,56.9,74.4,80.8,78.8,84.1,86.1
iOS,10.5,15.4,16.9,22.5,18.2,15.3,17.9,14.8,13.7
Microsoft,10.2,6.8,2.6,1.9,2.9,2.7,2.5,0.7,0.1
RIM,20.6,19.7,13,6.8,3,0.6,0.4,0.2,0
Symbian,48.8,44.2,27.7,8.5,0.6,0.2,0.1,0,0

From our chart example, we see we need to get the data into the following format:

{
"labels": ["2009","2010","2011","2012","2013","2014","2015","2016","2017"],
"datasets": [
{
"label": "Android",
"data": [1.6,9.6,36.4,56.9,74.4,80.8,78.8,84.1,86.1],
"backgroundColor": "#A9F7DF"
},
{
"label": "iOS",
"data": [10.5,15.4,16.9,22.5,18.2,15.3,17.9,14.8,13.7],
"backgroundColor": "#E3402C"
},
{
"label": "Microsoft",
"data": [10.2,6.8,2.6,1.9,2.9,2.7,2.5,0.7,0.1],
"backgroundColor": "#437E7B"
},
{
"label": "RIM",
"data": [20.6,19.7,13,6.8,3,0.6,0.4,0.2,0],
"backgroundColor": "#A5C5B1"
},
{
"label": "Symbian",
"data": [48.8,44.2,27.7,8.5,0.6,0.2,0.1,0,0],
"backgroundColor": "#BD198F"
}
]
}

Each JSON object in the datasets array corresponds to one set of bars in the bar chart. Inside each of the JSON objects, you’ll see that you can change the label, background color, border color, border width and also set the data.

To do this, we’ll add two pieces of logic: 1) a step to the pipe that converts the CSV to JSON, and 2) a formatting function that uses Lodash to format the JSON into the object format used by Chart.js.

First, let’s add the step to the pipe that converts the CSV to JSON and modify the callback function that executes when the pipe is run to simply handle the response text as JSON:

(function(window, document, Flexio, undefined) {
Flexio.setup('bbphhkgvrfkgdskssrcb')
Flexio.pipe()
.request('https://raw.githubusercontent.com/flexiodata/data/master/phone-market-share/phone-market-share.csv')
.convert('csv','json')
.run(function(err, response) {
var data = JSON.parse(response.text)
})

})(window, document, Flexio)

The ‘convert’ step takes the output from the ‘request’ function, which is the CSV data, and converts it from ‘csv’ to ‘json’. Then, when the pipe is run, the result of the ‘convert’ step is passed into the callback through the reponse parameter in ‘response.text’. Finally, in the callback, since the response is returned as JSON text, we convert it to an object using JSON.parse().

Next, let’s add a function that formats the JSON object into the form needed by the chart. To do this, we define another function ‘formatDataForChart(content)’ along with a helper function ‘getRandomColor()’ for generating random colors as follows:

function formatDataForChart(content)
{
var first_item = _.get(content, '[0]', {})
var column_labels = _.map(_.omit(first_item, ['os']), function(val, key) {
if (key != 'os')
return key
})

// use Lodash to reformat the JSON for use with Chart.js
var datasets = _.map(content, function(item) {
// use the 'os' column as our label
var item_label = _.get(item, 'os', 'Not Found')

// create an array of number values from each item's JSON object
var item_values = _.map(_.omit(item, ['os']), function(val) {
return parseFloat(val)
})

return {
label: item_label,
data: item_values,
backgroundColor: getRandomColor()
}
})

var chart_data = {
labels: column_labels,
datasets: datasets
}

return chart_data
}

function getRandomColor() {
var letters = '0123456789ABCDEF'.split('')
var color = '#'
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)]
}
return color
}

This function takes a JSON array as input, uses the first element of the array, minus ‘os’, to set the chart labels. Then, it uses the other values for the datasets portion of the chart data. Finally, it assigns a random color using ‘getRandomColor()’ to each dataset.

Step 4: Insert the CSV into the Chart.js Bar Chart

Now that we have the data in the form we need, we simply need to plug it into the chart. To do this, we need to do the following: 1) modify the render() function so that data can be passed in as a parameter, 2) use the formatting function to convert the data from a straight JSON array into the chart format:

function render(data)
{
var chart_data = formatDataForChart(data)
var ctx = document.getElementById('canvas').getContext('2d')

window.my_chart = new Chart(ctx, {
type: 'bar',
data: chart_data,
options: {
responsive: true,
legend: {
position: 'top'
},
title: {
display: true,
text: 'Use Flex.io to Create a Chart With Chart.js Directly From a CSV File'
}
}
})
}

Finally, to render the chart with the CSV data, we simply need to call the ‘render’ function in the Flexio.pipe() ‘run’ callback function:

(function(window, document, Flexio, undefined) {
Flexio.setup('bbphhkgvrfkgdskssrcb')
Flexio.pipe()
.request('https://raw.githubusercontent.com/flexiodata/data/master/phone-market-share/phone-market-share.csv')
.convert('csv','json')
.run(function(err, response) {
var data = JSON.parse(response.text)
render(data)
})

})(window, document, Flexio)

Once you’ve finish the above steps, you should have a simple bar chart that looks something like this:

Chart.js Result Chart

Additional Permutations

Different chart formats

In this example, we focused on a vertical bar chart. However, different types of charts in Chart.js have different formats. Depending on the format, we would need to modify the ‘formatDataForChart’ function with the appropriate parameter. However, the basic form is still similar to this example.

Rendering large CSVs

In this example, we used a relatively small CSV. However, your CSV might be significantly larger and you may want to add additional logic which cuts down the size of the CSV so that your chart renders more efficiently. In both cases, you can cut down the CSV using the Flex.io pipe serverside and save yourself bandwidth when the data is downloaded in the Flex.io ‘run’ callback. To simply filter the CSV in the pipe, you can add a ‘filter’ step. If you want to use more sophisticated methods for sampling the data, such as data decimation, you can add a custom ‘python’ step, then use the ‘scipy.signal.decimate’ function to cut down the CSV in the Flex.io ‘python’ step.

Need Any Help?

We hope you found this tutorial useful. If you have any questions, shoot us a note using the chat button below. We’re happy to help and look forward to seeing what you can build!