I want to plot trees using Python. Decision trees, Organizational charts, etc. Any library that helps me with that?
6 Answers
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:
It has a focus on phylogenetics, but it can actually deal with any type of hierarchical tree (clustering, decision trees, etc.)
5There's graphviz - . It uses the "DOT" language to plot graphs. You can either generate the DOT code yourself, or use pydot - . You could also use networkx - , 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 debugThen you install pydot, because pydot already does this for you. Then you can use networkx to "drive" pydot.
5For 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 1 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 4 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: .
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.
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.
1