1

I have seen other relate questions (like Basic bar chart with text as x axis labels), but still cannot figure out where the problem is in my example.

The MWE below contains a snippet of a .csv table with data, where the first column is a string. What I want to do, is to use the first column strings as xtickabels, and on each x position, plot the 3ith element (assuming the column numbering is 0-based, and i=1,2,3...) as a mark circle; as example, from row one, I'd want elements 3,6,9,12,...,33 - that is, a mark should be added at x=1 (c002) and y={0.000119, 0.000162, 0.000494, ..., 0.006253} (and the same would be done for each row, except for second row, x will be 2, for third row x=3 etc.); something like:

^
|   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

This MWE is how far I got so far:

\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}

I will eventually want to plot with discontinuities on x axis, which is why I use groupplot. Unfortunately, the above fails with:

! Package PGF Math Error: Could not parse input 'c002' as a floating point numb er, sorry. The unreadable part was near 'c002'..

See the PGF Math package documentation for explanation. Type H for immediate help. ...

l.60 ] \mytable;

So basically, I have two questions:

  • How do I get rid of the error, and use the first column strings as xticklabels?
  • What would be the best approach to plot the selected samples along the y axis, as I want them to? (Since the number of columns varies, the algorithm should simply ignore all data values that may turn up empty)
1

Ok, I did get somewhere, but it's still no full solution; so if anyone can suggest a better approach, I'd rather accept that answer.

The "Could not parse input '' as a floating point number" got solved by using xticklabels from table in the groupplot options AND x expr instead of x index in the \addplot table options. (Note, I've also tried with symbolic x coords and x index=\coordindex, and with that got: " ! Package pgfplots Error: Sorry, the input coordinate `0' has not been defined with 'symbolic x coords={c002,c003,c004,}... Maybe it has been misspelled?." ). I got to that thanks to this comment from pgfplots: how to load distinct symbolic ticks/labels from file?

"flexible ticklabels from table won't help here, because that's just for generating the labels, but not the coordinates. You're currently plotting the data points at (i|i), where i is the coordinate index, so filtering duplicates out of the labels won't help you. Rather, you need to map a, b, c... to x=1, 2, 3... and X, Y, Z to y=1, 2, 3... (which is what symbolic x coords does)."

Not sure I fully understand that, but what I need is that the labels for x=0,1,2,... are "c002","c003","c004",... - so that eventually I could control discontinuities by setting xmin and xmax as numbers (and the labels would follow those settings).

For the second part, I really couldn't find a proper syntax for \addplot table - so here I iterate through the table, and create a coordinate list, that I use with \addplot coordinates. And finally I get a rendering close to what I want:

test61.png

... but with the problem, that xlabels are incorrect - if I use xtick=data, only the first ("c002") is shown at correct location (probably the others are not shown because I do not use \addplot table here); if I don't use it, as above, then only "c003" and "c004" are printed, but not on a correct location. (see edit below)

So, if anyone can suggest how to make the xtick labels correct, and if there is a syntax so I can achieve the same output with \addplot table instead (without having to loop through the table to re-create coordinates), please post back an answer.

Here is the MWE so far:

\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}

EDIT: got the labels to solve; simply, do one \addplot table before the for loop, where simply the y value is set to 0; this would "plot" invisible points at the (xtickindex,0) coordinate - and forces the labels to appear. So simply paste this snippet before the \foreach (and enable the xtick=data) in the MWE above:

% use [mark=*,mark options={red}] to debug
\addplot+[mark=none] table[x expr=\coordindex, y expr=0.0] \mytable;

... and then the output is finally as expected:

test62.png

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.