In my aplication I am using Highcharts and I have and data like from API
var data=[
{Part1:6,Part2:3,Test2:7,Part4:4,Part5:2},
{Part1:8,Part2:5,Test2:8,Part4:6,Part5:7,Part6:2},
{Part1:8,Part2:5,Test2:8,Part4:6,Part5:7,Part6:2,Test:3}
]
and I need to convert it to
[
{ name:"Test", data: [null, null, 3] },
{ name:"Part6", data: [null, 2, 2] },
{ name:"Part5", data: [2, 7, 7] },
{ name:"Part4", data: [4, 6, 6] },
{ name:"Test2", data: [7, 8, 8] },
{ name:"Part2", data: [3, 5, 5] },
{ name:"Part1", data: [6, 8, 8] }
];
this is my example app snipped
var data=[
{Part1:6,Part2:3,Test2:7,Part4:4,Part5:2},
{Part1:8,Part2:5,Test2:8,Part4:6,Part5:7,Part6:2},
{Part1:8,Part2:5,Test2:8,Part4:6,Part5:7,Part6:2,Test:3}
]
var expected_result=
[
{name: 'Test', data: [null, null, 3] },
{name: 'Part6', data: [null, 2,2] },
{name: 'Part5', data: [2, 7, 7] },
{name: 'Part4', data: [4, 6, 6] },
{name: 'Test2', data: [7, 8, 8] },
{name: 'Part2', data: [3, 5, 5] },
{name: 'Part1', data: [6, 8, 8] }
];
Highcharts.chart('container', {
chart: {
type: 'column'
},
title: {
text: 'Stacked column chart'
},
xAxis: {
categories: ['Net', 'Brut', 'Others']
},
tooltip: {
headerFormat: '<b>{point.x}</b><br/>',
pointFormat: '{series.name}: {point.y}<br/>Total: {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: true
}
}
},
series: expected_result
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<figure class="highcharts-figure">
<div id="container"></div>
</figure>
How can I convert my base data to expected. Thanks in advance
const data = [
{ Part1: 6, Part2: 3, Part3: 7, Part4: 4, Part5: 2 },
{ Part1: 8, Part2: 5, Part3: 8, Part4: 6, Part5: 7, Part6: 2 },
{ Part1: 8, Part2: 5, Part3: 8, Part4: 6, Part5: 7, Part6: 2, Part7: 3 },
];
const maxNumberPart = Math.max.apply(
null,
data.map(d => Object.keys(d).length),
);
const result = new Array(maxNumberPart).fill(null).map((p, i) => ({ name: `Part${maxNumberPart - i}`, data: [] }));
data.forEach(obj => {
result.forEach(part => {
part.data.push(obj[part.name] ? obj[part.name] : null);
});
});
console.log(result);
UPD dynamic key names:
const data = [
{ Part1: 6, Part2: 3, Test2: 7, Part4: 4, Part5: 2 },
{ Part1: 8, Part2: 5, Part3: 8, Part4: 6, Part5: 7, Part6: 2 },
{ Part1: 8, Part2: 5, Part3: 8, Test: 6, Part5: 7, Part6: 2, Part7: 3 },
];
const keys = data.reduce((set, val) => {
Object.keys(val).forEach(key => set.add(key));
return set;
}, new Set());
const result = [...keys].map(key => ({
name: key,
data: [],
}));
data.forEach(obj => {
result.forEach(part => {
part.data.push(obj[part.name] ? obj[part.name] : null);
});
});
console.log(result);
You can group numbers first using a foreach and then fill the null value after
you can try this it is key agnostic
var data=[
{Part1:6,part2:3,part3:7,part4:4,part5:2},
{Part1:8,part2:5,part3:8,part4:6,part5:7,part6:2},
{Part1:8,part2:5,part3:8,part4:6,part5:7,part6:2,part7:3}
]
p={}
res=[]
for(let o of data ){
Object.entries(o).forEach(k=>{
if(!p[k[0]]) res.push({name:k[0],data:p[k[0]]=[]})
p[k[0]].push(k[1])
})
}
i=0
while(i<res.length){
while(res[i].data.length<3){
res[i].data.unshift(null)}
i++
}
console.log(res.reverse())
if your keys are not the same and each time they can be different you can
try this
var data=[
{Test:6,part2:3,part3:7,part4:4,part5:2},
{Part1:8,part2:5,part3:8,part4:6,part5:7,part6:2},
{Part1:8,part2:5,part3:8,part4:6,part5:7,part6:2,part7:3}
]
p={}
res=[]
for(let o of data ){
obarr= Object.entries(o)
obarr.forEach((k)=>{
if(!p[obarr.indexOf(k)]) res.push({name:k[0],data:p[obarr.indexOf(k)]=[]})
p[obarr.indexOf(k)].push(k[1])
})
}
i=0
while(i<res.length){
while(res[i].data.length<3){
res[i].data.unshift(null)}
i++
}
console.log(res.reverse())
Related
I'm using this code to get my chart working
var d1 = [
[0, 3],
[1, 8],
[2, 5]
];
var d2 = [
[0, 3],
[1, 8],
[2, 5]
];
var d3 = [
[0, 3],
[1, 8],
[2, 5]
];
var d4 = [
[0, 3],
[1, 8],
[2, 5]
];
function plotWithOptions() {
$.plot("#placeholder", [
{ label: "novo", data: d1 },
{ label: "revisao", data: d2 },
{ label: "bla1", data: d3 },
{ label: "bla2", data: d4 },
], {
series: {
stack: 0,
bars: {
show:true,
horizontal:true,
}
},
yaxis: {
tickLength: 1,
gridLines: false,
ticks: [
[0, 'Bob'],
[1, 'Chris'],
[2, 'Joe'],
]
}
});
}
$(document).ready(function(){
plotWithOptions();
});
The problem is that the tick names are not aligned to bars.
Am I doing something wrong?
I have a time series data which I want to show as a trellis chart:
Here is a basic version of Trellis Chart from the Highcharts website:
Instead of Erik, Gert, Helge, Torstein, I am working to replace it with groups: Client, DII, FII, PRO.
In this chart below, fruits name is a simple series but here I have a time series data: Fut Index Longs and Fut Index Shorts.
Each of the above groupings( Client, DII...) have their own version of Fut Index Longs and Fut Index Shorts.
I want to show Fut Index Longs, Fut Index Shorts as stacked with the x-axis denoting the different days.
I have tried to use a nested series to accomplish this, but there is no data being displayed. Here is my source:
var charts = [],
$containers = $('#trellis td'),
datasets = [
{
name: 'Client',
data:
[
{
name: "Fut Index Longs",
data: [["2014-02-10", 5], ["2014-02-11", 9], ["2014-02-12", 7]]
},
{
name: "Fut Index Shorts",
data: [["2014-02-10", 5], ["2014-02-11", 9], ["2014-02-12", 2]]
}
]
},
{
name: 'DII',
data:
[
{
name: "Fut Index Longs",
data: [["2014-02-10", 5], ["2014-02-11", 9], ["2014-02-12", 7]]
},
{
name: "Fut Index Shorts",
data: [["2014-02-10", 5], ["2014-02-11", 9], ["2014-02-12", 2]]
}
]
},
{
name: 'FII',
data:
[
{
name: "Fut Index Longs",
data: [["2014-02-10", 5], ["2014-02-11", 9], ["2014-02-12", 7]]
},
{
name: "Fut Index Shorts",
data: [["2014-02-10", 5], ["2014-02-11", 9], ["2014-02-12", 2]]
}
]
},
{
name: 'PRO',
data:
[
{
name: "Fut Index Longs",
data: [["2014-02-10", 5], ["2014-02-11", 9], ["2014-02-12", 7]]
},
{
name: "Fut Index Shorts",
data: [["2014-02-10", 5], ["2014-02-11", 9], ["2014-02-12", 2]]
}
]
}
];
$.each(datasets, function(i, dataset) {
charts.push(new Highcharts.Chart({
chart: {
renderTo: $containers[i],
type: 'bar',
marginLeft: i === 0 ? 100 : 10
},
title: {
text: dataset.name,
align: 'left',
x: i === 0 ? 90 : 0
},
credits: {
enabled: false
},
xAxis: {
type: 'datetime'
},
yAxis: {
allowDecimals: false,
title: {
text: null
},
min: 0,
max: 10
},
plotOptions: {
column: {
stacking: 'normal'
}
},
legend: {
enabled: false
},
series: [dataset]
}));
});
The link to jsfiddle: http://jsfiddle.net/g6jLhux2/
What am I doing wrong?
In your case, you need to use
series: dataset.data
Also, your x-axis are not datetime but categories, because datetime are supposed to be passed as numbers (milliseconds). You must then use:
xAxis: {
type: 'category'
},
if you want to properly show the data in your charts. See updated jsfiddle
Does it help you ?
I'm using eCharts to plot some scatterplots. I have several data series, and what I want is for each one to sequentially appear following an animation of my choice. What's happening instead is that the first series animates by my choice, but the subsequent ones revert to the default animation, even though (as far as I can see) I'm still defining the animation for them.
Following is the shortest complete example I can make ...
var chartOptions = function(seriesData) {
let option = {
xAxis: {
min: 0,
max: 11
},
yAxis: {
min: 0,
max: 11
},
series: [{
name: "Series 1",
type: 'scatter',
data: seriesData,
color: "red",
animationDelay: function(idx) {
return idx * 250;
},
animationEasingUpdate: "linear"
}, ]
};
return option;
};
var nextSeries = function(seriesData) {
let series = {
series: [{
name: "Next series",
type: 'scatter',
data: seriesData,
color: "blue",
animationDelay: function(idx) {
return idx * 250;
},
animationEasingUpdate: "linear"
}, ]
};
return series;
};
var series1 = [
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]
];
var series2 = [
[10, 10],
[9, 9],
[8, 8],
[7, 7],
[6, 6]
];
var series3 = [
[10, 10],
[1, 1],
[8, 8],
[2, 2],
[6, 6]
];
var seriesAll = [series1, series2, series3]
var options = chartOptions(series1);
var chart1 = echarts.init(document.getElementById("ChartView"));
chart1.setOption(options);
var i = 0;
var timer = setInterval(function() {
i++;
if (i >= seriesAll.length) {
clearInterval(timer)
} else {
var nextOptions = nextSeries(seriesAll[i])
chart1.setOption(nextOptions);
};
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0/echarts-en.js"></script>
<div id="ChartView" style="height:300px;max-width:300px;">
</div>
Well, you can clear all scatterplots first then plot next series like below:
chart1.setOption(nextSeries([]));
chart1.setOption(nextOptions);
var chartOptions = function(seriesData) {
let option = {
xAxis: {
min: 0,
max: 11
},
yAxis: {
min: 0,
max: 11
},
series: [{
name: "Series 1",
type: 'scatter',
data: seriesData,
color: "red",
animationDelay: function(idx) {
return idx * 250;
},
animationEasingUpdate: "linear"
}, ]
};
return option;
};
var nextSeries = function(seriesData) {
let series = {
series: [{
name: "Next series",
type: 'scatter',
data: seriesData,
color: "blue",
animationDelay: function(idx) {
return idx * 250;
},
animationEasingUpdate: "linear"
}, ]
};
return series;
};
var series1 = [
[1, 1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]
];
var series2 = [
[10, 10],
[9, 9],
[8, 8],
[7, 7],
[6, 6]
];
var series3 = [
[10, 10],
[1, 1],
[8, 8],
[2, 2],
[6, 6]
];
var seriesAll = [series1, series2, series3]
var options = chartOptions(series1);
var chart1 = echarts.init(document.getElementById("ChartView"));
chart1.setOption(options);
var i = 0;
var timer = setInterval(function() {
i++;
if (i >= seriesAll.length) {
clearInterval(timer)
} else {
var nextOptions = nextSeries(seriesAll[i])
chart1.setOption(nextSeries([]));
chart1.setOption(nextOptions);
};
}, 2000);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" > </script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/echarts/4.1.0/echarts-en.js"> </script>
<div id = "ChartView" style = "height:300px;max-width:300px;" >
</div>
I have a JSON object which is retrieved from MySQL using PHP.It is as follows:
{
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, null, null]
}
The content can vary as it totally depends on data retrieved from database at any point of time.Now in Javascript I 'm plotting HighCharts, and need to use the data retrieved from JSON object, i.e. I' m having series:
[{
name: 'A',
data: [1, 2, 3]
}, {
name: 'B',
data: [4, 5, 6]
}, {
name: 'C',
data: [7, , ]
}]
Here I have typed array data, but it has to be dynamic, as I'll not be knowing the contents of the array. My expected output is as follows:
[{
name: ' A ',
data: Array[' A ']
// should give the data of [1,2,3]
}, {
name: ' B ',
data: Array[' B ']
}, {
name: ' C ',
data: Array[' C ']
}]
Kindly suggest how to proceed?
You can use JSON_NUMERIC_CHECK http://php.net/manual/en/json.constants.php to form proper associative array in php.
For current scenario you can update you json data dynamically
{
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, null, null]
}
to required form
[{
"name": "A",
"data": [1, 2, 3]
}, {
"name": "B",
"data": [4, 5, 6]
}, {
"name": "C",
"data": [7, 0, 0]
}]
by using code below
var dataJ = {
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, null, null]
}
var highchartsData = []; //series data
Object.keys(dataJ).map((el) => {
highchartsData.push({
name: el,
data: dataJ[el].map(Number) //convert to number
})
})
var dataJ = {
'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, null, null]
}
var highchartsData = [];
Object.keys(dataJ).map((el) => {
highchartsData.push({
name: el,
data: dataJ[el].map(Number)
})
})
Highcharts.chart('container', {
title: {
text: 'Solar Employment Growth by Sector, 2010-2016'
},
subtitle: {
text: 'Source: thesolarfoundation.com'
},
yAxis: {
title: {
text: 'Number of Employees'
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
series: highchartsData,
responsive: {
rules: [{
condition: {
maxWidth: 500
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
});
#container {
min-width: 310px;
max-width: 800px;
height: 400px;
margin: 0 auto
}
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"></div>
After looking at your fiddle I think I know what's wrong. Your server response object has the data as an array of strings. Apparently highcharts will not automatically parse these strings as numbers, but you can map the array to numbers as such:
series: [{
name: 'A',
data: myo['A'].map(parseInt)
}, {
name: 'B',
data: myo['B'].map(parseInt)
}, {
name: 'C',
data: myo['C'].map(parseInt)
}]
I want to drop multiple data into 1 tooltip. Shared is false, this is correct. One line should only show its own value.
series: [
{
name: 'Installation',
data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175, 43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175],
data2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
data3: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
},
{
name: 'Other',
data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111, 12908, 5948, 8105, 11248, 8989, 11816, 18274],
data2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
data3: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
},
]
On code above I want to add a second and third data from a query.
tooltip: {
pointFormat: '{series.name}: <b>{point.y}</b><br/> Second: {point.data2} <br> Third: {point.data3}',
},
How to add these 'point.data2' and 'point.data3' values into the tooltip? I get null as return.
Thanks in advance.
In case of your chart you should be able to use pointFormatter instead of pointFormat and inside pointFormatter get your second and third data.
http://api.highcharts.com/highcharts/tooltip.pointFormatter
tooltip: {
pointFormatter: function() {
console.log(this)
var string = this.series.name + ': ' + this.y + '<br>';
string += 'Second: ' + this.series.options.data2[this.index] + '<br>';
string += 'Third: ' + this.series.options.data3[this.index];
return string;
}
},
You can find an example of a chart with pointFormatter in the link below:
http://jsfiddle.net/km8bovdz/
Yes, this will return null, because your data2 and data3 arrays are not associated with the point in any way.
The point is within the data array, and additional data elements should be attached to each point, rather than each series.
You achieve this by making each data point an object in the data array, like this (subset of your posted data):
series: [{
name: 'Installation',
data: [{
y: 43934,
data2: 1,
data3: 1
}, {
y: 52503,
data2: 2,
data3: 2
}, {
y: 57177,
data2: 3,
data3: 3
}]
}, {
name: 'Other',
data: [{
y: 12908,
data2: 1,
data3: 1
}, {
y: 5948,
data2: 1,
data3: 1
}, {
y: 8105,
data2: 1,
data3: 1
}]
}]
Fiddle example:
http://jsfiddle.net/jlbriggs/smxqwc1y/