# Is it necessary to convert labels in string to integer for scikit_learn and xgboost?

I have a tabular data with labels that are in string. I will feed the data to decision trees in scikit_learn and XGBoost classifier.

Is it necessary to convert the labels in string to integers for these algorithms? Will the algorithms work less effectively when the labels are not in numerical format?

I am using python v3.7

# TL;DR

If your labels are part of your feature matrix, you need to convert them to numerals using OneHotEncoding (docs). However, if your labels are just your targets, you can leave them as is.

## 1) Is it necessary to convert the strings to integers?

You did not specify if your string labels are one of your features in your feature matrix X, or if they are your target y. So, here is some data to cover both cases:

X = [
['sunny'],
['rainy'],
['rainy'],
['cloudy'],
['very rainy'],
['sunny'],
['partially cloudy']
]

y = [
'no umbrella',
'umbrella',
'umbrella',
'no umbrella',
'umbrella',
'no umbrella',
'no umbrella'
]


If you try to fit a DecisionTreeClassifier with this, like this:

from sklearn.tree import DecisionTreeClassifier
clf = DecisionTreeClassifier()
clf.fit(X, y)


You get an error:

ValueError: could not convert string to float: 'sunny'

So definitely, you need to convert them to integers, for example:

from sklearn.preprocessing import OrdinalEncoder
encoder = OrdinalEncoder()
encoder.fit(X)
X_encoded = encoder.transform(X)

>> [[3.]   # sunny
>>  [2.]   # rainy
>>  [2.]   # rainy
>>  [0.]   # cloudy
>>  [4.]   # very rainy
>>  [3.]   # sunny
>>  [1.]]  # partially cloudy


This transforms your labels into integers. And now you are able to .fit() your model.

This means that features in X must be transformed to integers, however, target labels in y can remain as strings.

## 2) Will the algorithms work less effectively?

If you don't convert your targets y into integers, there will be no decrease in your algorithms performance.

Now, given that you need to convert your string features X into numerals, the way that you convert will affect the algorithm.

In Sklearn you can use the OrdinalEncoder (docs) or the OneHotEncoder (docs). The way in which they encode X is different, observe:

OrdinalEncoder

from sklearn.preprocessing import OrdinalEncoder
encoder = OrdinalEncoder()
encoder.fit(X)
X_encoded = encoder.transform(X)

>> [[3.]   # sunny
>>  [2.]   # rainy
>>  [2.]   # rainy
>>  [0.]   # cloudy
>>  [4.]   # very rainy
>>  [3.]   # sunny
>>  [1.]]  # partially cloudy


OneHotEncoder

from sklearn.preprocessing import OneHotEncoder
encoder = OneHotEncoder()
encoder.fit(X)
X_encoded = encoder.transform(X)

[[0. 0. 0. 1. 0.]  # sunny
[0. 0. 1. 0. 0.]  # rainy
[0. 0. 1. 0. 0.]  # rainy
[1. 0. 0. 0. 0.]  # cloudy
[0. 0. 0. 0. 1.]  # very rainy
[0. 0. 0. 1. 0.]  # sunny
[0. 1. 0. 0. 0.]] # partially cloudy


For algorithms like DecisionTreeClassifiers, the second option, namely OneHotEncoder is better because there are more dimensions to finding boundary lines. So you can have a shallower trees. Where as, if you encode with a simple LabelEncoder, you will need to have deeper tree.

Have a look at the tree generated given the two types of input:

LabelEncoder, notice how 3 decisions nodes are needed.

OneHotEncoder, notice how only 2 decisions nodes are needed.