How to do Group Stacking available in ng2-charts? - ng2-charts

In the original Chart.js the Dataset Structure has a property called stack which can be used to stack group of data sets separately.
"stack: String The ID of the group to which this dataset belongs to (when stacked, each group will be a separate stack)"
I tried doing this in ng2-charts like so:
public barChartData: any[] =[
{
data: [],
label: 'Label',
type: 'bar',
stack: '1'
}
]
But didn't do anything.
Here is the dataset property from the ng2-charts:
datasets (Array<{data: Array | number[], label: string}>) - data see about, the label for the dataset which appears in the legend and tooltips
Is there a work around for stacking groups separately?
Thank you!

You are right about what the documentation says, I'm trying to do the same thing. I tried this as an example, it should work, according to the link : http://www.chartjs.org/docs/latest/charts/bar.html
in my .ts :
public barChartData:any[]=[
{data: [65, 59, 80, 81, 56, 55, 40], label: 'Series A', stack: '1'},
{data: [28, 48, 40, 19, 86, 27, 90], label: 'Series B', stack: '1'},
{data: [42, 24, 71, 14, 31, 49, 30], label: 'Series C', stack: '2'}
];
public barChartLabels:string[] = ['2006', '2007', '2008', '2009', '2010', '2011', '2012'];
public barChartOptions:any = {
responsive: true,
scales:{
xAxes:[{
stacked:true
}],
yAxes:[{
stacked:true
}]
}
};
public barChartType:string = 'bar';
in my HTML :
<canvas id="chart1" baseChart
[datasets]="barChartData"
[labels]="barChartLabels"
[options]="barChartOptions"
[chartType]="barChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"></canvas>
I found this sample of chart.js for grouped stack bar. Unfortunately it's plain JS : https://github.com/chartjs/Chart.js/blob/master/samples/charts/bar/stacked-group.html
EDIT :
use my code above and do npm install chart.js#2.6 --save
-> it worked directly for me
I found this solution while checking if stacks were checked when creating the bars. they weren't in my current version.

So I figured out that the way to do this is to un-stack the yaxis and then add the stack to the dataset property like so:
{
data: [],
label: 'dataset 1',
type: 'bar',
yAxisID: 'bar-y-axis1',
stack: '1'
},
{
data: [],
label: 'dataset 3',
type: 'bar',
yAxisID: 'bar-y-axis1',
stack: '1'
},
{
data: [],
label: 'dataset 4',
type: 'bar',
yAxisID: 'bar-y-axis1',
stack: '1'
},

Related

echarts: bar chart start at value?

echarts: bar chart bars are located left and right of the value on the category axis:
How to tell echarts to start the bar with the value on the category axis? Like this:
To clarify the problem, here ist another example. This is a chart of the hourly sum of precipitation. Every bar should show the sum from the bottom to the top of the hour, the data values are conencted to every bottom of the hour.
as you can see, the bars are not starting at 8:00, they are starting at 7:30.
Data: (timestamps are shown in CET)
series: [
{
name: "Niederschlag",
type: "bar",
data: [[1608534000000, 3], [1608537600000, 5], [1608541200000, 2], [1608544800000, 0], [1608548400000, 1] ],
barWidth: '100%'
}
]
It should look like this:
Start point of bar here doesn't matter, you need align labels to left: https://echarts.apache.org/en/option.html#series-bar.label.align
you need a hidden xAxis like below:
option = {
xAxis: [{
type: 'category',
data: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23],
show: false
}, {
type: 'category',
data: [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24],
boundaryGap: false,
axisTick: { alignWithLabel: true },
position: 'bottom'
}],
yAxis: {
type: 'value'
},
series: [{
data: [120, 200, 150, 80, 70, 110, 130,120,210,110,210],
type: 'bar',
barCategoryGap:'20%',
itemStyle: {
},
xAxisIndex: 0,
backgroundStyle: {
color: 'rgba(220, 220, 220, 0.8)'
}
}]
};
You have not provided the complete chart config, so I recommend using this one. Also pay attention on method useUTC and you need to know that "By default, echarts uses local timezone to formate time labels"
So I see this state of Chart by you data with offset -180:
var myChart = echarts.init(document.getElementById('chart'));
var chartData = [
[1608534000000, 3],
[1608537600000, 5],
[1608541200000, 2],
[1608544800000, 0],
[1608548400000, 1],
];
var option = {
tooltip: {},
xAxis: {
type: 'time',
data: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00', '07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00', '21:00', '22:00', '23:00'],
splitNumber: 24,
},
yAxis: {
type: 'value'
},
series: [{
name: "Niederschlag",
type: "bar",
data: chartData,
barWidth: '100%',
}],
useUTC: false,
};
myChart.setOption(option);
<script src="https://cdn.jsdelivr.net/npm/echarts#4.9.0/dist/echarts.min.js"></script>
<div id="chart" style="width: 1024px;height:400px;"></div>

