Tree plotting in Python

PythonPlotTreeData VisualizationVisualization

Python Problem Overview


I want to plot trees using Python. Decision trees, Organizational charts, etc. Any library that helps me with that?

Python Solutions


Solution 1 - Python

I develop ETE, which is a python package intended, among other stuff, for programmatic tree rendering and visualization. You can create your own layout functions and produce custom tree images: enter image description here

It has a focus on phylogenetics, but it can actually deal with any type of hierarchical tree (clustering, decision trees, etc.)

Solution 2 - Python

There's graphviz - http://www.graphviz.org/. It uses the "DOT" language to plot graphs. You can either generate the DOT code yourself, or use pydot - https://github.com/pydot/pydot. You could also use networkx - http://networkx.lanl.gov/tutorial/tutorial.html#drawing-graphs, which make it easy to draw to either graphviz or matplotlib.

networkx + matplotlib + graphviz gives you the most flexibility and power, but you need to install a lot.

If you want a quick solution, try:

Install Graphviz.

open('hello.dot','w').write("digraph G {Hello->World}")
import subprocess
subprocess.call(["path/to/dot.exe","-Tpng","hello.dot","-o","graph1.png"]) 
# I think this is right - try it form the command line to debug

Then you install pydot, because pydot already does this for you. Then you can use networkx to "drive" pydot.

Solution 3 - Python

For basic visualization I would consider using treelib,

It is very straightforward and easy to use:

 from treelib import Node, Tree

 tree = Tree()

 tree.create_node("Harry", "harry")  # No parent means its the root node
 tree.create_node("Jane",  "jane"   , parent="harry")
 tree.create_node("Bill",  "bill"   , parent="harry")
 tree.create_node("Diane", "diane"  , parent="jane")
 tree.create_node("Mary",  "mary"   , parent="diane")
 tree.create_node("Mark",  "mark"   , parent="jane")

 tree.show()

Output:

Harry
├── Bill
└── Jane
    ├── Diane
    │   └── Mary
    └── Mark 

Solution 4 - Python

Plotly can plot tree diagrams using igraph. You can use it offline these days too. The example below is intended to be run in a Jupyter notebook

import plotly.plotly as py
import plotly.graph_objs as go

import igraph
from igraph import *
# I do not endorse importing * like this

#Set Up Tree with igraph

nr_vertices = 25
v_label = map(str, range(nr_vertices))
G = Graph.Tree(nr_vertices, 2) # 2 stands for children number
lay = G.layout('rt')

position = {k: lay[k] for k in range(nr_vertices)}
Y = [lay[k][1] for k in range(nr_vertices)]
M = max(Y)

es = EdgeSeq(G) # sequence of edges
E = [e.tuple for e in G.es] # list of edges

L = len(position)
Xn = [position[k][0] for k in range(L)]
Yn = [2*M-position[k][1] for k in range(L)]
Xe = []
Ye = []
for edge in E:
    Xe+=[position[edge[0]][0],position[edge[1]][0], None]
    Ye+=[2*M-position[edge[0]][1],2*M-position[edge[1]][1], None] 

labels = v_label

#Create Plotly Traces

lines = go.Scatter(x=Xe,
                   y=Ye,
                   mode='lines',
                   line=dict(color='rgb(210,210,210)', width=1),
                   hoverinfo='none'
                   )
dots = go.Scatter(x=Xn,
                  y=Yn,
                  mode='markers',
                  name='',
                  marker=dict(symbol='dot',
                                size=18, 
                                color='#6175c1',    #'#DB4551', 
                                line=dict(color='rgb(50,50,50)', width=1)
                                ),
                  text=labels,
                  hoverinfo='text',
                  opacity=0.8
                  )
                  
# Create Text Inside the Circle via Annotations

def make_annotations(pos, text, font_size=10, 
                     font_color='rgb(250,250,250)'):
    L=len(pos)
    if len(text)!=L:
        raise ValueError('The lists pos and text must have the same len')
    annotations = go.Annotations()
    for k in range(L):
        annotations.append(
            go.Annotation(
                text=labels[k], # or replace labels with a different list 
                                # for the text within the circle  
                x=pos[k][0], y=2*M-position[k][1],
                xref='x1', yref='y1',
                font=dict(color=font_color, size=font_size),
                showarrow=False)
        )
    return annotations  
    
# Add Axis Specifications and Create the Layout

axis = dict(showline=False, # hide axis line, grid, ticklabels and  title
            zeroline=False,
            showgrid=False,
            showticklabels=False,
            )

layout = dict(title= 'Tree with Reingold-Tilford Layout',  
              annotations=make_annotations(position, v_label),
              font=dict(size=12),
              showlegend=False,
              xaxis=go.XAxis(axis),
              yaxis=go.YAxis(axis),          
              margin=dict(l=40, r=40, b=85, t=100),
              hovermode='closest',
              plot_bgcolor='rgb(248,248,248)'          
              )
              
# Plot

data=go.Data([lines, dots])
fig=dict(data=data, layout=layout)
fig['layout'].update(annotations=make_annotations(position, v_label))
py.iplot(fig, filename='Tree-Reingold-Tilf')
# use py.plot instead of py.iplot if you're not using a Jupyter notebook

Output

Solution 5 - Python

For a 2021 solution, I wrote a Python wrapper of the TreantJS library. The package creates an HTML file with a tree visualization. The user can optionally invoke R's webshot library to render high-res screenshots of the trees. The package is quite new, so any PRs, bug reports, or feature requests in the issues would be much appreciated! See: https://github.com/Luke-Poeppel/treeplotter.

The package has some annoying installation requirements (see Installation.md), so I wrote a MacOS installation helper (tested on Catalina and Big Sur). Any tips on reducing these constraints would also be welcome.

enter image description here

enter image description here

Solution 6 - Python

It's expirmental, but Google has a GraphViz api. It's convenient if you just want to quickly visualize a graph, but don't want to install any software.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionInjeniero BarsaView Question on Stackoverflow
Solution 1 - PythonjhcView Answer on Stackoverflow
Solution 2 - PythonwistyView Answer on Stackoverflow
Solution 3 - PythonRtmYView Answer on Stackoverflow
Solution 4 - PythonKevinHView Answer on Stackoverflow
Solution 5 - PythonLuke PoeppelView Answer on Stackoverflow
Solution 6 - PythonAustin MarshallView Answer on Stackoverflow