我正在使用 LaTeX 中的“forest”包来创建具有多个决策的决策树。除了两件事外,我基本上已经得到了我想要的结果:
- 我希望树叶上的圆圈是三角形。
- 我希望标签位于线条的中心并且不与矩形或圆形重叠。
一个简单的例子(使用 Beamer):
\documentclass{beamer}
\usepackage{beamerstyle}
\usepackage{tikz}
\usetikzlibrary{trees,shapes,snakes}
\usepackage{forest}
\tikzset{
decision/.style={rectangle, minimum height=10pt, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
chance/.style={circle, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
}
\begin{document}
\begin{frame}[fragile]
\scalebox{0.85}{
\begin{forest}
my label/.style={
edge label={node[auto,sloped,pos=.75,anchor=south]{#1}}
},
for tree={
grow=0,
child anchor=west,
parent anchor=east,
line width=0.2pt,
inner sep=1mm,
edge={thick, draw=blue},
l sep+=30mm,
s sep+=5mm,
if n children=0{
before typesetting nodes={
label/.wrap pgfmath arg={right:#1}{content()},
content={},
chance,
},
}{},
edge path={
\noexpand\path[\forestoption{edge}]
(!u.parent anchor) -- ([xshift=-1.6cm].child anchor) --
(.child anchor)\forestoption{edge label};
},
}
[, decision
[,decision,my label=Route 1
[,chance,my label=Fast
[-900, my label=Accident]
[100, my label=No Accident]
]
[,chance,my label=Slow
[-700, my label=Accident]
[50, my label=No Accident]
]
]
[,decision,my label=Route 2
[,chance,my label=Fast
[-600, my label=Accident]
[80, my label=No Accident]
]
[,chance,my label=Slow
[-500, my label=Accident]
[70, my label=No Accident]
]
]
]
\end{forest}
}
\end{frame}
\end{document}
编辑:感谢@AlanMunn 帮助我处理三角形。我把它们翻转过来了。还去掉了斜线,这样标签看起来更好看。我更喜欢斜线,但看起来不太好看。
\documentclass{beamer}
%\usepackage{beamerstyle}
\usepackage{tikz}
\usetikzlibrary{trees,shapes,snakes}
\usepackage{forest}
\tikzset{
decision/.style={rectangle, minimum height=10pt, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
chance/.style={circle, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
leaf-chance/.style={isosceles triangle, minimum width=10pt, draw=black, thick, fill=white, inner sep=0pt, shape border rotate=180, outer sep=-\pgflinewidth}
}
\begin{document}
\begin{frame}[fragile]
\scalebox{0.85}{
\begin{forest}
my label/.style={
edge label={node[auto, sloped,pos=.75,anchor=south]{#1}}
},
for tree={
grow=0,
child anchor=west,
anchor=west,
text ragged,
inner sep=1mm,
edge={thick, draw=blue},
l sep+=30mm,
s sep+=5mm,
if n children=0{
before typesetting nodes={
label/.wrap pgfmath arg={right:#1}{content()},
content={},
leaf-chance,
},
}{},
edge path={
\noexpand\path [draw, \forestoption{edge}] (!u.parent anchor) |- (.child anchor)\forestoption{edge label};
% alternatively, with angled lines
%\noexpand\path[\forestoption{edge}]
% (!u.parent anchor) -- ([xshift=-2.6cm].child anchor) --
% (.child anchor)\forestoption{edge label};
},
}
[, decision
[,decision,my label=Route 1
[,chance,my label=Fast
[-900, my label=Accident]
[100, my label=No Accident]
]
[,chance,my label=Slow
[-700, my label=Accident]
[50, my label=No Accident]
]
]
[,decision,my label=Route 2
[,chance,my label=Fast
[-600, my label=Accident]
[80, my label=No Accident]
]
[,chance,my label=Slow
[-500, my label=Accident]
[70, my label=No Accident]
]
]
]
\end{forest}
}
\end{frame}
\end{document}
答案1
这里有一种方法,它保留了线末端的标签,但改变了它们的锚点,右对齐了标记三角形的数字,并对直线方法进行了少许调整:
\documentclass{beamer}
\usepackage{forest}
\usetikzlibrary{shapes}
\tikzset{
decision/.style={rectangle, minimum height=10pt, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
chance/.style={circle, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
leaf-chance/.style={isosceles triangle, minimum width=10pt, draw=black, thick, fill=white, inner sep=0pt, shape border rotate=180, outer sep=-\pgflinewidth}
}
\begin{document}
\begin{frame}[fragile]
\scalebox{0.85}{
\begin{forest}
my label/.style={
edge label={node[auto, pos=1, anchor=south east]{#1}}
},
for tree={
grow=0,
child anchor=west,
anchor=west,
text ragged,
inner sep=1mm,
edge={ultra thick, draw=blue, rounded corners=2pt},
l sep+=30mm,
s sep+=5mm,
if n children=0{
before typesetting nodes={
label/.wrap pgfmath arg={[align=right, text width=25pt]right:#1}{content()},
content={},
leaf-chance,
},
}{},
edge path={
\noexpand\path [draw, \forestoption{edge}] (!u.parent anchor) |- (.child anchor)\forestoption{edge label};
},
}
[, decision
[,decision,my label=Route 1
[,chance,my label=Fast
[-900, my label=Accident]
[100, my label=No Accident]
]
[,chance,my label=Slow
[-700, my label=Accident]
[50, my label=No Accident]
]
]
[,decision,my label=Route 2
[,chance,my label=Fast
[-600, my label=Accident]
[80, my label=No Accident]
]
[,chance,my label=Slow
[-500, my label=Accident]
[70, my label=No Accident]
]
]
]
\end{forest}
}
\end{frame}
\end{document}
或者,用有角度的线条,也许像这样?
\documentclass{beamer}
\usepackage{forest}
\usetikzlibrary{shapes}
\tikzset{
decision/.style={rectangle, minimum height=10pt, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
chance/.style={circle, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
leaf-chance/.style={isosceles triangle, minimum width=10pt, draw=black, thick, fill=white, inner sep=0pt, shape border rotate=180, outer sep=-\pgflinewidth}
}
\begin{document}
\begin{frame}[fragile]
\scalebox{0.85}{
\begin{forest}
my label/.style={
edge label={node[auto, pos=1, anchor=south east]{#1}}
},
for tree={
grow=0,
child anchor=west,
anchor=west,
text ragged,
inner sep=1mm,
edge={thick, draw=blue, rounded corners=2pt},
s sep+=5mm,
l sep+=30mm,
if n children=0{
before typesetting nodes={
label/.wrap pgfmath arg={[align=right, text width=25pt]right:#1}{content()},
content={},
leaf-chance,
},
}{
},
edge path={
\noexpand\path[\forestoption{edge}]
(!u.parent anchor) -- ([xshift=-22.5mm].child anchor) -- (.child anchor)\forestoption{edge label};
}
}
[, decision
[,decision,my label=Route 1
[,chance,my label=Fast
[-900, my label=Accident]
[100, my label=No Accident]
]
[,chance,my label=Slow
[-700, my label=Accident]
[50, my label=No Accident]
]
]
[,decision,my label=Route 2
[,chance,my label=Fast
[-600, my label=Accident]
[80, my label=No Accident]
]
[,chance,my label=Slow
[-500, my label=Accident]
[70, my label=No Accident]
]
]
]
\end{forest}
}
\end{frame}
\end{document}
编辑
如果您不喜欢输入,以下代码可以更自动地生成上面的第二棵树:
\begin{forest}
my label/.style={
edge label={node[auto, pos=1, anchor=south east]{#1}}
},
for tree={
grow=0,
child anchor=west,
anchor=west,
text ragged,
inner sep=1mm,
edge={thick, draw=blue, rounded corners=2pt},
s sep+=5mm,
l sep+=30mm,
if n children=0{
if n=1{my label=Accident}{my label=No Accident},
before typesetting nodes={
label/.wrap pgfmath arg={[align=right, text width=25pt]right:#1}{content()},
content={},
leaf-chance,
},
}{
if level=2{
chance,
if n=1{my label=Fast}{my label=Slow}
}{decision}
},
edge path={
\noexpand\path[\forestoption{edge}]
(!u.parent anchor) -- ([xshift=-22.5mm].child anchor) -- (.child anchor)\forestoption{edge label};
}
}
[
[,my label=Route 1
[
[-900]
[100]
]
[
[-700]
[50]
]
]
[,my label=Route 2
[
[-600]
[80]
]
[
[-500]
[70]
]
]
]
\end{forest}
答案2
我认为,对于您的边缘标签,没有最佳解决方案。最简单的解决方案是使用参数将它们稍微向左移动pos=
。在这里,我将其设置为.4
适应“无事故”标签的长度。要制作三角形,您可以使用形状添加另一种样式isosceles triangle
:
\documentclass{beamer}
%\usepackage{beamerstyle} % not standard style
\usepackage{tikz}
\usetikzlibrary{trees,shapes,snakes}
\usepackage{forest}
\tikzset{
decision/.style={rectangle, minimum height=10pt, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
chance/.style={circle, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt},
leaf-chance/.style={isosceles triangle, minimum width=10pt, draw=black, fill=black!30!white, thick, inner sep=0pt}
}
\begin{document}
\begin{frame}[fragile]
\scalebox{0.85}{
\begin{forest}
my label/.style={
edge label={node[sloped,pos=.4,anchor=south]{#1}}
},
for tree={
grow=0,
child anchor=west,
parent anchor=east,
line width=0.2pt,
inner sep=1mm,
edge={thick, draw=blue},
l sep+=30mm,
s sep+=5mm,
if n children=0{
before typesetting nodes={
label/.wrap pgfmath arg={right:#1}{content()},
content={},
leaf-chance,
},
}{},
edge path={
\noexpand\path[\forestoption{edge}]
(!u.parent anchor) -- ([xshift=-1.6cm].child anchor) --
(.child anchor)\forestoption{edge label};
},
}
[, decision
[,decision,my label=Route 1
[,chance,my label=Fast
[-900, my label=Accident]
[100, my label=No Accident]
]
[,chance,my label=Slow
[-700, my label=Accident]
[50, my label=No Accident]
]
]
[,decision,my label=Route 2
[,chance,my label=Fast
[-600, my label=Accident]
[80, my label=No Accident]
]
[,chance,my label=Slow
[-500, my label=Accident]
[70, my label=No Accident]
]
]
]
\end{forest}
}
\end{frame}
\end{document}