Multiple bars with same category name show differently based on array of arrays or array of objects

I noticed that using
option = {
xAxis: {
type: 'category',
},
yAxis: {
type: 'value'
},
series: [ {
type: 'bar',
data: [
{ name: 'Sun', value: 50 },
{ name: 'Sun', value: 80 },
{ name: 'Mon', value: 100 }
]
}]
}
There are two bars with category as 'Sun'. But if I use
option = {
xAxis: {
type: 'category',
},
yAxis: {
type: 'value'
},
series: [{
type: 'bar',
data: [
['Sun',50],
['Sun',80],
['Mon',100]
]
}]
}
I see only one bar for 'Sun' with both data elements overlapping. Why does it work with array of objects differently? Also, if instead of using inline data, if I use dataset, then both array of arrays and array of objects behave the same where there is only one bar with overlap.
The reason I am looking for clarity on this is, I have a visualMap with a different attribute for color which makes the data repeat. I am trying to figure out if I need to create separate series or use the same series.
In general is bad idea to naming data points the same name. Strange that the data in the first case did not merge... If you need make the group then in the Echarts it's named stack. For the stack you can use the same name and it will be joined into one group.
VisualMap usually the global option and affects all series but you can limit with seriesIndex.
var myChart = echarts.init(document.getElementById('main'));
var option = {
xAxis: {
data: ["Cat1", "Cat2", "Cat3", "Cat4", "Cat5", "Cat6"]
},
visualMap: {
type: 'continuous',
range: [0, 70],
seriesIndex: 2,
color: ['green', 'blue', 'red'],
},
yAxis: {},
series: [{
name: 'Series1',
stack: 'group1',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
color: 'lightgray'
}, {
name: 'Series2',
stack: 'group1',
type: 'bar',
data: [5, 20, 36, 10, 10, 20],
color: 'gray'
}, {
name: 'Series3',
stack: 'group2',
type: 'bar',
data: [50, 20, 70, 10, 60, 40],
}]
};
myChart.setOption(option);
<script src="https://cdn.jsdelivr.net/npm/echarts#4.9.0/dist/echarts.min.js"></script>
<div id="main" style="width: 600px;height:400px;"></div>

ECharts - Getting a single splitLine to render in a stacked bar chart

