Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm growing desperate with amCharts doing the simplest task. Well, at least what I think is simple. I want to create a normal line chart with "normal" data. What do I mean with normal? Well, having an array with my y values, and maybe also one for x:
x = [1,2,3,4]
y = [5,6,7,8]
Shouldn't it be pretty easy to put something like this in a chart? And still I'm sitting here having no idea how to do this properly(!) in amcharts. I'm using Flask (Python) and can use jsonify to get my arrays into JSON files and send it to the client, but I'm not able to go any further.
Any ideas? I mean, shouldn't this be the most basic task? But all examples using amCharts doing special stuff with date formats for x..
Thank you very much!
First things first, if you are looking at plotting a line graph out of arbitrary X and Y coordinates (as opposed plotting series-based data), you're better off using XY chart than serial one.
Also, amCharts will not be able to plot data in separate arrays of coordinates.
You can either convert the data to a proper format at the moment of generation of data, so it looks like this:
chartData = [ {
x: 1,
y: 5
}, {
x: 2,
y: 6
}, {
x: 3,
y: 7
}, {
x: 4,
y: 8
}];
Or add some code that converts your data to amCharts-compatible data before supplying it to the chart:
/**
* Source data
*/
var x = [1,2,3,4];
var y = [5,6,7,8];
/**
* Convert source data to AmCharts-compatible format
*/
var chartData = [];
for( var i = 0; i < x.length; i++ ) {
chartData.push( {
"x": x[ i ],
"y": y[ i ]
} )
}
/**
* Create the chart
*/
var chart = AmCharts.makeChart( "chartdiv", {
"type": "xy",
"pathToImages": "http://www.amcharts.com/lib/3/images/",
"dataProvider": chartData,
"graphs": [ {
"bullet": "circle",
"bulletSize": 8,
"lineAlpha": 1,
"lineThickness": 2,
"fillAlphas": 0,
"xField": "x",
"yField": "y",
} ]
} );
Here's a working demo of the above:
http://codepen.io/amcharts/pen/15b2c710357a7e29eda11dc5caa07d44
following is the simpliest definition possible. The dateProvider is an array of objects where each element represents the x-axis item with it's y values.
AmCharts.makeChart("your element id",{
"type": "serial",
"pathToImages": "http://cdn.amcharts.com/lib/3/images/",
"categoryField": "category",
"graphs": [
{
"valueField": "column-1"
}
],
"dataProvider": [
{
"category": "1",
"column-1": "8"
},
{
"category": "2",
"column-1": 6
},
{
"category": "3",
"column-1": 2
},
{
"category": "4",
"column-1": 1
}
]
});
Live sample:
http://live.amcharts.com/2JmYT/edit/
Related
I'm working with plotly in JS, trying to draw a sunburst chart. Everything works, but i would like to make it so that the child sections on the chart each have a different color. I cant seem to figure it out, any help is extremely appreciated.
Here is how my sunburst looks:
Notice that "Enos" and "Noam" have the same color, I would like them to have either different colors, or at least different opacities.
Like so:
Here is my code:
var data = [{
"type": "sunburst",
"labels": ["Eve", "Awan", "Seth", "Enos", "Noam", "Enoch"],
"parents": ["", "Eve", "Eve", "Seth", "Seth", "Awan"],
"values": [100, 20, 80, 60, 20, 20]
}];
var layout = {
sunburstcolorway: ["#636efa", "#ef553b"]
};
Plotly.newPlot('myChart', data, layout)
If you want to have custom colors for your traces, then you need to set the colors array of the marker object. There you can set the color for every single part of the sunburst diagram:
var data = [{
"type": "sunburst",
"labels": ["Eve", "Awan", "Seth", "Enos", "Noam","Enoch"],
"parents": ["", "Eve", "Eve", "Seth", "Seth", "Awan"],
"values": [100, 20, 80, 60, 20, 20],
"opacity" : 1,
"marker": {
colors: ["#ffffff","#fc6e08","#3e81ed","#3293e3","#c429ad","#d99543"]
}
}];
var layout = {
// sunburstcolorway: ["#636efa", "#ef553b"]
};
Plotly.newPlot('myChart', data, layout)
So the first value ("Eve") has the first color of the array, the second value ("Awan")the second color, and so on. In the example, I set the opacity to 1 to get the real colors from the colors array.
when I try to draw pie chart on nodered , colors are always black. I m using dashboard-ui node. What is the missing ? or What is best way draw pie chart on nodered ui ?
msg.payload=[{
"series": [ "X", "Y"],
"colors":['#8b4513','#26138b'],
"data": [ 77,23],
"labels": [ "Jan","mon" ]
}];
There are two issues with this payload, which are stopping it from doing what you would expect:
the colors option is not currently supported as an input, and
the data must be an array of arrays, with the number of inner arrays being the same as the number of series to be shown (so in your case, an array of 1 array of y-values)
This revised payload works for me:
[
{
"series": [ "X", "Y" ],
"data": [
[ 77, 23 ]
],
"labels": [ "Jan", "mon" ]
}
]
The option to specify colors for each series would be a nice feature to add to the ui_chart node. For now, you will have to select the colors you want inside the node configuration editor. Please see the chart node's README for other examples of valid data inputs.
--
Steve
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I have an array of data containing objects like below
[
{
"name":"Q1'2016",
"y":0
},
{
"name":"Q2'2016",
"y":0
},
{
"name":"Q3'2016",
"y":0
},
{
"name":"Q4'2015",
"y":0
}
]
I want to sort them based on quarterly, so Q4'2015 should come first, then Q1'2016 and so on.
How can this be acheived?
You can use the sort method and give it a callback to sort your object based on a predicate; in your case, you want to inspect the objects' name property containing your quarter-year information. Since you'll likely have data with different quarters and years, you'll want to map the quarters to month values so you can convert them to year/month dates and compare them that way.
var data = [{
"name": "Q1'2016",
"y": 0
}, {
"name": "Q2'2016",
"y": 0
}, {
"name": "Q3'2016",
"y": 0
}, {
"name": "Q4'2015",
"y": 0
}];
var quarterToMonthMap = {
"Q1": 0,
"Q2": 3,
"Q3": 6,
"Q4": 9
}
function sortByQuarterYear(lhs, rhs) {
var lhsQuarterYear = lhs.name.split("'");
var rhsQuarterYear = rhs.name.split("'");
var lhsDate = new Date(lhsQuarterYear[1], quarterToMonthMap[lhsQuarterYear[0]]);
var rhsDate = new Date(rhsQuarterYear[1], quarterToMonthMap[rhsQuarterYear[0]]);
return lhsDate.getTime() - rhsDate.getTime();
}
document.write(JSON.stringify(data.sort(sortByQuarterYear)));
To sort by year and quarter you can use the following ES6 snippet (you can do the exact same thing using ES5, but I like writing ES6)
input.map((obj, index) => obj.name.split("'").reverse().concat(index)).sort().map(arr => input[arr[2]]);
Let's break this down a bit
input.map((obj, index) => obj.name.split("'").reverse().concat(index))
The map() method creates a new array with the results of calling a provided function on every element in this array.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Our "provided function" splits the "name" property of each object by the ' character, reverses the resulting array, and adds the current index into the resulting array.
This results in an array that looks like this:
[
["2016", "Q1", 0],
["2016", "Q2", 1],
["2016", "Q3", 2],
["2015", "Q4", 3]
]
Then we call .sort,
The sort() method sorts the elements of an array in place and returns the array. The sort is not necessarily stable. The default sort order is according to string Unicode code points.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
We then end up with an array like this:
[
["2015", "Q4", 3],
["2016", "Q1", 0],
["2016", "Q2", 1],
["2016", "Q3", 2]
]
So we now have an appendix of sorts, notice that the indexes that we threw in there aren't in order. We can use this lack of order to create order.
All we have to do is call map again, this time returning the original object related to the index that we have stored in our temporary arrays.
.map(arr => input[arr[2]]);
When we put it all together and call it, we end up with an array like this:
[
{
name: "Q4'2015",
y: 0
}, {
name: "Q1'2016",
y: 0
}, {
name: "Q2'2016",
y: 0
}, {
name: "Q3'2016",
y: 0
}
]
Here's a demo:
let input = [
{
"name":"Q1'2016",
"y":0
},
{
"name":"Q2'2016",
"y":0
},
{
"name":"Q3'2016",
"y":0
},
{
"name":"Q4'2015",
"y":0
}
];
input = input.map((obj, index) => obj.name.split("'").reverse().concat(index)).sort().map(arr => input[arr[2]]);
console.log(input);
To do the exact same thing in ES5:
input.map(function(obj, index){
return obj.name.split("'").reverse().concat(index);
}).sort().map(function(arr){
return input[arr[2]];
});
Using .sort() with a comparator function, you can easily re-format each value from "Q1'2016" to "2016Q1", allowing a simple alphanumeric comparison because "2016Q1" > "2015Q4".
function sortQuarters(arr) {
function reformat(v) {
return v.replace(/(Q\d)'(\d{4})/, "$2$1");
}
return arr.sort(function(a, b) {
return reformat(a.name).localeCompare(reformat(b.name));
});
}
console.log(sortQuarters([
{ "name":"Q1'2016", "y":0 },
{ "name":"Q3'2016", "y":0 },
{ "name":"Q2'2016", "y":0 },
{ "name":"Q4'2015", "y":0 }
]));
(Note that the reformatting I'm talking about is only within temporary variables used while sorting, it doesn't change the values in the array. Also note that the function I've shown modifies the order of the array passed to it and returns back the same array, it doesn't create a new array.)
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.
Looking for a way to make the following chart top out at 1 instead of 0.
I can set minimum: 1 in the valueAxes config section but that forces 1 to be the lower limit of what it will display regardless of where the line appears.
I don't see anything like this in the amcharts docs so I don't actually think its possible but I'm frequently wrong so I'm hoping thats the case.
There's no one-line solution to what you need.
Using minimum: 1 in combination with (or without) strictMinMax would force the scale to start at particular number, regardless of actual scope of the chart variables.
You can try a couple of more "involved" approaches.
Pre-calculate the minimum
Before the chart builds, cycle through the chart data and set minimum only if there are values close to it.
/**
* Create the chart
*/
var chart = AmCharts.makeChart("chartdiv", {
"type": "serial",
"theme": "light",
"path": "http://www.amcharts.com/lib/3/",
"dataProvider": [{
"year": "1950",
"value": 9
}, {
"year": "1951",
"value": 30
}, {
"year": "1952",
"value": 35
}, {
"year": "1953",
"value": 25
}, {
"year": "1954",
"value": 70
}, {
"year": "1955",
"value": 45
}, {
"year": "1956",
"value": 55
}],
"valueAxes": [{
"reversed": true,
// these are the made up properties that are used by our custom code
// set value axis minimum with "tentativeMinimum" if there are
// values withing "minimumThreshold" to it
"tentativeMinimum": 1,
"minimumThreshold": 9
}],
"graphs": [{
"id": "g1",
"bullet": "round",
"lineThickness": 2,
"type": "smoothedLine",
"valueField": "value"
}],
"categoryField": "year",
"categoryAxis": {
"labelsEnabled": false,
}
});
/**
* Add chart pre-processor
*/
AmCharts.addInitHandler( function( chart ) {
// check if there are any value axes defined
if ( typeof chart.valueAxes !== "object" || ! chart.valueAxes.length )
return;
// check if chart's value axis has "tentativeMinimum" set
// For the sake of simplicity we're just gonna take the first
// value axis and first graph.
// Normally we would want to check all value axes and their attached
// graphs to check for their respective values.
var axis = chart.valueAxes[0];
if ( axis.tentativeMinimum === undefined || axis.minimumThreshold === undefined )
return;
// get first charts valueField to check agains
var field = chart.graphs[0].valueField;
// cycle through the data
var min;
for ( var x = 0; x < chart.dataProvider.length; x++ ) {
if ( min === undefined || ( chart.dataProvider[x][field] < min ) )
min = chart.dataProvider[x][field];
}
// check if min is within the threshold
if ( min <= ( axis.tentativeMinimum + axis.minimumThreshold ) )
axis.minimum = axis.tentativeMinimum;
}, [ "serial" ] );
#chartdiv {
width: 400px;
height: 300px;
}
<script src="http://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="http://www.amcharts.com/lib/3/serial.js"></script>
<script src="http://www.amcharts.com/lib/3/themes/light.js"></script>
<div id="chartdiv"></div>
Swap out "0" label for "1"
Use value axis' labelFunction to simply replace zero with 1:
var chart = AmCharts.makeChart("chartdiv", {
...
"valueAxes": [{
"reversed": true,
"labelFunction": function( label ) {
return label === 0 ? 1 : label;
}
}],
...
});
Please note, that this will not influence actual value axis scale. However, the difference might not be noticeable.