13 Key Code Blocks for EDA-Classification Task | by Susan Maina | Towards Data Science

Following my previous article on the 11 code blocks for EDA which covered a regression task (predicting a continuous variable), here are the 13 code blocks for performing EDA on a classification task (predicting a categorical or binary feature).
EDA or Exploratory Data Analysis is an important machine learning step that involves learning about the data without spending too much time or getting lost in it. Here, you get familiar with the structure and general characteristics of the dataset, and the independent and dependent features, and their interactions. You will also get an idea of the data cleaning processes to employ, and the possible modeling techniques.
In this article, we will explore a dataset from Kaggle for a company running training courses on prospective employees. The task is to predict whether the trainees taking their courses are looking to change jobs and will leave their current position and join the company, or will stay at their current job even after completing the courses. The task is therefore a binary task and the target is 0 -stays (not looking for a job change), and 1 -leaves (looking for a job change)
The data can be downloaded from the Kaggle page here, and the feature definitions are also available on the same page. The full workflow code is here on my GitHub page so you can follow along.
The first step is to import the libraries we will use throughout the EDA project. We then read in the train.csv which I downloaded and saved in the same folder as my Jupyter notebook. I will perform EDA on the train set because it contains the target variable, and we are interested in understanding the individual features as well as their relationship with the target feature.
Shape (dimension of the DataFrame)
Shape (dimension of the DataFrame)
A DataFrame has rows and columns, and the Pandas .shape attribute returns a tuple of length 2, each value showing the length of each dimension, or (rows, columns).
(19158, 14)
We can see that the dataset has 19,158 rows and 14 columns. One of those columns in the target feature.
2. Data types of the various columns
We will now display all the columns’ data types. This helps us understand the kind of data we are dealing with, in terms of the numerical and categorical distributions. This will also shed light on some of the exploratory plots and graphs to use.
What to look out for;
Categorical features that should be numeric, and vice versa.
We see several categorical (object) features. We also see the target is a float, represented as 1.0 for those who left their job and 0.0 for those that stayed after training. This makes target a binary feature.
3. Display a few rows
We will now display a small section of our data. We use df.head() to display the first 5 rows, df.tail() to display the last 5, or df.sample() to pick 1 random row from the dataset. df.sample(5) displays 5 randomly selected rows.
What to look out for:
Do the column names make sense? You can check the column definitions again.
What values are in the columns? Do they make sense?
Can you see a significant number of missing values (NaNs)
What are some of the unique classes for the categorical features?
The table gives us an idea of the values present in the different features, and the column names are self-explanatory. We can see some significant missing values in columns such as gender and company_size.
The distribution of a feature refers to how often the values in that feature occur. For numeric (continuous) features, the values are grouped in ranges, also known as bins. We will use graphs to plot the distributions and get an intuitive idea of the values in each column. We will also display actual summary statistics that contain actual numbers of the distributions. It is important to use both graphs and statistics as they complement each other.
4. Plot a histogram grid of the numeric features
A histogram is a form of a bar chart that groups numbers into ranges and the height of the bars show how many values fall into that range. We will use Panda’s df.hist() function to plot a histogram of each numeric feature in the dataset. We will also pass to the function figsize=(8,8) and xrot=45 to increase the grid size and rotate the x-axis for readability.
What to look out for;
Potential outliers
Numeric features that should be categorical (indicator) features. For example, if there are only two possible values like 0 and 1.
Boundaries that do not make sense, such as a percentage value greater than 100.
As expected, we see that target, our dependent feature, is actually an indicator variable with only two possible values; 0 and 1. enrollee_id is an ID column, meaning that each value occurs only once hence the equal distribution among all bins.
5. Display the numeric features’ summary statistics
We will use Panda’s df.describe() function that returns an analysis of each numeric feature.
What to look out for;
The count, or the number of non-NaN values in the column. If the count is less than the overall rows in the data frame, that column contains missing (NaN) values.
The average value, or mean.
The std, or standard deviation of the values in the column
The minimum value
The 25th percentile value
The median, or 50th percentile
The 75th percentile
The maximum value. This could also indicate extreme (outlier) values.
We see that there are no missing values or significant outliers in any column.
Categorical features are columns that contain only a handful of unique values, and therefore each value belongs to a particular class or group. As with the numeric features, we will use both graphs and summary statistics to view the distributions of the different classes in each column.
6. Summary statistics of the Categorical features
We will use the Panda’s df.describe(include=’object’) that only displays the analysis of the features that have the datatype ‘object’.
What to look out for;
The count, or number of non-NaN values. Missing values are present if the count is less than the total rows of the DataFrame.
The number of unique classes.
The top most common value or class. If multiple values have the highest occurrence, an arbitrary top (and freq) value will be displayed.
The frequency (freq), or the number of occurrences of the top class.
We can see that many features have missing values.
7. Plot categorical distributions
We will now plot the categorical features to see how the classes are distributed for each feature. We will use Seaborn’s countplot which is like a bar graph where each bar represents a class and the height is the number of values in that class. Using the summary statistics above, we see that some features such as city have many unique classes and may not be readable when plotted. I decided to plot those with 22 or fewer unique classes.
What to look out for;
Sparse classes — those with very few values. These can affect a model’s performance.
Inconsistent names or typos eg labeling 2 similar classes differently.
We can now see the distributions of classes in the various categorical features.
We can segment our data into groups and observe the relationships between categorical and numeric features, particularly concerning the target.
8. Segment the target by numeric features
Here, we will separate the data by the target feature and observe how the numeric features are distributed among those who left (target = 1) and those who stayed (target = 0).
We will use Seaborn’s boxplot which displays the five-number summary of a numeric feature. The five numbers are minimum, first quartile (Q1 or 25% mark), median (Q2), third quartile (Q3 or 75% mark), and maximum. Check out this article for more on the box plot.
What to look out for:
Which target class is most affected by the numeric features
First, let us do some cleaning and convert 2 categorical columns into numeric.
On-the-fly data cleaning/feature engineering
We will convert experience and last_new_job into numeric features because they both represent the years of experience of the trainees. This will enable us to see how experience influenced a trainee’s decision to leave or stay at current employment. The code below replaces some values in a column then converts the entire column into a float datatype(int did not work because the columns have NaNs)
Now we get to creating box plots. We will first save the four numeric columns-of-interest in a list called num_cols. We will then loop through these columns as we create box plots of each feature against the target.
We can see that training_hours are equally distributed among those who stayed(target 0) and those who left (target 1). This means that training_hours might not be a good predictor for the target. However, we see that when it comes to experience and last_new_job, a bigger proportion of those who stayed are tending towards more years of experience and these could be good predictors.
Now that we have seen how the target changes with numeric features, we will do the same for categorical features.
9. Tabulate target across various categorical features using cross tab
The Panda’s .crosstab(col1, col2) function builds a cross-tabulation table that shows the relationship between two categorical features. The table shows the frequency by which groups of data from the two features appear. You can include the parameter normalize=’index’ to show the percentages across the rows instead of the real numbers. More on cross tabs here. Let us see this in action.
I will loop through 3 categorical columns (those with less than 4 unique classes) and display a cross tab of their relationships with the target. display() function is used because it shows a cleaner table than print()when running a loop.
These tables show how the categorical features’ classes are split among the target’s classes. Let us visualize these results below.
10. Count plot of target across various categorical features
We can plot the categorical relationships above to get a better feel of the interactions. We will create count plots of the data using Seaborn’s catplot() function and provide kind=’count’ as a parameter, which selects a count plot as the underlying axes-level function to use. Other plots you can create using catplot include box plots, bar plots, and violin plots.
What to look out for;
Categorical features that change significantly with the target classes.
In the code, we use the loop to plot only 3 categorical features against the target. Remember that target 0 left while target 1 stayed at their jobs. Notice the parameter sharey=False in catplot which disassociates the y-scales for each target class so that we can better view and compare the relationships.
We can see that the gender classes do not change much depending on the target, but there is a significant difference in how the target feature is distributed among relevant_experience and enrolled_university . We see a bigger proportion of those without relevant experience leaving their jobs. We also see more of those enrolled in a full-time course leaving. This shows that these two features are good predictors of the target.
11. Group numeric features by categorical features.
Now that we have observed how our target is distributed across the other input features, let us check how the categories are related to the numeric features.
We will use the DataFrame’s .groupby() function to group our data into categories and observe how the numeric features are distributed by calculating a metric such as mean, median, and standard deviation across the classes. The metric we will use is mean. We will also provide the columns for which to calculate the means.
Here, we get to compare various feature’s classes against the numeric features.
12. Correlation matrix for the various numeric features
A correlation matrix is a table used to summarize the associations between numeric features. The same features are shown in the rows and columns, and each cell holds the correlation coefficient of two features. The correlation coefficient is a measure of the strength of the relationship between the two variables and can take any value between -1 and 1. The correlation of a feature with itself is 1. Refer to the image below.
In python, calculating the correlations is as easy as calling the DataFrame’s .corr() function to return the pairwise correlation coefficients of all the numeric variables in the data frame.
Take a moment to scan through the numbers and then move on down to see them visualized in a heat map.
13. Heat map of the correlations
A heat map refers to a color-coded representation of data where the values are portrayed by color. We will use the Seaborn heatmap to visualize our grid above.
The code is sns.heatmap(corr, cmap=’RdBu_r’, annot=True, vmax=1, vmin=-1) We pass our correlation matrix corr, along with four other parameters which are optional. cmap=’RdBu_r’ specifies what color palette the heat map should use with dark-red cells showing a strong positive correlation and dark-blue showing a strong negative one. More on Seaborn’s color palettes here. annot=True includes the coefficient values in each cell while vmax=1 and vmin=-1 set the boundaries for the color bar, as our correlation values also fall in the same range.
What to look out for;
Strongly correlated features. These are either dark-red (strong positive) or dark-blue (strong negative).
Target feature’s strong correlations. If any features have a strong positive or negative correlation with the target.
We see that experience and last_new_job have a somewhat strong positive correlation. We also see a slightly weak negative relationship between the target and city_development_index.
That concludes our Exploratory Data Analysis for a classification task. We looked at the 13 code blocks for an EDA project for the HR classification dataset on Kaggle. These blocks of code are important to give you a top-level understanding of the dataset and its features. Find the complete code here. You can also check out the article 11 code blocks for EDA for a regression task.