Trying to get a single split line to render on a stacked bar graph.
Here's the code:
options = {
tooltip: {
trigger: 'item',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['Graph 1', 'Graph 2']
},
grid: {
left: '7%',
right: '5%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: [40, 41, 42, 43, 44],
axisLabel: {
interval: 1
},
splitLine: {
show: true,
interval: function (param) {
//return param === 1; //what I'm trying to get it to do
return param > 0 && param < 2; //this doesn't work
//return param > 0; //this works, but adds a split line to everything above 1 as well, not what I want. vice versa (param < 2) also works, but again not what I want
},
lineStyle: {
type: 'dashed',
width: 2,
color: '#767676'
}
}
}
],
yAxis: [
{
type: 'value',
name: 'Y',
nameLocation: 'middle',
nameTextStyle: {
padding: [0, 0, 8, 0],
color: '#767676',
fontSize: 14
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
splitLine: {
show: false
}
}
],
series: [
{
name: 'Graph 1',
type: 'bar',
barWidth: 20,
stack: 'Graph',
itemStyle: {
color: '#db0011'
},
data: [8000, 10000, 12000, 16000, 20000]
},
{
name: 'Graph 2',
type: 'bar',
barWidth: 20,
barGap: '-100%',
stack: 'Graph',
itemStyle: {
color: '#00a69d'
},
data: [4000, 5000, 6000, 8000, 10000]
}
]
};
As per the above code,
param > 0 works but will add a split line to everything beyond 1 (1 and 2)
likewise, param < 2 will add a split line to everything before 2 (0 and 1)
param > 0 and param < 2 doesn't work (no split line appears)
setting a fixed number causes a split line to appear at the end of the graph as well, despite not being in the right interval (e.g. if my items went from 40 - 80 and I set an interval of 7, then the split line would appear before 47, 54, 61, 68, 75 and on 40 and 80)
How do I get a single split line to appear?
I've also seen Echarts how do you add dashed vertical line in between specific bars on bar chart?, however I don't have enough knowledge on how to modify this to work with a stacked bar chart.
How I want it to look like:
The way I ended up resolving this is:
var option = {
tooltip: {
trigger: 'item',
axisPointer: {
type: 'shadow'
}
},
legend: {
data: ['Graph 1', 'Graph 2']
},
grid: {
left: '7%',
right: '5%',
bottom: '3%',
containLabel: true
},
xAxis: [
{
type: 'category',
data: [40, '', 41, '', 42, '', 43, '', 44],
axisLabel: {
interval: 1
},
splitLine: {
show: false
}
}
],
yAxis: [
{
type: 'value',
name: 'Y',
nameLocation: 'middle',
nameTextStyle: {
padding: [0, 0, 8, 0],
color: '#767676',
fontSize: 14
},
axisTick: {
show: false
},
axisLabel: {
show: false
},
splitLine: {
show: false
}
}
],
series: [
{
name: 'Graph 1',
type: 'bar',
barWidth: 20,
stack: 'Graph',
data: [8000, 0, 10000, 0, 12000, 0, 16000, 0, 20000],
markLine: {
silent: true,
symbol: 'none',
label: {
show: false
},
data: [
{
name: "Test",
xAxis: 2.5,
lineStyle: {
color: '#767676',
width: 2,
type: 'dashed'
}
},
]
}
},
{
name: 'Graph 2',
type: 'bar',
barWidth: 20,
barGap: '-100%',
stack: 'Graph',
data: [4000, 0, 5000, 0, 6000, 0, 8000, 0, 10000]
}
]
};
A few things to note:
Add a bunch of empty string entries for your labels (x-axis). As can be seen above, data is [40, '', 41, '', 42, '', 43, '', 44] instead of [40, 41, 42, 43, 44].
Add zeroes in your graph series relative to where you inserted empty string labels in your x-axis data above (e.g. 4000, 0, 5000, 0, 6000, 0, 8000, 0, 10000). Do this for each graph you have.
In any of the graphs, insert the above markLine syntax I added to Graph 1. You will need to adjust the value of xAxis until you get the middle point.
Demo: https://jsfiddle.net/k9hgj5zb/1/
Credits to this link: Draw horizontal target line using EChart.JS

How can I draw an additional horizontal grid line with a specific value in Google Bar chart (Not average value)

