Search code examples
python-3.xmachine-learninggraphvizdecision-treepydot

AttributeError: 'list' object has no attribute 'create_png'


This classifies the data as a decision tree. The decision tree is created but I am not able to view the decision tree.

import numpy as np
from sklearn import linear_model, datasets, tree
import matplotlib.pyplot as plt
iris = datasets.load_iris()
f = open('decision_tree_data.txt')
x_train = []
y_train = []
for line in f:
    line = np.asarray(line.split(),dtype = np.float32)
    x_train.append(line[:-1])
    y_train.append(line[:-1])
x_train = np.asmatrix(x_train)
y_train = np.asmatrix(y_train)
model = tree.DecisionTreeClassifier()
model.fit(x_train,y_train)
from sklearn.externals.six import StringIO
import pydot
from IPython.display import Image
dot_data = StringIO()
tree.export_graphviz(model, out_file=dot_data,  
                     feature_names=iris.feature_names,  
                     class_names=iris.target_names,  
                     filled=True, rounded=True,  
                     special_characters=True)  
graph = pydot.graph_from_dot_data(dot_data.getvalue()) 
Image(graph.create_png())

Solution

  • The function pydot.graph_from_dot_data returns a list in pydot >= 1.2.0 (in contrast to earlier versions of pydot).

    The reason was to homogenize the output, which in the past was a list if two graphs were returned, but a graph if a single graph was returned. Such branching is a common source of errors in user code (simple is better than complex [PEP 20]).

    The change applies to all functions that call the function dot_parser.parse_dot_data, which now returns a list in all cases.

    To address the error, you need to unpack the single graph that you expect:

    graph, = pydot.graph_from_dot_data(dot_data.getvalue())
    

    This statement also asserts that a single graph is returned. So if this assumption doesn't hold, and more graphs are returned, this unpacking will catch it. In contrast, graph = (...)[0] won't.

    Relevant pydot issues: