# pgfplots data time format

I have this type of data set:

Time          State
22:54:14.716    5
22:54:14.716    5
22:54:14.716    5
22:54:14.716    5
22:54:14.729    4
22:54:14.919    1
22:54:14.919    1
22:54:15.128    5


I would like to plot a graph with pgfplots but the package can not read properly the time format.

You'll have to tell PGFPlots how to handle these times, which can be done using a x coord trafo/.code key. I've defined a new style timeplot that takes care of that.

Note that because you're using a numerically disadvantageous data format (you need to handle 8 significant digits), you should centre your data by defining a zero point close to your actual data range (in your example, you could subtract 22 hours). I've defined a key timeplot zero that takes an hour value for that.

\documentclass[tikz,border=2mm]{article}
\usepackage{pgfplots}
\usepgfplotslibrary{dateplot}

\def\transformtime#1:#2:#3!{
\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
\pgfmathparse{#1*3600-\pgfkeysvalueof{/pgfplots/timeplot zero}*3600+#2*60+#3}
\pgfkeys{/pgf/fpu=false}
}

\pgfplotsset{
timeplot zero/.initial=0,
timeplot/.style={
x coord trafo/.code={\expandafter\transformtime##1!},
x coord inv trafo/.code={%
\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
\pgfmathsetmacro\hours{floor(##1/3600)+\pgfkeysvalueof{/pgfplots/timeplot zero}}
\pgfmathsetmacro\minutes{floor((##1-(\hours-\pgfkeysvalueof{/pgfplots/timeplot zero})*3600)/60)}
\pgfmathsetmacro\seconds{##1-floor(##1/60)*60}
\def\pgfmathresult{\pgfmathprintnumber{\hours}:\pgfmathprintnumber{\minutes}:\pgfmathprintnumber[fixed zerofill]{\seconds}}
\pgfkeys{/pgf/fpu=false}
},
scaled x ticks=false,
xticklabel=\tick
}
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
timeplot, timeplot zero=22,
xtick={22:54:14.75,22:54:15}]
Time          State
22:54:14.716    5
22:54:14.716    5
22:54:14.716    5
22:54:14.716    5
22:54:14.729    4
22:54:14.919    1
22:54:14.919    1
22:54:15.128    5
};
\end{axis}
\end{tikzpicture}
\end{document}

• thanks for the reply. Is possible to draw the line state changes in horizontal? ie to any changes, a horizontal line maintains the new state, rather than an oblique line that connects two points ? – user21431 Oct 29 '12 at 8:45
• @user21431: Sure, just use \addplot +[const plot] .... – Jake Oct 29 '12 at 11:01
• @user21431: Glad it helped! If you consider your question solved, you can accept the answer by clicking the tick mark next to it (and upvoting) – Jake Oct 29 '12 at 22:53
• This code unfortunately fails if, in the data, 22 is replaced by 08 (or 09) with the error ! Package PGF Math Error: Digit '8' invalid for base 8 (in '08*3600-08*3600+54*60+14.75'). As pointed out here, "removing the leading zeros eliminated the error, so it looks like pgfplots thinks that a leading zero means a number in an octal basis, so any digits larger than 7 generates an error". Manually remove these zeros is not always possible. Is there a way to improve this answer in this respect? – Denis Bitouzé Oct 19 '14 at 9:44
• @DenisBitouzé I have copied Jake's approach here and modified it such that it solves the base-8-problem (and handles sub-second parts). See tex.stackexchange.com/questions/249923/… – Christian Feuersänger Jun 12 '15 at 15:37

\def\removeleadingzeros#1{\if0#1 \expandafter\else#1\fi}


new definitions: (mostly adding leading 0 to x label and no floating point for seconds)

\def\transformtime#1:#2:#3!{
\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
%\pgfmathparse{#1*3600-\pgfkeysvalueof{/pgfplots/timeplot zero}*3600+#2*60+#3}
\pgfkeys{/pgf/fpu=false}
}

\pgfplotsset{
timeplot zero/.initial=0,
timeplot/.style={
x coord trafo/.code={\expandafter\transformtime##1!},
x coord inv trafo/.code={%
\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
\pgfmathsetmacro\hours{floor(##1/3600)+\pgfkeysvalueof{/pgfplots/timeplot zero}}
\pgfmathsetmacro\minutes{floor((##1-(\hours-\pgfkeysvalueof{/pgfplots/timeplot zero})*3600)/60)}
\pgfmathsetmacro\seconds{##1-floor(##1/60)*60}
\def\pgfmathresult{\pgfmathparse{mod(\hours,60)<10?"0":{},int(mod(\hours,60))}\pgfmathresult:\pgfmathparse{mod(\minutes,60)<10?"0":{},int(mod(\minutes,60))}\pgfmathresult:\pgfmathparse{mod(\seconds,60)<10?"0":{},int(mod(\seconds,60))}\pgfmathresult}
\pgfkeys{/pgf/fpu=false}
},
scaled x ticks=false,
xticklabel=\tick
}
}


Further I removed the floating point for the seconds I did not need. But it should be easy to add.

Example:

\begin{tikzpicture}
\begin{axis}[
timeplot, timeplot zero=0,
xtick={02:08:08,11:30:15}]
Time          State
02:08:00    1
03:54:02    2
04:54:03    3
05:54:04    4
06:54:05    5
07:54:06    6
08:54:07    5
09:54:08    4
10:54:09    3
11:54:10    2
12:54:11    1
};
\end{axis}
\end{tikzpicture}


Cheers