plotlyplotly.js

How can I use x0/dx in Plotly for a date-based x axis?


I happen to be using Plotly.js, but I suspect this is generic to Plotly across all platforms.

I'm trying to plot a scatter plot of voting intentions, with trend lines over time. There are relatively few polls, so it's okay for each poll marker to have an full x/y pair of values. However, I'm computing the trend line values on a daily basis - so it would be useful to be able to just specify a start date and an interval (1 day). It looks like Plotly supports this using x0 and dx instead of an array of x values, but my trend lines are all jammed up against the first value for each line - the dx value appears to have no effect.

The repro below shows three graphs:

(Obviously these aren't actually suitable trend lines for the values given - they're just intended to demonstrate the problem.)

const config = {displayModeBar: false};

// Working graph, but with explicit x values
{
  var polls = {
    type: 'scatter',
    mode: 'markers',
    x: ['2024-12-05', '2024-12-07' ],
    y: [2, 5],
    marker: {color: 'green'}
  };
  var trend = {
    type: 'scatter',
    mode: 'lines',
    line: {color: 'red'},
    x: ['2024-12-05', '2024-12-06', '2024-12-07', '2024-12-08' ],
    y: [1, 4, 2, 3],
  };
  var layout = {
    xaxis: {title: 'Date'}
  };
  Plotly.newPlot('working1', [polls, trend], layout, config);
}

// Working graph, using an x axis of numbers instead of dates
{
  var polls = {
    type: 'scatter',
    mode: 'markers',
    x: [3, 5],
    y: [2, 5],
    marker: {color: 'green'}
  };
  var trend = {
    type: 'scatter',
    mode: 'lines',
    line: {color: 'red'},
    x0: 3,
    dx: 1,
    y: [1, 4, 2, 3],
  };
  var layout = {
    xaxis: {title: 'Number'}
  };
  Plotly.newPlot('working2', [polls, trend], layout, config);
}

// Broken graph, but this is what effectively what I want to specify.
{
  var polls = {
    type: 'scatter',
    mode: 'markers',
    x: ['2024-12-05', '2024-12-07' ],
    y: [2, 5],
    marker: {color: 'green'}
  };
  var trend = {
    type: 'scatter',
    mode: 'lines',
    line: {color: 'red'},
    x0: '2024-12-05',
    dx: 1,
    y: [1, 4, 2, 3],
  };
  var layout = {
    xaxis: {title: 'Date'}
  };
  Plotly.newPlot('broken', [polls, trend], layout, config);
}
<script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script>
<p>Working: explicit x value dates</p>
<div id="working1" style="width:600px;height:250px;"></div>
<p>Working: x0/dx with integer values</p>
<div id="working2" style="width:600px;height:250px;"></div>
<p>Broken: x0/dx with dates</p>
<div id="broken" style="width:600px;height:250px;"></div>

I'm aware that dx is intended to be a number, but I've tried 1, "1d", "1D", "P1D", "1 day" etc, and it makes no difference.


Solution

  • The broken attempt is really close - but the dx: 1 actually means one millisecond where you want one day. (It's unfortunate that the documentation doesn't state this, as far as I can see.)

    When viewed across a span of multiple days, it's hard to see differences of milliseconds at all. If you take away the poll data and just leave the trend line, it's much easier to see what's going on. If you run the snippet below, you'll see the x axis go from midnight to "3 milliseconds past midnight".

    // Still broken code, but making it easier to see what's going on.
    const config = {displayModeBar: false};
    {
      var trend = {
        type: 'scatter',
        mode: 'lines',
        line: {color: 'red'},
        x0: '2024-12-05',
        dx: 1,
        y: [1, 4, 2, 3],
      };
      var layout = {
        xaxis: {title: 'Date'}
      };
      Plotly.newPlot('broken', [trend], layout, config);
    }
    <script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script>
    <p>Broken: x0/dx with dates</p>
    <div id="broken" style="width:600px;height:250px;"></div>

    So to fix this, you just need to specify a dx value which is the number of milliseconds in a day. There are 86,400 seconds in a day, so 86,400,000 milliseconds.

    // Fixed code.
    const config = {displayModeBar: false};
    {
      var polls = {
        type: 'scatter',
        mode: 'markers',
        x: ['2024-12-05', '2024-12-07' ],
        y: [2, 5],
        marker: {color: 'green'}
      };
      var trend = {
        type: 'scatter',
        mode: 'lines',
        line: {color: 'red'},
        x0: '2024-12-05',
        dx: 86_400_000,
        y: [1, 4, 2, 3],
      };
      var layout = {
        xaxis: {title: 'Date'}
      };
      Plotly.newPlot('fixed', [polls, trend], layout, config);
    }
    <script src="https://cdn.plot.ly/plotly-2.35.2.min.js"></script>
    <p>Fixed: x0/dx with dates</p>
    <div id="fixed" style="width:600px;height:250px;"></div>