TikZ 概率树中行上方的文本

TikZ 概率树中行上方的文本

我有以下代码

\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-qtree}
\begin{document}
\begin{tikzpicture}
\tikzset{grow'=right, level distance=32pt}
\tikzset{execute at begin node=\strut}
\tikzset{every tree node/.style={anchor=base west}}
\Tree [ [.J [.J ] [.S ] ]
[.S [.J ]
[.S ] ] ] ]
\end{tikzpicture}
\end{document}

这给了我以下信息:

在此处输入图片描述

然而,我想让它看起来如下所示:

在此处输入图片描述

我该如何调整我的代码以便让标签位于边缘旁边?

答案1

这是一棵树,所以我会使用 Forest。labelled tree下面定义的样式允许您以以下形式编写每个节点

<content>:<label for edge>

代码应该自动找出要做什么以及将标签放在哪里。

例如,我们可以写:

\begin{forest}
  for tree={
    grow'=0,
    parent anchor=children,
    child anchor=parent,
    l sep'+=20pt,
  },
  delay={
    where content={}{}{
      content/.wrap value={\strut #1},
    },
  },
  labelled tree,
  sloped labels,
  [
    [J:0.3
      [J:0.3]
      [S:0.7]
    ]
    [S:0.7
      [J:0.3]
      [S:0.7]
    ]
  ]
\end{forest}

生产

半自动标记树

完整代码labelled tree

\documentclass[border=10pt,multi,tikz]{standalone}
\usepackage{forest}
\forestset{
  declare boolean register=sloped labels,
  not sloped labels,
  my edge label/.style={
    tempcountc/.option=grow,
    if reversed={
      tempcountc-/.register=tempcountb,
    }{
      tempcountc+/.register=tempcountb,
    },
    if sloped labels={
      temptoksa=sloped,
    }{
      temptoksa=,
    },
    edge label/.expanded={node [midway, shift=(\foresteregister{tempcountc}:10pt), \foresteregister{temptoksa}] {#1}}
  },
  labelled tree/.style={
    before typesetting nodes={
      where={(n_children())>1}{
        tempcounta/.pgfmath={int(((n_children())+1)/2)},
        if={isodd(n_children())}{
          for n/.wrap pgfmath arg={{##1}{calign with current}}{(tempcounta)},
        }{},
        for nodewalk={
          n=1,
          filter={current and siblings}{n()<(tempcounta)},
        }{
          for nodewalk={
            c,
            while={int(n_children())==1}{
              on invalid={fake}{n=1},
            }{},
          }{
            tempcountb'=-90,
            split option={content}{:}{content,my edge label},
          },
        },
        for nodewalk={
          n'=1,
          filter={current and siblings}{n()>=(tempcounta)},
        }{
          for nodewalk={
            c,
            while={int(n_children())==1}{
              on invalid={fake}{n=1},
            }{},
          }{
            tempcountb'=-270,
            split option={content}{:}{content,my edge label},
          },
        },
      }{},
      for nodewalk={
        fake=r,
        while={int(n_children())==1}{
          on invalid={fake}{n=1},
        }{},
      }{
        tempcountb'=-270,
        split option={content}{:}{content,my edge label},
      },
    },
  },
}
\begin{document}
\begin{forest}
  for tree={
    grow'=0,
    parent anchor=children,
    child anchor=parent,
    l sep'+=20pt,
  },
  delay={
    where content={}{}{
      content/.wrap value={\strut #1},
    },
  },
  labelled tree,
  sloped labels,
  [
    [J:0.3
      [J:0.3]
      [S:0.7]
    ]
    [S:0.7
      [J:0.3]
      [S:0.7]
    ]
  ]
\end{forest}
\end{document}

但是,如果您的树遵循问题中所示的结构,您可能不想费心为每个节点添加内容和标签,因为这些总是相同的。

在这种情况下,您可能会对recursive tree自动添加这些内容的样式感兴趣。要指定标签和节点内容,只需写入,

recursive tree,
first option=<content>:<probability>,
second option=<content>:<probability>,

在树的序言中。例如,

\begin{forest}
  for tree={
    grow'=0,
    l sep'+=20pt,
  },
  recursive tree,
  first option=S:0.7,
  second option=J:0.3,
  [
    [
      []
      []
    ]
    [
      []
      []
    ]
  ]
\end{forest}

产生与上面相同的输出。

即使这样也显得没有必要那么冗长。如果我们可以告诉 Forest 要实现多少次递归,然后让样式完成剩下的工作,那就太好了。我们可以使用键

recur=<integer>,

这将<integer>在根节点下方(或右侧)添加级别。也就是说,

\begin{forest}
  before packing={
    for tree={
      grow'=0,
      l sep'+=20pt,
    },
  },
  recursive tree,
  first option=S:0.7,
  second option=J:0.3,
  recur'=2,
  [
  ]
\end{forest}

将创建与上面相同的输出。此外,

\begin{forest}
  before packing={
    for tree={
      grow'=0,
      l sep'+=20pt,
    },
  },
  recursive tree,
  first option=Health:0.89,
  second option=Disease:0.11,
  recur'=5,
  [
  ]
\end{forest}

将产生

自动构建并标记树

对于相对较少的代码来说,这是一个很大的树!

完整代码recursive tree

\documentclass[border=10pt,tikz]{standalone}
\usepackage{forest}
\forestset{
  declare boolean register=sloped labels,
  not sloped labels,
  declare toks register=first option,
  first option=A:0.5,
  declare toks register=second option,
  second option=B:0.5,
  declare toks register=first option name,
  declare toks register=second option name,
  declare toks register=first option probability,
  declare toks register=second option probability,
  first option name=first,
  second option name=second,
  first option probability=1,
  second option probability=0,
  declare count register=recur,
  recur'=0,
  my edge label/.style={
    tempcountc/.option=grow,
    if reversed={
      tempcountc-/.register=tempcountb,
    }{
      tempcountc+/.register=tempcountb,
    },
    if sloped labels={
      temptoksa=sloped,
    }{
      temptoksa=,
    },
    edge label/.expanded={node [midway, shift=(\foresteregister{tempcountc}:10pt), \foresteregister{temptoksa}] {#1}}
  },
  recursive tree/.style={
    sloped labels,
    before typesetting nodes={
      split register={first option}{:}{first option name,first option probability},
      split register={second option}{:}{second option name,second option probability},
      where n=1{
        content/.register=first option name,
        before packing={
          tempcountb'=-90,
          my edge label/.register=first option probability,
        },
      }{
        if n'=1{
          content/.register=second option name,
          before packing={
            tempcountb'=-270,
            my edge label/.register=second option probability,
          },
        }{}
      },
      for tree={
        parent anchor=children,
        child anchor=parent,
      },
    },
    delay={
      if recur=0{}{
        tempcountd'=1,
        repeat={(recur)}{
          delay n/.wrap pgfmath arg={%
            {####1}{
              where n children=0{
                append={[]},
                prepend={[]},
              }{},
            }%
          }{(tempcountd)},
          tempcountd+=1,
        },
      },
    },
  },
}
\begin{document}
\begin{forest}
  for tree={
    grow'=0,
    l sep'+=20pt,
  },
  recursive tree,
  first option=S:0.7,
  second option=J:0.3,
  [
    [
      []
      []
    ]
    [
      []
      []
    ]
  ]
\end{forest}
\begin{forest}
  before packing={
    for tree={
      grow'=0,
      l sep'+=20pt,
    },
  },
  recursive tree,
  first option=S:0.7,
  second option=J:0.3,
  recur'=2,
  [
  ]
\end{forest}
\begin{forest}
  before packing={
    for tree={
      grow'=0,
      l sep'+=20pt,
    },
  },
  recursive tree,
  first option=Health:0.89,
  second option=Disease:0.11,
  recur'=5,
  [
  ]
\end{forest}
\end{document}

答案2

注释可以通过\edge命令插入,参见“5 显式边缘”部分tikz-qtree,例如:

\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-qtree}
\begin{document}
\begin{tikzpicture}
\tikzset{grow'=right, level distance=32pt}
\tikzset{execute at begin node=\strut}
\tikzset{every tree node/.style={anchor=base west}}
\Tree [
  \edge node[above]{.3};
  [.J
    \edge node[above]{.3}; [.J ]
    \edge node[below]{.7}; [.S ]
  ]
  \edge node[below]{.7};
  [.S
    \edge node[above]{.3}; [.J ]
    \edge node[below]{.7}; [.S ]
  ]
]
\end{tikzpicture}
\end{document}

结果

源文件和结果的表示都更加紧凑:

\documentclass{article}
\usepackage{tikz-qtree}
\begin{document}
\begin{tikzpicture}[
  grow'=right, level distance=32pt,
  J/.style={above=.2em, node contents={.3}},
  S/.style={below=.2em, node contents={.7}},
]
\Tree [
  \edge node[J]; [.J
    \edge node[J]; [.J ]
    \edge node[S]; [.S ]
  ]
  \edge node[S]; [.S
    \edge node[J]; [.J ]
    \edge node[S]; [.S ]
  ]
]
\end{tikzpicture}
\end{document}

紧凑结果

相关内容