6

I want to plot values from a big table. Since it has too many numbers, I want to draw the line and only some marks (because there is other lines in the plot, therefore, to avoid confusion). I know that I can use mark repeat={<integer>} for that (or use each nth point={<integer>}, depending on the situation). However, with that, I know that the first point in the graphic will have a mark, put not always the last point, because it depends on the <integer>.

How can I draw always a mark for the first and last points and some in the middle of both, automatically?

\documentclass[10pt,border=0pt]{standalone}

\usepackage{tikz}
\usepackage{tikzscale}
\usepackage{pgfplots}
\usepackage{pgfplotstable}

\usetikzlibrary{plotmarks}

\pgfplotstableread{%
x1 y1
1 2
2 4
3 1
4 5
5 9
6 11
7 15
8 12
9 10
10 1
}\mytable

\pgfplotsset{mytick x interval/.style args={#1:#2:#3}{%
        xmin=#1,xmax=#3,xincrement={#1}{#2},
        xtick={#1,\xval,...,#3}
    },
    xincrement/.code 2 args={\pgfmathparse{#1+#2}\xdef\xval{\pgfmathresult}}
}

\pgfplotsset{mytick y interval/.style args={#1:#2:#3}{%
        ymin=#1,ymax=#3,yincrement={#1}{#2},
        ytick={#1,\yval,...,#3}
    },
    yincrement/.code 2 args={\pgfmathparse{#1+#2}\xdef\yval{\pgfmathresult}}
}

\pgfplotsset{every tick/.style={black,}}

\pgfplotsset{%
    compat=1.8,
    compat/show suggested version=false,
    mytick x interval=0:1:10,
    mytick y interval=0:1:15,
    xlabel={x-axis},
    ylabel={y-axis},
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[mark options={fill=white,solid}]
    \addplot[thick,mark=pentagon*,mark repeat={2}] table[x=x1, y=y1] {\mytable};
  \legend{val}
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

  • A simple way would be to use \addplot[thick,mark=pentagon*,mark repeat={2}] table {\mytable} plot coordinates {+(0,0)};, but this would lead to the final plot mark being drawn twice if it is already included with the "real" plot marks. I guess that's not what you had in mind? – Jake May 29 '13 at 13:34
  • @Jake you are right. Each mark shall be drawn only one time. – cacamailg May 29 '13 at 14:55
  • I was thinking in something like (which I don't know if really works): get the first value; get the last value; do some calculations between both (and setting an interval) and round the result to be used as <value> in mark repeat={<value>}. – cacamailg May 29 '13 at 15:02
9

You could use the scatter functionality, which allows you to execute code before each marker. In that code, you can then check whether \coordindex (the index of the current marker, starting at 0) is the same as \numcoords-1 (the total number of coordinates).

Here's a style mark repeat*=<n>, which draws every nth marker and the final marker:

\pgfplotsset{
    mark repeat*/.style={
        scatter,
        scatter src=x,
        scatter/@pre marker code/.code={
            \pgfmathtruncatemacro\usemark{
                or(mod(\coordindex,#1)==0, (\coordindex==(\numcoords-1))
            }
            \ifnum\usemark=0
                \pgfplotsset{mark=none}
            \fi
        },
        scatter/@post marker code/.code={}
    }
}

Complete code:

\documentclass[10pt,border=0pt]{standalone}

\usepackage{tikz}
\usepackage{tikzscale}
\usepackage{pgfplots}
\usepackage{pgfplotstable}

\usetikzlibrary{plotmarks}

\pgfplotstableread{%
x1 y1
1 2
2 4
3 1
4 5
5 9
6 11
7 15
8 12
9 10
10 1
}\mytable

\pgfplotsset{
    mark repeat*/.style={
        scatter,
        scatter src=x,
        scatter/@pre marker code/.code={
            \pgfmathtruncatemacro\usemark{
                or(mod(\coordindex,#1)==0, (\coordindex==(\numcoords-1))
            }
            \ifnum\usemark=0
                \pgfplotsset{mark=none}
            \fi
        },
        scatter/@post marker code/.code={}
    }
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[mark options={fill=white,solid}]
    \addplot[
            mark=pentagon*, thick,
            mark repeat*=2
    ] table[x=x1, y=y1] {\mytable};
\end{axis}
\end{tikzpicture}
\end{document}
  • Thanks! It indeed works. However, I am not sure if it is "elegant" using the opacity, because the mark is drawn in both cases, only the opacity is set to 1 or 0. – cacamailg May 29 '13 at 17:49
  • @cacamailg: You're absolutely right. I've edited my answer. – Jake May 29 '13 at 18:04
  • That is exactly what I was looking for :). – cacamailg May 29 '13 at 18:10
  • 1
    @cacamailg: I've improved the answer a little bit further by not relying on the \pgfplotspointmetatransformed macro, which is prone to numerical inaccuracies, but instead using \numcoords, which contains the total number of coordinates. – Jake May 29 '13 at 18:20
  • the code above does not work if each nth point={} is also used. How can I put both working together? – cacamailg Jul 18 '14 at 18:07

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.