Charts in Angular js with JSON Object - javascript

I am trying to implement chart representation in angular js.
http://jtblin.github.io/angular-chart.js/
I was able to implement simple charts but I have a below data to be represented. It is in JSON format. I need help on how to convert JSON to arrays to be represented as charts. Below is JSON
[{"value": {"DE":2,"NP":20,"BD":28,"TW":1},
"end_time":"2016-07-05T07:00:00+0000"},
{"value":{"DE":5,"NP":11,"BD":22,"BE":2,"FJ":2},
"end_time":"2016-07-06T07:00:00+0000"},
{"value":{"DE":5,"NP":24,"BD":29},
"end_time":"2016-07-07T07:00:00+0000"}]
I am trying to convert it to the format
$scope.labels = ["January", "February", "March", "April", "May", "June","July"];
$scope.series = ['Series A', 'Series B'];
$scope.data = [
[65, 59, 80, 81, 56, 55, 40],
[28, 48, 40, 19, 86, 27, 90]
];
I understand that I need to iterate over my JSON object and create arrays.
My question is I have different labels in each of the JSON object. How do I convert it create an array with all the labels in each of the value and still maintain the order of counts.Like below
$scope.labels = ["DE", "NP", "BD", "TW", "BE", "FJ"];
$scope.series = ["2016-07-05T07:00:00+0000","2016-07-06T07:00:00+0000","2016-07-07T07:00:00+0000"]
$scope.data = [ [2,20,28,1,0,0],
[5,11,22,0,2,2],
[5,24,29]
]
If this can be better achieved using different libraries or charts in angularjs please do suggest

Have you even attempted something? You didn't show any solution. Anyway, here's a possible implementation
var source = [
{"value": {"DE":2,"NP":20,"BD":28,"TW":1},
"end_time":"2016-07-05T07:00:00+0000"},
{"value":{"DE":5,"NP":11,"BD":22,"BE":2,"FJ":2},
"end_time":"2016-07-06T07:00:00+0000"},
{"value":{"DE":5,"NP":24,"BD":29},
"end_time":"2016-07-07T07:00:00+0000"}
]
var $scope = {};
$scope.labels = [];
$scope.data = [];
$scope.series = [];
source.forEach(function(item){
$scope.series.push(item.end_time)
var values = []
Object.keys(item.value).forEach(function(key) {
if ($scope.labels.indexOf(key) === -1) {
$scope.labels.push(key)
}
values.push(item.value[key])
})
$scope.data.push(values)
})
console.log($scope)

Related

Reading CSV in D3 and converting it to array of arrays

I have the following small dataset hardcoded into a variable in my code:
var dataset = [['CENTRAL', 44, 552, 18565],
['NORTHERN', 42, 945, 20092],
['SOUTHERN', 96, 795, 30095],
['PARK', 1, 640, 9341],
['MISSION', 66, 1198, 18542],
['TENDERLOIN', 23, 113, 10735],
['RICHMOND', 9, 561, 9082],
['TARAVAL', 81, 789, 11966],
['INGLESIDE', 5, 1368, 13414],
['BAYVIEW', 7, 985, 14711]];
Now, this dataset is taken directly from a .csv file, that looks like this:
District,Prostitution,VehicleTheft,Totalcrimecount
CENTRAL,44,552,18565
NORTHERN,42,945,20092
SOUTHERN,96,795,30095
PARK,1,640,9341
MISSION,66,1198,18542
TENDERLOIN,23,113,10735
RICHMOND,9,561,9082
TARAVAL,81,789,11966
INGLESIDE,5,1368,13414
BAYVIEW,7,985,14711
However, I'd obviously like to be able to just read in the file, which I've attempted using this:
var dataset_csv = d3.csv("datafile.csv", function(d){
console.log(dataset_csv = d)
});
Which gives me an array of objects that look like this:
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
District: "CENTRAL"
Prostitution: "44"
Totalcrimecount: "18565"
VehicleTheft: "552"
My question is, and it might be trivial, how can I transform those objects into an array data structure like my initial dataset? I've been battling with it for some time now. Any hints greatly appreciated.
Use Array#map to iterate over each object and Object.keys to catch only the keys values.
var dataset_csv = [{District: "CENTRAL", Prostitution: "44", Totalcrimecount: "18565", VehicleTheft: "552"}, {District: "WEST", Prostitution: "22", Totalcrimecount: "4324", VehicleTheft: "53"}, {District: "EAST", Prostitution: "11", Totalcrimecount: "23434" , VehicleTheft: "76"}],
datasetArr = dataset_csv.map(v => Object.keys(v).map(c => Number(v[c]) ? Number(v[c]) : v[c]));
console.log(datasetArr);