How can I draw an additional horizontal grid line with a specific value in Google Bar chart. The line I want to draw is not the average. It is a specific value.
What I am getting
What I need
How can I do this?
EDIT
This my data model:
var data = google.visualization.arrayToDataTable([
["Month", "Points", { role: "style" }, "TARGET GOAL"],
["Apr-19", 17, "#c4c4c4", 25],
["May-19", 32, "#c4c4c4", 25],
["Jun-19", 20, "#c4c4c4", 25],
["Jul-19", 22, "#c4c4c4", 25],
["Aug-19", 27, "#c4c4c4", 25],
["Sep-19", 26, "#c4c4c4", 25],
["Oct-19", 18, "#008600", 25],
["Nov-19", 18, "#008600", 25],
["Dec-19", 18, "#008600", 25],
]);
And in options object I have this:
seriesType: 'bars',
series:{
3: {
type: 'line'
}
}
Since 25 is the value I want to be rendered as a line and it is in the 4th position.
And finally
var chart = new google.visualization.ComboChart(document.getElementById("container_id"));
Am I missing something?
EDIT-2 Complete script:
google.charts.load("current", {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart_ebcg_unitary);
function drawChart_ebcg_unitary() {
var data = google.visualization.arrayToDataTable([
["Month", "Points", { role: "style" }, "TARGET GOAL"],
["Apr-19", 17, "#c4c4c4", 25],
["May-19", 32, "#c4c4c4", 25],
["Jun-19", 20, "#c4c4c4", 25],
["Jul-19", 22, "#c4c4c4", 25],
["Aug-19", 27, "#c4c4c4", 25],
["Sep-19", 26, "#c4c4c4", 25],
["Oct-19", 18, "#008600", 25],
["Nov-19", 18, "#008600", 25],
["Dec-19", 18, "#008600", 25],
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2]);
var options = {
chartArea: {
left: 50,
width: "90%",
height: 250
},
title: "",
width: '100%',
height: 350,
bar: {groupWidth: "90%"},
legend: {position: "none"},
seriesType: 'bars',
series:{
1: {
type: 'line'
}
},
vAxis: {
minValue: 0,
title: 'SALES UNITS'
},
hAxis: {
title: 'MONTH'
},
annotations: {
textStyle: {
fontName: 'Arial, sans-serif',
color: '#000000',
fontSize: 12,
bold: true
},
alwaysOutside: true
}
};
var chart = new google.visualization.ComboChart(document.getElementById("ecbg_unitary"));
chart.draw(view, options);
}
jQuery(window).resize(function () {
drawChart_ebcg_unitary();
});
EDIT 3: Average line
How can I make the average line (please see screenshot) value (25) to appear only once, i.e at the end of the line rather than showing it on every month's column. This needs to look similar as in the screenshot under (What I need) section. Please advise.
use a ComboChart, which allows you to draw series of different types.
in the options, set the main seriesType.
then use the series option, to change the type of a specific series...
{
seriesType: 'bars',
series: {
1: {
type: 'line'
}
}
}
see following working snippet...
google.charts.load("current", {packages:['corechart']});
google.charts.setOnLoadCallback(drawChart_ebcg_unitary);
function drawChart_ebcg_unitary() {
var data = google.visualization.arrayToDataTable([
["Month", "Points", { role: "style" }, "TARGET GOAL"],
["Apr-19", 17, "#c4c4c4", 25],
["May-19", 32, "#c4c4c4", 25],
["Jun-19", 20, "#c4c4c4", 25],
["Jul-19", 22, "#c4c4c4", 25],
["Aug-19", 27, "#c4c4c4", 25],
["Sep-19", 26, "#c4c4c4", 25],
["Oct-19", 18, "#008600", 25],
["Nov-19", 18, "#008600", 25],
["Dec-19", 18, "#008600", 25],
]);
var view = new google.visualization.DataView(data);
view.setColumns([0, 1,
{
calc: "stringify",
sourceColumn: 1,
type: "string",
role: "annotation"
},
2, 3]);
var options = {
chartArea: {
left: 50,
width: "90%",
height: 250
},
title: "",
width: '100%',
height: 350,
bar: {groupWidth: "90%"},
legend: {position: "none"},
seriesType: 'bars',
series:{
1: {
type: 'line'
}
},
vAxis: {
minValue: 0,
title: 'SALES UNITS'
},
hAxis: {
title: 'MONTH'
},
annotations: {
textStyle: {
fontName: 'Arial, sans-serif',
color: '#000000',
fontSize: 12,
bold: true
},
alwaysOutside: true
}
};
var chart = new google.visualization.ComboChart(document.getElementById("ecbg_unitary"));
chart.draw(view, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="ecbg_unitary"></div>
EDIT
to display the annotation for the average only once,
use your own calculation for the annotation,
and only return a value if the row index equals the last row...
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc: 'stringify',
sourceColumn: 1,
type: 'string',
role: 'annotation'
},
2, 3, {
calc: function(dt, row) {
var annotation = null;
if (row === (dt.getNumberOfRows() - 1)) {
annotation = dt.getFormattedValue(row, 3);
}
return annotation;
},
type: 'string',
role: 'annotation'
}
]);

Highcharts markers on bar charts

I have made a chart similar to this (http://www.highcharts.com/demo/bar-basic) using Highcharts, and now I would like to add a marker in the form of a vertical line on each of the bars.
I've been trying to use "scatter" but that only allows me to add one marker per group of bars. Is there any way to change that? Or any other solutions? Thanks!
You have two solutions:
use scatter as you said, but calculate x-position (for example two bar series mean -0.25 and +0.25 to x-category. For example [1.25, 200] to show for second bar in second category.
use column range series with minPointLength set: http://jsfiddle.net/7F4hQ/ and stacks to connect series together
plotOptions: {
bar: {
dataLabels: {
enabled: true
}
},
columnrange: {
minPointLength: 5,
borderWidth: 0
}
},
series: [{
stack: 1,
name: 'Year 1800',
data: [107, 31, 635, 203, 2]
}, {
stack: 2,
name: 'Year 1900',
data: [133, 156, 947, 408, 6]
}, {
stack: 3,
name: 'Year 2008',
data: [973, 914, 4054, 732, 34]
}, {
stack: 1,
linkedTo: 0,
type: 'columnrange',
name: 'Year 1800',
data: [ [107, 108], [107, 108],[107, 108], [107, 108],[107, 108] ]
}, {
stack: 2,
linkedTo: 1,
type: 'columnrange',
name: 'Year 1900',
data: [ [107, 108], [107, 108],[107, 108], [107, 108],[107, 108] ]
}, {
stack: 3,
linkedTo: 2,
type: 'columnrange',
name: 'Year 2008',
data: [ [10, 11], [107, 108],[107, 108], [107, 108],[107, 108] ]
}]
I think Bullet Chart is what you were looking for. They might have added this feature in later versions. You can add as many bars as you want.