我有一个 CSV,我想用它\node
在 tikzpicture 中画点。我可以让它读取数据并画一些东西,但它只画最后一行,而且画了好几次。
我知道通常循环只在最后的环境foreach
中处理,因此我尝试使用和包,但没有区别。axis
pgfplotsinvokeforeach
datatool
下面是 MWE,虽然\DTLforeach
被注释掉了,但是其他方面与pgfplotsinvokeforeach
循环完全相同。
请注意,我还添加了一个带有“a”标签的手动点,以显示该点与循环点之间的厚度差异,表明它在循环中多次绘制它。
我在这里做错了什么?我应该看到三个点,其标签根据数据放置filecontents
(不包括手动数据)。
\documentclass{article}
\usepackage{datatool}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{filecontents}
\begin{document}
\begin{filecontents*}{formants.csv}
label,f1,f2
"i",1800,275
"o",235,487
"a",650,810
\end{filecontents*}
% using datatool
\DTLloaddb[keys={formantlabel,formantone,formanttwo}]{formants}{formants.csv}
\DTLforeach*{formants}{\formantlabel=formantlabel,\formantone=formantone,\formanttwo=formanttwo}{%
\formantlabel, \formantone, \formanttwo \\
}
% using pgfplots functions
\pgfplotstableread[col sep=comma]{formants.csv}{\formants}
\pgfplotstablegetrowsof\formants
\pgfmathsetmacro\numberofrows{\pgfplotsretval-1}
\begin{figure}[h]
\begin{tikzpicture}
\begin{axis}[
xmin = 0,
xmax = 2000,
ymin = 0,
ymax = 1000
]
% this works but only shows the last one
\pgfplotsinvokeforeach{0,...,\numberofrows}{
\pgfplotstablegetelem{#1}{label}\of\formants
\pgfmathsetmacro{\flabel}{\pgfplotsretval}
\pgfplotstablegetelem{#1}{f1}\of\formants
\pgfmathsetmacro{\fone}{\pgfplotsretval}
\pgfplotstablegetelem{#1}{f2}\of\formants
\pgfmathsetmacro{\ftwo}{\pgfplotsretval}
\node[label={180:{\flabel}},circle,fill,inner sep=2pt] at (axis cs:\fone, \ftwo) {}; %
}
% this also works but again only shows the last one
% \DTLforeach*{formants}{
% \formantlabel=formantlabel,\formantone=formantone,\formanttwo=formanttwo}{%
% \node[label={180:{\formantlabel}},circle,fill,inner sep=2pt] at (axis cs:\formantone, \formanttwo) {}; %
% }
\node[label={180:{a}},circle,fill,inner sep=2pt] at (axis cs:650.886, 910.603) {}; % test
\end{axis}
\end{tikzpicture}
\end{figure}
\end{document}
另请注意,这是 XeLaTeX,以防万一。
这是我这边的情况,下方的“a”点是循环点,颜色比上方的点深。图上方的文本是一个循环,显示数据正在被正确读取。
答案1
您必须在循环内部展开\flabel
、\fone
和,然后将其传递给。\ftwo
\node
\documentclass{article}
\usepackage{datatool}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{filecontents}
\begin{document}
\begin{filecontents*}{formants.csv}
label,f1,f2
"i",1800,275
"o",235,487
"a",650,810
\end{filecontents*}
% using datatool
\DTLloaddb[keys={formantlabel,formantone,formanttwo}]{formants}{formants.csv}
\DTLforeach*{formants}{\formantlabel=formantlabel,\formantone=formantone,\formanttwo=formanttwo}{%
\formantlabel, \formantone, \formanttwo \\
}
% using pgfplots functions
\pgfplotstableread[col sep=comma]{formants.csv}{\formants}
\pgfplotstablegetrowsof\formants
\pgfmathsetmacro\numberofrows{\pgfplotsretval-1}
\begin{figure}[h]
\begin{tikzpicture}
\begin{axis}[
xmin = 0,
xmax = 2000,
ymin = 0,
ymax = 1000
]
% this works but only shows the last one
\pgfplotsinvokeforeach{0,...,\numberofrows}{
\pgfplotstablegetelem{#1}{label}\of\formants
\pgfmathsetmacro{\flabel}{\pgfplotsretval}
\pgfplotstablegetelem{#1}{f1}\of\formants
\pgfmathsetmacro{\fone}{\pgfplotsretval}
\pgfplotstablegetelem{#1}{f2}\of\formants
\pgfmathsetmacro{\ftwo}{\pgfplotsretval}
\edef\tmp{[label={180:{\flabel}},circle,fill,inner sep=2pt]
at (axis cs:\fone, \ftwo) {};} %
\expandafter\node\tmp
}
% this also works but again only shows the last one
% \DTLforeach*{formants}{
% \formantlabel=formantlabel,\formantone=formantone,\formanttwo=formanttwo}{%
% \node[label={180:{\formantlabel}},circle,fill,inner sep=2pt] at (axis cs:\formantone, \formanttwo) {}; %
% }
\node[label={180:{a}},circle,fill,inner sep=2pt] at (axis cs:650.886, 910.603) {}; % test
\end{axis}
\end{tikzpicture}
\end{figure}
\end{document}