6

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?

DaveL17
  • 1,673
  • 7
  • 24
  • 38
user2711286
  • 141
  • 1
  • 6

4 Answers4

8

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.

mugimugi
  • 446
  • 7
  • 19
7

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!

user2711286
  • 141
  • 1
  • 6
  • 2
    It is working great! Thanks for your solution. I then added the following to the `options.scales`: `xAxes: [{ticks: {callback: (value) => {return new Date(value).toLocaleDateString("fa-IR", {month: "short",year: "numeric"});}}}],` – pmsoltani Apr 15 '20 at 14:40
  • Worked for me to use Chart.bundle.min.js Added the type time to get the time values: ``options: {"scales": {"xAxes": [{"type": "time"}]}}`` – Fredrik Aug 22 '20 at 21:50
  • As written, your answer is unclear. Posts can be displayed in several different orders making it difficult to know which post you're referring to. It's better to reference the other answer directly. – DaveL17 Dec 03 '22 at 23:51
6

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.

chillichief
  • 1,164
  • 12
  • 22
  • This should be the accepted answer. It doesn't require the original data to be modified or changes to the core libraries. It would also work for those using CDN delivery of Chart.js. – DaveL17 Dec 03 '22 at 23:59
0

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";
DutchJelly
  • 116
  • 9