# Correct Way of Displaying Features in Decision Tree

I am creating a very basic decision tree, the dataset being as follows (columns 1 to 11 are features and column 12 is prediction, I am slicing away column 0 in processing phase as in code below):

|--------------------+---+------+----+----+-----+-----+-----+-----+-------+-----+-------+------------|
|       domain       | A | AAAA | MX | NS | SOA | TXT | CAA | SSL | ccTLD | TTL | WHOIS | mal_or_ben |
|--------------------+---+------+----+----+-----+-----+-----+-----+-------+-----+-------+------------|
| fedoraproject.org  | 2 |  2   | 1  | 2  |  1  |  0  |  2  |  0  |   0   |  0  |   0   |     1      |
|--------------------+---+------+----+----+-----+-----+-----+-----+-------+-----+-------+------------|
| blackswanstore.com | 1 |  0   | 1  | 2  |  1  |  2  |  0  |  0  |   0   |  1  |   1   |     0      |
|--------------------+---+------+----+----+-----+-----+-----+-----+-------+-----+-------+------------|
|    comcast.net     | 1 |  0   | 1  | 2  |  1  |  1  |  0  |  0  |   0   |  0  |   1   |     1      |
|--------------------+---+------+----+----+-----+-----+-----+-----+-------+-----+-------+------------|
|     achren.org     | 1 |  0   | 1  | 2  |  1  |  0  |  0  |  0  |   0   |  1  |   1   |     0      |
|--------------------+---+------+----+----+-----+-----+-----+-----+-------+-----+-------+------------|


although when I am passing the dataset, I dont actually pass the top row with the column names, just:

fedoraproject.org,2,2,1,2,1,0,2,0,0,0,0,1
blackswanstore.com,1,0,1,2,1,2,0,0,0,1,1,0


This is how I am preparing my decision tree:

# read data from csv

# x is predictor variable and y is outcome
X = balance_data.values[:, 1:12]
Y = balance_data.values[:, 12]

X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=200)
y_train = y_train.astype('int')
y_test = y_test.astype('int')

# criterion as gini index
clf_gini = DecisionTreeClassifier(criterion="gini", random_state=200,
max_depth=5, min_samples_leaf=5)
clf_gini.fit(X_train, y_train)

# export gini criterion
with open("graph.dot", "w") as f:
f = tree.export_graphviz(clf_entropy, out_file=f)

# plot using graphviz - needs pydot and graphviz installed and set to system path
graph = Source(tree.export_graphviz(clf_entropy, out_file=None,
feature_names=["A", "AAAA", "MX", "NS", "SOA",
"TXT", "CAA", "SSL", "ccTLD",
"TTL", "WHOIS"]))
graph.format = "png"
graph.render("graph_render", view=True)


So, in order to pass the feature name, what I am doing is just passing the column names in order as in the csv input. Is this correct (I am very new to this) or am I missing something here?

Thanks!

If you pass header=None, pandas.read_csv assumes that the first row contains data and names the columns '0' to '12'.

Instead you should pass header=0 to specify that the column names are in the first row or equivalently skip the header argument.

You can then still continue with X = balance_data.values[:, 1:12], because calling values returns a numpy array without the column names.

Alternatively, you could also select your feature columns like so:

feature_names = ['A','AAAA',....]
X = balance_data[feature_names].values


You can then pass the same list of feature_names to graphviz.

Also note that you don't have to pass a numpy array to scikit-learn's functions. It can handle pandas DataFrames as well, so values is optional.

• Thanks a ton for the reply. Just a small query, unlike the pandas slice syntax (X = balance_data.values[:, 1:12] ), in this notation, my feature_names = ["A", "AAAA",... "WHOIS"] starts at A and ends at WHOIS, not the 12th column, that is mal_benign? – Jishan Mar 21 '18 at 15:30
• that is correct... you would have Y=balance_data["mal_or_ben"].values – oW_ Mar 22 '18 at 16:20