6

These three dots should be spread out over a period of 50 seconds, but for some reason they all appear at 13:00:30.

\documentclass{minimal}
\usepackage{pgfplots}
\usepgfplotslibrary{dateplot}

\begin{document}
\begin{tikzpicture}

  \begin{axis}[
    date coordinates in=x,
    xtick=data,
    xticklabel={\hour:\minute:\second},
    scaled x ticks=false, 
    xticklabel style={anchor=east,rotate=45},
    xticklabels={13:00:30,
      13:00:40,
      13:00:50}
    ]
    \addplot table [col sep=comma,trim cells=true,y=value1,scatter,only marks] {data.csv};
  \end{axis}

\end{tikzpicture}
\end{document}

data.csv looks like this:

date,                   value1
2013-06-03 13:00:00,       2
2013-06-03 13:00:15,       3
2013-06-03 13:00:50,       14

If you change line 3 to e.g. 13:01:00 it works like a charm. So how do I increase pgfplots "resolution"?

Stefan Pinnow
  • 29,535
Lars
  • 163
  • 1
    Welcome at tex.sx! The date plot library cannot handle seconds. In order to support them, you would need a custom transformation; perhaps one which is based only on time values and transforms them to some "suitable" number? It might be based on x coord trafo (the inverse trafo is unnecessary if you provide tick labels explicitly anyway). – Christian Feuersänger Jun 11 '13 at 18:25

1 Answers1

6

The dateplot library shipped with pgfplots cannot handle seconds due to limited accuracy.

If you need accuracy of this granularity, you can probably ignore the DATE part of your input. In this case, a solution could be as follows:

\documentclass{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{dateplot}

\def\checkSameDate#1{%
    \ifnum\coordindex=0
        \gdef\itsDate{#1}%
    \else
        \def\temp{#1}%
        \ifx\temp\itsDate
        \else
            \PackageError{custom}{Sorry, expected the same date but got two different ones \itsDate\space and #1}{}%
        \fi
    \fi
}%

\def\ensuretwodigits#1{%
    \ifnum#1<10
        \edef\pgfmathresult{0#1}%
    \else
        \edef\pgfmathresult{#1}%
    \fi
}%

\pgfplotsset{
    % invoked with
    % 2013-06-03 23:59:00
    % -> 
    %  #1 = 2013
    %  #2 = 06
    %  #3 = 03
    %  #4 = 23
    %  #5 = 59
    %  #6 = 00
    @datetime to number/.code args={#1-#2-#3 #4:#5:#6}{%
        \checkSameDate{#1-#2-#3}%
        % 
        % convert to full seconds:
        \pgfmathparse{#4*3600+60*#5 + #6}%
    },
    %
    % This is a style which activates the new feature:
    date same day in x/.style={%
        x coord trafo/.style={/pgfplots/@datetime to number=##1},
        scaled x ticks=false,
        plot coordinates/math parser=false,
        %
        % the following keys are ONLY here to format tick labels
        x coord inv trafo/.code={%
            \begingroup
            % compute the value
            \pgfkeys{/pgf/fpu}%
            %
            % ... \seconds
            \pgfmathparse{mod(##1,60)}%
            \pgfmathfloattoint{\pgfmathresult}%
            \ensuretwodigits{\pgfmathresult}%
            \global\let\seconds=\pgfmathresult
            %
            % ... \minutes
            \pgfmathparse{mod( (##1 - \seconds)/60,60)}%
            \pgfmathfloattoint{\pgfmathresult}%
            \ensuretwodigits{\pgfmathresult}%
            \global\let\minutes=\pgfmathresult
            %
            % ... \hours
            \pgfmathparse{(##1 - 60*\minutes - \seconds)/3600}%
            \pgfmathfloattoint{\pgfmathresult}%
            \ensuretwodigits{\pgfmathresult}%
            \global\let\hours=\pgfmathresult
            \endgroup
        },
        xticklabel style={
            /pgf/number format/fixed,
        },
        xticklabel=\hours:\minutes:\seconds,
    },
}

\begin{document}
\begin{tikzpicture}
  \begin{axis}[
    %xtick=data,
    xticklabel style={anchor=east,rotate=45},
    date same day in x,
    ]
    \addplot table [col sep=comma,trim cells=true,y=value1,scatter,only marks] {
date,                   value1
2013-06-03 23:59:00,       2
2013-06-03 23:59:10,       3
2013-06-03 23:59:20,       3
2013-06-03 23:59:30,       3
2013-06-03 23:59:40,      3
2013-06-03 23:59:50,       14
2013-06-03 23:59:59,       14
};
  \end{axis}

\end{tikzpicture}
\end{document}

enter image description here

My idea is to provide a trivial transformation which ignores the DATE part and maps the TIME part to a number. I added a sanity check which verifies that that date part is the same.

EDIT: I added an inverse transformation which allows to format tick labels automatically, even if pgfplots chose the tick positions automatically.