Creating a categorical bar chart from csv file in c3.js - javascript

I have code for a simple bar chart using c3.js:
<!DOCTYPE html>
<html lang="en">
<head>
<title>C3</title>
<meta charset="utf-8" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
</head>
<body>
<div id="chart"></div>
<script>
var chart = c3.generate({
data: {
url: 'data/output.csv'
type: 'bar'
}
});
</script>
</body>
</html>
The file output.csv looks like this:
A,B,C,D
25,50,75,100
And the graph ends up looking like this:
which is all of the data in one group.
What I'd want to do is producing the following, without hard coding the data, but rather, getting it from the CSV file like the first example:
<!DOCTYPE html>
<html lang="en">
<head>
<title>C3</title>
<meta charset="utf-8" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
</head>
<body>
<div id="chart"></div>
<script>
var chart = c3.generate({
bar: {
width: 15
},
padding: {
left: 60
},
data: {
x: 'Letter',
columns:
[
['Letter', 'A','B','C','D'],
['value', 25,50,75,100]
],
type: 'bar',
onclick: function(e) { console.log(ylist[e.x]);a = this;}
},
axis: {
x: {
type: 'category'
}
},
legend: {
show: false
}
});
</script>
</body>
</html>
which would give a graph that looks like this:
Here is a jFiddle link.
My main issue is not knowing if there is a way to split the CSV file into categories, since it seems like c3.js will always put a CSV file into a time series.

C3 uses the first line in your csv as a header line and then returns a set of objects like {A:25},{B:50} which C3 will find difficult/impossible to use in the way you'd like.
Instead parse the csv outside the chart using D3's parseRows function. Then prepend a row descriptor which C3 can use to know which bit of the file does what.
https://jsfiddle.net/bm57gye5/2/
// This is a separate bit of html which is explained below
<pre id="data">
A,B,C,D
25,50,75,100
</pre>
// Actual javascript
var unparsedData = d3.select("pre#data").text();
var data = d3.csv.parseRows( unparsedData );
data[0].splice (0,0,"Letter");
data[1].splice (0,0,"Data");
console.log ("data", data);
var chart = c3.generate({
bar: {
width: 15
},
padding: {
left: 60
},
data: {
columns: data,
x: "Letter",
type: 'bar',
onclick: function(e) { console.log(ylist[e.x]);a = this;}
},
axis: {
x: {
type: 'category'
}
},
legend: {
show: false
}
});
To access the csv from a url (in the jsfiddle I just reference the data as part of the html) to feed into csv.parseRows you'll need to use d3.text and a callback as so:
d3.text("data/output.csv", function(unparsedData)
{
var data = d3.csv.parseRows(unparsedData);
... parsing / c3 chart generation continues on here as above ...
}

Related

Getting can't convert undefined to object while reading from json file

Scenario :
A json file
Read json data and plot graph using highcharts
Problem: Getting can't convert undefined to object when loading html without breakpoint in mozilla firefox.
When loading with a breakpoint the graph is getting perfectly plotted.
without breakpoint, getting myjson as undefined in function chartFormyJson
Code :
I have a node project and I am starting http server using npm run serve.
Index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="scriptFile.js"></script>
</head>
<body>
<div id="container" style="width:100%; height:400px;"></div>
</body>
</html>
scriptFile.js
var myjson;
fetch('./data.json').then(response => response.json()).then(data => {
myjson=data["myjson"];
})
if( document.readyState !== 'loading' ) {
console.log( 'document is already ready, just execute code here' );
chartFormyJson();
} else {
document.addEventListener('DOMContentLoaded', function () {
console.log( 'document was not ready, place code here' );
chartFormyJson();
});
}
function chartFormyJson(){
var myChart = Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Plot bar graph per year'
},
yAxis: {
title: {
text: 'Count'
}
},
xAxis: {
categories: Object.keys(myjson)
},
series: [{
data: Object.values(myjson)
}]
});
}
Need guidance in why it happening this way.Seems something related with loading of data/variables/order of call to js from html.But I am not an expert on these so will really appreciate any help on this.
Let me know if any further info is needed.

How to export csv in CanvasJS in Javascript?

