I'm trying to render a scatter plot in chart.js of (x,y) data where x is a date string. I've seen many examples and tutorials online where the instructor uses a function to generate the time stamp for an example chart, but I haven't found any examples that use real data like one might collect.
I have data that looks like this (collected from cron):
2017-07-08T06:15:02-0600,23.375
2017-07-08T06:20:02-0600,23.312
2017-07-08T06:25:02-0600,23.312
2017-07-08T06:30:02-0600,23.25
I tried a data like this in chart.js (both with and without "quotes" around the data string):
data: [{
x: 2017-07-08T06:15:02-0600,
y: 23.375
},{
x: 2017-07-08T06:20:02-0600,
y: 23.312
},{
x: 2017-07-08T06:25:02-0600,
y: 23.312
},{
x: 2017-07-08T06:30:02-0600,
y: 23.25
}],
Nothing renders. What am I doing wrong?
According to the documentation of scatter charts:
Unlike the line chart where data can be supplied in two different formats, the scatter chart only accepts data in a point format.
So you can't use values like 2017-07-08T06:15:02-0600. You can convert dates into numbers and use them in your data.
In your case:
data: [{
x: 1499516102000,
y: 23.375
}, {
x: 1499516402000,
y: 23.312
}, {
x: 1499516702000,
y: 23.312
}, {
x: 1499517002000,
y: 23.25
}
]
Now your xAxes will be with numbers, so you can use a callback to modify xAxes labels.
That advice isn't quite right. The javascript moment.js makes it possible to plat scatter data using dates as the x axis value. For some reason the bundled version in Chart.bundle.js wasn't working for me, so I downloaded moment.js directly. I'm using this to setup:
<script src="js/moment.js"></script>
<script src="js/Chart.min.js"></script>
and this for my chart.js data details:
data: [
{x: moment("2017-07-08T06:15:02-0600"), y: 23.375},
{x: moment("2017-07-08T06:20:02-0600"),y: 23.312},
{x: moment("2017-07-08T06:25:02-0600"),y: 23.312},
{x: moment("2017-07-08T06:30:02-0600"),y: 23.25}
],
It's working great!
Another solution that worked great for me, was to just use the line type for the chart, configure it for using dates for the x axis, and addtionally disable the lines, so that it just looks like a scatterplot.
new Chart(ctx, {
type: 'line',
data: {
datasets: [{
x: 2017-07-08T06:15:02-0600,
y: 23.375
},{
x: 2017-07-08T06:20:02-0600,
y: 23.312
},{
x: 2017-07-08T06:25:02-0600,
y: 23.312
},{
x: 2017-07-08T06:30:02-0600,
y: 23.25
}]
},
options: {
showLine: false,
scales: {
x:{
type: 'time',
display: true,
title: {
display: true,
text: 'Date'
},
},
}
}
}
);
I see this as a quite elegant solution. The documentation even specifies:
The scatter chart supports all of the same properties as the line chart. By default, the scatter chart will override the showLine property of the line chart to false.
I couldn't find a working example from these answers, so here's mine.
new Chart(document.getElementById("chart"), {
type: "line",
data: {
datasets: [
{
showLine: false,
fill: false,
data: [
{
x: new Date(Date.now()),
y: 100,
},
{
x: new Date(Date.now() + 1000 * 60 * 60),
y: 200,
},
{
x: new Date(Date.now() + 2000 * 60 * 60),
y: 300,
},
{
x: new Date(Date.now() + 3000 * 60 * 60),
y: 400,
},
],
},
],
},
options: {
plugins: {
legend: {
display: false,
},
title: {
text: "Chart.js Time Scale",
display: true,
},
},
scales: {
x: {
type: "time",
time: {
unit: "hour",
// Luxon format string
// tooltipFormat: "DD T",
},
title: {
display: true,
text: "Hour",
},
},
y: {
title: {
display: true,
text: "value",
},
},
},
},
});
I pulled it from here: https://www.chartjs.org/docs/latest/samples/scales/time-line.html
You'll need to install momentjs and its adapter:
npm install moment chartjs-adapter-moment --save
..and then import all libraries like
import Chart from "chart.js/auto";
import "chartjs-adapter-moment";
Related
I'm working on a heat map with a lot of dates, but I've now removed weekends from the data. Unfortunately, that had the side effect of adding blanks to the heat map.
I've tried the connecting nulls option to no avail: https://api.highcharts.com/highcharts/plotOptions.series.connectNulls
Also tried: showEmpty:false
And I'm aware of https://www.highcharts.com/demo/spline-irregular-time, but don't know if I can apply that here.
Here is a pic:
Ideally I would figure this out because I intend on thinning out the data further. For example I may remove every other day.
Here is the pertinent chart code:
{
...
xAxis: {
type: 'datetime',
labels: {
align: 'left',
x: 5,
y: 14,
format: '{value:%B}'
},
tickInterval: 30 * 24 * 3600 * 1000,
},
series: [{
boostThreshold: 100,
borderWidth: 0,
nullColor: '#EFEFEF',
colsize: 24 * 36e5, // one day
tooltip: {
headerFormat: '<b>Details</b><br/>',
pointFormat: 'Date: {point.x:%A, %b %e, %Y}<br/>Underlying Price: ${point.y}<br/>Positon Value:{point.positionvalue}<br/>NET:{point.net}<br/>ROI:{point.roi}%'
},
turboThreshold: Number.MAX_VALUE // #3404, remove after 4.0.5 release
}]
...
app.chart.config["series"][0]["data"] = chartData;
The chartData variable looks something like:
[{
net: -0.2
positionvalue: -0.54
roi: -30.3
value: -30.3
x: 1591329600000
y: 55
}]
If you need to see it in prod I can attach my url.
UPDATE:
Here is a fiddle:
https://jsfiddle.net/vo8syrhn/
I think that the only solution for this case is use the breaks feature. Notice that using it requires including the broken-axis module.
<script src="https://code.highcharts.com/modules/broken-axis.js"></script>
Demo: https://jsfiddle.net/BlackLabel/t72dfwz9/
API: https://api.highcharts.com/highcharts/xAxis.breaks
One way to do it is to omit the xAxis.type. You can see a demo on jsFiddle - https://jsfiddle.net/r32z7esd/ (note data for 2020-06-05 is missing)
html code
<script src="https://code.highcharts.com/highcharts.js"></script>
<div id="chart">
</div>
js
Highcharts.chart("chart", {
title: {
text: "chartTitle"
},
xAxis: {
categories: ['2020-06-06','2020-06-04','2020-06-03']
},
yAxis: [{
title: {
text: "yAxis1Title"
}
}],
series: [{type:'column',data:[3,4,7]}]
});
I'm displaying a balance of a bank account over time. My goal is to have individual tool tips that show the balance AND the transaction that the balance change corresponds to.
I know I can format the Y value with a formatter, but after looking for a few hours I can't find a way to add data to each tool tip. For example the first tool tip might change the balance from 100 to 50, the tooltip would say 'credit card payment' the next tool tip might change the balance to 500 and the tool tip would say 'Paycheck'. here's what I'm doing in my options:
series: [{
name: 'Balance',
data: [
{
x: new Date('2018-02-12').getTime(),
y: 76
}, {
x: new Date('2019-02-12').getTime(),
y: 100
},
{
x: new Date('2020-02-12').getTime(),
y: 200
}, {
x: new Date('2021-02-12').getTime(),
y: 300
},
{
x: new Date('2022-02-12').getTime(),
y: 150
}, {
x: new Date('2023-02-12').getTime(),
y: 22
}
]
}],
options: {
chart: {
type: 'line',
stacked: false,
height: 380,
zoom: {
type: 'x',
enabled: true,
autoScaleYaxis: true
},
toolbar: {
autoSelected: 'zoom'
}
},
dataLabels: {
enabled: false
},
markers: {
size: 2,
},
title: {
text: 'Account balance over time',
align: 'left'
},
yaxis: {
labels: {
formatter: function (val) {
return val.balance;
},
},
title: {
text: 'Balance'
},
},
xaxis: {
type: 'datetime',
},
tooltip: {
shared: true,
y: {
formatter: function (val) {
return "$"+val;
}
}
}
},
Here is what the tooltips look like now:
Above the word 'balance' Id like it to say the actual transaction that's changing the balance. I'm wondering if this is possible at all with apex charts.
Have you tried these options from the docs: https://apexcharts.com/docs/options/tooltip/
There is a 'custom' function you can pass to create your own custom html
under the section called 'custom: function || Array of functions'
Here is the codepen they provide.
tooltip: {
custom: function({ series, seriesIndex, dataPointIndex, w }) {
return (
'<div class="arrow_box">' +
"<span>" +
w.globals.labels[dataPointIndex] +
": " +
series[seriesIndex][dataPointIndex] +
"</span>" +
"</div>"
);
}
}
Also, there is the 'formatter: function' where you can just provide a function to the formatter, similar to what you've already done.
I am trying to display dates on xAxes with Chart.js
I tried this with 2 dates but it shows nothing.
Probably something I did wrong with the labels or date format.
<canvas id="graph"></canvas>
<script>
var ctx = document.getElementById('graph').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: ["2013-02-08", "2013-02-10"],
datasets: [{
label: "Something",
data: [{
x: "2013-02-08",
y: 1
}, {
x: "2013-02-10",
y: 10
}]
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day'
}
}]
}
}
});
</script>
Need help :)
Your code looks fine except that you don't need to define data.labels since the data in your dataset is defined as individual points through objects containing x and y properties.
Chart.js internally uses Moment.js for the functionality of the time axis. Therefore you should use the bundled version of Chart.js that includes Moment.js in a single file.
var ctx = document.getElementById('graph').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [{
label: "Something",
data: [
{ x: "2013-02-08", y: 1 },
{ x: "2013-02-10", y: 10 }
]
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: 'day'
}
}]
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
<canvas id="graph"></canvas>
I am trying to plot a bar chart with multiple datasets on a time series, however some of the data gets lost along the way.
for simplicity I have removed the ajax call and plotted some data:-
var config = {
type: 'bar',
data: {
datasets: [{
label: "Dataset 1",
data: [{
x: new Date('2017-03-01'),
y: 1
}, {
x: new Date('2017-03-02'),
y: 2
}, {
x: new Date('2017-03-03'),
y: 3
}, {
x: new Date('2017-03-04'),
y: 4
}],
backgroundColor: "red"
}, {
label: "Dataset 2",
data: [{
x: new Date('2017-03-01'),
y: 1
}, {
x: new Date('2017-03-02'),
y: 2
}, {
x: new Date('2017-03-03'),
y: 3
}, {
x: new Date('2017-03-04'),
y: 4
}],
backgroundColor: "blue"
}]
},
options: {
scales: {
xAxes: [{
type: "time",
time: {
unit: 'day',
round: 'day',
displayFormats: {
day: 'MMM D'
}
}
}],
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
}
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart(ctx, config);
using the above configuration dataset 1 point 1 and dataset 2 point 4 (so basically the first and last points) do not get drawn.
Any ideas where I am going wrong here?
Also I am using this time series version because I was hoping to have "gaps" in the chart, for example dataset 1 might have a series for 2017-03-01 and dataset 2 might not, in this case dataset 2's next date will bunch up to dataset 1's making it look like it does belong to that date.
Any help would be appreciated
I had the exact same issue when displaying a bar chart with time as the X axes.
Inside your xAxes you need to add an additional configuration option:
xAxes: [{
offset: true
}]
Description from the ChartJS documentation:
If true, extra space is added to the both edges and the axis is scaled to fit into the chart area. This is set to true in the bar chart by default.
ChartJS Documentation Cartesian
I have a simple c3js line chart w/3 different lines. When I "unselect" all 3 data sources, the x-axis tick values disappear. I was wondering if there was anyway to reverse this behavior? I'd like to show the x-axis tick values even when there is no data present.
The xaxis tick values are of a 'timeseries' type. Thanks!
Here is my c3 config for the line chart:
bindto: '#test',
data: {
x: 'date',
xFormat: '%m%d',
columns: [],
},
legend: {
position: 'bottom',
},
axis: {
y: {
tick: {
format: function (d) { return d + '%'; },
count: 5,
},
max: 100,
padding: {
top: 0,
bottom: 0,
},
},
x: {
type: 'timeseries',
tick: {
culling: false,
},
},
},
color: {
pattern: [testRateColor, firstRateColor, secRateColor],
},
Unfortunately this functionality is baked into c3.js and the only way to change this (aside from working purely from d3) is monkey patching. You will find the offender on line 6814 of c3.js:
tickExit = tick.exit().remove(),
If you change this to:
tickExit = function() {},
The ticks are no longer removed.