I've been trying and failing to implement data decimation in vue chartJS, I'm assuming parsing is the hurdle stopping me as it is the one requirement I cant seem to fulfil.
The dataset must have an indexAxis of 'x'
The dataset must be a line
The X axis for the dataset must be either a 'linear' or 'time' type axis
Data must not need parsing, i.e. parsing must be false
The dataset object must be mutable. The plugin stores the original data as dataset._data and then defines a new data property on the dataset.
My current chart options are:
oilOptions: {
responsive: true,
scales: {
y: {
... // Formatting and title
},
x: {
type: 'time'
... // Formatting and title
}
},
plugins: {
title: {
...
},
zoom: {
...
},
decimation: {
enabled: true,
algorithm: 'lttb',
samples: 500
}
The dataset is historical Brent oil price data structured like:
{
labels: [
"1987-05-20",
"1987-05-21",
...
],
datasets: [
label: "Brent Oil Price",
fill: false,
borderWidth: 2,
borderColor: "rgb(75, 192, 192)",
tension: 0.5,
pointRadius: 0,
// parsing: false (This stops data from rendering anyway)
data: [
18,
18,
...
]
]
I'm using vue-chartjs but that shouldn't be an issue.
Any help would be appreciated, my other option would be to reduce the data on the backend before passing it to the client, or have a separately saved reduced data set on my DB.
No parsing means that you need to provide the data like the internal format so no labels array and objects in your data array like so:
{
datasets: [{
label: "Brent Oil Price",
fill: false,
borderWidth: 2,
borderColor: "rgb(75, 192, 192)",
tension: 0.5,
pointRadius: 0,
parsing: false
data: [{
x: '1987-05-20',
y: 5
},
{
x: '1987-05-21',
y: 6
}
]
}]
}
The internal data format can be found in the docs here
Related
I'm using Apache ECharts 5.2.2 and try to show some markAreas in the chart on a time axis.
Apache ECharts provide some useful examples to get into some specific options. Area Pieces is an example where you can set up your own EChartsOption with markArea.
I tried to adjust the example to my needs but I fail to get it running on time axis using Date object.
If you paste the following EChartsOption into the example, you get an idea.
option = {
xAxis: {
type: 'time', // changed from 'category'
boundaryGap: false
},
yAxis: {
type: 'value',
boundaryGap: [0, '30%']
},
visualMap: {
type: 'piecewise',
show: false,
dimension: 0,
seriesIndex: 0,
pieces: [
{
min: new Date('2019-10-11'), // old tag was gt
max: new Date('2019-10-13'), // old tag was lt
color: 'rgba(0, 0, 180, 0.4)'
},
{
min: new Date('2019-10-15'), // old tag was gt
max: new Date('2019-10-17'), // old tag was lt
color: 'rgba(0, 0, 180, 0.4)'
}
]
},
series: [
{
type: 'line',
smooth: 0.6,
symbol: 'none',
lineStyle: {
color: '#5470C6',
width: 5
},
markLine: {
symbol: ['none', 'none'],
label: { show: true },
data: [{ xAxis: new Date('2019-10-11') }, { xAxis: new Date('2019-10-13') }, { xAxis: new Date('2019-10-15') }, { xAxis: new Date('2019-10-17') }]
},
areaStyle: {},
data: [
// changed from string
[new Date('2019-10-10'), 200],
[new Date('2019-10-11'), 560],
[new Date('2019-10-12'), 750],
[new Date('2019-10-13'), 580],
[new Date('2019-10-14'), 250],
[new Date('2019-10-15'), 300],
[new Date('2019-10-16'), 450],
[new Date('2019-10-17'), 300],
[new Date('2019-10-18'), 100]
]
}
]
};
visualMap defines pieces that has a begin tag min and an end tag max of the visualized area to highlight. Unfortunately, the area does not accept the beginning and ending of the defined Date object and highlights the whole chart.
What am I doing wrong to get it running on time axis? I found a bug report that is fixed in version 5.2.1 for string time data. Even string is not working so I guess, I do something wrong here... Any clue?
Thanks in advance!
I finally did it.
The tags min and max in pieces needs a number to handle data in time axis correctly. So, giving the timestamp of Date object by calling method getTime() is enough.
pieces: [
{
min: new Date('2019-10-11').getTime(),
max: new Date('2019-10-13').getTime(),
color: 'rgba(0, 0, 180, 0.4)'
},
{
min: new Date('2019-10-15').getTime(),
max: new Date('2019-10-17').getTime(),
color: 'rgba(0, 0, 180, 0.4)'
}
]
Maybe, someone else have the same problem. The documentation of Apache ECharts is sometimes not accurate enough.
I used chart js to display data but the labels are not applying properly, it applies to single column
my chart code is :
var dates = ['Lonely','Relationship','Anexity','Hurt','Fear'];
var ctxallSelect = document.getElementById('Emotional');
window.allEmotion = new Chart(ctxallSelect, {
type: 'bar',
data: {
labels: dates,
datasets: [{
label: 'Lonely',
backgroundColor: [
'rgb(0, 156, 182)'
],
borderColor: [
'rgb(0, 156, 182)'
],
data:[this.state.Lonely],
fill: false,
}, {
label: 'Relationship',
fill: false,
backgroundColor: [
'rgb(0, 156, 182)'
],
borderColor: [
'rgb(0, 156, 182)'
],
data: [this.state.Relationship],
},
But my chart label appear as below:
Your issue is related to way you are setting your data inside dataset.
I did a live demo for you solving the issue:
https://codesandbox.io/s/boring-banach-lvffs?file=/src/App.js
Data is an array, each position of that array means one column, so you should do like:
datasets: [
{
label: "Lonely",
.....
data: [30]
},
{
label: "Relationship",
.....
data: [0,45]
},
I have an app in PHP using Laravel and I've got two arrays I have to join in a single chart. Both show a quantity per month. I could write a single label as the documentation shows for a normal use case but both lines don't necessarily include the same amount of months so I'd like to associate each y axis figure to its specific month label.
var ctx = document.getElementById('flujomes');
var entregas = #json($ar_entregas);
var reversas = #json($ar_reversas);
console.log(entregas);
console.log(reversas);
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "Número de entregas",
data: entregas,
backgroundColor: [
'rgba(255, 99, 132, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
],
borderWidth: 1
},
{
label: "Número de reversas",
data: reversas,
backgroundColor: [
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(54, 162, 235, 1)'
],
borderWidth: 1
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
},
responsive: true,
maintainAspectRatio: false,
}
});
However it doesn't work as I expected:
So chart.js picks up the data but it doesn't know where x points actually are.
The problem is that the library doesn't know who to handle the x values that you are giving, only if you are using a linear axis (numerical data) it will be able to do this correctly without other options.
There are two ways to solve this,
Option 1 - Define a category axis
Since you know the values that will be on the labels you can set them with the type: 'category' , so library knows where to put the points correctly like the following example:
var chart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "Data 1",
data: [{
x: '2018-2',
y: 98
}, {
x: '2018-4',
y: 74
}, {
x: '2018-5',
y: 52
}],
}, {
label: "Data 2",
data: [{
x: '2018-3',
y: 25
}, {
x: '2018-5',
y: 52
}],
}]
},
options: {
scales: {
xAxes: [{
type: 'category',
labels: ['2018-2', '2018-3', '2018-4', '2018-5']
}]
},
tooltips: {
mode: 'x',
callbacks: {
title: function(tooltipItems, data) {
let tI = tooltipItems[0];
return data.datasets[tI.datasetIndex].data[tI.index].x;
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.0/Chart.min.js"></script>
<canvas id="ctx"></canvas>
Option 2 - Transform the labels into dates
Another possible solution will be to transform the labels from text into Date() with moment like moment("2018-2") and then set a min and max as ticks value, and also the display format, with something like:
xAxes: [{
type: 'time',
time: {
displayFormats: {
quarter: 'YYYY-MM'
}
}
}]
This is in overall a more complex solution.
Update - fix, wrong tooltip title
As mention the first solution will lead to when a user hover a point the title of the tooltip will be different from the x label, that is because that point carries a wrong index value (this index is used to return the label position).
In attempting to solve this, and since the Scatter charts create a similar result with what we are trying to achieve, I have locked up at the controller of this type here, but without luck, because in this situations or the title is ignored or the value is also wrong.
So what I came up with is something like this:
tooltips: {
mode: 'x', // optional
callbacks: {
title: function(tooltipItems, data) {
let tI = tooltipItems[0];
return data.datasets[tI.datasetIndex].data[tI.index].x;
}
}
}
Basically instead of searching the index in the labels array, it will get the original x data value.
In picture, I want Dataset2 be thicker than dataset1. How can custom doughnut chart like the picture?
This feature was added in v2.8 in 2019 (https://github.com/chartjs/Chart.js/pull/5951).
You can now use the weight property to assign relative widths of datasets.
// following Timo Hulzenboom's example
datasets: [
{
data: [50, 30, 20],
backgroundColor: ['#64D28C', '#F49356', '#F45656']
weight: 0.33, // will be half as thick
},
{
data: [memoryUsageValue, leftoverMemory],
backgroundColor: [PercentageColor, '#FFFFFF']
weight: 0.67,
}
]
Edit: additional documentation at https://www.chartjs.org/docs/latest/charts/doughnut.html#styling
I was also searching for this option havent found it yet.
For now I added an extra dataset with borderWidth: 42 so that the sides of ether the inner data or outdoor
datasets: [
{
data: [100],
backgroundColor: ['#FFFFFF'],
borderWidth: 42
},
{
data: [50, 30, 20],
backgroundColor: ['#64D28C', '#F49356', '#F45656']
},
{
data: [memoryUsageValue, leftoverMemory],
backgroundColor: [PercentageColor, '#FFFFFF']
}
]
Colored borders to show how it works
Non colored border for result
There is a weight: prob you can add yo your datasets
I am using Chart.js v2.5.0 to create a chart like this:
Note that sometimes the bar will go over the red dotted line. Sometimes the red dotted line will be at a different position (its normally at 25, but will be at other levels on some months).
My issue is that I want the red dotted lines to extend to the full width of the column. As you can see on the first column the red dotted line only goes halfway into the column. I have the same issue at the other end of the chart, the red dotted line only goes halfway into the column.
My current implementation here is to have a mixed chart, one is a bar chart and another is a line chart - with data like so:
data = {
labels: ['Jan 21st', 'Feb 21st', 'Mar 21st', 'Apr 21st']
datasets: [
{
type: 'bar',
label: 'A',
data: [10, 25, 18, 37],
},
{
type: 'line',
label: 'B',
data: [25, 25, 25, 25],
fill: false,
borderWidth: 1,
borderColor: '#f00',
borderDash: [5,4],
lineTension: 0,
steppedLine: true
}
]
}
Does Chart.js have an option or method for making the red dotted lines extend to the full column width?
I have had another idea, but I am not sure if this is possible: Can I use a bar graph for the red dotted line, and only show the top line of the bar graph?
Unfortunately, there isn't a way to "configure" the chart to achieve what you want. It all has to do with how the line chart scale drawing works. With that said, you can still achieve this behavior by tricking chart.js using some "dummy" data.
Basically, you create a "dummy" first and last label. Then add a corresponding "dummy" first and last value to your bar data array (this data will never be displayed). Then add a corresponding "dummy" first and last value to your line data array, but make sure you set the value the same as the next/prev value to end up with a straight line (otherwise your line will angle at the beginning and end). Here is what I mean.
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['dummy1', 'Jan 21st', 'Feb 21st', 'Mar 21st', 'Apr 21st', 'dummy2'],
datasets: [
{
type: 'bar',
label: 'A',
// the 1st and last value are placeholders and never get displayed on the chart
data: [0, 10, 25, 18, 37, 0],
},
{
type: 'line',
label: 'B',
// the 1st and last value are placeholders and never get displayed on the chart
// to get a straight line, the 1st and last values must match the same value as
// the next/prev respectively
data: [25, 25, 25, 25, 25, 25],
fill: false,
borderWidth: 1,
borderColor: '#f00',
borderDash: [5,4],
lineTension: 0,
steppedLine: true
}
]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}],
xAxes: [{
// exclude the 1st and last label placeholders by specifying the min/mix ticks
ticks: {
min: 'Jan 21st',
max: 'Apr 21st',
}
}],
}
}
});
Checkout this codepen example to see it in action.