I want to load a csv file to my html file to plot some data.
I have figured out how to plot in html but the next challenge is to import data from a csv file. I am new to html and javascript and would appreciate inputs or even other modules aside from CanvasJS.
<!DOCTYPE HTML>
<html>
<head>
<meta charset ="UTF-8">
<script>
window.onload = function () {
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
theme: "light2",
title:{
text: "DOE TEST Chart"
},
axisY:{
includeZero: false
},
data: [{
type: "line",
dataPoints: dataPoints
}]
});
$.get("file:////C:/Users/TestDev/Documents/html_files/js_plots/Sample/zpw.csv", getDataPointsFromCSV);
function getDataPointsFromCSV(csv) {
var csvLines = points = [];
csvLines = csv.split(/[\r?\n]\r|\n]+/);
for (var i = 0; i < csvLines.length; i++) {
if (csvLines[i].length > 0){
points = csvLines[i].split(",");
dataPoints.push({
label: points[0],
y: parseFloat(points[1])
});
}
}
chart.render();
}
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 370px; max-width: 920px; margin: 0px auto;"></div>
<script src="../../canvasjs.min.js"></script>
</body>
</html>
Try moving the Sample folder containing the csv file into your project and use a relative url like "Sample/zpw.csv"
Due to security issues browsers doesn't allow you to read files from local filesystem. However, you can save your CSV in Google-Sheets and export it as CSV and use the link to the CSV in $.get("Google-Sheet-CSV-URL").

Highstock Navigator and xAxis show numbers instead of dates

Data loaded from local csv file. Webpage run on local Node 'Connect' and 'serveStatic' webserver.
Navigator and the xAxis shows numbers instead of dates stored in the csv file, hence rangeselector and zoom doesn't work.
Code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/data.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<script src="https://code.highcharts.com/stock/modules/export-data.js"></script>
</head>
<body>
<div id="container" style="width:80%; height:600px;"></div>
</body>
<script>
$(function () {
var myChart = Highcharts.stockChart('container', {
title: {
text: 'Consumption'
},
xAxis: {
type: 'datetime',
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Kilogram'
}
},
navigator: {
xAxis: {
isInternal: true
},
yAxis: {
isInternal: true
}
},
data: {
csvURL: window.location.origin + '/trend.csv'
}
});
});
</script>
</html>
The 'isInternal' parameters are set to workaround this issue.
When I select 'View data table' in the menu the following is displayed:
Date Value
09-06-2018 18:00:15 1296.26098632813
09-06-2018 18:28:09 1451.98901367188
2 563.752014160156
3 429.237213134766
4 445.504516601563
5 1216.92199707031
...
There is something odd going on with the dates. It looks like only the first two rows are processed correctly.
Can anyone please take a look, and maybe point me in the right direction?
Sample from csv file:
DateTime;Value
09/06/2018 18:00:15;1296.26098632813
09/06/2018 18:28:09;1451.98901367188
09/06/2018 18:56:03;563.752014160156
09/06/2018 19:23:57;429.237213134766
The problem comes from your dates being formatted dd/mm/YYYY HH:MM:SS, when javascript expects mm/dd/YYYY HH:MM:SS. If there are just dates, then this can be handled with dateFormat. However, since there is also time involved, it fails. To take care of that we can parse dates manually, like this:
function parseEUdate(d) {
return (new Date(
d.substring(6,10), //Year
d.substring(3,5) - 1, //Month
d.substring(0,2), //Day
d.substring(11,13), //Hour
d.substring(14,16), //Minute
d.substring(17,19) //Second
)).getTime()
}
This is then used in highcharts like this:
data: {
parseDate: function(d) {
return parseEUdate(d)
},
...
}
Working JSFiddle example: https://jsfiddle.net/ewolden/frjp96w8/75/
API on parseDate: https://api.highcharts.com/highstock/data.parseDate
Date() documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Cannot read property 'Chart' of undefined

I want to present a pie chat, the data came from csv file (excel).
I have html file (index.html) and js file (loadData2.js),
when I print the data in js file I get It like : word,number
donald,8
trump,12
refused ,2
to,7
release ,3
his,6
so I see the data ok.
one field is a word and the other is a number.
I get an error: "Uncaught TypeError: $(...).CanvasJSChart is not a function(…)"
my html code:
<!DOCTYPE html>
<html>
<head>
<title>hw 1</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script src="includes/loadData2.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="canvas/canvasjs.min.js"></script>
</head>
<body>
<div id="chartContainer" style="height: 300px; width: 100%;">
<script>
(function(){
getData2();
})();
</script>
</div>
</body>
</html>
my js code:
function getData2()
{
console.log("hello");
$.get('data/words.csv', function(data) {
console.log(data);
//Better to construct options first and then pass it as a parameter
var options = {
exportEnabled: true,
animationEnabled: true,
title: {
text: "Exporting Chart as Image"
},
data: [
{
type: "splineArea", //change it to line, area, bar, pie, etc
dataPoints: [data]
}
]
};
$("#chartContainer").CanvasJS.Chart(options);
});
}
what I need to do to in order to see my chart on the screen?
Thanks,
You are including CanvasJs, and trying to use its jQuery plugin.
replace <script src="canvas/canvasjs.min.js"></script> by the right file and it'll work.
<script src="https://cdnjs.cloudflare.com/ajax/libs/canvasjs/1.7.0/jquery.canvasjs.min.js"></script>
To create a Chart using the regular library would go like this :
var options = {
exportEnabled: true,
animationEnabled: true,
title: {
text: "Exporting Chart as Image"
},
data: [
{
type: "splineArea", //change it to line, area, bar, pie, etc
dataPoints: [data]
}
]
};
var chart = new CanvasJS.Chart("chartContainer",options);
chart.render

Simple Line Chart using HighChart

I am trying to generate a simple line chart using HighChart. The source code is given below. The challenge is that I am getting my X-Axis and Y-Axis on the screen but the chart itself is missing. When I move the cursor across the screen, I can see the X and Y values displayed on the screen. I have tried to debug the program but I am not able to find a solution. Can someone guide me?
Regards
Sachin
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="js/highcharts.js"></script>
<!--[if IE]>
<script type="text/javascript" src="../js/excanvas.compiled.js"></script>
<![endif]-->
<!-- 2. Add the JavaScript to initialize the chart on document ready -->
<script type="text/javascript">
$(document).ready(function() {
var options = {
chart: {
renderTo: 'container',
type: 'line'
},
title: {
text: 'Pollution Level'
},
xAxis: {
categories: [''],
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Pollution %'
}
},
series: []
};
$.get('data/graphs/pollution.csv', function(data) {
window.alert(data);
// Split the lines
var lines = data.split('\n');
window.alert(lines);
lines = lines.map(function(line) {
var data = line.split(',');
data[1] = parseFloat(data[1]);
return data;
});
window.alert(lines);
var series = {
data: lines
};
options.series.push(series);
var chart = new Highcharts.Chart(options);
});
});
</script>
</head>
<body >
<div id="container" style="width: 610px; height: 610px; margin: 0 auto"></div>
</body>
</html>
Update 1-Mar-2016
I have modified the program as follows. I am still not able to get a line chart. The funny thing is that if I change the type of chart from 'line' to 'column' I can see a chart. Not sure of the problem. Please advise.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript" src="js/highcharts.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<!--[if IE]>
<script type="text/javascript" src="../js/excanvas.compiled.js"></script>
<![endif]-->
<!-- 2. Add the JavaScript to initialize the chart on document ready -->
<script type="text/javascript">
$(document).ready(function() {
var options = {
chart: {
renderTo: 'container',
defaultSeriesType: 'line'
},
title: {
text: 'Pollution Level'
},
xAxis: {
categories: [''],
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Pollution %'
}
},
series: [ {
plotLines: [{
color: '#000000'
}],
data: []
}]
};
$.get('data/graphs/pollution.csv', function(data) {
window.alert(data);
// Split the lines
var lines = data.split('\n');
window.alert(lines);
var series = {
data: [],
name: 'serie1'
};
lines = lines.map(function(line) {
var data = line.split(',');
if (data[0] != "DATE"){
options.xAxis.categories.push(data[0]);
data1 = parseFloat(data[1]);
series.data.push(parseFloat(data[1]));
return data;
}
});
options.series.push(series);
var chart = new Highcharts.Chart(options);
});
});
</script>
</head>
<body >
<div id="container" style="width: 610px; height: 610px; margin: 0 auto"></div>
<?php
?>
</body>
</html>
Be sure you are fetching valid values instead of a string:
Please, check this section:
lines = lines.map(function(line) {
var data = line.split(',');
data[1] = parseFloat(data[1]);
return data;
});
Q: Could you share your CSV (pollution.csv)?
Thanks for your data: please check the following example
The parsing section is:
for (i = 0; i < lines.length; i++) {
var items = lines[i].split(',');
if (i == 0) {
ctg[0] = items[0];
ctg[1] = items[1];
} else {
dataYAxis.push([(new Date(items[0])).getTime(), parseFloat(items[1])]);
}
}
As you can see, I isolated the titles (DATE, LVL) from the data, the next step is to save data in dataYAxis array: date first and data second. I am using 'datetime' in xAxis to show date in xAxis' labels.

Categories