17

How can I mark the maximum or minimum value of a function like x^2 in pgfplots?

\begin{tikzpicture}
   \begin{axis}
      \addplot+[mark=none] plot {x^2};
   \end{axis}
\end{tikzpicture}
1
  • 1
    Do you assume that you know the point where max/min is attained?
    – percusse
    Feb 29 '12 at 0:57
25

You can use the scatter mechanism for this, which allows you to execute code before each marker is drawn. If you set point meta rel=per plot, the macro \pgfplots@metamin contains the lowest meta value, and \pgfplots@metamax contains the largest meta value. By default, the meta value is the same as the y value.

I've defined two new styles, mark min and mark max that will switch off the plot markers for all but the smallest and largest value, respectively.

If you also want to print the coordinates of the extremal values, you need to make the x-coordinate available using visualization depends on=<value> \as <\macroname>.

\documentclass{standalone}
\usepackage{pgfplots}

\makeatletter
\pgfplotsset{
    /tikz/max node/.style={
        anchor=south
    },
    /tikz/min node/.style={
        anchor=north
    },
    mark min/.style={
        point meta rel=per plot,
        visualization depends on={x \as \xvalue},
        scatter/@pre marker code/.code={%
            \ifx\pgfplotspointmeta\pgfplots@metamin
                \def\markopts{}%
                \node [min node] {
                    \pgfmathprintnumber[fixed]{\xvalue},%
                    \pgfmathprintnumber[fixed]{\pgfplotspointmeta}
                };
            \else
                \def\markopts{mark=none}
            \fi
            \expandafter\scope\expandafter[\markopts,every node near coord/.style=green]
        },%
        scatter/@post marker code/.code={%
            \endscope
        },
        scatter,
    },
    mark max/.style={
        point meta rel=per plot,
        visualization depends on={x \as \xvalue},
        scatter/@pre marker code/.code={%
        \ifx\pgfplotspointmeta\pgfplots@metamax
            \def\markopts{}%
            \node [max node] {
                \pgfmathprintnumber[fixed]{\xvalue},%
                \pgfmathprintnumber[fixed]{\pgfplotspointmeta}
            };
        \else
            \def\markopts{mark=none}
        \fi
            \expandafter\scope\expandafter[\markopts]
        },%
        scatter/@post marker code/.code={%
            \endscope
        },
        scatter
    }
}
\makeatother

\begin{document}
\begin{tikzpicture}
 \begin{axis}
    \addplot +[mark min, every node near coord/.style=] plot {x^2};
    \addplot +[mark max] plot {-x^2+5*x+5};
\end{axis}
\end{tikzpicture}

\end{document}
9
  • Very cool! I'll be using this. Is there any way to extract the (x,y) values of the max/min point? I'm imagining using it as a node and placing the coordinate above or below the mark.
    – qubyte
    Feb 29 '12 at 4:22
  • 1
    @MarkS.Everitt: Good idea, I've edited my answer accordingly.
    – Jake
    Feb 29 '12 at 4:55
  • Is this version dependent? I am still running pgfplots 1.4.1, and the code provided doesn't work for me. I get an error at the addplot command (Package pgfkeys Error: I do not know the key '/tikz/visualization depends on' and I am going to ignore it.) May 10 '12 at 15:57
  • 1
    @StephenBosch: Yeah, I think this feature was only introduced in version 1.5. It's a good idea to update, pgfplots is being so actively developed that you'd miss out on a lot of nifty features if you stick with an old version.
    – Jake
    May 10 '12 at 16:04
  • @Jake: Okay, I finally went to a source install of texlive, and I'm running pgfplots 1.5.1 now. It works with the functions in your example, but not with mine; mine's a 4th degree polynomial and I'm only interested in the local maximum for the domain I've set. It seems to ignore the domain completely. Am I doing something wrong, or is there a way to fix it so it will work? May 10 '12 at 23:11
7

It's not an answer to the question but with pgf 2.1 CVS and without pgfplots (why ?) we can draw something interesting with the datavisualization library. Perhaps It would be possible to use pgfplots with this library.

Actually I don't know how to add Jake's style.

enter image description here

Update code I cleaned the code

\documentclass[11pt]{article}
\usepackage{tikz}
\usetikzlibrary{
  datavisualization,
  datavisualization.polar,% not useful here but interesting to know
  datavisualization.formats.functions}

\begin{document}  

  \pgfdvdeclarestylesheet{my colors}
{
  default style/.style={visualizer color=black},
  1/.style={visualizer color=blue},
  2/.style={visualizer color=red},
}

\begin{tikzpicture}[baseline,scale=2]
  \datavisualization [ scientific axes=clean,
                       visualize as smooth line/.list={f,g},% not sin and cos
                       style sheet=my colors,
                       f={label in legend={text=$f(x)$}},
                       g={label in legend={text=$g(x)$}},
                       data/format=function ]
  data [set=f] {
    var x : interval [-5:5];
    func y =  \value x * \value x;
  } 
    info {
    \draw [blue,fill=blue!20,] (visualization cs: x={(0)}, y=0) circle [radius=1pt]
      node [below,font=\footnotesize] {min point};
  }
  data [set=g] {
    var x : interval [-5:5];
    func y = - \value x * \value x +5* \value x +5;
  } 
      info {
    \draw [red,fill=red!20] (visualization cs: x={(2.5)}, y=11.25) circle [radius=1pt]
      node [above,font=\footnotesize] {max point};
  }  ;
\end{tikzpicture}

\end{document} 

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.