7

I am having trouble getting a forest tree to fit on the page. I was wondering what techniques there are to squash the tree below so it doesn't take up so much horizontal space. Ideas I had (but have been unable to execute) were:

1) Forcing nodes to be a maximum width (so the text flows to multi lines)

2) Allowing nodes at the same level in the tree to have different vertical positions on the page (so that they can overlap).

Any suggestions would be appreciated! If I am using completely the wrong package for this situation, please let me know.

\documentclass[a4paper,12pt]{article}

\usepackage{forest}

\begin{document}

\begin{forest}
    [What could prevent a transaction?
        [Customer can't top up
            [Customer has insufficient funds
                [Seasonal/short term issue]
                [Poor customer selection]
                [Change in circumstances]
            ]
            [Can't execute top up
                [Customer doesn't know where to go]
                [Top up process unclear to customer]
                [Top up merchant does not know the process]
                [Merchant fraud]
                [Agent fraud]
            ]
        ]
        [Customer doesn't want to top up
            [Dissatisfied with unit
                [Performance below expectations
                    [Unit degradation]
                    [Poor installation]
                ]
                [Unresolved maintenance issue]
                [Unit stolen or vandalised]
            ]
        ]
    ]
\end{forest}

\end{document}

EDIT: For those who come across this question in future, here are the elements of the answers that I found most useful. These may be obvious to experienced forest users, apologies...

1) Growing a tree horizontally, rather than vertically, use this code after \begin{forest}:

for tree={
child anchor=west,
parent anchor=east,
grow'=east}

2) Controlling text width, simply add text width= inside the for tree={} mentioned above.

3) Creating individual styles for nodes: name/.style={} (see cfr's answer)

4) Altering the alignment of an individual node so that it sits equivalent to a different level in the tree: Put in a blank row (ie. nest within [ ]).

Thanks for the very helpful responses.

  • What is your preamble? – Alenanno May 9 '15 at 14:58
  • The TikZ option text width helps with the maximum width. The option align can be used to set the vertical alignment of the lines. For example: for tree={node options={text width=2.5cm, align=left}}. – Qrrbrbirlbel May 9 '15 at 15:16
  • Take a look at Margins and positioning with tikz-dependency, How to format a language tree?, and Reducing forest tree width without squashing for ideas. Those examples don't all use forest specifically, but they all involve tikz-based trees/graphs, so the principles would apply here too. – Jason Zentz May 9 '15 at 16:50
  • Thanks for the comments Qrrbrbirlbel and Jason. Alenanno - my preamble for this project is enormous but I just cut it down to an MWE. – David May 10 '15 at 7:36
11

No problem wrapping, but honestly, with this amount of horizontal information at one level you are going to have trouble doing this vertically. I suggest laying it out horizontally, and you are also going to have to select a smaller font or scale it a little. Maybe something like the below:

\documentclass[a4paper,12pt]{article}

\usepackage{forest}

\begin{document}

