5

As in this question, I need to add a linear regression line to a plot which has dates on the x axis, but I get following error: ! Package PGF Math Error: Could not parse input '2017-01-01' as a floating point number, sorry.

Unfortunately, the dates are not all consecutive as in the linked question, so I cannot use the proposed answer, that is using x expr=\coordindex.

How could I do?

\documentclass{standalone}
\usepackage{pgfplotstable}
\pgfplotsset{compat=1.14}
\usepgfplotslibrary{dateplot}
\usepackage{filecontents}

\begin{filecontents}{testtable.csv}
date;value
2017-01-01;0
2017-01-02;1
2017-01-11;2
2017-01-12;3
2017-02-01;4
2017-02-02;5
\end{filecontents}
\pgfplotstableread[col sep=semicolon]{testtable.csv}\testtable

\begin{document}
\begin{tikzpicture}
\begin{axis} [date coordinates in=x]
\addplot+ [only marks] table {\testtable};
\addplot+ table [y={create col/linear regression={y=value}}] {\testtable};
\end{axis}
\end{tikzpicture}
\end{document}
  • 1
    \pgfcalendardatetojulian will convert the date into a number. See page 906 of PGF manual. – John Kormylo Apr 29 '17 at 14:22
  • Intrernally pgfplots uses % #1 the date % #2 the hours % #3 the minutes % #4 is either empty or is the seconds. % #5 a macro which will be filled with the date part. % #6 the macro which will contain a number in the range [0,1] % representing hours and minutes. % % If you don't have seconds, you have to provide the second ':' sign % as dummy! In that case #4 will be empty. \def\pgfplotslibdateplot@map@time#1 #2:#3:#4\dateto#5\timeto#6{% – John Kormylo Apr 29 '17 at 14:38
  • @JohnKormylo I know about \pgfcalendardatetojulian. The question is: how to use this macro inside the \addplot command? Could you set up an mwe, please? – Luigi Apr 29 '17 at 18:24
  • 1
    You can use it to create a new column using pgfplotstable. – John Kormylo Apr 30 '17 at 2:21
8
+100

As was already suggested by John Kormylo in the comments below the question, the key is to convert the dates to integers in a new column of the data table.

For more details, please have a look at the comments in the code.

% used PGFPlots(Table) v1.14
% (borrowed code from <https://tex.stackexchange.com/a/302298/95441>)
\begin{filecontents*}{testtable.csv}
date;value
2017-01-01;0
2017-01-02;1
2017-01-11;2
2017-01-12;3
2017-02-01;4
2017-02-02;5
\end{filecontents*}
\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usepackage{pgfcalendar}    % <-- to convert the dates to Julian integers
\usepackage{pgfplots}
\usepackage{pgfplotstable}  % <-- to manipulate the data file/table
    \usepgfplotslibrary{dateplot}
    \pgfplotsset{compat=1.14}
    \pgfplotstableread[col sep=semicolon]{testtable.csv}\data
    % add new column with Julian integer numbers
        % therefore a counter is needed
        \newcount\julianday
    \pgfplotstablecreatecol[
        create col/assign/.code={
            % convert the number of the current row and save it to `\julianday'
            \pgfcalendardatetojulian{\thisrow{date}}{\julianday}
            % then give the entry of `\julianday' to `\entry' which is then
            % given to the current cell
            \edef\entry{\the\julianday}
            \pgfkeyslet{/pgfplots/table/create col/next content}\entry
        },
    ]{JulianDay}{\data}
    % because the `dateplot' library shifts automatically all dates to 0 using
    % the first found coordinate we can't use the created `JulianDay' data
    % directly for `linear regression', but have to do the same first with
    % the data
        % get the first coordinate of the column ...
        \pgfplotstablegetelem{0}{JulianDay}\of{\data}
        % ... and store it in `\xmin'
        \pgfmathtruncatemacro{\xmin}{\pgfplotsretval}
    % now create another column with the shifted values
    \pgfplotstablecreatecol[
        expr={\thisrow{JulianDay}-\xmin},
    ]{JulianDayMod}{\data}
\begin{document}
% --------------------------------------------------------
%% for debugging purposes only
%% show resulting numbers, if you want
%\pgfplotstabletypeset[
%    column type=l,
%    columns={date,JulianDay,JulianDayMod,value},
%    columns/date/.style={string type},
%    columns/JulianDay/.style={/pgf/number format/fixed},
%]\data
% --------------------------------------------------------
\begin{tikzpicture}
    \begin{axis}[date coordinates in=x]
        \addplot+ [only marks] table [x=date,y=value] {\data};
        \addplot+ [mark=none]  table [
            x=date,
            % now we can use the newly created column to do the linear regression
            y={create col/linear regression={
                x=JulianDayMod,
                y=value,
            }}
        ] {\data};
    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.