4

I want to draw some curves and some special coordinates on the curves, then label the nodes on the axes. So far I have done it manually like this (it's a diagram for the Markowitz risk premium in case you have heard of it):

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{pgfplots}
\usetikzlibrary{calc,intersections,through,backgrounds}
\title{Plotty}
\date{October 2013}

\begin{document}

\begin{tikzpicture}[scale=1]
    \begin{axis}[xmin=0,ymin=0,ymax=10,xmax=10,xticklabels={,,},yticklabels={,,},axis x line=center,axis y line=center,clip=false,
                    xlabel=$w$,ylabel=$U(x)$]
        \draw[name path=ucurve] (axis cs:0,0) .. controls (axis cs:2,9) .. (axis cs:10,10) coordinate[pos=0.2](n1) coordinate[pos=0.9](n2);
        \draw[name path=eucurve] (n1) -- (n2) coordinate[pos=0.5](n3);
        \draw[dotted] let \p1 = (n3) in (n3) -- (\x1,0) node[below,blue]{$E(w)$};
        \draw[dotted,name path global=uintersect] let \p1 = (n3) in (n3) -- (0,\y1) node[left,blue]{$E(U(w))=U(E(w)-\pi)$};
        %Calculate the intersection
        \draw[dotted,name intersections={of=ucurve and uintersect,by=I}] let \p1 = (I) in (I) -- (\x1,0) node[below,blue]{$E(w)-\pi$};
        \draw[dotted] let \p1 = (n1) in (n1) -- (\x1,0) node[below,blue]{$90$};
        \draw[dotted] let \p1 = (n1) in (n1) -- (0,\y1) node[left,blue]{$U(90)$};
        \draw[dotted] let \p1 = (n2) in (n2) -- (\x1,0) node[below,blue]{$P_u$};
        \draw[dotted] let \p1 = (n2) in (n2) -- (0,\y1) node[left,blue]{$U(P_u)$};
    \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

As you can see, I'm trying to do this manually by generating the paths to the axes. However, things get quite messy because I don't take into account the label size.

  1. How can I avoid the overlapping labels? I feel that there must be a plot option or something to label coordinates on the axes.

  2. How can I optimize my code? I'm just starting with pgfplots and I've found out there are hundreds of ways to achieve the same results, so maybe I'm not doing this right. Particularly the intersections library seems overkill for my needs...

  • Welcome to TeX.SX! Looks like you don't really need PGFPlots; TikZ would be good enough for your purpose. – Herr K. Oct 29 '13 at 2:53
  • @JavierIEG -- Add this 'shift={(0.3cm,-0.3cm)}' to where the label is issued, to adjust the location should do the trick – Jesse Oct 29 '13 at 3:33
2

I usually find it helpful to make the font of a graph smaller, e.g. \footnotesize. In this case, making the fonts smaller would solve your problem. I also changed the codes a bit, so that there is less repetition of the same codes.

Code

\documentclass{article}
% \usepackage[utf8]{inputenc}
\usepackage{tikz}
% \usepackage{pgfplots}
\usetikzlibrary{calc,intersections,through,backgrounds}
\title{Plotty}
\date{October 2013}

\begin{document}

\begin{tikzpicture}[font=\footnotesize]
    \tikzset{
        ylab/.style={left,text=blue},
        xlab/.style={below,text=blue},
    }
    % axis
    \draw[<->](0,11) node[left]{$U(x)$} -- (0,0) -- (10,0) node[below]{$w$};

    % utility
    \draw[name path=ucurve] (0,0) .. controls (2,9) .. (10,10) coordinate[pos=0.2](n1) coordinate[pos=0.9](n2);
    \draw[name path=eucurve] (n1) -- (n2) coordinate[pos=0.5](n3);

    % labeling
    \draw[dotted,name path=dotted_line] let \p1=(n1), \p2=(n2), \p3=(n3) in
        (0,\y1) node[ylab]{$U(90)$} -- (n1) -- (\x1,0) node[xlab]{$90$}
        (0,\y2) node[ylab]{$U(P_u)$} -- (n2) -- (\x2,0) node[xlab]{$P_u$}
        (0,\y3) node[ylab]{$E(U(w))=U(E(w))-\pi)$} -- (n3) -- (\x3,0) node[xlab]{$E(w)$}
    ;

    % uncomment to show all intersection points of ucurve and dotted_line
    % \fill [name intersections={of=ucurve and dotted_line, name=i, total=\t}]
    %     [red, opacity=0.5, every node/.style={above left, black, opacity=1}]
    %     \foreach \s in {1,...,\t}{(i-\s) circle (2pt) node {\footnotesize\s}}
    % ;

    \draw[dotted,name intersections={of=ucurve and dotted_line}] let \p4=(intersection-3) in
        (intersection-3)--(\x4,0) node[xlab]{$E(w)-\pi$}
    ;
\end{tikzpicture}

\end{document}

Output

enter image description here

  • If the axes labels still overlap (say, after scaling), then the answers to this question will be useful. – Herr K. Oct 29 '13 at 4:01
  • 1) That graph looks way better than mine! Its amazing how whitespace makes diagrams easier to the eye... So i take it that there is no library or option for node labels that puts them on axes automaticaly? 2) Your code is far better than mine. Can you give me some references to the commands you used? namely "[<->]" option and style settings. 3)Is there something like "best practices" on pgfplots/tikz? For instance, best way to define styles? Separating curves, nodes and labeling makes sense? Does it make the compiler take more time? – JavierIEH Oct 29 '13 at 12:38
  • I can't edit the comment for some reason. I forgot, whats the best way to scale the graph so that longer labels fit well? I can imagine that increasing the coordinates of the graph one by one is not the best way to do that – JavierIEH Oct 29 '13 at 12:54
  • @JavierIEH: 1) I'm not aware of any library that implements drawing lines from axes to a point on a curve. 2) The main reference is TikZ/PGF Manual and A very minimal introduction to TikZ. The [<->] in particular means adding arrows on both ends of a line. – Herr K. Oct 29 '13 at 15:05
  • @JavierIEH: 3) "Best practices" of TikZ is very broad, and possibly have a very long answer. A quick search on the tikz-pgf tag on this site shows this, this, and this related posts. Part of a "best practice" for me is to browse the Q&A here on TeX.SX and learn bits and pieces from them :) – Herr K. Oct 29 '13 at 15:08
2

An quick method is to modify this line by adding shift={(0.3cm,-0.3cm)} to fine tune the location.

    \draw[dotted,name intersections={of=ucurve and uintersect, by=I}] let \p1 = (I) in (I) -- (\x1,0) node[shift={(0.3cm,-0.3cm)},blue]{$E(w)-\pi$};

enter image description here

  • That works! but i wonder if there is a library that can handle this sort of common situation where you want to label nodes on the axes. Do you know of any? – JavierIEH Oct 29 '13 at 12:36
  • 1
    @JavierIEH -- To place labels on the axes systematically, the \foreach \x/\xtext in {...} loop is my first choice. Yet this still relies on basic nodes techniques that has [options] capability providing fine tunes for the case when the x-grid distance is not uniform. PGFmanual p. 135-136 has some examples for systematic approaches. – Jesse Oct 29 '13 at 13:21
  • Thank you, i upvoted your answer but selected the other one because gave me insight to other related matters of my question. – JavierIEH Oct 29 '13 at 17:22
  • @JavierIEH -- Yes, Indeed. – Jesse Oct 29 '13 at 18:44

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.