Load javascript array into Chartist.js as serie

I decided it would be a fun project to see if i could take data from Google Analytics and display that in a custom dashboard, and hopefully learn a thing or two about using json, and javascript.
after a lot of debugging i now managed to pull the data from the Google Analytics server with their php api, and save the output into data.json on the server.
below the data.json, it's valid as per JSONLint.com:
{
"0": {
"date": "20160113",
"pageviews": "46",
"sessions": "21"
},
"1": {
"date": "20160114",
"pageviews": "66",
"sessions": "18"
},
"2": {
"date": "20160112",
"pageviews": "50",
"sessions": "14"
},
"3": {
"date": "20160116",
"pageviews": "19",
"sessions": "14"
},
"4": {
"date": "20160117",
"pageviews": "23",
"sessions": "14"
},
"5": {
"date": "20160115",
"pageviews": "38",
"sessions": "11"
},
"6": {
"date": "20160118",
"pageviews": "35",
"sessions": "9"
},
"7": {
"date": "20160119",
"pageviews": "15",
"sessions": "7"
}
}
Now i've tried to use the data from data.json and feed it into chartist's labels/series in order to draw a graph.
var labelArray = [];
var seriesArray = [];
var labelOutput = [];
$.getJSON("data.json", function(json) {
//var jsonObj = JSON.parse(json);
for (var i in json){
labelArray.push(json[i].date);
};
for (var i in json){
seriesArray.push(json[i].sessions);
};
// var myData = {
// labels:
// }
// labelOutput = labelArray.join(',')
// seriesOutput = serieArray.join(',')
console.log(labelArray);
console.log(seriesArray);
// this will show the info it in firebug console
});
new Chartist.Line('.ct-chart', {
labels: [labelArray],
series: [[seriesArray]]
});
However I'm currently out of ideas why this would not work, the labels on X and Y axis are correctly shown, but no graph shows up.
I've tried using .join to see if that makes a difference, but using labelOutput instead of labelArray also doesn't change anything.
In the console the array that is being fed into chartist seems all right to me, if I copy paste it from the console into the script everything works.
Current output for labelArray and seriesArray:
labelArray
Array [ "20160113", "20160114", "20160112", "20160116", "20160117", "20160115", "20160118", "20160119" ]
seriesArray
Array [ "21", "18", "14", "14", "14", "11", "9", "7" ]
Anyone knows why chartist.js does manage to add the correct labels along the axes but fails to read the same data and draw the chart?
Although the answer by #mnutsch works, there is an easier way to add dynamic content into the chart.
You can simply add the arrays directly as parameters, which I think is what the OP was trying to do.
response object would be the ajax data
var seriesVals = [];
var labelsVals = [];
for (var i = 0; i < response.length; i++) {
seriesVals.push(response[i].total);
labelsVals.push(response[i].response_code);
}
var pieData = {
series: seriesVals,
labels: labelsVals
};
In case anyone comes across this later, you can also do it like this:
//Create javascript arrays with the values and labels, replace this with code to read from the database/API/etc.
var array_1_values = [100, 120, 180, 200, 90]; //these are the values of the first line
var array_2_values = [20, 35, 65, 125, 245]; //these are the values of the second line
var array_labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']; //these are the labels that will appear at the bottom of the chart
//create a prototype multi-dimensional array
var data_chart1 = {
labels: [],
series: [
[],
[]
]
};
//populate the multi-dimensional array
for (var i = 0; i < array_1_values.length; i += 1)
{
data_chart1.series[0].push(array_1_values[i])
data_chart1.series[1].push(array_2_values[i])
data_chart1.labels.push(array_labels[i])
}
//set the size of chart 1
var options_chart1 = {
width: '300px',
height: '200px'
};
//create chart 1
new Chartist.Line('#chart1', data_chart1, options_chart1);
In case anyone else stumbles upon the problem, below is what I came up with to get it to work.
After another day of trail and error i managed to pinpoint the problem.
The problem was:
In the original situation I tried to use a plain array as input for both labels and series. However, Chartist requires objects to render the labels/series as well as the graph.
The below works for me pulling the data from the data.json, adding it to an object and provide it to chartist.
var labelArray = {};
var seriesArray = {};
var labelOutput = [];
var Output
// $.getJSON("data.json", function(json) {
$.ajax({
url: 'data.json',
async: false,
dataType: 'text',
success: function(json) {
labelArray = JSON.parse(json);
data = {
labels:
[
labelArray[0].date,
labelArray[1].date,
labelArray[2].date,
labelArray[3].date,
labelArray[4].date,
labelArray[5].date,
labelArray[6].date
],
series: [[
labelArray[0].sessions,
labelArray[1].sessions,
labelArray[2].sessions,
labelArray[3].sessions,
labelArray[4].sessions,
labelArray[5].sessions,
labelArray[6].sessions
]]
}
}
});
new Chartist.Line('.ct-chart', data);
Decided to go with $.ajax to get the json file rather than getJSON as this allows me to disable asynchronous loading, ensuring the data is available when the graph is drawn.
Also, it is possible to set the dataType to Json rather than text, but this gives error in the JSON.parse line. Assuming that is because it tries to parse json as json, and fails to do so. But this is the only way i managed to get it to work, and add the json to an object.
Most likely the whole labelArray[0].date, labelArray[1].date is rather inefficient and should be improved but it works for now.