\resizebox{\textwidth}{!}{%
\begin{forest}
  for tree={
    child anchor=west,
    parent anchor=east,
    grow'=east,
  %minimum size=1cm,%new possibility
  text width=4cm,%
    draw,
    anchor=west,
    edge path={
      \noexpand\path[\forestoption{edge}]
        (.child anchor) -| +(-5pt,0) -- +(-5pt,0) |-
        (!u.parent anchor)\forestoption{edge label};
    },
  }
    [What could prevent a transaction?
        [Customer can't top up
            [Customer has insufficient funds
                [Seasonal/short term issue]
                [Poor customer selection]
                [Change in circumstances]
            ]
            [Can't execute top up
                [Customer doesn't know where to go]
                [Top up process unclear to customer]
                [Top up merchant does not know the process]
                [Merchant fraud]
                [Agent fraud]
            ]
        ]
        [Customer doesn't want to top up
            [Dissatisfied with unit
                [Performance below expectations
                    [Unit degradation]
                    [Poor installation]
                ]
                [Unresolved maintenance issue]
                [Unit stolen or vandalised]
            ]
        ]
    ]
\end{forest}
}%
\end{document}

enter image description here

  • Thanks Aubrey, I wasn't even aware that forest could flow horizontally! That makes everything much more readable. :-) – David May 10 '15 at 7:39
8

I'm not saying this is wise, but you could present the tree vertically if you use landscape and you rethink it a little.

For example:

\documentclass[a4paper,12pt]{article}
\usepackage{forest,pdflscape}
\pagestyle{empty}
\begin{document}
\forestset{
  skip one/.style={
    replace by={
      [,
        shape=coordinate,
        l*=.25,
        append
      ]
    },
  },
  customer/.style={
    content={Customer},
    draw=red,
    inner color=red!10,
    outer color=red!20,
    for descendants={
      draw=red,
      inner color=red!10,
      outer color=red!20,
    },
    before drawing tree={
      for descendants={
        edge={draw=red}
      },
    }
  },
  merchant/.style={
    content={Merchant},
    draw=blue,
    inner color=blue!10,
    outer color=blue!20,
    for descendants={
      draw=blue,
      inner color=blue!10,
      outer color=blue!20,
    },
    before drawing tree={
      for descendants={
        edge={draw=blue}
      }
    },
  },
  agent/.style={
    content={Agent},
    draw=green!50!black,
    inner color=green!50!black!10,
    outer color=green!50!black!20,
    for descendants={
      draw=green!50!black,
      inner color=green!50!black!10,
      outer color=green!50!black!20,
    },
    before drawing tree={
      for descendants={
        edge={draw=green!50!black}
      },
    }
  },
  nobody/.style={
    for descendants={
      draw=black,
      inner color=gray!10,
      outer color=gray!20,
    },
    before drawing tree={
      for descendants={
        edge={draw=black}
      },
    }
  },
}
\begin{landscape}
\noindent
\begin{forest}
    for tree={
      parent anchor=south,
      child anchor=north,
      draw,
      thick,
      font=\small\sffamily,
      align=center,
      delay={
        where content={}{
          shape=coordinate,
        }{},
      },
    },
    before packing={
      for tree={
        if={isodd(n_children())}{
          for children={
            if={equal(n,int((1+n_children("!u"))/2))}{
              calign with current,
            }{},
          },
        }{},
        edge path={
          \noexpand\path [draw, thick, \forestoption{edge}] (!u.parent anchor) -- ++(0,-5pt) |- ($(.child anchor) + (0,5pt)$) -- (.child anchor)\forestoption{edge label};
        },
      },
    },
    [What could prevent a transaction?, inner color=gray!10, outer color=gray!20,
      [, customer
        [Can't top up
            [Insufficient funds
                [Seasonal/short term issue, skip one, l*=2]
                [Poor selection, skip one]
                [Changed circumstances, skip one, l*=4]
            ]
            [Unable to top up
              [, customer
                [Process unclear, skip one]
                [Unsure where to go, skip one, l*=2]
              ]
              [, merchant
                [Process unfamiliar
                ]
                [Fraud
                ]
              ]
              [, agent
                [Fraud]
              ]
            ]
        ]
        [Doesn't want to top up
            [Dissatisfied with unit, nobody
              [, l*=2.5
                [Performance below expectations, skip one, l*=2
                    [Unit degradation]
                    [Poor installation]
                ]
                [Unresolved maintenance issue, skip one]
                [Unit stolen or vandalised, skip one, l*=2]
              ]
            ]
        ]
      ]
    ]
\end{forest}
\end{landscape}
\end{document}

rethinking tree

  • 1
    +1 cfr, thanks for your suggestion - you have explained to me how to arrange that tree very effectively and I will be using that in future! However I have chosen Aubrey's answer as it presents the information very effectively on the page. Really appreciate your help though and it will come in helpful in future. – David May 10 '15 at 7:38
  • 1
    @David I like Aubrey's answer. I would have suggested something similar. I was just curious to figure out an alternative. (I like drawing trees with forest.) If it is useful to you again or to somebody else, that's all good. Let me know if you have any questions about the code. Otherwise, good luck! – cfr May 10 '15 at 13:02
  • there is some excellent code in here. I was unaware of the availability of styles that could be applied to descendants! I have a massive family tree project at the moment and this will be very useful. I will edit the original post to point out the uses of /.style and l*=3. – David May 11 '15 at 8:33
  • 1
    I do have a question regarding skipping a level. How exactly do you avoid the node appearing when you put in a blank level? I think that I don't quite understand the "skip one" code. – David May 11 '15 at 10:09
  • 1
    @David Thanks. There is actually a node there but it has shape=coordinate so it is a point rather than taking up space. Hence it looks as if there is no node there. – cfr May 11 '15 at 13:01

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.