ChartJS large data range - chart.js

I have a dataset which has large range between the largest and the smallest. My problem is that the smallest bar becomes invisible when the largest bar has too much data. Take a look at the screenshot below.
In the screenshot, the second, third, fifth and sixth bars all have one data point but they are being invisible. So my question is,
1) Is there anyway to make small data point visible for bar chart such as by setting min-height property on them?
2) If not, how can I make the chart so that hovering works on whole y-axis for a particular bar when the data is too small so that when I hover over the y-axis it shows label with data?
I've tried setting different styles on the bars to no avail.

Since you haven't provided your code, I can only tell you to use a logarithmic scale for your chart.
See this example for reference:
var dataPoints = [
{ x: 1994, y: 25437639 },
{ x: 1995, y: 44866595 },
{ x: 1996, y: 77583866 },
{ x: 1997, y: 120992212 },
{ x: 1998, y: 188507628 },
{ x: 1999, y: 281537652 },
{ x: 2000, y: 414794957 },
{ x: 2001, y: 502292245 },
{ x: 2002, y: 665065014 },
{ x: 2003, y: 781435983 },
{ x: 2004, y: 913327771 },
{ x: 2005, y: 1030101289 },
{ x: 2006, y: 1162916818 },
{ x: 2007, y: 1373226988 },
{ x: 2008, y: 1575067520 },
{ x: 2009, y: 1766403814 },
{ x: 2010, y: 2023202974 },
{ x: 2011, y: 2231957359 },
{ x: 2012, y: 2494736248 },
{ x: 2013, y: 2728428107 },
{ x: 2014, y: 2956385569 },
{ x: 2015, y: 3185996155 },
{ x: 2016, y: 3424971237 }
];
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
zoomEnabled: true,
theme: "dark2",
title:{
text: "Growth in Internet Users Globally"
},
axisX:{
title: "Year",
valueFormatString: "####",
interval: 2
},
axisY:{
logarithmic: true, //change it to false
title: "Internet Users (Log)",
titleFontColor: "#6D78AD",
lineColor: "#6D78AD",
gridThickness: 0,
lineThickness: 1,
includeZero: false,
labelFormatter: addSymbols
},
axisY2:{
title: "Internet Users",
titleFontColor: "#51CDA0",
logarithmic: false, //change it to true
lineColor: "#51CDA0",
gridThickness: 0,
lineThickness: 1,
labelFormatter: addSymbols
},
legend:{
verticalAlign: "top",
fontSize: 16,
dockInsidePlotArea: true
},
data: [{
type: "line",
xValueFormatString: "####",
showInLegend: true,
name: "Log Scale",
dataPoints: dataPoints
},
{
type: "line",
xValueFormatString: "####",
axisYType: "secondary",
showInLegend: true,
name: "Linear Scale",
dataPoints: dataPoints
}]
});

Related

apexcharts draw line chart on top of scatter chart

Currently using "Scatter Charts" to display my xy coordinates, working great. Another requirement is to draw a line chart based on average numbers on top of the scatter chart. Is this possible?
Link to Scatter Charts - https://apexcharts.com/angular-chart-demos/scatter-charts/basic/
Sample graph -
Yes, you can draw mixed charts with ApexCharts. You even have a demo of what you are looking for: Line Scatter – ApexCharts.js
I put the demo here for convenience:
let options = {
series: [{
name: 'Points',
type: 'scatter',
data: [{
x: 1,
y: 2.14
}, {
x: 1.2,
y: 2.19
}, {
x: 1.8,
y: 2.43
}, {
x: 2.3,
y: 3.8
}, {
x: 2.6,
y: 4.14
}, {
x: 2.9,
y: 5.4
}, {
x: 3.2,
y: 5.8
}, {
x: 3.8,
y: 6.04
}, {
x: 4.55,
y: 6.77
}, {
x: 4.9,
y: 8.1
}, {
x: 5.1,
y: 9.4
}, {
x: 7.1,
y: 7.14
},{
x: 9.18,
y: 8.4
}]
}, {
name: 'Line',
type: 'line',
data: [{
x: 1,
y: 2
}, {
x: 2,
y: 3
}, {
x: 3,
y: 4
}, {
x: 4,
y: 5
}, {
x: 5,
y: 6
}, {
x: 6,
y: 7
}, {
x: 7,
y: 8
}, {
x: 8,
y: 9
}, {
x: 9,
y: 10
}, {
x: 10,
y: 11
}]
}],
chart: {
height: 350,
type: 'line'
},
fill: {
type: 'solid'
},
markers: {
size: [6, 0]
},
tooltip: {
shared: false,
intersect: true
},
legend: {
show: false
},
xaxis: {
type: 'numeric',
min: 0,
max: 12,
tickAmount: 12
}
};
let chart = new ApexCharts(document.querySelector('#chart'), options);
chart.render();
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<div id="chart"></div>
This particular example has not been integrated using Angular, but I think you can do it quite easily. Take a look at this page if you need additional inspiration: Angular Mixed Chart / Combination Chart Examples – ApexCharts.js

