Trazar datos de series de tiempo

Trazar datos de series de tiempo

Me gustaría trazar series de tiempo trimestrales con características especiales del eje x. En particular, me gustaría ver marcas pequeñas que indiquen cuándo comienzan los trimestres y marcas más grandes que indiquen cuándo comienzan los años, pero solo me gustaría etiquetar los años (y no los trimestres). Con fines ilustrativos, el siguiente ejemplo hace exactamente lo que quiero, excepto que el código no es nada flexible.

\documentclass{article}   
\usepackage{pgfplots}   
\usepackage{filecontents}
\pgfplotsset{width=8cm,compat=newest}   
\usepgfplotslibrary{dateplot}     

\usetikzlibrary{calc}

\begin{filecontents}{Quarterly.dat}
date    Y
2009-02-15  1
2009-05-15  2
2009-08-15  3
2009-11-15  4
2010-02-15  4
2010-05-15  4
2010-08-15  4
2010-11-15  4
2011-02-15  4
2011-05-15  4
2011-08-15  4
2011-11-15  4
2012-02-15  4
2012-05-15  4
2012-08-15  4
2012-11-15  4
2013-02-15  4
2013-05-15  4
2013-08-15  4
2013-11-15  4
\end{filecontents}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
mark =none,
xmin=2008-12-01,
xmax=2012-02-01,
major tick length=4pt,
minor tick length=2pt,
date coordinates in=x,
minor x tick num=3,
xtick={2009-01-01,2010-01-01,2011-01-01,2012-01-01}, 
xticklabels= {\year,\year,\year},
x tick label style={anchor=east,xshift=1.5cm,yshift=-0.3cm},
]
\addplot [only marks,green]table [x=date,y=Y]{Quarterly.dat}; %
\end{axis}
\end{tikzpicture}
\end{document} 

El código no es flexible por varias razones. Por ejemplo, si escribo xtick={2009-01-01,2010-01-01,2011-01-01,2012-01-01,2013-01-01}, minor x tick num=3deja de funcionar (probablemente porque los ticks no están a la misma distancia). El ejemplo también requiere que lo configure manualmente xshift(en el ejemplo xshift=1.5cm). Sería fantástico si el código pudiera etiquetar automáticamente todos los años para cualquier serie temporal trimestral. También intenté usar la opción extra x ticks, pero sin éxito.

captura de pantalla

Respuesta1

Resulta que esta es una muy buena práctica para x coord trafo/.codey x coord inv trafo/.code. Antes de eso déjame explicarte un poco.

Su problema se divide en las siguientes tres partes:

  • En primer lugar, las garrapatas importantes deberían aparecer cada víspera de año nuevo. Pero dateplotno sabe nada sobre el año nuevo.
  • En segundo lugar, las garrapatas menores aparecen sólo si las garrapatas mayores se separan uniformemente. Pero los años duran 365 o 366 días.
  • En tercer lugar, desea controlar el diseño.

Hay una manera muy fácil de superarlo: hacer años tan anchos entre sí. Más precisamente, uso 2015.09314 para representar hoy, 3 de febrero de 2015. Esto cambia todo porque:

  • Las vísperas de año nuevo ahora están representadas por números enteros ypgfplots AMAentero.
  • Los años miden una unidad.
  • Controlar el diseño es más fácil con algo como xmin=2008.

Así que todo lo que tienes que hacer es consultar tikzlibrarypgfplots.dateplot.code.texy escribir el tuyo propio year coordinates in. En el siguiente código, /pgfplots/#1 coord trafose utiliza para transformar su entrada 2015-2-3a un número decimal 2015.09314para luego pgfplotspoder trazar datos. Por otro lado, x coord inv trafose utiliza para transformar el número decimal en un texto de etiqueta. (Por ejemplo, MMXVen lugar de 2015.) (No hice este porque el valor predeterminado es lo suficientemente bueno). (Bueno... lo configuré 1000 sepa nada en otra sintaxis).

\documentclass[border=1cm]{standalone}
\usepackage{pgfplots}
    \usepgfplotslibrary{dateplot}
\begin{filecontents}{\jobname-Quarterly.dat}
date Y
2009-01-01 9
2009-12-31 9
2010-01-01 0
2010-12-31 0
2014-01-01 4
2014-12-31 4
\end{filecontents}

\makeatletter
\pgfplotsset{
    /pgfplots/year coordinates in/.code={
        \pgfkeysalso{%
            #1 tick label style={/pgf/number format/1000 sep=}, % "2015" rather than "2,015"
            #1 tick label as interval,
            minor #1 tick num=11 % January, ..., December
        }
        \pgfkeysdef{/pgfplots/#1 coord trafo}{
            \begingroup
            \edef\pgfplotstempjuliandate{##1}
            % check if we also have a TIME like '2006-01-01 11:21'
            \expandafter\pgfutil@in@\expandafter:\expandafter{\pgfplotstempjuliandate}
            \ifpgfutil@in@
                % we have a TIME!
                \expandafter\pgfplotslibdateplot@map@time\pgfplotstempjuliandate:\dateto\pgfplotstempjuliandate\timeto\pgfplotstemptime
            \else
                \let\pgfplotstemptime=\pgfutil@empty
            \fi
            \expandafter\pgfcalendardatetojulian\expandafter{\pgfplotstempjuliandate}\c@pgf@counta
            \expandafter\pgfcalendardatetojulian\expandafter{\year-1-0}\c@pgf@countb
            \expandafter\pgfcalendardatetojulian\expandafter{\year-12-31}\c@pgf@countc
            \advance\c@pgf@counta by-\c@pgf@countb % now a = #days from 1/1 to temp
            \advance\c@pgf@countc by-\c@pgf@countb % now b = #days of that year
            \ifx\pgfplotstemptime\pgfutil@empty
                % no time:
                \pgfmathparse{\year+\the\c@pgf@counta/\the\c@pgf@countc}
            \else
                % add time fraction (which should be in the range
                % [0,1]).
                \ifdim\pgfplotstemptime pt<1pt
                    % discard prefix '0.':
                    \expandafter\pgfplotslibdateplot@discard@zero@dot\pgfplotstemptime\to\pgfplotstemptime
                    \pgfmathparse{\year+(\the\c@pgf@counta.\pgfplotstemptime)/\the\c@pgf@countc}%
                \else
                    % assume \pgfplotstemptime=1pt :
                    \advance\c@pgf@counta by1
                    \pgfmathparse{\year+\the\c@pgf@counta/\the\c@pgf@countc}
                \fi
            \fi
            \pgfmath@smuggleone\pgfmathresult
            \endgroup
        }
    }
}

\begin{document}
    \begin{tikzpicture}
        \begin{axis}[year coordinates in=x,minor x tick num=1]
            \addplot [only marks]table[x=date,y=Y]{\jobname-Quarterly.dat};
        \end{axis}
    \end{tikzpicture}
\end{document}

información relacionada