I'm new using highcharts and JSON.
My javascript code is this:
$(document).ready(function() {
var options = {
chart: {
renderTo: 'grafica',
type: 'spline'
},
series: [{}]
};
$.getJSON('ajax/gettipomov.aspx', function(data) {
options.series[0].data = data;
var chart = new Highcharts.Chart(options);
});
});
And the data returned by the server and received by JavaScript is this:
[{"tipoMov":"Ajuste negativo","valorTipoMov":5},{"tipoMov":"Ajuste positivo","valorTipoMov":5},{"tipoMov":"Compra","valorTipoMov":5}, {"tipoMov":"Transferencia","valorTipoMov":5},{"tipoMov":"Venta","valorTipoMov":5}]
The problem is that chart is not showing any data, the chart is blank: image
The JSON Encoding that I use is:
var encoder = new JavaScriptSerializer();
return encoder.Serialize(obj);
That's the format expected:
{ "name": "Ajuste negativo", "y": 5 },
{ "name": "Ajuste positivo", "y": 5 },
{ "name": "Compra", "y": 5},
{ "name": "Transferencia", "y": 5},
{ "name": "Venta", "y": 5}
tipoMov and valorTipoMov mean nothing to Highcharts, so change your Object to return the properties named accordingly.
Related
I am using Django to build a web serivce in Python and one of my tasks is to parse a .json file within my project.
The code compiles but the var json_data trying to hold the data becomes null when I try to access the json file.
<head>
<meta charset="UTF-8">
<title>Network Graph3</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<script>
// import json;
window.onload = function () {
var arr = [];
var json_data = open("{% static 'static/json/graphData.json' %}");
var obj = JSON.parse(json_data);
var i;
console.log(json_data)
if (obj == null){
return
}
for (i = 0; i < obj.documents; i++){
point = obj.documents[i];
arr[point.id].y = point.score;
}
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
theme: "light2",
title:{
text: "Dialog Sentiment Analysis"
},
axisY:{
includeZero: false
},
data: [{
type: "line",
dataPoints: arr
// [
// { y: 450 },
// { y: 414},
// { y: 520, indexLabel: "highest",markerColor: "red", markerType: "triangle" },
// { y: 460 },
// { y: 450 },
// { y: 500 },
// { y: 480 },
// { y: 480 },
// { y: 410 , indexLabel: "lowest",markerColor: "DarkSlateGrey", markerType: "cross" },
// { y: 500 },
// { y: 480 },
// { y: 510 }
// ]
}]
});
chart.render();
}
</script>
</head>
The sample json data looks like:
{"documents": [{"id": "0", "score": 0.8365770578384399},
{"id": "2", "score": 0.9896875619888306},
{"id": "3", "score": 0.5},
{"id": "4", "score": 0.5},
{"id": "6", "score": 0.12722820043563843},
{"id": "7", "score": 0.16494140028953552},
{"id": "8", "score": 0.7551238536834717},
{"id": "9", "score": 0.12901419401168823},
{"id": "10", "score": 0.5},
{"id": "11", "score": 0.7559014558792114},
in javascript open() is for opening URL in new tab/window not reading the content, use XMLHttpRequest() or jQuery $.ajax() / .getJSON(). or you mean want to do python open() ?
code for javascript
window.onload = function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
// proccess json here
readJson(xhr.responseText);
}
}
xhr.open('GET', "/'static/json/graphData.json=", true);
xhr.send(null);
}
function readJson(json_data) {
var arr = [];
var obj = JSON.parse(json_data);
var i;
console.log(json_data)
....
....
}
So many issues here...
I'm assuming your code is expected to call the open() python function and on this case you cannot call it from javascript context as it will be evaluated to window.open() (which has nothing to do with python) rather than python function.
So all you have to do is read json file from view and return back to template context as serialized json string, something like this:
from django.shortcuts import render
def my_view(request):
context = {"data": None}
with open('data.json') as f:
context['data'] = json.load(f)
return render(request, 'templates/my_template.html', context)
Now just use JSON.parse().
Another option is rely on $.getJSON() if you are using jQuery or similar library or AJAX, fetching json data from server via HTTP (it requires json file has public access via HTTP).
I have variable data having json data as below:
[
{
"BillingMonth":"11",
"BillingYear":"2016",
"Volume":"72",
"BillingMonthName":"November",
"BillingProduct":"Product1"
},
{
"BillingMonth":"11",
"BillingYear":"2016",
"Volume":"617",
"BillingMonthName":"November",
"BillingProduct":"Product2"
},
{
"BillingMonth":"12",
"BillingYear":"2016",
"Volume":"72",
"BillingMonthName":"December",
"BillingProduct":"Product1"
},
{
"BillingMonth":"12",
"BillingYear":"2016",
"Volume":"72",
"BillingMonthName":"December",
"BillingProduct":"Product2"
}
]
What I want to split above json data using javascript/jquery and get them stored in two variables data1, data2 having json data as below as result:
{
type: "stackedBar",
legendText: "Product1",
showInLegend: "true",
data1: [
{ x: November, y: 72 },
{ x: December, y: 72 },
]
}
and
{
type: "stackedBar",
legendText: "Product2",
showInLegend: "true",
data2: [
{ x: November, y: 617 },
{ x: December, y: 72 },
]
}
The above will bind in canvas js stackedbar chart.
Thanks!
Hey here's a solution I had a lot of fun working on I hope it works well for you. I wasn't sure if you would always have 2 products product1, product2 so I went with a more general approach for n amount of products. The result is in an array format, but you can use es6 destructuring to get the two variables data1 and data2 like I did below:
/*
* helper function to restructure json in the desired format
*/
function format(obj) {
var formatted = {
"type": "stackedBar",
"legendText": obj.BillingProduct,
"showInLegend": "true",
"data": [{
"x": obj.BillingMonthName,
"y": obj.Volume
}]
}
return formatted;
}
/*
* returns an array of unique products with corresponding BillingMonth/Volume data
*/
function getStackedBarData(data) {
// transform each obj in orignal array to desired structure
var formattedData = data.map(format);
// remove duplicate products and aggregate the data fields
var stackedBarData =
formattedData.reduce(function(acc, val){
var getProduct = acc.filter(function(item){
return item.legendText == val.legendText
});
if (getProduct.length != 0) {
getProduct[0].data.push(val.data[0]);
return acc;
}
acc.push(val);
return acc;
}, []);
return stackedBarData;
}
var data = [{
"BillingMonth": "11",
"BillingYear": "2016",
"Volume": "72",
"BillingMonthName": "November",
"BillingProduct": "Product1"
}, {
"BillingMonth": "11",
"BillingYear": "2016",
"Volume": "617",
"BillingMonthName": "November",
"BillingProduct": "Product2"
}, {
"BillingMonth": "12",
"BillingYear": "2016",
"Volume": "72",
"BillingMonthName": "December",
"BillingProduct": "Product1"
}, {
"BillingMonth": "12",
"BillingYear": "2016",
"Volume": "72",
"BillingMonthName": "December",
"BillingProduct": "Product2"
}]
var dataVars = getStackedBarData(data);
var data1 = dataVars[0];
var data2 = dataVars[1];
console.log(data1);
console.log(data2);
Hope this helps you!
I've written the following tableau webconnector to pull data from an internal API, using earthquakeUSGS.html as a guideline (https://github.com/tableau/webdataconnector). The API returns json (see code below). I've been using the "Web data connector simulator 2.0" and all has been going well. I get the correct Table, however, Im unable to "Fetch Table Data". As this is my first js script, Im very sure that is were the error is. To iterate through the data I used the answer from Korijn in this post Iterate through nested json object array
The Problem: Is probably with the js iterator over the json object. If anyone can take a look at the json (below), and have a look at my iterator, I would greatly appreciate it. This is what makes it impossible for me to fetch data.
test.js
(function() {
// Create the connector object
var myConnector = tableau.makeConnector();
// Define the schema
myConnector.getSchema = function(schemaCallback) {
var cols = [{
id: "prog",
alias: "PrognosisTime",
dataType: tableau.dataTypeEnum.string
}, {
id: "start",
alias: "Start",
dataType: tableau.dataTypeEnum.date
}, {
id: "val",
alias: "Value",
dataType: tableau.dataTypeEnum.float
}];
var tableSchema = {
id: "table",
alias: "187",
columns: cols
};
schemaCallback([tableSchema]);
};
// Download the data
myConnector.getData = function(table, doneCallback) {
$.getJSON("http://myapi.com/119%2C7777/Flattened?start=today&end=today&timeZone=CET&asOf=now&aggregation=None", function(resp) {
var feat = resp.features,
tableData = [];
tableData.push(
{"table":feat.properties.table}
);
// Iterate over the JSON object
//var SeriesId = feat.SeriesId
for(var i = 0; i <feat.DataPoints.length; i++){
var PrognosisTime = feat.DataPoints.PrognosisTime;
var Start = feat.DataPoints.Start;
var Value = feat.DataPoints.Value;
}
table.appendRows(tableData);
doneCallback();
});
};
tableau.registerConnector(myConnector);
// Create event listeners for when the user submits the form
$(document).ready(function() {
$("#submitButton").click(function() {
tableau.connectionName = "Neas"; // This will be the data source name in Tableau
tableau.submit(); // This sends the connector object to Tableau
});
});
})();
json from API
[
{
"SeriesId": 119,
"DataPoints": [
{
"PrognosisTime": null,
"Start": "2016-08-24T00:00:00",
"Value": 26.19
},
{
"PrognosisTime": null,
"Start": "2016-08-24T01:00:00",
"Value": 23.9
},
{
"PrognosisTime": null,
"Start": "2016-08-24T02:00:00",
"Value": 22.82
}
]
},
{
"SeriesId": 7777,
"DataPoints": [
{
"PrognosisTime": null,
"Start": "2016-08-24T00:00:00",
"Value": 36.39
},
{
"PrognosisTime": null,
"Start": "2016-08-24T00:15:00",
"Value": 28.81
},
{
"PrognosisTime": null,
"Start": "2016-08-24T00:30:00",
"Value": 24.28
}
]
}
]
The problem is this line:
var feat = resp.features
resp is an array from your JSON, there is nothing called features. So, simply iterate over resp (or feat = resp) and pull out your DataPoints array.
When loading external JSON file in HighCharts it shows nothing in the browser. I have following JSON data. I have included highchart.js and jquery.js in the head of my HTML code, but still I cannot get a bar chart in my browser. No error is shown in console when checking the console.
var json = [{
"key": "Apples",
"value": "4"
}, {
"key": "Pears",
"value": "7"
}, {
"key": "Bananas",
"value": "9"
}];
var processed_json = new Array();
$.map(json, function(obj, i) {
processed_json.push([obj.key, parseInt(obj.value)]);
});
$('#container').highcharts({
chart: {
type: 'column'
},
xAxis: {
type: "category"
},
series: [{
data: processed_json
}]
});
That is because the order of execution is different than we expect. ie The JSON loading section execution is happening before it get initialized.
You can put the JSON loading section code in one function and call that function after initialization function is completed(.success or .done in the HTML element's event).
I had one AJax function so I called this JSON loading function in the success of that AJAX call.
Code:
var json = [{
"key": "Apples",
"value": "4"
}, {
"key": "Pears",
"value": "7"
}, {
"key": "Bananas",
"value": "9"
}];
var processed_json = new Array();
$.map(json, function(obj, i) {
processed_json.push([obj.key, parseInt(obj.value)]);
});
if (processed_json.length != 0) {
loadJson();
}
function loadJson() {
$('#container').highcharts({
chart: {
type: 'column'
},
xAxis: {
type: "category"
},
series: [{
data: processed_json
}]
});
}
Does anyone know how I would go making a multi bar graph to be single series? In a working example that i've seen of how i want my graph to look, this function was being used for the data.
function dataFactory(seriesNum, perSeries) {
return new d3.range(0,seriesNum).map(function(d,i) { return {
key: 'Stream ' + i,
values: new d3.range(0,perSeries).map( function(f,j) {
return {
y: 10 + Math.random()*100,
x: j
}
})
};
});
}
Below is the code i'm currently using and I will also upload a picture so you can see that my labels are off position because it isn't single series.
function loadBar(){
$.getJSON('data5.json', function (json) {
var data1 = [];
for (var key in json) {
if (json.hasOwnProperty(key)) {
var item = json[key];
data1.push({
key: item.key,
values: item.values
});
}
}
var chart;
nv.addGraph(function() {
chart = nv.models.multiBarChart()
.color(d3.scale.category10().range())
.margin({bottom: 100})
.transitionDuration(300)
.delay(0)
//.rotateLabels(45)
;
chart.multibar
.hideable(true);
chart.reduceXTicks(false).staggerLabels(true).groupSpacing(0.2);
chart.xAxis
.axisLabel("Players")
.showMaxMin(false);
chart.yAxis
.axisLabel('Hours Played')
.tickFormat(d3.format('d'));
d3.select('#chart1 svg')
.datum(data1)
.call(chart);
nv.utils.windowResize(chart.update);
chart.dispatch.on('stateChange', function(e) { nv.log('New State:', JSON.stringify(e)); });
return chart;
});
});
}
$(document).ready(function(){
loadBar();
});
data5.json(just in case someone needs to see it)
{
"Member1": {
"key":"test10",
"values": [
{
"x": "test10",
"y": 20
}
]
},
"Member2":{
"key":"test9",
"values": [
{
"x": "test9",
"y": 10
}
]
},
"Member3":{
"key":"test8",
"values": [
{
"x": "test8",
"y": 4
}
]
},
"Member4":{
"key":"test7",
"values": [
{
"x": "test7",
"y": 12
}
]
},
"Member5":{
"key":"test6",
"values": [
{
"x": "test6",
"y": 30
}
]
},
"Member6":{
"key":"test5",
"values": [
{
"x": "test5",
"y": 8
}
]
}
,
"Member7":{
"key":"test4",
"values": [
{
"x": "test4",
"y": 27
}
]
},
"Member8":{
"key":"test3",
"values": [
{
"x": "test3",
"y": 17
}
]
},
"Member9":{
"key":"test2",
"values": [
{
"x": "test2",
"y": 2
}
]
},
"Member10":{
"key":"test1",
"values": [
{
"x": "test1",
"y": 55
}
]
}
![enter image description here][2]}
The expected data format for the multi-bar chart is an array of object, each of which represent a data series. Within each series object, there should be a key property naming that series, and a values array with the data points. The values array should have an object for each bar, with a categorical x value and a numerical y value.
For example, if I "stringify" the results of their data-generating function (after reducing the parameters so I only get two data series with five bars each), it looks like this:
[{
"key": "Stream0",
"values": [{
"x": 0,
"y": 0.16284738584101344
}, {
"x": 1,
"y": 2.370283172738109
}, {
"x": 2,
"y": 0.1631208266452718
}, {
"x": 3,
"y": 0.24609871793543797
}, {
"x": 4,
"y": 1.5096133160633776
}]
}, {
"key": "Stream1",
"values": [{
"x": 0,
"y": 0.12566330679904006
}, {
"x": 1,
"y": 0.1321859413211272
}, {
"x": 2,
"y": 1.4798247902549135
}, {
"x": 3,
"y": 0.10870538273358979
}, {
"x": 4,
"y": 0.16155091711225184
}]
}]
The graph looks like this:
Each series is graphed in a different colour. The bars are grouped according to their x value, side-by-side or you can switch to stacked.
The reason you were getting one narrow bar for each of your categories is because you have 11 different data series, each with one bar that has a different x-value. So for each x-value, the graph leaves room for all the data series to be plotted side-by-side, even though it doesn't have data for them.
You either need to group all your bars into one data series, with the test identified via the x-value, or you need to give them all the same x-value, with the test identified via the series key.
I know you've already got the first option pretty much working, based your other question on the discrete bar chart function.
The easiest way to modify this code to see what it looks like the other way (11 series, each with only one bar), is to tell the chart function to just use a constant value for x:
chart.x(function(d){return "test";})
With that, and data similar to yours (many series, each with only one data point), you get a chart that switches from a bar chart to a stacked area chart, like this:
(P.S., You'll of course want to remove the number-formatting tickFormat function so that you don't get "NaN" like in these pictures!)