我有一个日期图,需要以编程方式在每个月的第一天(或第 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}
设置\dateticks
为2016-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}