How are levels of a categorical variable defined in Python?

Viewed 1571

I know that logistic regression uses 0s and 1s for the dependent variable. But how are the 0s and 1s allocated when the variable is defined as a category, "Healthy" vs. "Sick"? In other words, what is the reference level? Is "Healthy" given a 0 because H is first in the alphabet?

Testing CSV

import pandas as pd
import numpy as np
import os
from sklearn.model_selection import RepeatedKFold, cross_val_score
from sklearn.linear_model import LogisticRegression
# index_col=0 eliminates the dumb index column
baseball_train = pd.read_csv(r"baseball_train.csv",index_col=0,
                             dtype={'Opp': 'category', 'Result': 'category', 
                                    'Name': 'category'}, header=0)
baseball_test = pd.read_csv(r"baseball_test.csv",index_col=0,
                            dtype={'Opp': 'category', 'Result': 'category', 
                                   'Name': 'category'}, header=0)
# take all independent variables
X = baseball_train.iloc[:,:-1]
# drop opp and result because I don't want them
X = X.drop(['Opp','Result'],axis=1)
# dependent variable
y = baseball_train.iloc[:,-1]

# Create logistic regression
logit = LogisticRegression(fit_intercept=True)
model = logit.fit(X,y)

Here, Name is the dependent variable with categories: "Nolan" and "Tom" not 0s and 1s

2 Answers

If you are using Pandas to read and encode your data, the categories are sorted (just like sklearn, see below).

import pandas as pd
import io

txt = """
HR,HBP,Name
0,0,Tommy
0,1,Nolan
0,2,Tommy
1,1,Nolan"""

df = pd.read_csv(io.StringIO(txt), dtype={'Name': 'category'})
print(df)
  HR  HBP Name
0 0   0   Tommy
1 0   1   Nolan
2 0   2   Tommy
3 1   1   Nolan

If you look at the codes you can see that although Tommy was mentioned first its encoding is 1 and Nolan got 0.

print(df.Name.cat.codes)
0    1
1    0
2    1
3    0
dtype: int8

If you want to get everything as a dictionary:

encoded_categories = dict(enumerate(df.Name.cat.categories))
print(encoded_categories)

{0: 'Nolan', 1: 'Tommy'}


Initial answer

You labeled the question with scikit-learn, so I assume you are using LabelEncoder from sklearn.preprocessing. In that case the values are indeed sorted.

Simple example

from sklearn import preprocessing

le = preprocessing.LabelEncoder()
le.fit(["paris", "paris", "tokyo", "amsterdam"])

fit calls _encode which in case of a Python list or tuple (or anything except for a numpy array) sorts the it before encoding. numpy arrays are sorted as well by using numpy.unique.

You can check it via

print(le.classes_)
>> ['amsterdam' 'paris' 'tokyo']

So in your case

np.array_equal(le.fit(["healthy", "sick"]).classes_, 
               le.fit(["sick", "healthy"]).classes_)
>> True

np.array_equal(le.fit(["healthy", "sick"]).classes_, 
               le.fit(["sick", "healthy", "unknown"]).classes_)
>> False
Related