pgfplots:在每个月的第一天打勾

pgfplots:在每个月的第一天打勾

我有一个日期图,需要以编程方式在每个月的第一天(或第 n 天)打勾。我设置了以下 mwe,但不起作用:

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

\newcommand{\dateticks}{
  \foreach \i in {1,...,11}
    {\ifnum\i<10
       2016-0\i-01,%
     \else
       2016-\i-01,%
     \fi
       2016-12-01
     }
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
date coordinates in=x,
%xtick={\dateticks},        % <- This doesn't work
xtick={2016-01-01,2016-02-01,2016-03-01,2016-04-01,2016-05-01,2016-06-01,%
       2016-07-01,2016-08-01,2016-09-01,2016-10-01,2016-11-01,2016-12-01},
xticklabel=\day/\month,
xticklabel style={rotate=90},
]
\addplot coordinates {(2016-01-23,10) (2016-03-05,20) (2016-09-14,10)};
\end{axis}
\end{tikzpicture}
\end{document}

1)有什么建议吗?

2)有没有更好的(并且更加独立于用户的)方法来实现我的目标?

答案1

您的方法的问题在于,xtick={\dateticks}处理选项时不会发生任何扩展。xtick表示只有一个元素的列表,即\dateticks

解决此问题的一种方法是将图片放入宏并提供列表作为参数。

\newcommand\mygraph[1]{... xtick={#1} ...}

\dateticks现在,在移交给之前,很容易进行扩展\mygraph

\expandafter\mygraph\expandafter{\dateticks}

在这样做之前,我们必须确保它\dateticks包含日期列表,而不包含其他任何内容。

\newcommand\dateticks{2016-01-01}
\foreach \i in {2,...,12}{\xdef\dateticks{\dateticks,2016-\ifnum\i<10 0\fi\i-01}}

在此处输入图片描述

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.14}
\usepgfplotslibrary{dateplot}
\newcommand\dateticks{2016-01-01}
\foreach \i in {2,...,12}{\xdef\dateticks{\dateticks,2016-\ifnum\i<10 0\fi\i-01}}
\newcommand\mygraph[1]%
  {\begin{tikzpicture}
    \begin{axis}%
      [date coordinates in=x,
       xtick={#1},
       xticklabel=\day/\month,
       xticklabel style={rotate=90},
      ]
      \addplot coordinates {(2016-01-23,10) (2016-03-05,20) (2016-09-14,10)};
    \end{axis}
   \end{tikzpicture}%
  }
\begin{document}
\expandafter\mygraph\expandafter{\dateticks}
\end{document}

编辑:以下是生成任意开始日期和任意月份数的刻度的方法。执行后

\setdateticks{YYYY-MM-DD}{N}

该宏\dateticks包含 N 个日期的列表,以 YYYY-MM-DD 开头,每个日期的月份以 1 为增量。例如,\setdateticks{2016-12-01}{3}设置\dateticks2016-12-01,2017-01-01,2017-02-01。以下是定义 的代码\setdateticks

\newcommand\dateticks{}
\newcommand\splitdate{}
\def\splitdate#1-#2#3-#4-%
  {\def\YYYY{#1}%
   \ifnum#2=0\def\MM{#3}\else\def\MM{#2#3}\fi
   \def\DD{#4}%
  }
\newcommand\setdateticks[2]%
  {\def\dateticks{#1}%
   \bgroup
   \splitdate#1-%
   \foreach \i in {2,...,#2}
     {\pgfmathtruncatemacro\mm{mod(\MM+\i-2,12)+1}%
      \pgfmathtruncatemacro\yyyy{\YYYY+divide(\MM+\i-2,12)}%
      \xdef\dateticks{\dateticks,\yyyy-\ifnum\mm<10 0\fi\mm-\DD}%
     }%
   \egroup
  }

以下是上图的完整代码。

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.14}
\usepgfplotslibrary{dateplot}
\newcommand\dateticks{}
\def\splitdate#1-#2#3-#4-%
  {\def\YYYY{#1}%
   \ifnum#2=0\def\MM{#3}\else\def\MM{#2#3}\fi
   \def\DD{#4}%
  }
\newcommand\setdateticks[2]%
  {\def\dateticks{#1}%
   \bgroup
   \splitdate#1-%
   \foreach \i in {2,...,#2}
     {\pgfmathtruncatemacro\mm{mod(\MM+\i-2,12)+1}%
      \pgfmathtruncatemacro\yyyy{\YYYY+divide(\MM+\i-2,12)}%
      \xdef\dateticks{\dateticks,\yyyy-\ifnum\mm<10 0\fi\mm-\DD}%
     }%
   \egroup
  }
\newcommand\mygraph[1]%
  {\begin{tikzpicture}
    \begin{axis}%
      [date coordinates in=x,
       xtick={#1},
       xticklabel=\day/\month,
       xticklabel style={rotate=90},
      ]
      \addplot coordinates {(2016-01-23,10) (2016-03-05,20) (2016-09-14,10)};
    \end{axis}
   \end{tikzpicture}%
  }
\begin{document}
\setdateticks{2016-01-01}{12}
\expandafter\mygraph\expandafter{\dateticks}
\end{document}

答案2

我认为对我来说最好的解决方案是使用键xtick/.expanded而不是通常的xtick加上xdef宏,如以下工作示例所示:

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

\begin{document}
\def\dateticks{2016-01-01}
\foreach \i in {2,...,12}
  {\xdef\dateticks{\dateticks,2016-\ifnum\i<10 0\fi\i-01}}

\begin{tikzpicture}
\begin{axis}[
  date coordinates in=x,
  xtick/.expanded={\dateticks},
  xticklabel=\day/\month,
  xticklabel style={rotate=90},
]
\addplot coordinates {(2016-01-23,10) (2016-03-05,20) (2016-09-14,10)};
\end{axis}
\end{tikzpicture}
\end{document}

相关内容