How to count and display the occurrence of a number in a json array of numbers

Please forgive me if this is a dumb or basic question but I have not been able to find a good solution. I have a json array of numbers:
[30, 37,34,56,76,87,54,34,2,4,2,5,5,3,4,3,4, 90]
I would like to count how many times each number occurs and use that data to produce a graph using d3js. How can I go about doing this? If there is a D3 method that does this, that would be great. But a javascript/jquery solution would do as well.
In plain Javascript:
var items = [30, 37, 34, 56, 76, 87, 54, 34, 2, 4, 2, 5, 5, 3, 4, 3, 4, 90],
histogram = items.reduce(function (r, a) {
r[a] = (r[a] || 0) + 1;
return r;
}, {});
document.write('<pre>' + JSON.stringify(histogram, 0, 4) + '</pre>');
For the graphing, check out c3. This can be easily done with something like this:
var chart = c3.generate({
data: {
x: 'x',
columns: [
numbers.unshift('x'),
occurrences.unshift('occurrences'),
],
type: 'bar'
} });
where numbers is an array of all distinct numbers and occurrences is an array of the numbers of time each occurs.
Demo

how to loop through array of objects and separate nested array of arrays

I have JSON that I currently use for a kendo-ui chart. I need to use the data for a grid so I need to separate the nested data array of arrays into there own object. Javascript or linq.js will work fine. here is the JSON I am starting with.
customSeries = [{
"name": "Chantal Hamlet - Green Castle Homes",
"subId": "10223",
"bldId": "13551",
"data": [
[179900, 1386],
[214900, 1440],
[194500, 1496],
[217900, 1504],
[189900, 1542],
[184900, 1546],
[192500, 1570]
],
}, {
"name": "Ella Sea Condos - Sahnow Construction",
"subId": "9761",
"bldId": "27380",
"data": [
[199900, 1500]
]
}, {
"style": "smooth",
"color": "blue",
"data": [
[20000, 200],
[40000, 400],
[40000, 400]
],
"name": "Subject Property"
}]
I need to end up with 2 separate arrays.
First Array
Array1 = [{
"name": "Chantal Hamlet - Green Castle Homes",
"subId": "10223",
"bldId": "13551"
}, {
"name": "Ella Sea Condos - Sahnow Construction",
"subId": "9761",
"bldId": "27380"
}, {
"style": "smooth",
"color": "blue",
"name": "Subject Property"
}]
Second Array
Array2 = [
{
"data": [
[179900, 1386],
[214900, 1440],
[194500, 1496],
[217900, 1504],
[189900, 1542],
[184900, 1546],
[192500, 1570]
]
}, {
"data": [
[199900, 1500]
]
}, {
"data": [
[20000, 200],
[40000, 400],
[40000, 400]
]
}
]
You could use Array.prototype.map method.
var Array1 = customSeries.map(function(el) {
return {
name: el.name,
subId: el.subId,
bldId: el.bldId
};
});
var Array2 = customSeries.map(function(el) {
return {
data: el.data
};
});
Update:
The above code not work when your elements in customSeries don't have fixed keys except data.
If you using lodash, you could do this:
var Array1 = customSeries.map(function(el) {
return _.omit(el, 'data');
});
var Array2 = customSeries.map(function(el) {
return _.pick(el, 'data');
});
Depending on the length of the array, you might want to do this in a single pass. Using linq.js here won't help much for this, it'll just be added overhead with no real benefit.
If you don't mind obliterating your original data, you can process them both simultaneously by going through each of the items and add a copy of the data array to the second array while deleting the data from the item.
var array1 = data,
array2 = [];
array1.forEach(function (item) {
array2.push({
data: item.data
});
delete item.data;
});
If you'd rather keep your original data, you'll have to clone each item as you process them.
var array1 = [],
array2 = [];
data.forEach(function (item) {
var noData = yourCloneMethod(item); // replace call with preferred clone method
delete noData.data;
array1.push(noData);
array2.push({
data: item.data
});
});
You might want to look into using lodash, it has a lot of great functions for manipulating arrays and performing MapReduce functions.

