14

I have a table with data from a file and before anything, I sort the data. Then I would like to filter only the rows that have a specific value. There has been a similar question which almost contains the answer to my question:

Selecting rows to be displayed with pgfplotstable

In addition to that I would like to know how to plot the filtered data.

Here is an example:

\documentclass{minimal}
\usepackage{pgfplotstable} 
\usepackage{pgfplots}   

\begin{document}
\pgfplotstableread{
T   A   B   C
20  0   450 43
23  0   400 42
25  0   350 41
30  0   320 40
40  0   300 40
20  10  400 38
23  10  380 37
25  10  350 36
30  10  310 35
40  10  280 34
}\data

\pgfplotstablesort[sort key={T}]{\sorted}{\data} %get the data and sort by column 'T'

   %select data in column 'T' that complies with a certain value and write the table
   \pgfplotstabletypeset[row predicate/.code={%
   \pgfplotstablegetelem{#1}{T}\of{\sorted}
   \ifnum\pgfplotsretval=20\relax
   \else\pgfplotstableuserowfalse\fi}]
   {\sorted}

   \begin{tikzpicture}
    \begin{axis}[
     xlabel=A,
     ylabel=B]
   \addplot table[
    x=A,
    y=B]
   {\filtered}; %here the filtered data from above needs to be addressed, how to do that?
   \end{axis}
   \end{tikzpicture}

   \end{document}

What I don't know is how to address the filtered data above to plot it. I thought it might work by generating a table named \filtered.

Henri Menke
  • 109,596
wonder
  • 261

1 Answers1

14

You can use the x filter/.code={} instructions (thanks to Jake for spotting a mistake)

\documentclass{minimal}
\usepackage{pgfplotstable} 
\usepackage{pgfplots}   

\begin{document}
\pgfplotstableread{
T   A   B   C
20  0   450 43
23  0   400 42
25  0   350 41
30  0   320 40
40  0   300 40
20  10  400 38
23  10  380 37
25  10  350 36
30  10  310 35
40  10  280 34
}\data

\pgfplotstablesort[sort key={T}]{\sorted}{\data}

   \pgfplotstabletypeset[row predicate/.code={%
   \pgfplotstablegetelem{#1}{T}\of{\sorted}
   \ifnum\pgfplotsretval=20\relax
   \else\pgfplotstableuserowfalse\fi}]
   {\sorted}


   \begin{tikzpicture}
    \begin{axis}[
     xlabel=A,
     ylabel=B,
    x filter/.code={\pgfplotstablegetelem{\coordindex}{T}\of{\sorted}
                    \ifnum\pgfplotsretval=20
                    \else
                    \def\pgfmathresult{}
                    \fi
                   },
    ]
   \addplot[only marks] table[x=A,y=B] {\sorted};
   \end{axis}
   \end{tikzpicture}
   \end{document}

enter image description here

If the entries of the table involves nonintegers then \ifnum would complain hence it needs another step.

\documentclass{minimal}
\usepackage{pgfplotstable} 
\usepackage{pgfplots}   

\begin{document}
\pgfplotstableread{
T   A   B   C
0.567641034 0.111435797 0.886143166 0.536835288
0.919931469 0.702921973 0.285814111 0.796042178
0.073058973 0.921420655 0.806947507 0.570962079
0.697073289 0.017461888 0.313614435 0.905702895
0.536575411 0.814853755 0.152870278 0.556116015
0.574615343 0.162798271 0.553041948 0.605668041
0.567641034 0.248224272 0.448683336 0.092672169
0.117628849 0.115555917 0.193712749 0.561100742
0.625852254 0.993854404 0.950034992 0.595500664
0.975451837 0.152198913 0.647432196 0.790471281
0.692695418 0.099750965 0.122178502 0.141174403
0.106974613 0.905644903 0.491119067 0.795346
0.727907584 0.408384001 0.586645737 0.172061294
}\data

\pgfplotstablesort[sort key={T}]{\sorted}{\data}



   \begin{tikzpicture}
    \begin{axis}[
     xlabel=A,
     ylabel=B,
    x filter/.code={\pgfplotstablegetelem{\coordindex}{T}\of{\sorted}
                    \pgfmathtruncatemacro{\tempva}{abs(\pgfplotsretval - 0.567641034) == 0 ? 1: 0}
                    \ifnum\tempva>0%true
                    \else%false
                    \def\pgfmathresult{}
                    \fi
                   },
    ]
   \addplot[only marks] table[x=A,y=B] {\sorted};
   \end{axis}
   \end{tikzpicture}
   \end{document}

which leads to the same output above. I have modified a table entry as it is almost passing the test if lowered slightly. So you should be careful about the numerical precision.

percusse
  • 157,807
  • @Jake Thanks you are right, that's probably the way but when I did that 2 more coordinates from T column value leaks in. Any idea why? – percusse Aug 07 '12 at 13:38
  • I tried both codes and they worked fine. @percusse Maybe you have the \addplot twice in the code. – wonder Aug 07 '12 at 13:46
  • @wonder @Jake Nevermind, I was supplying the [x=A,y=B] options to addplot instead of table. I'll fix it in a sec. – percusse Aug 07 '12 at 13:49
  • One additional question: The above discussed filtering/plotting seems only to work with integers. What needs to be changed if there are floats the table? – wonder Aug 09 '12 at 09:18
  • @percusse Thank you. If I do so, I get an error: '! Missing = inserted for \ifnum' in case that the float 20.256 is present in the table. If no float 20.256 is present in the table there is another error '! Use of \tempvar doesn't match its definition' – wonder Aug 09 '12 at 20:36
  • @wonder I've updated the solution for decimal points. Can you give it a try? – percusse Aug 09 '12 at 21:14
  • @percusse: instead of using pgfmathparse to do the comparison, you can use \ifdim\pgfplotsretval pt=20.256pt in place of \ifnum\pgfplotsretval=20 (so you just add pt to turn the values into lengths). – Jake Aug 10 '12 at 06:24
  • @percusse: I tried it and with the minimum example given above it works fine. But just if the data for the y axis in the table contains also floats it does not work. Unfortunately (of course) it is the same problem with the typesetting of the filtered table. – wonder Aug 10 '12 at 07:20
  • @Jake: The trick with the virtual treatment as length in pt is quite nice. It works for the plotting of the diagram. I tried to use this for the plotting of the table too, but there I failed. – wonder Aug 10 '12 at 07:36
  • @wonder I don't get any problems as you can see from the updated example. – percusse Aug 10 '12 at 08:06
  • @wonder: It works for me (I just replaced \ifnum\pgfplotsretval=20 with \ifdim\pgfplotsretval pt=20.256pt\relax). What error message do you get? – Jake Aug 10 '12 at 08:06
  • @Jake I don't see any problem or replicate it. Why is that length comparison needed, is it more sensitive? – percusse Aug 10 '12 at 08:27
  • @percusse: It's just a different approach that doesn't require the use of of an intermediate \pgfmathparse step. I'm not sure whether there's any difference in precision (if anything, I would guess that your approach is more precise), but the \ifdim approach uses less lines and is (in my opinion) a little more readable. – Jake Aug 10 '12 at 08:39
  • @Jake: The strange thing was that there did not appear any error message. It just plotted everything without filtering. Now I copied your code again to test it with my orginal table and it works fine. Maybe I justed changed some small detail and so the filter was ignored. Is there a possibility to also use the code for plotting the filtered data as a table? – wonder Aug 10 '12 at 09:07
  • @wonder: Yes, you can use the same code in pgfplotstabletypeset. – Jake Aug 10 '12 at 09:11
  • @Jake: I tried to use it with pgfplotstabletypeset but it did not filter correctly. But it returned no error message as well. I used it as: \pgfplotstabletypeset[row predicate/.code={% \pgfplotstablegetelem{#1}{T}\of{\sorted} \pgfmathtruncatemacro{\tempva}{abs(\pgfplotsretval - 0.567641034) == 0 ? 1: 0} \ifnum\tempva>0%true \else%false \def\pgfmathresult{} \fi }, ]{\sorted} I don't know where the error is. – wonder Aug 10 '12 at 09:40
  • 2
    @wonder Please give us a part of your real data and state what is missing so we can give a full working answer. This progress, as you might imagine, is only incremental and becomes difficult to address all issues at one shot each time we implement another detail. – percusse Aug 10 '12 at 09:43
  • @percusse Actually the problem is more complicated than I thought. I maybe simplified it too much. Sorry. My original data table contains columns with text, columns with integers, floats and even sometimes cells with no value, where I have put in nan. I even want to filter by two columns. From the table I first want to filter by column L and than by column C. Then I want to plot the table sorted by column T and a diagram with T and one of the columns D or V according to the table (see the next following comment). – wonder Aug 10 '12 at 10:48
  • The less simplified table is: L C T D V<br> A 0 20 1.00346 205<br> A 0 23 1.00118 177<br> A 0 25 0.99964 155<br> A 0 30 0.99579 115<br> A 0 40 0.98807 69.5<br> A 9.2 20 0.98444 nan<br> A 9.2 30 0.97664 66<br> A 9.2 40 0.96862 43<br> A 30 20 0.96936 nan<br> A 30 23 0.96622 16.1<br> A 30 30 0.964 15.3<br> B 0 20 1.05104 535<br> B 0 23 1.04876 439<br> B 0 25 1.0472 373<br> B 0 30 1.04327 234<br> B 0 40 1.03555 115<br> B 9.6 20 1.02981 nan<br> B 9.6 23 1.02749 152<br> B 9.6 25 1.0259 134 – wonder Aug 10 '12 at 10:48
  • Please excuse the confusing design of my table presentation. I tried to use <br> as a row-separator but it didn't work like I expected. – wonder Aug 10 '12 at 10:55
  • @wonder No problem. It's indeed different than what you have asked here. Let's stop commenting here and post a new question (which is more than welcome) and place all the complications that you might think of and we can work on that problem more thoroughly (and since Jake is also interested, there is almost a guarantee that we can reach to a solution :P). The solution however seems to have some massaging of the data. See for example http://tex.stackexchange.com/questions/64864/write-a-column-selectively-to-the-appropriate-row-using-pgfplotstable .There are limitations to DB operations. – percusse Aug 10 '12 at 10:58
  • @percusse: Thanks a lot. Then I will post a new question with the detailed problems and post the new topic here. – wonder Aug 10 '12 at 11:08
  • I have posted the problem as a new question. You can find it at: How can I filter/select data (float, text) from a table and plot it? – wonder Aug 10 '12 at 12:56