# Copy DateListPlot ticks in ListLinePlot (for large data)

It is not very surprising that plotting a PackedArray is faster to plot than a list of pairs (date, value), nonetheless the plotting time may be prohibitive with DateListPlot.

The function benchmark below takes a size as an argument, and compute a list of points to plot in three different ways:

• ListLinePlot of List of pairs (real, real)
• DateListPlot of List of pairs (date, real)
• DateListPlot of TimeSeries

As you can see, ListLinePlot is much faster.

benchmark[n_] := Block[{y, t, t2, ts},
y = RandomReal[{0, 10}, n];
t = Sort@RandomReal[{UnixTime[], UnixTime[] + 10000}, n];
t2 = FromUnixTime /@ t;
ts = TimeSeries[Transpose@{t2, y}];

{AbsoluteTiming@ListLinePlot[Transpose[{t, y}]],
AbsoluteTiming@DateListPlot[Transpose[{t2, y}]],
AbsoluteTiming@DateListPlot@ts}[[All, 1]]
]

nvals = 75*Range[60]^2;
tab = ParallelTable[benchmark[n], {n, nvals}];
ListLinePlot[Transpose[{nvals, #}] & /@ Transpose@tab,
PlotLabel -> "Timing vs Size", PlotLabels -> {"ListLinePlot", "DateListPlot",
"DateListPlot@TimeSeries"}, ImageSize -> Large]


In practice, waiting several seconds can be limiting, for example when plotting multiple curves with long time series with a dynamic range selection.

In such cases, using DateListPlot is prohibitive, so I would like to use ListLinePlot instead. However, the date formatting is neat.

Question Is it possible to display dates on the $$x$$-axis with ListLinePlot, to mimick the rendering of DateListPlot while preserving an efficient timing?

• It is not clear to me what question you are asking. I don't see any serious performance issues in your plot. All three timing results seem to be O[n]. Is there a real, practical problem with plotting 250000 dates taking 10 sec. rather than 2. Feb 28, 2021 at 0:36
• @m_goldberg I edited to ask a specific question. Yes, there a real practical problems where the timing difference has implications and that's how I discovered the timing different between the two (plotting 8 times series with 40000 points each). Feb 28, 2021 at 7:53

We can use the function SystemDateListPlotDumpDateTicks to generate date ticks. Its argument pattern is:

SystemDateListPlotDumpDateTicks[{mindate, maxdate}, ndivisons] (* or *)

SystemDateListPlotDumpDateTicks[{mindate, maxdate}, ndivisons, labelformat]


Example:

data1 = TimeSeries[{1, 1, 2, 3, 5, 8, 11}, {"Jan 1, 2015"}];
data2 = TimeSeries[{5, 8, 9, 6, 2, 4, 7}, {"Jan 1, 2015"}];

DateListPlot[{data1, data2}, PlotLegends -> {"first", "second"}]


ListPlot[{data1, data2}, PlotLegends -> {"first", "second"}, Joined -> True,
Ticks -> {SystemDateListPlotDumpDateTicks[{##}, 5] &, Automatic}]


If you use Frame -> True or use a PlotTheme such as "Detailed" that adds a frame, then we need to use FrameTicks instead of Ticks:

ListPlot[{data1, data2}, PlotLegends -> {"first", "second"},
Joined -> True,
FrameTicks -> {{Automatic, Automatic},
{SystemDateListPlotDumpDateTicks[{##}, 5] &, Automatic}},
PlotTheme -> "Detailed"]


To align grid lines with date ticks, we can specify horizontal grids using SystemDateListPlotDumpDateTicks:

ListPlot[{data1, data2}, PlotLegends -> {"first", "second"},
Joined -> True,
GridLines -> {SystemDateListPlotDumpDateTicks[{##}, 5] &, Automatic},
GridLinesStyle -> Directive[GrayLevel[0.4, 0.5], AbsoluteThickness[1],
AbsoluteDashing[{1, 2}]],
FrameTicks -> {{Automatic, Automatic},
{SystemDateListPlotDumpDateTicks[{##}, 5] &, Automatic}},
PlotTheme -> "Scientific"]


FWIW, using Graphics + GraphicsComplex may be faster than ListPlot:

Graphics[GraphicsComplex[Join[data1["Path"], data2["Path"]],
{ColorData[97] @ 1, Line[Range @ data1["PathLength"]],
ColorData[97] @ 2, Line[data1["PathLength"] + Range @ data2["PathLength"]]}],
Axes -> True,
AxesOrigin -> {Min[#["FirstTime"] & /@ {data1, data2}], 0},
AspectRatio -> 1/GoldenRatio,
Ticks -> {SystemDateListPlotDumpDateTicks[{##}, 5] &, Automatic}]


• Nice! Do you know why some PlotThemes (such as Detailed or Scientific) overwrites the ticks so your first solution no longer works? I see no conflicting options in ChartingResolvePlotTheme["Detailed", ListPlot], yet. Feb 28, 2021 at 8:59
• @anderstood, the two themes both add frame; so we need to use FrameTicks instead of Ticks.
– kglr
Feb 28, 2021 at 9:04
• Would you know why data1 = Table[{UnixTime[{2021, 03, 04, 15} + {0, 0, 0, i}], RandomReal[]}, {i, 0, 50}]; ListPlot[data1, Ticks -> {SystemDateListPlotDumpDateTicks[{##}, 10] &, Automatic}] wrongly shows data on 7th March? data1[[-1, 1]] // FromUnixTime returns correctly 6th March. Mar 4, 2021 at 20:12
• @anderstood, SystemDateListPlotDumpDateTicks interprets the dates as AbsoluteTime`.
– kglr
Mar 4, 2021 at 20:44