Dynamically changing Label in Line chart

I am getting the following JSON object from a webserver in response object:
(JSON Array :[{"JUL":"5"},{"AUG":"7"},{"SEP":"9"},{"OCT":"11"},{"NOV":"13"}, {"DEC":"15"},{"JAN":"17"},{"FEB":"19"},{"MAR":"21"},{"APR":"23"},{"MAY":"25"},{"JUN":"27"}])
I am taking keys of the JSON object in an array
var al_key = [];
//For loop for x axis dispaly.
alert("al_key.length --------->"+al_key.length);
var jsonObj = []; //declare array
for (var i = 0; i < al_key.length; i++) {
jsonObj.push({value: i, text: al_key[i].value});
}
// Add axes
chart.addAxis("x", {min:1, max: 12 ,labels: jsonObj , fixLower: "major", microTicks: true, majorTickStep: 1});
chart.addAxis("y", { min: 0, max: 50, vertical: true, fixLower: "major", fixUpper: "major", includeZero: true });
However, it's not working the way I expect it to. Any suggestions as to where I am getting this wrong? Or alternative ways to display months on the x-axis dynamically? Thanks in advance for any help.
Pasted response as a question edit:
Actually i am getting JSONArray Object which contain single JSONObject which contains values like
//Server side coding..
JSONObject object=new JSONObject();
object.put("JAN":"17");
object.put("FEB":"19");
object.put("MAR":"21");
object.put("APR":"23");
object.put("MAY":"24");
object.put("JUN":"27");
JSONArray arrayObj=new JSONArray();
arrayObj.add(object);
On System.out.println(arrayObj); // our json appears like {"JAN":"17"},{"FEB":"19"},{"MAR":"21"},{"APR":"23"}, //{"MAY":"24"},{"JUN":"27"}];
On jsp:
//Call to the database to fetch the desired value
dojo.xhrGet( { url : "/POC/Action.do",
handleAs : "json",
sync: true,
load : function(response, ioArgs) {
alert("retrived response ------"+response);
for(var i in response)
for(var x in response[i])
output.push(response[i][x]);
alert("Get value to draw line chart---------------------->"+output);
},
error: function(response, ioArgs){
dojo.byId("grid").innerHTML = "An error occurred, with response: " + response;
return response;
},
handleAs: "json" });
the response object contain the return value (JSONArray object);
now this key is need to be displayed in the x axis of the chart. Do i need to again get the key and prepare the json object which is formed in the form said above by you..
In reply to your updated information:
Change the way you send the JSON (based on the limited info available,I am assuming is a Java servlet using the org.jon package)
JSONArray array = new JSONArray();
arrayObj.put (new JSONObject("{'month':'JAN', 'value':'17'}");
// and repeat for the rest of the data
You can use it then in your dojo chart as I wrote below (jsonObj3).
Original comment.
Check at the examples here, specially the part:
labels: [{value: 0, text: "zero"},
{value: 2, text: "two"},
{value: 4, text: "four"}
and add the two series
addSeries("Series A", [1, 2, 3, 4, 5], {stroke: {color: "red"}, fill: "lightpink"}).
addSeries("Series B", [5, 4, 3, 2, 1], {stroke: {color: "blue"}, fill: "lightblue"}).
For the series, the JSON might be
var months = ["JUL","AUG","SEP","OCT","NOV","DEC","JAN","FEB","MAR","APR","MAY","JUN"];
var jsonObj2 = [];
for (var i = 0; i < months.length ; i++) {
jsonObj2.push({value: i, text: months[i]});
}
If you want one single JSON object, try arranging it like this:
var data = [{month: "JUL", value:"5"},
{month: "AUG", value:"7"},
{month: "SEP", value:"9"},
{month: "OCT", value:"11"},
{month: "NOV", value:"13"},
{month: "DEC", value:"15"},
{month: "JAN", value:"17"},
{month: "FEB", value:"19"},
{month: "MAR", value:"21"},
{month: "APR", value:"23"},
{month: "MAY", value:"25"},
{month: "JUN", value:"27"}];
var jsonObj3 = [];
for (var i = 0; i < data.length ; i++) {
jsonObj3.push({value: i, text: data[i].month});
}

Categories