How to plot a line with (x,y) points?

Noob question, apologies, but reading through the docs it was not obvious, and doing the obvious thing is resulting all points on x==0 !?
Many thanks in advance!
My current code is
new Chart(canvasId,{
type: 'line',
data: {
datasets: [
{
label: 'Some Data',
data: [
{ x: 0, y: 2.344317674636841 },
{ x: 9, y: 2.2913742065429688 },
{ x: 19, y: 2.2962939739227295 },
{ x: 29, y: 2.26206374168396 },
{ x: 39, y: 2.2287118434906006 },
{ x: 49, y: 2.1946732997894287 },
{ x: 59, y: 2.192193031311035 },
{ x: 69, y: 2.1846773624420166 },
{ x: 79, y: 2.122765064239502 },
{ x: 89, y: 2.1172447204589844 },
{ x: 99, y: 2.125208616256714 },
]
},
]
}
});
You are using a line chart which uses a catagory scale by default for the x axes and as you can read in this section of the docs that does not work with integers https://www.chartjs.org/docs/3.9.1/general/data-structures.html#object
So you will need to set options.scales.x.type to 'linear'

Render bars from multiple datasets at full-width when there is no overlapping data in ChartJS

Examples within. For reference, I am using the latest version of ChartJS (3.2.1) and the latest version of react-chartjs-2 (3.0.3).
I want to know how to make my bar chart display in a specific way given multiple, varying datasets. I'd like for the bars on the chart to render at their standard widths, while also allowing side-by-side overlapping where necessary.
ChartJS will handle this in my "ideal" way when you're using one dataset which may have two values that fall on the same X-Axis coordinate, but I can't seem to mimic this behavior when using multiple datasets.
It seems as though whenever two datasets share an axis, the bar widths either adjust to accommodate both sets of data even if they don't occupy the same space, or they stack on top of one another when should they occupy the same space. My goal is to only have the bars "shrink" their width when necessary, and keep their full-width otherwise.
Here is an example of what I would like to see with multiple datasets (this is how ChartJS handles the rendering when there is one dataset with barThickness: "flex" set):
In the middle, you'll notice the bar widths automatically adjusted to make room for one another.
Here is an example of what I get when I use two datasets that do not have any points where they overlap (barThickness: "flex" is set on both):
And, lastly, here is an example with some points of overlap when using two datasets:
So far the only way I've even sniffed a way around this is by creating multiple x-axes, one for one dataset, one for the other, and one for overlap. Then, by manipulating my data structures, creating datasets for each axis that contain exactly the datapoints that correspond to the desired bar widths.
That's certainly a solution, but I am dealing with a production codebase, thousands of rows of data, and several additional datasets (all of which have varying states, conditions for visibility, and rules). It becomes next-to-impossible to manage all of them together like this, let alone in a maintainable way. I've gone through the vast majority of StackOverflow questions and ChartJS documentation trying to find a cleaner solution, but have come up short thus far and would appreciate your help.
A simplified version of the code below. I've included some unused bits and pieces (mostly commented out) just to show the things I've tried thus far:
var ctx1 = document.getElementById("canvas1").getContext("2d");
var ctx2 = document.getElementById("canvas2").getContext("2d");
var ctx3 = document.getElementById("canvas3").getContext("2d");
function getBackgroundColor(data) {
const bar = data.dataset.data[data.dataIndex];
return bar.projection ? "green" : "black";
}
const dataset1Labels = ['Mar 2021', 'Apr 2021', 'May 2021', 'Jun 2021', 'Jul 2021', 'Aug 2021']
const dataset2Labels = ['Jan 2020', 'Feb 2020', 'Mar 2020', 'Apr 2020', ...dataset1Labels]
const dataset3Labels = ['Jan 2020', 'Feb 2020', 'Mar 2020', 'Apr 2020', 'May 2020', 'Jun 2020', 'Jul 2020', 'Aug 2020', ...dataset1Labels]
const dataset1 = [
{ x: "Mar 2021", y: 1, projection: false },
{ x: "Apr 2021", y: 4, projection: false },
{ x: "May 2021", y: 6, projection: false },
{ x: "May 2021", y: 9, projection: true },
{ x: "Jun 2021", y: 11, projection: true },
{ x: "Jul 2021", y: 13, projection: true },
{ x: "Aug 2021", y: 16, projection: true },
]
const dataset2 = [
{ x: "Jan 2020", y: 1 },
{ x: "Feb 2020", y: 4 },
{ x: "Mar 2020", y: 6 },
{ x: "Apr 2020", y: 8 },
{ x: "Mar 2021", y: 6 },
{ x: "Apr 2021", y: 8 },
]
const dataset3 = [
{ x: "Jan 2020", y: 1 },
{ x: "Feb 2020", y: 4 },
{ x: "Mar 2020", y: 6 },
{ x: "Apr 2020", y: 8 },
{ x: "May 2020", y: 10 },
{ x: "Jun 2020", y: 12 },
{ x: "Jul 2020", y: 12 },
{ x: "Aug 2020", y: 16 },
{ x: "Mar 2021", y: 1 },
{ x: "Apr 2021", y: 4 },
{ x: "May 2021", y: 6 },
]
var myChart = new Chart(ctx1, {
type: 'bar',
data: {
labels: dataset1Labels,
datasets: [{
label: "2 data types, distinguished by color",
data: dataset1,
backgroundColor: getBackgroundColor,
barThickness: "flex",
}]
},
options: {
plugins: {
title: {
display: true,
text: '1 dataset. Can Overlap. Full width bars.'
},
legend: {
position: "bottom",
},
},
scales: {
x: {
id: "dates",
offset: true,
},
}
}
});
var myChart2 = new Chart(ctx2, {
type: 'bar',
data: {
labels: dataset2Labels,
datasets: [
{
label: "previous year",
data: dataset2,
backgroundColor: "blue",
xAxisID: "dates",
},
{
label: "current year",
data: dataset1,
backgroundColor: "green",
},
]},
options: {
plugins: {
title: {
display: true,
text: '2 datasets. Cannot Overlap. Full width bars.'
},
legend: {
position: "bottom",
},
},
scales: {
x: {
id: "dates2",
display: false,
stacked: false,
bounds: "ticks",
grid: {
offset: true,
},
},
}
}
});
var myChart3 = new Chart(ctx3, {
type: 'bar',
data: {
labels: dataset3Labels,
datasets: [
{
label: "previous year",
data: dataset3,
backgroundColor: "blue",
// group: false,
// barThickness: "flex",
// categoryPercentage: 1,
// barPercentage: 1,
},
{
label: "current year",
data: dataset1,
backgroundColor: "green",
// group: false,
// categoryPercentage: 1,
// barThickness: "flex",
// barPercentage: 1,
},
]},
options: {
plugins: {
title: {
display: true,
text: '2 datasets. Can overlap. Half-width bars.'
},
legend: {
position: "bottom",
},
},
scales: {
x: {
id: "dates3",
display: false,
grid: {
offset: true,
},
},
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.2.1/dist/chart.min.js"></script>
<h2>Chart #1</h2>
<canvas id="canvas1"></canvas>
<h2>Chart #2</h2>
<p>Note that March and April 2021 both have data from both datasets, but only one dataset is visible</p>
<canvas id="canvas2"></canvas>
<h2>Chart #3</h2>
<canvas id="canvas3"></canvas>

Chartjs create chart with big data and fixed labels

I want to create chart of type line with chatjs. The problem is, I have date formatted: { x: real number from 0 to 1, y: integers from 0 to infinite }, and I want fixed labels to the chart in x-axis, something like: [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1].
This is how I'd like to set the chart configuration:
type: 'line',
data: {
labels: ['0', '0.1', '0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '1'],
datasets: [{
label: 'data',
data: [
{ x: 0.3, y: 446 },
{ x: 0.3331, y: 6863 },
{ x: 0.874, y: 12 },
{ x: 0.2244, y: 1565 },
{ x: 0.38899, y: 32221 },
{ x: 0.23685545, y: 3112324 },
{ x: 0.11332, y: 444423 },
{ x: 0.97694, y: 21212334 },
],
}]
},
But this is obviously not working, How can I do it?
So I found out there is another chart type of scatter. This is typically used to only points on axes chart, but it can configured to have lines between the points. Also, if marking the points on graph is unneccessary there is a configuration option to set those points' radius to 0 and this makes those hidden.
https://www.chartjs.org/docs/latest/charts/scatter.html#scatter-chart

chart.js automatic x axis distributed in time milliseconds

I'm building a local html file that will generate some graphs using chartjs when offline. I'm just testing some example data I have.
See fiddle below.
http://jsfiddle.net/joshmoto/0odcemL7/
The issue is, i've set 8 points of data for each dataset, but the graph is only outputting 2 points for each dataset.
I need my x axis to display a automatic time grid distributed in seconds. My time data consists millisecond data, but my x axis grid needs to show steps in seconds. But my points must remain accurately positioned on the graph within the steps as the data is milliseconds.
.
var ctx = document.getElementById('log_chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Engine Speed',
backgroundColor: '#ff0000',
borderColor: '#ff0000',
fill: false,
data: [{
t: new Date(0.37),
y: 2640
}, {
t: new Date(0.85),
y: 2560
}, {
t: new Date(1.33),
y: 2560
}, {
t: new Date(1.78),
y: 2560
}, {
t: new Date(2.23),
y: 2680
}, {
t: new Date(2.7),
y: 2920
}, {
t: new Date(3.16),
y: 3200
}, {
t: new Date(3.63),
y: 3520
}]
}, {
label: 'Mass Air Flow - Sensor',
backgroundColor: '#00FFFF',
borderColor: '#00FFFF',
fill: false,
data: [{
t: new Date(0.02),
y: 19.58
}, {
t: new Date(0.45),
y: 16.28
}, {
t: new Date(0.92),
y: 8.56
}, {
t: new Date(1.39),
y: 8.47
}, {
t: new Date(1.86),
y: 23.36
}, {
t: new Date(2.33),
y: 45.78
}, {
t: new Date(2.78),
y: 56.03
}, {
t: new Date(3.23),
y: 62.36
}]
}],
},
options: {
scales: {
// xAxes: [{
// type: 'time',
// displayFormats: {
// quarter: 'ss.SSS'
// },
// time: {
// unit: 'second'
// }
// }]
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0/dist/Chart.min.js"></script>
<div class="container">
<div class="col-12 mt-3 mb-3">
<canvas id="log_chart" width="600" height="200"></canvas>
</div>
</div>
Basically the data works like this...
t is the x axis but in time format seconds.
y is the value ranging from 0 - 5000
I'm trying my hardest to follow the docs but struggling to work this one out, I can't see anything obvious. If anyone can help out that would be awesome.
I think you need to provide more information to Chart.js so that it knows what to do with the X-Axis. On previous projects, I've given a labels property within the data.
Example -
// document ready
(function ($) {
var ctx = document.getElementById('log_chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [1, 2, 3, 4, 5, 6, 7, 8],
datasets: [
{
label: 'Engine Speed',
backgroundColor: '#ff0000',
borderColor: '#ff0000',
fill: false,
data: [2640,2560,2560,2560, 2680, 2920, 3200, 3520]
},
{
label: 'Mass Air Flow - Sensor',
backgroundColor: '#00FFFF',
borderColor: '#00FFFF',
fill: false,
data: [19.58, 16.28, 8.56, 8.47, 23.36, 45.78, 56.03, 62.36]
}
],
},
options: {
scales: {
yAxes: [{
stacked: false
}],
}
}
});
})(jQuery);
So the labels property can then fill your X axis, and your data sets just plot the raw data onto the graph. The problem you'll run into with this kind of dataset is that the sensors readings are significantly lower than the engine speed, so not well represented on the chart. You'll have to work out some kind of way of normalising this data so it can be properly represented, e.g. adding a multiply to the mass airflow sensor readings.
I figured out using x axis type: linear; and removed the date functionality and just used the raw millisecond data in x rather than t.
See working example below.
var ctx = document.getElementById('log_chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: 'Engine Speed',
backgroundColor: '#ff0000',
borderColor: '#ff0000',
fill: false,
data: [{
x: 0.37,
y: 2640
}, {
x: 0.85,
y: 2560
}, {
x: 1.33,
y: 2560
}, {
x: 1.78,
y: 2560
}, {
x: 2.23,
y: 2680
}, {
x: 2.7,
y: 2920
}, {
x: 3.16,
y: 3200
}, {
x: 3.63,
y: 3520
}]
}, {
label: 'Mass Air Flow - Sensor',
backgroundColor: '#00FFFF',
borderColor: '#00FFFF',
fill: false,
data: [{
x: 0.02,
y: 19.58
}, {
x: 0.45,
y: 16.28
}, {
x: 0.92,
y: 8.56
}, {
x: 1.39,
y: 8.47
}, {
x: 1.86,
y: 23.36
}, {
x: 2.33,
y: 45.78
}, {
x: 2.78,
y: 56.03
}, {
x: 3.23,
y: 62.36
}]
}],
},
options: {
responsive: true,
title: {
display: true,
text: "Chart.js Time Scale"
},
scales: {
xAxes: [{
type: 'linear',
position: 'bottom'
}]
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0/dist/Chart.min.js"></script>
<div class="container">
<div class="col-12 mt-3 mb-3">
<canvas id="log_chart" width="600" height="200"></canvas>
</div>
</div>