字符串列刻度标签并使用组图在 y 轴上绘制选定的样本?

字符串列刻度标签并使用组图在 y 轴上绘制选定的样本?

我已经看到了其他相关问题(例如以文本作为 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中使用groupplotANDx expr而不是在选项x index中使用 得到解决\addplot table。(请注意,我也尝试使用symbolic x coordsx 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”...... - 以便最终我可以通过设置xminxmax数字来控制不连续性(并且标签将遵循这些设置)。

对于第二部分,我真的找不到合适的语法\addplot table- 所以在这里我遍历表格,并创建一个坐标列表,我使用它\addplot coordinates。最后我得到了一个接近我想要的渲染:

测试61.png

...但问题是,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;

...然后输出最终如预期的那样:

测试62.png

相关内容