I am not a JavaScript expert and I am trying to put a simple pie chart together using the data from a csv file. The sample code for the pie chart with its input data looks like below and it works perfectly.
var pie = new d3pie("pie", {
header: {
title: {
text: "A Very Simple Pie",
fontSize: 30
}
},
data: {
content: [
{ label: "JavaScript", value: 264131 },
{ label: "Ruby", value: 218812 },
{ label: "Java", value: 157618}
]
}
});
but when I try to use the data from the csv file. It says no data is provided. I obviously try to pass the dynamic data to the data.content but it seems like I am not doing it correctly. Below is my code:
var input_data = []
d3.csv("data.csv", function (data) {
input_data.push({
label: data["First"],
value: +data["Age"]
});
});
console.log(input_data); // This shows [{label: "james", value:30},{"John",value:22}]
var pie = new d3pie("pie", {
header: {
title: {
text: "Simple Pie",
fontSize: 30
}
},
data: {
content: input_data
}
});
Any idea what I am doing wrong here?
As noted in my comment, your problem is because d3.csv acts asynchronously, and input_data isn't populated when d3pie tries to create your chart.
There is something highly suspicious going on with input_data in the other examples -- it should be called for every item in data, but seems only to be called once. Rather than using input_data to collate intermediate results, it's much easier to use javascript's map function to transform your csv data into the format you want:
d3.csv("data.csv", function (data) {
var pie = new d3pie("pie", {
header: {
title: {
text: "Simple Pie",
fontSize: 30
}
},
data: {
content: data.map( function(d){
return { label: d['First'], value: +d['Age'] }
})
}
});
});
map iterates over an array and produces an array as output, so it's much cleaner and easier than creating extra arrays on to which you push data, etc.
You probably want to put your d3pie code inside your callback function because you want to call it after the data returns (see this example):
var input_data = []
d3.csv("data.csv", function (data) {
input_data.push({
label: data["First"],
value: +data["Age"]
});
console.log(input_data); // This shows [{label: "james", value:30},{"John",value:22}]
var pie = new d3pie("pie", {
header: {
title: {
text: "Simple Pie",
fontSize: 30
}
},
data: {
content: input_data
}
});
});
const promise = d3.csv("data.csv", function (data) {
input_data.push({
'label': data["First"],
'value': +data["Age"]
});
});
promise.then(function(){
var pie = new d3pie("pieChart", {
header: {
title: {
text: "Simple Pie",
fontSize: 30
}
},
data: {
content: input_data
}
});
});
I have a rails app that fetches currency information data of the value of the sterling pound compared to the Kenyan shilling from a JSON API.
I want to use this data to plot a time-series graph of the value of the pound over a long period of time.
I'm using AJAX to populate data to a highcharts chart and my code is as follows:
<div id="currency", style="width: 220px, height:320px">
<script type="text/javascript">
$(document).ready(function(){
localhost = {}; //global namespace variable
localhost.currenctHTML = ""; //currency HTML built here
localhost.currencyValue = []; //array of percentage changes
localhost.currencyDate = []; //array of currency names
localhost.chart1 = {yAxisMin : null, yAxisMax : null};//obj holds things belonging to chart1
var url = '/forexes.json'
$.ajax({
url: url,
cache: false,
dataType: 'jsonp', //will set cache to false by default
context: localhost,
complete: function(data){
var a=JSON.parse(data.responseText);
// console.log(a);
var data_mapped = a.map(function (data){
return data.forex;
}).map(function (data) {
return {
currencyDate: data.published_at,
currencyValue: data.mean
}
});
this.currencyDate = _.pluck(data_mapped, 'currencyDate');
this.currencyValue = _.pluck(data_mapped, 'currencyValue');
console.log(this.currencyDate);
this.chart1.data.series[0].data = this.currencyValue;
this.chart1.data.xAxis.categories = this.currencyDate;
chart = new Highcharts.Chart(this.chart1.data);
}
});
localhost.chart1.data = { //js single-threaded, this obj created before callback function completed
chart: {
renderTo: "currency"
},
title: {
text: "Forex by Day"
},
xAxis: {
categories: null, //will be assigned array value during ajax callback
title: {
text: null
}
},
yAxis: {
title: {
text: "Pounds"
}
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat("%B %e, %Y", this.x) + ': ' +
"$" + Highcharts.numberFormat(this.y, 2);
}
},
series: [{
name: 'Pound',
data: null
}
]
};
});
</script>
</div>
**** returns
this.chart1.data.xAxis.categories = ["2003-01-01T00:00:00.000Z", "2003-01-02T00:00:00.000Z", "2003-01-03T00:00:00.000Z", "2003-01-04T00:00:00.000Z", "2003-01-05T00:00:00.000Z"]
this.chart1.data.series[0].data = [147.653, 148.007, 147.971, 148.202, 148.384, 147.888]
How do I use this data to generate a highstocks line chart resembling this
In the highstock you cannot use categories, only datetime type, so you should parse your data to timestamp and use it in the data.
I am attempting to create a dynamic flot graph dependant upon the data given to it, my flot graph is using JSON for its information and here is an example of the dataset:
{
"total":[[1377691200,115130],[1377694800,137759],[1377698400,137759],[1377702000,137759],[1377705600,137759],[1377709200,139604],[1377712800,137759],[1377716400,137759],[1377720000,137759],[1377723600,137759],[1377727200,137759],[1377730800,138156],[1377734400,137759],[1377738000,137759],[1377741600,137759],[1377745200,137759],[1377748800,138156],[1377752400,137759],[1377756000,137759],[1377759600,168831],[1377763200,137759],[1377766800,0],[1377770400,0]],
"dev0":[[1377691200,115130],[1377694800,137759],[1377698400,137759],[1377702000,137759],[1377705600,137759],[1377709200,139604],[1377712800,137759],[1377716400,137759],[1377720000,137759],[1377723600,137759],[1377727200,137759],[1377730800,138156],[1377734400,137759],[1377738000,137759],[1377741600,137759],[1377745200,137759],[1377748800,138156],[1377752400,137759],[1377756000,137759],[1377759600,168831],[1377763200,137759],[1377766800,0],[1377770400,0]],
"dev1":[[1377691200,0],[1377694800,0],[1377698400,0],[1377702000,0],[1377705600,0],[1377709200,0],[1377712800,0],[1377716400,0],[1377720000,0],[1377723600,0],[1377727200,0],[1377730800,0],[1377734400,0],[1377738000,0],[1377741600,0],[1377745200,0],[1377748800,0], [1377752400,0],[1377756000,0],[1377759600,0],[1377763200,0],[1377766800,0],[1377770400,0]]
}
The script i have created already:
$(".bytes_portal_pop").click(function(e) {
e.preventDefault();
var graph=$(this).data('graph');
var range=$(this).data('range');
var divid=$(this).data('divid');
var title=$(this).data('boxtitle');
$.getJSON("/action/sites/GetFlotStats/?graph=" + graph + "&range=" + range, function(json) {
//succes - data loaded, now use plot:
var plotarea = $("#" + divid);
var dev0=json.dev0;
var dev1=json.dev1;
$.plot(
$("#" + divid),
[
{
data: dev0,
lines:{show: true, fill: true},
label: "dev0",
},
{
data: dev1,
lines:{show: true, fill: true},
label: "dev1",
},
],
{
xaxis: {mode:"time"},
grid: {hoverable: true},
tooltip: true,
tooltipOpts: {
content: "Traffic: %y GB"
}
}
);
});
$("#boxtitleB_flot").html(title);
});
This way works fine and displays the two lines as i need however i would like it to be dynamic i.e. so i dont have to define each graph line i believe todo this i simply need a for or each() loop on the
var dev0=json.dev0;
and
{
data: dev0,
lines:{show: true, fill: true},
label: "dev0",
},
Any help achieving this would be much appreciated.
Correct, just loop it and generate your series objects dynamically.
Given a json return like:
jsonObj = {
"total":[[1377691200,115130],[1377694800,137759],[1377698400,137759],[1377702000,137759],[1377705600,137759],[1377709200,139604],[1377712800,137759],[1377716400,137759],[1377720000,137759],[1377723600,137759],[1377727200,137759],[1377730800,138156],[1377734400,137759],[1377738000,137759],[1377741600,137759],[1377745200,137759],[1377748800,138156],[1377752400,137759],[1377756000,137759],[1377759600,168831],[1377763200,137759],[1377766800,0],[1377770400,0]],
"dev0":[[1377691200,115130],[1377694800,137759],[1377698400,137759],[1377702000,137759],[1377705600,137759],[1377709200,139604],[1377712800,137759],[1377716400,137759],[1377720000,137759],[1377723600,137759],[1377727200,137759],[1377730800,138156],[1377734400,137759],[1377738000,137759],[1377741600,137759],[1377745200,137759],[1377748800,138156],[1377752400,137759],[1377756000,137759],[1377759600,168831],[1377763200,137759],[1377766800,0],[1377770400,0]],
"dev1":[[1377691200,0],[1377694800,0],[1377698400,0],[1377702000,0],[1377705600,0],[1377709200,0],[1377712800,0],[1377716400,0],[1377720000,0],[1377723600,0],[1377727200,0],[1377730800,0],[1377734400,0],[1377738000,0],[1377741600,0],[1377745200,0],[1377748800,0], [1377752400,0],[1377756000,0],[1377759600,0],[1377763200,0],[1377766800,0],[1377770400,0]]
};
Create an array of series like:
var series = [];
$.each(jsonObj, function (key, val) {
var serie = {};
serie.label = key;
serie.data = val;
series.push(serie);
});
And then create the plot:
$.plot(
$("#placeholder"),
series,
{}
);
Fiddle here.