我已经看到了其他相关问题(例如以文本作为 x 轴标签的基本条形图),但仍然无法弄清楚我的例子中的问题出在哪里。
下面的 MWE 包含一个带有数据的 .csv 表片段,其中第一列是一个字符串。我想要做的是使用第一列字符串作为xtickabels
,并在每个 x 位置上,绘制3i
第元素(假设列编号从 0 开始,并且i=1,2,3...
)作为标记圆;例如,从第一行开始,我想要元素 3,6,9,12,...,33 - 也就是说,应该在 x=1(c002
)和 y={0.000119, 0.000162, 0.000494,...,0.006253} 处添加一个标记(并且对每一行都执行相同的操作,除了第二行,x 为 2,第三行 x=3 等);类似于:
^
| o o
| o o o
| o
| o o o
|___________>
c c c c
0 0 0 0
0 0 0 0
2 3 4 5
这个 MWE 是我迄今为止取得的进展:
\documentclass{article}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{adjustbox}
\usepackage{tikz}
\usetikzlibrary{pgfplots.groupplots}
\usetikzlibrary{shapes}
\usetikzlibrary{positioning}
\usetikzlibrary{decorations.pathreplacing}
\pgfplotstableread[
col sep=comma,
header=false,
% columns/0/.style={string type}, % nowork here; on table typeset only
]{
c002,128,64,0.000119,-1,-1,0.000162,-1,-1,0.000494,-1,-1,0.001540,1,65,0.001906,0,1,0.002997,1,1,0.003341,0,65,0.004432,1,65,0.004797,0,1,0.005889,1,1,0.006253,0,65,
c003,128,64,0.000166,-1,-1,0.000463,-1,-1,0.001546,1,65,0.001936,0,1,0.002981,1,1,0.003362,0,65,0.004437,1,65,0.004939,0,1,0.005918,1,1,0.006269,0,65,,,,
c004,128,64,0.000118,-1,-1,0.000161,-1,-1,0.000456,-1,-1,0.001518,1,65,0.001903,0,1,0.002973,1,1,0.003339,0,65,0.004410,1,65,0.004795,0,1,0.005866,1,1,0.006252,0,65,
}\mytable
\begin{document}
\begin{center}
\begin{tikzpicture}
\begin{groupplot}[
group style={
group name=my fancy plots,
group size=1 by 1,
yticklabels at=edge left,
%xticklabels at=edge bottom,
%vertical sep=0pt,
horizontal sep=0pt,
},
height=6cm,
ymin=-6, ymax=6,
domain=0:80,
xticklabels from table={\mytable}{[index]0},
xtick=data,
]
\nextgroupplot[
xmin=0,xmax=5,
xtick={0,5,10},
axis y line=left,
%axis x discontinuity=parallel, % disc. is at start, so avoid for first
axis x line=bottom,
x axis line style=-, % switch off the axis arrow tips,
%width=4.5cm, % don't set width,
x=0.1cm, % set x scale (for width)
%visualization depends on={value \thisrowno{0} \as \labela}, % note the value prefix
%xticklabels from table={\mytable}{[index]0},
%xtick=data,
]
% \coordindex yields the current index of the table row (starting with 0).
\addplot table[
columns/0/.style={string type}, % nope
x index = \coordindex, %
y expr = \thisrowno{2},
] \mytable;
\end{groupplot}
\end{tikzpicture}
\end{center}
我最终想要绘制 x 轴上的不连续性,这就是我使用的原因groupplot
。不幸的是,上面的操作失败了:
!PGF 软件包数学错误:无法将输入“c002”解析为浮点数,抱歉。无法读取的部分位于“c002”附近。
请参阅 PGF Math 包文档以了解解释。输入 H 可立即获得帮助。...
l.60 ] \mytable;
所以基本上,我有两个问题:
- 我如何摆脱错误,并使用第一列字符串作为 xticklabels?
- 正如我希望的那样,沿 y 轴绘制选定样本的最佳方法是什么?(由于列数不同,算法应该简单地忽略所有可能为空的数据值)
答案1
好的,我确实取得了一些进展,但仍然不是完整的解决方案;所以如果有人能提出更好的方法,我宁愿接受这个答案。
“无法将输入解析为浮点数”的问题通过在选项xticklabels from table
中使用groupplot
ANDx expr
而不是在选项x index
中使用 得到解决\addplot table
。(请注意,我也尝试使用symbolic x coords
和x index=\coordindex
,结果得到:“!包 pgfplots 错误:抱歉,输入坐标“0”未定义为“符号 x 坐标 = {c002,c003,c004,} ... 可能拼写错误?”
)。我得到这个答案要感谢来自pgfplots:如何从文件中加载不同的符号刻度/标签?
“表格中的灵活刻度标签在这里无济于事,因为那只是用于生成标签,而不是坐标。您目前正在 (i|i) 处绘制数据点,其中 i 是坐标索引,因此从标签中过滤重复项对您没有帮助。相反,您需要将 a、b、c... 映射到 x=1、2、3... 并将 X、Y、Z 映射到 y=1、2、3...(这是符号 x 坐标的作用)。”
不确定我是否完全理解这一点,但我需要的是 x=0,1,2,... 的标签是“c002”,“c003”,“c004”...... - 以便最终我可以通过设置xmin
和xmax
数字来控制不连续性(并且标签将遵循这些设置)。
对于第二部分,我真的找不到合适的语法\addplot table
- 所以在这里我遍历表格,并创建一个坐标列表,我使用它\addplot coordinates
。最后我得到了一个接近我想要的渲染:
...但问题是,xlabels 不正确 - 如果我使用。(见下面的编辑)xtick=data
,则只有第一个(“c002”)显示在正确的位置(可能其他的没有显示,因为我\addplot table
在这里没有使用);如果我不使用它,如上所述,则只会打印“c003”和“c004”,但不在正确的位置
因此,如果有人可以建议如何使 xtick 标签正确,并且如果存在语法以便我可以使用来实现相同的输出\addplot table
(而不必循环遍历表格来重新创建坐标),请回复答案。
到目前为止的 MWE 如下:
\documentclass{article}
\usepackage{pgfplots}
\usepackage{pgfplotstable}
\usepackage{adjustbox}
\usepackage{tikz}
\usetikzlibrary{pgfplots.groupplots}
\usetikzlibrary{shapes}
\usetikzlibrary{positioning}
\usetikzlibrary{decorations.pathreplacing}
\usepackage{etoolbox}
\pgfplotstableread[
col sep=comma,
header=false,
columns/0/.style={string type}, % nowork here; on table typeset only
]{
c002,128,64,0.000119,-1,-1,0.000162,-1,-1,0.000494,-1,-1,0.001540,1,65,0.001906,0,1,0.002997,1,1,0.003341,0,65,0.004432,1,65,0.004797,0,1,0.005889,1,1,0.006253,0,65,
c003,128,64,0.000166,-1,-1,0.000463,-1,-1,0.001546,1,65,0.001936,0,1,0.002981,1,1,0.003362,0,65,0.004437,1,65,0.004939,0,1,0.005918,1,1,0.006269,0,65,,,,
c004,128,64,0.000118,-1,-1,0.000161,-1,-1,0.000456,-1,-1,0.001518,1,65,0.001903,0,1,0.002973,1,1,0.003339,0,65,0.004410,1,65,0.004795,0,1,0.005866,1,1,0.006252,0,65,
}\mytable
\pgfplotstablegetrowsof{\mytable} %Determine no. of rows
\pgfmathtruncatemacro{\rows}{\pgfplotsretval} % pgfmathsetmacro float, this int
\pgfmathtruncatemacro{\lastrow}{\rows-1}
\pgfplotstablegetcolsof{\mytable} %
\edef\numcolsstr{\pgfplotsretval}%
\pgfmathtruncatemacro{\lastcol}{\numcolsstr-1}
\begin{document}
% https://tex.stackexchange.com/questions/153853/pgfplots-how-to-load-distinct-symbolic-ticks-labels-from-file/153971#153971
\def\xlistmacro{}
\def\xliststring{}
\pgfplotstableforeachcolumnelement{[index]0}\of\mytable\as\entry{%
\xifinlist{\entry}{\xlistmacro}{}{
\listxadd{\xlistmacro}{\entry}
\edef\xliststring{\xliststring\entry,}
}
}
\begin{center}
\begin{tikzpicture}
\begin{groupplot}[
group style={
group name=my fancy plots,
group size=1 by 1,
yticklabels at=edge left,
%xticklabels at=edge bottom,
%vertical sep=0pt,
horizontal sep=0pt,
% no xtick/labels here: ! Undefined control sequence.
%\mytable ->\pgfpl@@ {0}\pgfpl@@ {1}
%xticklabels from table={\mytable}{0},%{[index]0},
%xtick=data,
},
height=6cm,
ymin=0, ymax=7e-3,
domain=0:80,
xticklabels from table={\mytable}{0},%{[index]0},
%xticklabels/.expand once={\xliststring}, % also works
% xtick=data, % will only print the first, 'c002', and no others
xlabel=test variants,
x tick label style={rotate=-45, anchor=west, align=center, font=\tiny},
x=0.5cm, % set x scale (for width)
/tikz/only marks, % no lines - scatter plot
]
\nextgroupplot[
xmin=0,xmax=5,
axis y line=left,
%axis x discontinuity=parallel, % disc. is at start, so avoid for first
axis x line=bottom,
x axis line style=-, % switch off the axis arrow tips,
%width=4.5cm, % don't set width,
% y filter/.code={\ifx\pgfmathresult\empty\else#1\fi},
mark=o, % is ignored for individual addplots
]
%%\coordindex yields the current index of the table row (starting with 0).
%% the below works as expected (but don't know how to select only certain
%% samples via table - so here only one sample is plotted as per y expr):
% \addplot table[
% %x index = \coordindex, % causes: Could not parse input 'c002' as a floating point
% x expr = \coordindex, % passes!
% y expr = \thisrowno{3},
% ] \mytable;
%
%% NOTE: in pgfplots 1.5.1, adding even empty braces to \addplot here
%% causes the coordinates plot not to be shown! example - try the below:
% \addplot[] coordinates{ (0,2e-4) (0,4e-4) };
\foreach \r in {0,1,...,\lastrow}{%
\xdef\tempCoords{} %
\pgfplotstablegetelem{\r}{[index]0}\of\mytable%
\xdef\rowlabel{\pgfplotsretval}
\foreach \c in {1,2,...,\lastcol}{ % skip column 0
\pgfmathtruncatemacro{\modres}{mod(\c,3)} % modulo
\ifnum\modres=0{%
\pgfplotstablegetelem{\r}{[index]\c}\of\mytable%
%\typeout{[\r,\c]: '\pgfplotsretval' \ifx\pgfplotsretval\empty EMPTY \else\fi } % [199,27]: '' EMPTY ...
\ifx\pgfplotsretval\empty\else{
\xdef\tempCoords{\tempCoords (\r,\pgfplotsretval)\space}}\fi % end \ifx
% \xdef\tempCoords{\tempCoords (\rowlabel,\pgfplotsretval)\space}}\fi % end \ifx
}\fi % end \ifnum
} % end \foreach \c
\typeout{coordinates {\tempCoords};}
% note: using this plainly:
%\addplot coordinates {\tempCoords};
% causes: ! Package pgfplots Error: Sorry, I could not read the plot coordinates near '(0,0.000119) ...
% note: have to use \addplot+[] here, else \addplot[] resets!
% also, color=blue controls stroke of mark, but not its fill
\edef\temp{ \noexpand\addplot+[color=blue,mark=*,mark options={blue},] coordinates{ \tempCoords }; }
\temp % execute addplot command
} % end \foreach \r
\end{groupplot}
\end{tikzpicture}
\end{center}
\end{document}
编辑:得到要解决的标签;简单地说,\addplot table
在 for 循环之前做一个,其中 y 值设置为 0;这会在 (xtickindex,0) 坐标处“绘制”不可见的点 - 并强制显示标签。因此,只需将此代码片段粘贴在上面 MWE 中的\foreach
(并启用) 之前:xtick=data
% use [mark=*,mark options={red}] to debug
\addplot+[mark=none] table[x expr=\coordindex, y expr=0.0] \mytable;
...然后输出最终如预期的那样: