<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[KNIME Projects by V2K]]></title><description><![CDATA[Hi! I’m a data science enthusiast who loves building data-oriented projects. I share my experiments and learnings in this blog. Feel free to reach me via Linked]]></description><link>https://vijayv2k.com</link><generator>RSS for Node</generator><lastBuildDate>Mon, 12 Oct 2026 18:18:45 GMT</lastBuildDate><atom:link href="https://vijayv2k.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Predicting Employee Attrition - Supervised Classification Machine Learning]]></title><description><![CDATA[Introduction
Employee attrition is one of the major problems that every organization faces, regardless of the sector. It refers to the lifecycle of an organization’s workforce and is an inevitable part of any business. It is defined as the process by...]]></description><link>https://vijayv2k.com/predicting-employee-attrition-supervised-classification-machine-learning</link><guid isPermaLink="true">https://vijayv2k.com/predicting-employee-attrition-supervised-classification-machine-learning</guid><category><![CDATA[KNIME]]></category><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[Supervised learning]]></category><category><![CDATA[Supervised Machine Learning]]></category><category><![CDATA[classification]]></category><category><![CDATA[logistic regression]]></category><category><![CDATA[Random Forest]]></category><category><![CDATA[gradient-boosting]]></category><category><![CDATA[decisiontree]]></category><category><![CDATA[predictive analysis]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[churn analysis]]></category><category><![CDATA[attrition]]></category><category><![CDATA[employee engagement]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Fri, 14 Feb 2025 07:36:08 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739514631201/21b60973-e9ac-4c29-8396-1f14d5793b28.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction"><strong>Introduction</strong></h3>
<p>Employee attrition is one of the major problems that every organization faces, regardless of the sector. It refers to the lifecycle of an organization’s workforce and is an inevitable part of any business. It is defined as the process by which employees leave the workforce for personal or professional reasons. However, it becomes a cause of concern when attrition crosses a particular boundary. For example, attrition among female employee groups could be a significant issue that needs special attention. The different reasons for employee attrition include relocation, lack of professional growth, dissatisfaction, number of accidents, stress level due to overload, conflict, improper clarity, supervisor dissatisfaction, demographic reasons due to marital status, kinship responsibilities, children, age, and tenure, job dissatisfaction due to job involvement, job met expectations, job discontent, monotonous job, less promotional chances, instrumental communication, alternate job opportunities, improper work group cohesion and coworker dissatisfaction, lack of compensation, dissatisfaction in pay and distributive justice, personal reasons, pursuing another better opportunity, pursue higher studies, relocation because of a spouse, organization not delivering on the promise made during recruitment and many more.</p>
<p>Organizations must frame strategies and ideas to control the growing employee attrition rate. The primary responsibility of HR analytics is to help organizations understand what is most important to their employees. The goal is to improve understanding and design of interventions, thereby increasing employee engagement and productivity and reducing unwanted attrition risk. Predictive analytics capabilities enable the design of an employee retention model to keep these valuable employees engaged on board.</p>
<p>Organizations are better off when they can retain good employees and the organizational knowledge they possess. Due to attrition, organizations suffer productivity losses, revenue generation opportunities, and lost profits precisely due to changes in senior management. It becomes a significant cause of concern if employees leave the workforce faster than they are hired; these problems include financial considerations because of the cost incurred due to recruiting, hiring, onboarding, and training new employees. Due to these reasons, companies should use various metrics to measure the reasons for attrition. However, it should be clear that zero attrition (no one leaves the organization) is not possible and not suitable for the organization.</p>
<p>It is critical to understand the reasons that drive unwanted attrition in organizations. The most important reason can be dissatisfaction related to pay. In such a scenario, organizations should follow competitors regarding salary levels, pay increases, and retention schemes to check whether attrition rates align with other local companies in the industry. However, this is not enough; the organization must also check other reasons. Some other observations shared by HR personnel show that the attrition among female employees is generally higher and is lower among new recruiters from top educational institutions. However, a systematic approach will be to analyze the data after developing a comprehensive list of drivers of attrition through interviews with managers, employees, and HR staff. However, a deep insight can be gained by evaluating the results of exit interviews.</p>
<p>It is possible to dig deeper to determine the compelling reasons for attrition by using practical tools and, accordingly, determining strategies. For designing strategies to prevent attrition, different parameters that can be measured related to attrition include involuntary attrition rate, new hire attrition contribution, retention rate, attrition breakdown by performance rating, attrition reason breakdown, employee engagement by employee commitment index, employee engagement index, employee retention index, market opportunity index, offer fit index, voluntary attrition rate, cost of employee attrition, average attrition value, average voluntary attrition value, attrition value per FTA, attrition cost rate, etc. Strategies related to recruiting profiles, manager and employee training programs, career planning and development plans, and pay policies will be better to reduce attrition.</p>
<h3 id="heading-supervised-classification-machine-learning"><strong>Supervised Classification Machine Learning</strong></h3>
<p>Classification is a machine learning technique for solving problems predicting a dependent categorical variable. The classification problem occurs when the dependent variable has two or multiple categories and is predicted by a set of independent variables. Most of the data in real-world problems require the concept of classification. It should be specified that any number of dependent variable categories can exist in classification. However, logistic regression applies only to two categories (binary classification). Logistic regression predicts binary values, such as whether the customer will buy or not, Pass/Fail, Yes/No, 0/1. It measures the probability of event=success and event=failure. The different steps that can be used in prediction using classification techniques include the following:</p>
<ol>
<li><p><strong>Data exploration:</strong> This step requires preparing data to develop an efficient model. It includes appropriately understanding data, handling missing values, feature engineering, etc.</p>
</li>
<li><p><strong>Model development:</strong> Predictive analytics is extracting information from existing datasets to determine patterns and predict future outcomes and trends. We divide the dataset into training and test datasets to assess the patterns and predict outcomes. It is better always to split the data using a particular seed value to have the same data split. This further means that the result generated will always be the same if we split the data. This will help the system generate the same random numbers as specified in the function; otherwise, we would not be able to have uniformity across the different executions of the same program. This will help us always fetch the same result since the same observations will be in the training and test datasets. The model is developed according to the required independent variables on the training dataset. Many supervised machine learning classification techniques are available in KNIME based on different algorithms, such as Naïve Bayes, k-nearest neighbors (k-NN), support vector machines (SVM), decision tree, random forest, bagging, and gradient boosting.</p>
</li>
<li><p><strong>Feature selection:</strong> Feature selection is critical in building predictive machine learning models. It involves selecting the most relevant features (variables, predictors) from your data that contribute significantly to the target variable's prediction. Here’s a breakdown of the process and its importance:</p>
<p> Why Feature Selection?</p>
<ul>
<li><p>Improves Model Performance: Reducing the number of irrelevant or redundant features can enhance model accuracy and reduce overfitting.</p>
</li>
<li><p>Reduces Complexity: Simplifies the model, making it more interpretable and faster to train.</p>
</li>
<li><p>Enhances Generalization: Focuses on the most critical features, leading to better generalization of new data.</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>Methods of Feature Selection</strong></p>
<ol>
<li><p><strong>Filter Methods</strong>: These methods apply statistical techniques to evaluate the importance of each feature independently of the model.</p>
<p> a) Correlation Coefficient: Measures the correlation between each feature and the target variable.</p>
<p> b) Chi-Square Test: Evaluates the independence of categorical features concerning the target variable.</p>
<p> c) ANOVA: Assesses the relationship between continuous features and the target variable.</p>
</li>
<li><p><strong>Wrapper Methods</strong>: These methods evaluate the performance of a subset of features by training and testing a model. They are more computationally intensive but often provide better results.</p>
<p> a) Recursive Feature Elimination (RFE): Iteratively removes the least important features and evaluates model performance.</p>
<p> b) Forward/Backward Selection: This method adds or removes features one at a time based on their contribution to the model's performance.</p>
</li>
<li><p><strong>Embedded Methods</strong>: These methods perform feature selection as part of the model training process. They are model-specific and incorporate feature selection into the model's construction.</p>
<p> a) LASSO (Least Absolute Shrinkage and Selection Operator): Adds a penalty term to the model that shrinks the coefficients of less important features to zero.</p>
<p> b) Tree-Based Methods: Decision trees and random forests naturally perform feature selection based on feature importance scores.</p>
</li>
</ol>
<ol start="4">
<li><p><strong>Predicting the model</strong>: The developed model predicts the values of the user-defined input of the test dataset. It stores the predicted value of the dependent variable for the given values of the input independent variables.</p>
</li>
<li><p><strong>Determining the model's accuracy</strong>: This is the most crucial step because it finally reports the accuracy of the created model. This step shows the final result of the algorithm used on the data. The primary focus is on increasing the model's accuracy with meaningful interpretations. The model's accuracy is determined by comparing the test dataset's predicted and original values. The difference in the preceding values shows the model’s inaccuracy. Different techniques such as accuracy score, classification report, confusion matrix, receiver operating characteristics (ROC), and area under the curve (AUC) are used for measuring the results of classification problems.</p>
<p> <strong>a) Accuracy score</strong>: The accuracy is determined using the two inputs: the dependent variable's predicted values and the dependent variable's original values from the test data. The accuracy score is calculated between 0% and 100%.</p>
<p> <strong>b) Confusion matrix</strong>: This is used to determine to what extent prediction has been done appropriately. A confusion matrix is a table often used to describe the performance of a classification model on a set of test data for which the actual values are known. To understand the confusion matrix, let us assume the results of a binary classifier. Two possible predicted classes are “yes” and “no”. If we were predicting employee attrition, “yes” would mean they have left the company, and “no” would mean they have not. Suppose the model made 100 predictions (100 employees being analyzed for leaving the company). The model predicted “yes” 40 times and “no” 60 times. However, 45 people left the company in the original dataset, and 55 did not. The confusion matrix will be created as follows:</p>
<p> <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739519422315/0cb84b42-4abb-466c-8a27-ebe2555726a0.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>True Positives (TP): These are cases in which the model predicted “yes,” and the employees have left the company.</p>
</li>
<li><p>True Negatives (TN): These are cases in which the model predicted “no,” and the employees have not left the company.</p>
</li>
<li><p>False Positives (FP) (“Type I error”): We predicted “yes”, but they have not left the company.</p>
</li>
<li><p>False Negatives (FN) (“Type II error”): We predicted “no”, and they left the company.</p>
</li>
<li><p>Accuracy: Accuracy is determined by (TP+TN)/Total = (30+45)/100 = 0.75 (75%)</p>
</li>
</ul>
</li>
</ol>
<p>    Two other terms frequently used to evaluate a model are Sensitivity and Specificity.</p>
<ul>
<li><p>Sensitivity (True Positive Rate): % of correctly predicted “yes” is determined by TP/(TP+FN) = 30/(30+15) = 0.67 (67%)</p>
</li>
<li><p>Specificity (True Negative Rate): % of correctly predicted “no” is determined by TN/(TN+FP) = 45/(45+10) = 0.82 (82%)</p>
</li>
</ul>
<p>    <strong>c) Classification report</strong>: The report displays different values, precision, recall, sensitivity, specificity, F1-score (F-measure), and Cohen’s kappa. Precision is the True Positives ratio to the True and False Positives sum. This further means the percentage of correct for all the positives. Recall is the ratio of True Positives to the sum of the True Positives and False Negatives. This displays the percentage of records that were classified correctly. The F1 score is a weighted harmonic mean of precision and recall; the highest score is 1.0, and the lowest is 0.0. It is suggested that the F1 score be considered when comparing models and classifiers because they consider precision and recall scores in their computation. It should be noted that the F1-score is always lower than accuracy measures. Cohen's Kappa is a statistic that measures inter-rater agreement for categorical items. It considers the possibility of the agreement occurring by chance.</p>
<p>    <strong>d) ROC curve and AUC</strong>: The ROC curve is a commonly used graph that summarizes the performance of a classifier over all possible thresholds. It is generated by plotting the True Positive Rate (y-axis) against the False Positive Rate (x-axis). The ROC curve is usually a good graph to summarize the quality of our classifier. The higher the curve above the diagonal baseline, the better the predictions. The model's performance is determined by looking at the area under the ROC curve, and the value is stored in AUC. The highest value of AUC is 1, while the least is 0.5, which depicts the 45-degree random line. It should be noted that if there is any value less than 0.5, we should do the exact opposite of the recommendation of the model to get a value more than 0.5. It should be noted that the ROC curve is a graphical plot that illustrates the diagnostic ability of a binary classifier system as its discrimination threshold is varied.</p>
<ol start="6">
<li><strong>Creating a better model</strong>: The main objective of any analyst is to create a better model. Different approaches, such as hyper-parameter tuning and feature engineering, are adopted to achieve this.</li>
</ol>
<h3 id="heading-employee-attrition-data"><strong>Employee Attrition Data</strong></h3>
<p>The EmployeeAttrition.csv file helps us understand KNIME usage. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder on the KNIME Community Hub.</p>
<blockquote>
<p><em>The</em> <a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj"><em>Predicting Employee Attrition – Supervised Classification Machine Learning</em></a> <em>workflow can be downloaded from the KNIME Community Hub.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516201647/68ed3aac-8a45-41be-8edb-98faa0c3c12d.png" alt class="image--center mx-auto" /></p>
<p>After downloading the CSV file from the Data folder, you are ready.</p>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516245141/bb03e310-6a18-4778-8247-51e03a75c1ad.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the <strong>EmployeeAttrition.csv</strong> CSV dataset. The above table shows that the employee dataset has 14999 observations and 10 columns.</p>
<h3 id="heading-data-exploration"><strong>Data Exploration</strong></h3>
<p>The <strong>Statistics</strong> node primarily determines the descriptive summary statistics of the columns in the dataset. This node calculates statistical moments such as minimum, maximum, mean, standard deviation, variance, median, overall sum, number of missing values, and row count across all numeric columns. It counts all nominal values together with their occurrences. The node provides the following three output tables</p>
<p>a) Statistics Table: All statistic moments for all numeric columns,</p>
<p>b) Nominal Histogram Table: Nominal values for all selected categorical columns and</p>
<p>c) Occurrences Table: The most frequent/infrequent values from the categorical columns (Top/bottom)</p>
<p>The variable <strong>LeftCompany</strong> is related to employees who have left the organization (employee attrition, yes – left the company &amp; no – not left the company), and the rest of the columns are independent variables. We can observe from the statistics table output that an employee's <strong>SatisfactionLevel</strong> and <strong>LastEvaluation</strong> are measured between 0 and 1. The average satisfaction level is 0.613, and the average last evaluation score is 0.716. The variables <strong>WorkAccident</strong>, <strong>LeftCompany</strong>, and <strong>PromotionLast5years</strong> have binary values (yes and no). The highest number of projects an employee has undertaken is 7, and the maximum time spent in the organization by an employee is 10 years. The average time spent by an employee is 3.5 years, and the average monthly hours spent by an employee is 201 hours. The <strong>Salary</strong> is represented in the form of low, medium, and high. Similarly, the <strong>Department</strong> column represents the department to which the employee belongs. The number of employees who left the company is 3571 (23.8%), and 11428 (76.2%) are in the organization.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516296477/25d224de-2295-41b8-a9b9-e98d77eaf726.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-data-visualization">Data Visualization</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516348460/a458be9f-fecf-4cc0-940d-d89ea7f34750.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-displaying-department-wise-employees-count"><strong>Displaying Department-wise Employees Count</strong></h3>
<p>We will use the Bar Chart node to generate a bar plot that displays the department-wise employee count.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516379317/0e6c1d0f-c72a-4cf9-b66a-b46571874161.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516399121/c32e3253-dd1e-49e5-9f78-f77a86faceb8.png" alt class="image--center mx-auto" /></p>
<p>The chart shows that the Sales department had the most employees, followed by the technical and support departments. The Accounting, HR, and Management departments had the fewest employees.</p>
<h3 id="heading-displaying-attrition-by-department"><strong>Displaying Attrition by Department</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516418331/533aebb4-b667-43dd-99fc-656fb98e5c83.png" alt class="image--center mx-auto" /></p>
<p>Say we wanted to count the attrition aggregated across departments. We can use the <strong>Pivot</strong> node to perform this aggregation using column settings: group by <strong>LeftCompany</strong>, pivot by <strong>Department</strong>, and count by <strong>Salary</strong>. Subsequently, we will use the <strong>Bar Chart</strong> node to display the attrition count for each department.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516450777/c63bd75d-c13b-4392-a09d-62575809f973.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516470369/fa7f30c4-4778-4018-bd3e-0b526d911dbf.png" alt class="image--center mx-auto" /></p>
<p>The chart shows that people have left from all the departments. However, fewer people have left the Sales department, and proportionately more people have left from the technical, IT, product management, and marketing departments.</p>
<h3 id="heading-displaying-attrition-rate-by-department"><strong>Displaying Attrition Rate by Department</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516498610/4a33cf49-ffbd-4c1c-9975-5ac9a8589f70.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516517920/f6f33cd5-33f1-4a5a-9df0-2afc1fef220a.png" alt class="image--center mx-auto" /></p>
<p>The chart shows that the HR department has the highest attrition rate, followed by the accounting department. However, the attrition rate is lower in the research and development and management departments.</p>
<h3 id="heading-visualizing-employee-details"><strong>Visualizing Employee Details</strong></h3>
<p>We will use the Python View node to construct a count plot displaying the number of employees in the <strong><em>LeftCompany</em></strong>, <strong><em>Salary</em></strong>, <strong><em>TimeSpendCompany</em></strong>, <strong><em>PromotionLast5years</em></strong>, <strong><em>NumberProject</em></strong>, and <strong><em>WorkAccident</em></strong> columns.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Visualization of employee details</span>
<span class="hljs-comment"># Importing libraries</span>
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO

<span class="hljs-comment"># Plotting </span>
fig = plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">10</span>)) 

<span class="hljs-comment">#Count plot for displaying number of employees who left/stayed</span>
plt.subplot(<span class="hljs-number">231</span>) 
sns.countplot(x=<span class="hljs-string">'LeftCompany'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'LeftCompany'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"viridis"</span>) 
plt.title(<span class="hljs-string">"Left Company"</span>)

<span class="hljs-comment">#Count plot for displaying number of employees with different salaries</span>
plt.subplot(<span class="hljs-number">232</span>)
sns.countplot(x=<span class="hljs-string">'Salary'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'Salary'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"mako"</span>)
plt.title(<span class="hljs-string">"Salary-wise Employees"</span>)

<span class="hljs-comment">#Count plot according to number of years spent in organization</span>
plt.subplot(<span class="hljs-number">233</span>)
sns.countplot(x=<span class="hljs-string">'TimeSpendCompany'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'TimeSpendCompany'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"vlag"</span>)
plt.title(<span class="hljs-string">"Time Spent"</span>)

<span class="hljs-comment">#Count plot for displaying number of employees according to promotion</span>
plt.subplot(<span class="hljs-number">234</span>)
sns.countplot(x=<span class="hljs-string">'PromotionLast5years'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'PromotionLast5years'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"rainbow"</span>)
plt.title(<span class="hljs-string">"Employees Promotions"</span>)

<span class="hljs-comment">#Count plot for displaying number of employees for number of projects</span>
plt.subplot(<span class="hljs-number">235</span>)
sns.countplot(x=<span class="hljs-string">'NumberProject'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'NumberProject'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"terrain"</span>)
plt.title(<span class="hljs-string">"Employees by Number of Projects"</span>)

<span class="hljs-comment">#Count plot for displaying number of employees for work accident</span>
plt.subplot(<span class="hljs-number">236</span>)
sns.countplot(x=<span class="hljs-string">'WorkAccident'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'WorkAccident'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"prism"</span>)
plt.title(<span class="hljs-string">"Work Accident"</span>)

<span class="hljs-comment"># Create buffer to write into</span>
buffer = BytesIO()

<span class="hljs-comment"># Create plot and write it into the buffer</span>
fig.savefig(buffer, format=<span class="hljs-string">'svg'</span>)

<span class="hljs-comment"># The output is the content of the buffer</span>
output_image = buffer.getvalue()

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516575762/9b0034df-1fda-4009-996e-8079de5aab16.png" alt class="image--center mx-auto" /></p>
<p>We can observe from the chart that employees left, promotion, and work accidents are binary variables. Nearly 23.8% of the employees have left the organization; very few employees have been given promotions in the organization in the last 5 years, and accidents also rarely happen in the workplace. More employees belong to the low-salary group, more have spent 3 years in the organization, and a maximum number of employees have three or four projects.</p>
<h3 id="heading-determining-correlation-between-variables"><strong>Determining Correlation Between Variables</strong></h3>
<p>We will use the <strong>Linear Correlation</strong> node to generate a correlation matrix heatmap based on a selected set of columns.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516607685/86a220af-c8cc-4702-a6d8-3e221a7423b8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516631558/5fc5acbe-821e-4429-8d3b-908ce1303110.png" alt class="image--center mx-auto" /></p>
<p>The squared table shows the pair-wise correlation values of all columns. The color range varies from dark red (strong negative correlation) to dark blue (strong positive correlation). If a correlation value for a pair of columns is unavailable, the corresponding cell contains a missing value (shown as a cross in the color view). Hovering the mouse over each box in the views window will display the corresponding pair-wise correlation value. It is clear from the chart that there is a good correlation between the last evaluation, the number of projects, and average monthly hours. This is evident because the good performers might be given a lot of projects to work with. Surprisingly, a negative correlation exists between satisfaction level and number of projects.</p>
<h3 id="heading-association-between-attrition-and-categorical-variables"><strong>Association Between Attrition and Categorical Variables</strong></h3>
<p>We will use the <strong>Python View</strong> node to generate multiple count plots between the <strong><em>LeftCompany</em></strong> column and the <strong><em>NumberProject</em></strong>, <strong><em>Salary</em></strong>*,* <strong><em>WorkAccident</em></strong>*,* <em>and</em> <strong><em>PromotionLast5years</em></strong> categorical columns.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Count plot between employee attrition and categorical variables</span>
<span class="hljs-comment"># Importing libraries</span>
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO

<span class="hljs-comment"># Plotting </span>
fig = plt.figure(figsize=(<span class="hljs-number">15</span>,<span class="hljs-number">8</span>))
plt.suptitle(<span class="hljs-string">'Association between Attrition and Categorical Variables'</span>,
fontsize=<span class="hljs-number">20</span>, fontweight=<span class="hljs-string">'bold'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Number of Projects</span>
plt.subplot(<span class="hljs-number">221</span>)
sns.countplot(x=<span class="hljs-string">'NumberProject'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'LeftCompany'</span>, palette=<span class="hljs-string">"Set1_r"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Number of Projects'</span>)
plt.ylabel(<span class="hljs-string">'Number of Employees'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Salary</span>
plt.subplot(<span class="hljs-number">222</span>)
sns.countplot(x=<span class="hljs-string">'Salary'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'LeftCompany'</span>, palette=<span class="hljs-string">"Set2_r"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Salary'</span>)
plt.ylabel(<span class="hljs-string">'Number of Employees'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Work Accident</span>
plt.subplot(<span class="hljs-number">223</span>)
sns.countplot(x=<span class="hljs-string">'WorkAccident'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'LeftCompany'</span>, palette=<span class="hljs-string">"Set3_r"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Work Accident'</span>)
plt.ylabel(<span class="hljs-string">'Number of Employees'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Promotion in Last 5 Years</span>
plt.subplot(<span class="hljs-number">224</span>)
sns.countplot(x=<span class="hljs-string">'PromotionLast5years'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'LeftCompany'</span>, palette=<span class="hljs-string">"Set1"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Promotion in Last 5 years'</span>)
plt.ylabel(<span class="hljs-string">'Number of Employees'</span>)

<span class="hljs-comment"># Create buffer to write into</span>
buffer = BytesIO()

<span class="hljs-comment"># Create plot and write it into the buffer</span>
fig.savefig(buffer, format=<span class="hljs-string">'svg'</span>)

<span class="hljs-comment"># The output is the content of the buffer</span>
output_image = buffer.getvalue()

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516693779/18bddf13-5fd7-4cf7-852a-4f59bdeb8b1a.png" alt class="image--center mx-auto" /></p>
<p>From the chart of the number of projects and number of employees, we can see that people who had three projects did not leave the organization. But people with 2, 4, 5, and 6 projects left the organization. This means there is no association between the “number of projects” and “number of employees.” It can be observed from the chart that more employees who were offered low to medium-salary packages have left the organization compared to those offered high salaries. It is evident from the chart that many employees left the organization regardless of the work accident. So, work accidents are not an essential factor in leaving the organization. Nearly 4000 employees might have left the organization unsatisfied with their promotion process. From the preceding four categorical data, we can reasonably assume that “promotion” and “salary” may be why employees leave the organization.</p>
<h3 id="heading-association-between-attrition-and-continuous-variables"><strong>Association Between Attrition and Continuous Variables</strong></h3>
<p>We will use the <strong>Python View</strong> node to generate multiple count plots between the <strong><em>LeftCompany</em></strong> column and the <strong><em>LastEvaluation</em></strong>, <strong><em>SatisfactionLevel</em></strong>, and <strong><em>AverageMonthlyHours</em></strong> continuous columns.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Load your data (example) </span>
df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas() 

<span class="hljs-comment"># Count plot between employee absenteeism and categorical variables</span>
<span class="hljs-comment"># Importing libraries</span>
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO

<span class="hljs-comment"># Association between employees attrition and continuous variables</span>
absent_no=df[df[<span class="hljs-string">"LeftCompany"</span>]==<span class="hljs-string">'No'</span>]
absent_yes=df[df[<span class="hljs-string">"LeftCompany"</span>]==<span class="hljs-string">'Yes'</span>]

<span class="hljs-comment"># Creating and setting the new palette</span>
new_palette = [<span class="hljs-string">"#861B04"</span>, <span class="hljs-string">"#F86C4D"</span>, <span class="hljs-string">"#E5F803"</span>, <span class="hljs-string">"#4DB5F8"</span>, <span class="hljs-string">"#C4FC05"</span>, <span class="hljs-string">"#F30BF0"</span>, <span class="hljs-string">"#05FC93"</span>, <span class="hljs-string">"#FC0593"</span>, <span class="hljs-string">"#FC8F05"</span>]
sns.set_palette(palette=new_palette)

fig, (ax1, ax2, ax3) = plt.subplots(nrows=<span class="hljs-number">3</span>, figsize=(<span class="hljs-number">13</span>,<span class="hljs-number">9</span>))

<span class="hljs-comment"># Kernel density plot for employee attrition and last evaluation</span>

sns.kdeplot(data=absent_no, x=<span class="hljs-string">"LastEvaluation"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#861B04'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax1)

sns.kdeplot(data=absent_yes, x=<span class="hljs-string">"LastEvaluation"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#F86C4D'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax1)

ax1.set_title(<span class="hljs-string">'Last Evaluation &amp; Left Company'</span>)
ax1.legend([<span class="hljs-string">'No'</span>,<span class="hljs-string">'Yes'</span>])

<span class="hljs-comment"># Kernel density plot for employee attrition and satisfaction level</span>
sns.kdeplot(data=absent_no, x=<span class="hljs-string">"SatisfactionLevel"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#4DB5F8'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax2)

sns.kdeplot(data=absent_yes, x=<span class="hljs-string">"SatisfactionLevel"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#C4FC05'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax2)

ax2.set_title(<span class="hljs-string">'Satisfaction Level &amp; Left Company'</span>)
ax2.legend([<span class="hljs-string">'No'</span>,<span class="hljs-string">'Yes'</span>])

<span class="hljs-comment"># Kernel density plot for employee attrition and average monthly hours</span>
sns.kdeplot(data=absent_no, x=<span class="hljs-string">"AverageMonthlyHours"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#05FC93'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax3)

sns.kdeplot(data=absent_yes, x=<span class="hljs-string">"AverageMonthlyHours"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#FC0593'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax3)

ax3.set_title(<span class="hljs-string">'Average Monthly Hours &amp; Left Company'</span>)
ax3.legend([<span class="hljs-string">'No'</span>,<span class="hljs-string">'Yes'</span>])

plt.tight_layout()

<span class="hljs-comment"># Create buffer to write into</span>
buffer = BytesIO()

<span class="hljs-comment"># Create plot and write it into the buffer</span>
fig.savefig(buffer, format=<span class="hljs-string">'svg'</span>)

<span class="hljs-comment"># The output is the content of the buffer</span>
output_image = buffer.getvalue()

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516732192/49b70176-35f2-4009-86ba-dc8346011c5e.png" alt class="image--center mx-auto" /></p>
<p>The chart shows that people who left the organization had evaluation scores less than 0.6 and greater than 0.8. This means that either high performers or low performers left the organization. Employees who performed average stayed in the organization to a great level. This is the same scenario with monthly hours. Employees with low or high average monthly hours left the organization, while those with average hours stayed back. However, more employees who had lower satisfaction levels left the organization.</p>
<h3 id="heading-scatter-plot-matrix-for-continuous-columns-by-attrition"><strong>Scatter Plot Matrix for Continuous Columns by Attrition</strong></h3>
<p>We will first use the <strong>Color Manager</strong> node to assign specific colors for the categories (Yes and No) in the <strong><em>LeftCompany</em></strong> column. Subsequently, we will use the <strong>Scatter Plot Matrix</strong> node to create a pair-wise scatter plot matrix of <strong><em>SatisfactionLevel</em></strong>, <strong><em>LastEvaluation</em></strong>, and <strong><em>AverageMonthlyHours</em></strong> columns with <strong><em>LeftCompany</em></strong> (Yes and No) as the color dimension for employees.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516791341/f1d396af-829c-4120-aa5b-b4fd8810d0e8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516811692/894c5aa5-e824-4f5d-9ab1-57cbd7432a38.png" alt class="image--center mx-auto" /></p>
<p>It is clear from the chart that employees with higher last evaluation and satisfaction levels, higher last evaluation and lower satisfaction levels, and medium last evaluation and medium satisfaction levels tend to leave. However, employees with a lower last evaluation, irrespective of satisfaction level, and employees with the highest satisfaction level and highest last evaluation also do not leave. This is because these employees might be getting higher salaries, and they do not leave. Similarly, employees with more monthly hours tend to leave, and employees with fewer monthly hours, irrespective of <strong><em>LastEvaluation</em></strong> and <strong><em>SatisfactionLevel</em></strong>, do not leave. Thus, <strong><em>AverageMonthlyHours</em></strong> is a significant reason behind leaving the organization. However, employees with higher satisfaction levels do not leave, irrespective of the monthly hours.</p>
<h3 id="heading-dummy-encoding"><strong>Dummy Encoding</strong></h3>
<p>As part of feature engineering, converting each category into different columns represented by binary values (0, 1) is essential. We will use the <strong>One to Many</strong> node to transform all possible category values in the selected columns into a new column. It is worth noting that the number of new columns created for a particular column is the same as the number of categories in the column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516892041/23aa8ed0-279b-4c71-9d1d-d4a058783871.png" alt class="image--center mx-auto" /></p>
<p>The <strong>One to Many</strong> node creates new columns according to the number of categories for each variable. Ten new columns have been made since the Department has ten categories. Similarly, three new columns are designed for <strong><em>Salary</em></strong>, and two are for <strong><em>WorkAccident</em></strong> and <strong><em>PromotionLast5years</em></strong>. The result clearly shows that there are 14999 observations with 27 columns. Among these, 17 new columns have binary integer values.</p>
<p>In classification prediction, one category for each categorical variable is considered a reference, and others are considered dummy variables. For this process, the following dummy and reference variables are created for each attribute:</p>
<ul>
<li><p>For department, “management_Department” is the reference variable.</p>
</li>
<li><p>For salary, “low_Salary” is a reference variable.</p>
</li>
<li><p>For work accident, “No_WorkAccident” is a reference variable.</p>
</li>
<li><p>For promotion in the last five years, “Yes_PromotionLast5years” is the reference variable.</p>
</li>
</ul>
<h3 id="heading-dropping-reference-variables"><strong>Dropping Reference Variables</strong></h3>
<p>It is essential to retain only requirement columns for the analysis. Hence, the reference and categorical variables are removed using the <strong>Column Filter</strong> node before creating the classification model. <strong><em>LeftCompany</em></strong> is considered the dependent variable.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516962447/e8a771e0-6751-4526-ba44-0d2b80ecd87e.png" alt class="image--center mx-auto" /></p>
<p>After dropping the unwanted columns, the table has 14999 rows and 19 columns.</p>
<h3 id="heading-data-partitioning"><strong>Data Partitioning</strong></h3>
<p>The complete dataset clearly shows a much higher number of loan rejections than approvals. As a result, we would need to utilize stratified sampling based on the <strong><em>LeftCompany</em></strong> column in the <strong>Partitioning</strong> node. The random seed option helps to divide the dataset exactly according to the seed value. This is done intentionally to produce the same results for ease of replication. For this partitioning, the seed value is 30000. The dataset is split in the ratio of 70:30 for the training and test datasets, respectively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739516994397/c0128e8b-247d-4ea4-be8f-5eafede492c2.png" alt class="image--center mx-auto" /></p>
<p>The first partition training table has 10499 rows and 19 columns; the second partition test table has 4500 rows and 19 columns.</p>
<h3 id="heading-predicting-employee-attrition-using-logistic-regression-all-attributes"><strong>Predicting Employee Attrition Using Logistic Regression (All Attributes)</strong></h3>
<p>Predict employee attrition using the logistic regression model with all the independent variables. The characteristic of logistic regression helps to solve many real-world problems. Most of the data occurring in real-world problems require the concept of classification. It is essential to mention here that most of the necessary assumptions for regression need not be fulfilled before applying the logistic regression. First, logistic regression does not require a linear relationship between the dependent and independent variables. Second, the error terms do not need to be normally distributed. Third, homoscedasticity is not required. However, logistic regression requires the data to be normal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739519025822/e3738e94-ac95-49e5-842b-e1991828fae2.png" alt class="image--center mx-auto" /></p>
<p>We will run the logistic regression model on the training dataset using the <strong>Logistic Regression Learner</strong> node, with <strong><em>LeftCompany</em></strong> as the target column and ‘No’ as the reference category. We will include all the independent variables that we had filtered earlier. Subsequently, with the <strong>Logistic Regression Predictor</strong> node, we will predict the response on the test dataset. The resultant output contains three new columns, one containing the prediction for each row and two more containing the predicted probabilities for the target column's two categories (yes and no). They represent the probability that a row in the input data falls into a specific category.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517031854/a33d1d51-b235-4d7e-b4c3-d73c67bc31d4.png" alt class="image--center mx-auto" /></p>
<p>We will use the <strong>Scorer</strong> node to compare the actual (<strong><em>LeftCompany</em></strong>) and predicted  (<strong><em>LeftCompPredLogistic</em></strong>) columns by their attribute value pairs and show the confusion matrix. Additionally, the node provides several accuracy statistics such as True-Positives, False-Positives, True-Negatives, False-Negatives, Recall, Precision, Sensitivity, Specificity, Cohen’s Kappa, and F-measures, as well as the overall accuracy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517057511/dd64c2cf-5379-4ba3-954a-3e456d72ae39.png" alt class="image--center mx-auto" /></p>
<p>We will also use the <strong>ROC Curve</strong> node to visualize and find the Area Under the Curve (AUC) for the model based on the predicted probabilities column (LeftCompany=’Yes’).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517083865/78217333-4316-47f8-8918-01b7b003eba0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517105191/df18fde5-f56a-4f5c-909d-9f0611af9c3e.png" alt class="image--center mx-auto" /></p>
<p>The logistic regression model's accuracy for the test data is 0.797. The confusion matrix shows that True Positives are 404 and True Negatives are 3181. Similarly, False Positives are 248 and False Negatives are 667. Hence, accuracy is 0.797, and misclassification is 0.203. This further means that Sensitivity is 0.26 and Specificity is 0.92.</p>
<p>The results of the scorer report can be explained as follows:</p>
<p>Precision is the ratio of True Positives to the sum of True and False Positives. This further means that the percentage of correct positives. Our results show that the precision for ‘Yes’ is 0.62 and for ‘No’ is 0.827. This means that the records having ‘Yes’ are correctly predicted as 62%, and records having ‘No’ are correctly predicted as 82.7%. Recall is the ratio of True Positives to the sum of True Positives and False Negatives. This displays the percentage of records that are classified correctly. Our result shows that recall values are 0.377 and 0.928 for ‘Yes’ and ‘No’, respectively. This further suggests that the accuracy is lower at 0.377 for the categorical value of “Yes”. The F1 score is the weighted harmonic mean of precision and recall; the highest score is 1.0, and the lowest is 0.0. Our test data's F1-scores are 0.469 and 0.874 for ‘Yes’ and ‘No’, respectively. Cohen’s Kappa value is 0.352 (fair agreement), which is low in our case. From the ROC curve, we can observe that the AUC of 0.826 is excellent.</p>
<p>While all these metrics are helpful, each serves a specific purpose in fine-tuning the model and ensuring it meets the desired performance criteria for its particular applications.</p>
<p>Let's explore how these metrics can be used effectively in predicting employee attrition:</p>
<p><strong>Accuracy</strong></p>
<ul>
<li><p><strong>Utility</strong>: Provides a general sense of the model’s overall performance by showing the proportion of correct predictions.</p>
</li>
<li><p><strong>Context</strong>: Useful when the cost of false positives and false negatives is similar. Attrition prediction shows how well the model is doing overall, but it might not capture the nuances of the data if there’s a class imbalance.</p>
</li>
</ul>
<p><strong>Precision</strong></p>
<ul>
<li><p><strong>Utility</strong>: Focuses on the accuracy of positive predictions (predicting an employee will leave).</p>
</li>
<li><p><strong>Context</strong>: Important when the cost of a false positive is high (e.g., unnecessary interventions). In predicting attrition, high precision means when the model predicts an employee will leave, it’s likely correct.</p>
</li>
</ul>
<p><strong>Recall</strong></p>
<ul>
<li><p><strong>Utility</strong>: Measures the model’s ability to capture all actual positives.</p>
</li>
<li><p><strong>Context</strong>: Crucial when the cost of missing a true positive is high (e.g., failing to identify an at-risk employee). High recall ensures that most employees at risk of leaving are identified.</p>
</li>
</ul>
<p><strong>F1-Score (F-Measure)</strong></p>
<ul>
<li><p><strong>Utility</strong>: Balances precision and recall by providing a single metric. It’s the harmonic mean of precision and recall.</p>
</li>
<li><p><strong>Context</strong>: Useful when there’s a need to balance the trade-offs between precision and recall in attrition prediction, ensuring neither false positives nor false negatives are disproportionately high.</p>
</li>
</ul>
<p><strong>Cohen's Kappa</strong></p>
<ul>
<li><p><strong>Utility</strong>: Adjusts for agreement occurring by chance, measuring how much better the model is compared to random guessing.</p>
</li>
<li><p><strong>Context</strong>: Useful for evaluating the model’s performance beyond what would be expected by chance, especially in imbalanced datasets. It provides a more nuanced understanding of the model’s predictive power.</p>
</li>
</ul>
<p><strong>False Positive Rate (FPR)</strong></p>
<ul>
<li><p><strong>Utility</strong>: Measures the proportion of negative instances incorrectly classified as positive (employees predicted to leave but stay).</p>
</li>
<li><p><strong>Context</strong>: Important in scenarios where the cost of false positives is high. In attrition prediction, a high FPR might lead to unnecessary interventions for employees not at risk.</p>
</li>
</ul>
<p>In predicting employee attrition:</p>
<ul>
<li><p><strong>Accuracy</strong> gives an overall idea but may not be sufficient if the classes are imbalanced.</p>
</li>
<li><p><strong>Precision</strong> ensures that identified at-risk employees are likely to leave.</p>
</li>
<li><p><strong>Recall</strong> ensures that most at-risk employees are flagged.</p>
</li>
<li><p><strong>F1-Score</strong> balances the trade-offs between precision and recall.</p>
</li>
<li><p><strong>Cohen’s Kappa</strong> provides a measure that accounts for chance agreement.</p>
</li>
<li><p><strong>FPR</strong> helps minimize unnecessary interventions for employees who are not at risk.</p>
</li>
</ul>
<p>Using these metrics together helps you comprehensively evaluate and fine-tune the model, ensuring it’s effective and reliable in predicting employee attrition.</p>
<h3 id="heading-feature-selection"><strong>Feature Selection</strong></h3>
<p>Now that we have established metrics for a classification model that predicts whether an employee will leave the company or not using all of the features (attributes/independent variables) available in the dataset. The subsequent step is to analyze whether we can achieve better prediction accuracy using fewer features. We shall use the feature reduction nodes in KNIME to do the same.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517226065/2b836e3f-ecef-41b1-a85a-30a05c97f718.png" alt class="image--center mx-auto" /></p>
<p>We will apply the ‘Forward Feature Selection’ strategy to the <strong>Feature Selection Loop Start</strong> node. This iterative approach starts with no feature selected. Each iteration adds the feature that improves the model the most to the feature set. The <strong>Feature Selection Loop End</strong> node is used at the end of the feature selection loop to select features according to the feature selection strategy. In our case, we use the ‘Accuracy’ score variable as our objective is to improve/maximize the model's accuracy. Alternatively, we can use other score metrics like ‘Cohen’s Kappa’ or ‘Error’ depending on our model performance objective. Subsequently, we use the <strong>Feature Selection Filter</strong> node to choose the set of reduced features we want to take forward to build the classification model. In our case, we select the subset of six features with an accuracy of 0.824. The rationale is that it is the subset with the least number of features among the options with the highest accuracy of 0.824. Therefore, we can achieve the highest accuracy possible with the least features. Check the ‘include static columns’ option to include the target variable <strong><em>LeftCompany</em></strong> in the dataset.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517263987/e6f12f2e-1bbc-4b15-874a-a6520bab7ef0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517284266/fff7fb8a-f832-429f-9740-32359e5cadd3.png" alt class="image--center mx-auto" /></p>
<p>Our chosen features subset has the following six independent variables: <strong><em>SatisfactionLevel</em></strong>, <strong><em>NumberProject</em></strong>, <strong><em>marketing_Department</em></strong>, <strong><em>medium_Salary</em></strong>, <strong><em>high_Salary</em></strong>, and <strong><em>Yes_WorkAccident</em></strong>, along with the target variable <strong><em>LeftCompany</em></strong>.</p>
<h3 id="heading-predicting-employee-attrition-using-the-subset-of-attributes"><strong>Predicting Employee Attrition Using the Subset of Attributes</strong></h3>
<p>We will now predict employee attrition on the reduced subset of the attributes dataset by applying different classification machine learning algorithms. After that, we will collate all the accuracy statistics derived by using these models to the test data to compare the performance of various models and choose the best model to serve the desired objective.</p>
<h3 id="heading-predicting-employee-attrition-using-logistic-regression-selected-attributes-subset"><strong>Predicting Employee Attrition Using Logistic Regression (Selected Attributes Subset)</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517332632/830aeacf-2bf1-4a95-860c-500901c56db9.png" alt class="image--center mx-auto" /></p>
<p>We will run the logistic regression model on the training dataset using the <strong>Logistic Regression Learner</strong> node, with <strong><em>LeftCompany</em></strong> as the target column and ‘No’ as the reference category. We will include only the six independent variables that we had filtered earlier. Subsequently, with the <strong>Logistic Regression Predictor</strong> node, we will predict the response on the test dataset. The resultant output contains three new columns, one containing the prediction for each row and two more containing the predicted probabilities for the target column's two categories (yes and no). They represent the probability that a row in the input data falls into a specific category.</p>
<p>We will use the <strong>Scorer</strong> node to compare the actual (<strong><em>LeftCompany</em></strong>) and predicted columns by their attribute value pairs and show the confusion matrix. Additionally, the node provides several accuracy statistics such as True-Positives, False-Positives, True-Negatives, False-Negatives, Recall, Precision, Sensitivity, Specificity, Cohen’s Kappa, and F-measures, as well as the overall accuracy. We will also use the <strong>ROC Curve</strong> node to visualize and find the Area Under the Curve (AUC) for the model based on the predicted probabilities column (LeftCompany=’Yes’).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517367886/6cae214d-a8ad-4f76-9b52-1d1c5408f8ce.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517387586/658223f4-4dee-45cc-9182-70c0e1072a2e.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-predicting-employee-attrition-using-decision-tree-selected-attributes-subset"><strong>Predicting Employee Attrition Using Decision Tree (Selected Attributes Subset)</strong></h3>
<p>Decision trees are primarily used in machine learning and data mining applications. They are graphs that represent choices and their outcomes in a tree structure. The nodes in the graph represent an event or choice, and the edges represent the decision rules or conditions. The decision tree classifier is a supervised learning algorithm that can be used for both classification (categorical dependent variable) and regression (continuous dependent variable). However, the factors that help us to decide which algorithm to use are discussed below:</p>
<p><strong>Situations to Use Decision Tree Model</strong></p>
<ol>
<li><p>A decision tree is preferred in cases of high nonlinearity and a complex relationship between dependent and independent variables.</p>
</li>
<li><p>A decision tree model is a simple and easy-to-understand graphical representation, even for people from nonanalytical backgrounds. No statistical knowledge is required to understand and interpret the results.</p>
</li>
<li><p>A decision tree is one of the fastest ways to identify the most significant variables and the relation between two or more variables. Decision trees can help us create new variables/features with better power to predict the target variable.</p>
</li>
<li><p>The decision tree model is a nonparametric method unaffected by outliers and missing values. Hence, we do not need to check assumptions. Less data cleaning is required, and imputation is not needed.</p>
</li>
</ol>
<p><strong>Situations When the Decision Tree Model Should Not Be Used</strong></p>
<ol>
<li><p>The linear regression algorithm should be adopted if a linear model well approximates the relationship between the dependent and independent variables.</p>
</li>
<li><p>Overfitting is one of the most real challenges in decision tree models. Setting constraints on model parameters and pruning solves this problem.</p>
</li>
<li><p>A decision tree should not be adopted while predicting a dependent continuous variable because while working with continuous numerical variables, it generally loses information when categorizing numerical variables into different categories.</p>
</li>
</ol>
<p>Decision trees are typically drawn upside down such that the terminal node (leaf) is at the bottom and the root node is at the top. The root node represents the entire population or sample, divided into two or more homogeneous sets. Splitting is a process of dividing a node into two or more sub-nodes. When a sub-node splits into further sub-nodes, it is called a decision node. A node divided into sub-nodes is called the parent node of the sub-nodes; sub-nodes are the children of the parent node. The decision to make strategic splits heavily affects a tree’s accuracy. The creation of sub-nodes increases the homogeneity of the resultant sub-nodes. It then selects the split that results in the most homogeneous sub-nodes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517498194/56fc3938-bb10-45ab-8e6b-ea633bcaf33f.png" alt class="image--center mx-auto" /></p>
<p>We will run the decision tree model on the training dataset using the <strong>Decision Tree Learner</strong> node, with <strong><em>LeftCompany</em></strong> as the target column. We will include only the six independent variables that we had filtered earlier. Subsequently, we will predict the response on the test dataset with the <strong>Decision Tree Predictor</strong> node. The <strong>Scorer</strong> and <strong>ROC Curve</strong> nodes are used to calculate the performance statistics for this model.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517529328/6d015386-445f-42d9-a861-c3771219f71e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517546771/887ad2ea-f253-470f-892e-82b8f2ff2c7b.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-predicting-employee-attrition-using-random-forest-selected-attributes-subset"><strong>Predicting Employee Attrition Using Random Forest (Selected Attributes Subset)</strong></h3>
<p>Random forest is an extension of bagging. This algorithm also takes a random selection of features rather than using all the features to grow trees along with a random subset of data, as in the bagging algorithm. Decision trees, prone to overfit, have been transformed into random forests by training many trees over various subsamples of the data (in terms of observations and predictors used to train them). Hence, a lot of random trees are generated. Since there are many random trees, it is called a random forest.</p>
<p>We know that error occurs due to two main reasons: bias and variance. A too-complex model has a low bias but a significant variance, while a too-simple model has a low variance but a considerable bias. Hence, we need different ways to solve the problem. We need a variance reduction algorithm for a complex model and a bias reduction algorithm for a simple model. Random forest and boosting algorithms help reduce bias to a great extent in simple models. Random forest also reduces the variance of many complex models with low bias. The trees are large in number, and they are selected randomly. Additional random variable selection makes them even more independent and performs better than the bagging algorithm.</p>
<p>The parameters that control model complexity in decision trees are the pre-pruning parameters that stop the building of the tree before it is fully developed. The main advantage of decision trees is that they can be easily visualized and understood by nonexperts since the algorithm is entirely invariant to data scaling. However, the main drawback of decision trees is that they tend to overfit even with pre-pruning and provide more generalization performance. Hence, most applications use a random forest instead of a single decision tree.</p>
<p>Random forest is mighty and often works well without heavy tuning of the parameters and does not require data scaling.  Random forest shares all the benefits of a decision tree. However, decision trees are used only if we need a compact representation of the decision-making process. Random forest helps interpret hundreds of trees in detail, and the trees in random forests tend to be deeper than decision trees. Thus, if a nonexpert wants to make a visual prediction, a single decision tree might be better. Random forest works well on large datasets and training but might be time-consuming and can be parallelized across multicore processors. Random forest performs poorly on high dimensional, sparse data such as text.</p>
<p>Random forest is considered to be a solution to all data science problems. Like a decision tree, random forest can also perform both regression and classification tasks. This method combines a group of weak models to form a robust model. In a random forest, we grow multiple trees instead of a single tree in the decision tree model. In a classification problem, each tree gives a classification, interpreted as the tree that voted for that class. The forest chooses the classification with the most votes (trees in the forest). In regression problems, the algorithm takes the average of outputs by different trees. In the random forest approach, many decision trees are created. Every observation is fed into every decision tree. The most common outcome for each observation is used as the final output. A new observation is fed into all the trees, and a majority vote is taken for each classification model.</p>
<p>The major drawback of random forest is that, like a decision tree, they are appropriate for classification problems but not equally good for regression problems as they do not give precise continuous-nature predictions. Regression does not predict beyond the range in the training data, and it sometimes overfits the datasets. However, because of their high prediction power, a data analyst generally uses random forest for prediction.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517611660/71d04bc0-776e-4a65-a1d2-1771719b3edf.png" alt class="image--center mx-auto" /></p>
<p>We will run the random forest model on the training dataset using the <strong>Random Forest Learner</strong> node, with <strong><em>LeftCompany</em></strong> as the target column. We will include only the six independent variables that we had filtered earlier. Subsequently, we will predict the response on the test dataset with the <strong>Random Forest Predictor</strong> node. The <strong>Scorer</strong> and <strong>ROC Curve</strong> nodes are used to calculate the performance statistics for this model.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517639660/3951e146-dccc-4358-9a27-f58a51fdff09.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517655145/5f90f6d2-ff6f-4ff6-acd9-ac005cd5d0ed.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-predicting-employee-attrition-using-gradient-boosted-trees-selected-attributes-subset"><strong>Predicting Employee Attrition Using Gradient Boosted Trees (Selected Attributes Subset)</strong></h3>
<p>Boosting is another ensemble technique to create a collection of predictors, and gradient boosting is an extension of the boosting method. An ensemble of trees is built one by one, and individual trees are summed sequentially. In this algorithm, a new tree learns sequentially from the previous tree, which fits relatively simple models to the data. We fit consecutive trees, and at every step, the goal is to reduce errors from the previous tree. If an input is wrongly interpreted, its weight is increased so that the next step classifies it correctly. Combining the whole set at the end converts weak learners into a better-performing mode. The model works in a chain or nested iterative model. Thus, the new models are not independent parallel models, but each model is built based on all the previous small models by weighting. Hence, the latest model gets boosted from the earlier model. This helps in reducing the bias of a large number of small models with low variance. This algorithm supports different loss functions and works well with interactions, but it is prone to overfitting and requires careful tuning of different hyper-parameters.</p>
<p>Unlike bagging, booting does not focus on reducing the variance of learners. Still, it focuses on reducing the high variance of learners by averaging lots of models fitted on bootstrapped data samples generated with replacement from the training data to avoid overfitting. Boosting is a sequential technique that works on the principle of ensemble. It combines a set of weak learners and delivers improved prediction accuracy. At any instant t, the model outcomes are weighted based on the outcomes of the previous instant t-1. The outcomes predicted correctly are given a lower weight, and the ones misclassified are weighted higher. This technique is followed for a classification problem, while a similar method is used for regression.</p>
<p>Another major difference between the two techniques is that in bagging, the various models generated are independent of each other and have equal weightage, whereas boosting is a sequential process in which each new model generated is added to improve the performance of the previous collection of models.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517705338/954ff01b-23c7-4ef8-925a-aa53c9f38418.png" alt class="image--center mx-auto" /></p>
<p>We will run the gradient-boosted trees model on the training dataset using the <strong>Gradient Boosted Trees Learner</strong> node, with <strong><em>LeftCompany</em></strong> as the target column. We will include only the six independent variables that we had filtered earlier. Subsequently, we will predict the response on the test dataset with the <strong>Gradient Boosted Trees Predictor</strong> node. The <strong>Scorer</strong> and <strong>ROC Curve</strong> nodes are used to calculate the performance statistics for this model.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517726406/1b5f9471-a472-4bb8-8a19-6f0af4aa0af8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517738193/c7985c77-d8dd-4b09-87f5-9ced76ea3253.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-collating-the-performance-metrics-for-comparison"><strong>Collating the Performance Metrics for Comparison</strong></h3>
<p>Now that we have developed multiple models. The next logical step is to choose the optimum classification model to predict employee attrition based on the performance metrics. To do so, we will collate all the performance statistics from the various classification models and then conduct a comparative analysis.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517770916/605524f5-417b-49f7-b4ce-729afc0fdd5a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517799044/91f1cb9f-8213-44cc-9f8d-adf57463e549.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517823369/cfc3e06e-b687-45de-ac0e-95ebcb9b6fcd.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># This example script plots a histogram using matplotlib and assigns it to the output view</span>
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> matplotlib

<span class="hljs-comment"># Set the backend to 'Agg' to ensure compatibility with non-GUI environments</span>
matplotlib.use(<span class="hljs-string">'Agg'</span>)

<span class="hljs-comment"># Only use numeric columns</span>
data = knio.input_tables[<span class="hljs-number">0</span>].to_pandas()

<span class="hljs-comment"># Determine the feature selection category with the highest F-score for each "Measure Names"</span>
highlight_data = data.loc[data.groupby(<span class="hljs-string">"Measure Name"</span>)[<span class="hljs-string">"Measure Value"</span>].idxmax()]

<span class="hljs-comment"># Create FacetGrid</span>
g = sns.FacetGrid(data, col=<span class="hljs-string">"Measure Name"</span>, col_wrap=<span class="hljs-number">3</span>, height=<span class="hljs-number">4</span>, aspect=<span class="hljs-number">1.5</span>, sharey=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Add the plots</span>
g.map_dataframe(sns.barplot, x=<span class="hljs-string">"Classification Model"</span>, y=<span class="hljs-string">"Measure Value"</span>, hue=<span class="hljs-string">"Classification Model"</span>, palette=<span class="hljs-string">"muted"</span>, legend=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Highlight the bars with the highest F-score</span>
<span class="hljs-keyword">for</span> ax, (measure_name, group) <span class="hljs-keyword">in</span> zip(g.axes.flat, data.groupby(<span class="hljs-string">"Measure Name"</span>)):  <span class="hljs-comment"># Use .flat to ensure compatibility</span>
    highlight = highlight_data[highlight_data[<span class="hljs-string">"Measure Name"</span>] == measure_name]
    <span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> ax.patches:
        <span class="hljs-keyword">if</span> p.get_x() + p.get_width() / <span class="hljs-number">2.</span> <span class="hljs-keyword">in</span> highlight[<span class="hljs-string">"Classification Model"</span>].values:
            p.set_edgecolor(<span class="hljs-string">'red'</span>)
            p.set_linewidth(<span class="hljs-number">2</span>)

<span class="hljs-comment"># Rotate x-axis labels for better readability</span>
<span class="hljs-keyword">for</span> ax <span class="hljs-keyword">in</span> g.axes.flat:  <span class="hljs-comment"># Use .flat to ensure compatibility</span>
    <span class="hljs-keyword">for</span> label <span class="hljs-keyword">in</span> ax.get_xticklabels():
        label.set_rotation(<span class="hljs-number">45</span>)
        label.set_ha(<span class="hljs-string">'right'</span>)

<span class="hljs-comment"># Adjust layout to prevent label overlap</span>
plt.tight_layout()

<span class="hljs-comment"># Show data labels on each of the bars for 3 decimal places</span>
<span class="hljs-keyword">for</span> ax <span class="hljs-keyword">in</span> g.axes.flat:  <span class="hljs-comment"># Use .flat to ensure compatibility</span>
    <span class="hljs-keyword">for</span> p <span class="hljs-keyword">in</span> ax.patches:
        <span class="hljs-keyword">if</span> p.get_height() &gt; <span class="hljs-number">0</span>:  <span class="hljs-comment"># Avoid warnings for bars with height 0</span>
            ax.text(p.get_x() + p.get_width() / <span class="hljs-number">2.</span>, p.get_height(), <span class="hljs-string">'{:.3f}'</span>.format(p.get_height()), 
                    fontsize=<span class="hljs-number">9</span>, color=<span class="hljs-string">'black'</span>, ha=<span class="hljs-string">'center'</span>, va=<span class="hljs-string">'bottom'</span>)

<span class="hljs-comment"># Increase the padding between chart titles and the charts</span>
plt.subplots_adjust(top=<span class="hljs-number">0.9</span>)

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(plt.gcf())  <span class="hljs-comment"># Use plt.gcf() to get the current figure</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517837959/76d48b1d-c20c-41f1-b7e3-07f3e6642767.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739517852467/16946936-7119-4611-ad5d-d97a500b132a.png" alt class="image--center mx-auto" /></p>
<p>Our comparative analysis indicates that we can effectively use a selected subset of attributes rather than the complete dataset for future predictions while maintaining model accuracy. Based on the above comparative table and graph, it is safe to conclude that the <strong>Decision Tree</strong> model strikes the optimum balance across the performance parameters for predicting employee attrition with a selected subset of attributes.</p>
<h3 id="heading-best-practices-for-using-these-metrics-effectively"><strong>Best Practices for Using these Metrics Effectively</strong></h3>
<p>Here are some best practices for using Accuracy, Cohen's Kappa, and False Positive Rate effectively in your machine learning projects:</p>
<p><strong>Model Accuracy</strong></p>
<ul>
<li><p><strong>Combine with Other Metrics</strong>: Always use accuracy with other metrics like precision, recall, and F1-score, especially when dealing with imbalanced datasets.</p>
</li>
<li><p><strong>Cross-Validation</strong>: Use cross-validation to get a more reliable estimate of your model's accuracy.</p>
</li>
<li><p><strong>Monitor Over Time</strong>: Track accuracy to detect performance drift or data changes.</p>
</li>
</ul>
<p><strong>Cohen's Kappa</strong></p>
<ul>
<li><p><strong>Interpret Correctly</strong>: Understand the range and meaning of Kappa values. Remember that values close to 1 indicate strong agreement, while values close to 0 indicate agreement similar to chance.</p>
</li>
<li><p><strong>Class Distribution Check</strong>: Be mindful of class distributions, as highly imbalanced data can affect the interpretation of Kappa.</p>
</li>
<li><p><strong>Compare with Other Metrics</strong>: Use Cohen's Kappa alongside other metrics to get a fuller picture of model performance.</p>
</li>
</ul>
<p><strong>False Positive Rate (FPR)</strong></p>
<ul>
<li><p><strong>Threshold Tuning</strong>: Adjust the decision threshold to balance FPR with other metrics, such as False Negative Rate (FNR) and Precision.</p>
</li>
<li><p><strong>Context Awareness</strong>: Consider the specific context of your application. In scenarios like medical diagnosis, prioritize minimizing FPR to avoid false alarms.</p>
</li>
<li><p><strong>ROC Curve</strong>: Use the Receiver Operating Characteristic (ROC) curve to analyze the trade-off between True Positive Rate (TPR) and FPR at different thresholds.</p>
</li>
</ul>
<p><strong>General Best Practices</strong></p>
<ul>
<li><p><strong>Understand Context</strong>: Tailor the choice of metrics to the specific application and the consequences of different types of errors.</p>
</li>
<li><p><strong>Data Quality</strong>: Ensure high-quality data with accurate labels. Poor data quality can skew all metrics.</p>
</li>
<li><p><strong>Continuous Monitoring</strong>: Implement continuous monitoring to detect any changes in model performance and take corrective actions promptly.</p>
</li>
<li><p><strong>Transparency</strong>: Document and communicate the chosen metrics and their implications to stakeholders.</p>
</li>
<li><p><strong>Iterative Evaluation</strong>: Regularly revisit and refine the metrics as the model evolves and the application context changes.</p>
</li>
</ul>
<p>By following these best practices, you can make more informed decisions about model performance and ensure your machine-learning models are reliable and effective.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In conclusion, predicting employee attrition using supervised classification machine learning techniques offers organizations a powerful tool to understand and mitigate the factors leading to employee turnover. By leveraging data-driven insights, companies can identify at-risk employees and implement targeted interventions to enhance retention. The process involves data exploration, model development, feature selection, and accuracy assessment, ensuring the predictive model is robust and reliable. By focusing on key metrics such as precision, recall, and F1-score, organizations can fine-tune their models to balance the trade-offs between false positives and false negatives, ultimately leading to more effective human resource strategies. This approach helps retain valuable talent and contributes to maintaining organizational knowledge and reducing the costs associated with high attrition rates.</p>
]]></content:encoded></item><item><title><![CDATA[Identify Core Factors in Performance Appraisal - Principal Component Analysis]]></title><description><![CDATA[Introduction
Performance appraisal is a regular review of an employee’s job performance and overall contribution to a company. It evaluates an employee’s attitude, knowledge, skills, commitment, achievements, etc. Organizations use performance apprai...]]></description><link>https://vijayv2k.com/identify-core-factors-in-performance-appraisal-principal-component-analysis</link><guid isPermaLink="true">https://vijayv2k.com/identify-core-factors-in-performance-appraisal-principal-component-analysis</guid><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[data analytics]]></category><category><![CDATA[Principal Component Analysis (PCA) ]]></category><category><![CDATA[performance]]></category><category><![CDATA[performance metrics]]></category><category><![CDATA[Dimensionality Reduction]]></category><category><![CDATA[appraisals]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Thu, 06 Feb 2025 07:47:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738826179335/9ff0faba-c17c-4493-b38d-4226ce5a1e98.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction"><strong>Introduction</strong></h3>
<p>Performance appraisal is a regular review of an employee’s job performance and overall contribution to a company. It evaluates an employee’s attitude, knowledge, skills, commitment, achievements, etc. Organizations use performance appraisals to justify pay increases, bonuses, and termination decisions. They can be conducted at any given time but are annual, semi-annual, or quarterly. Organizations need to provide employees with big-picture feedback on their work and consider many dimensions that contribute to measuring performance appraisal. However, since the number of dimensions is large, grouping similar dimensions is necessary. This article focuses on determining important factors that emerge by grouping similar dimensions using two essential techniques: exploratory factor analysis and principal component analysis. The methods discussed can be used to determine factors related to different aspects of the HR department.</p>
<h3 id="heading-unsupervised-machine-learning"><strong>Unsupervised Machine Learning</strong></h3>
<p>Unsupervised machine learning algorithms are used when the output is unknown, and no predefined instructions are available to the learning algorithms. In unsupervised learning, the learning algorithm only has input data, and knowledge is extracted from these data. These algorithms create a new representation of the data that is easier to comprehend than the original data and help improve the accuracy of advanced algorithms by consuming less time and reducing memory. Standard unsupervised machine learning algorithms include association rule mining, dimensionality reduction algorithms, and clustering.</p>
<h3 id="heading-dimension-reduction-techniques"><strong>Dimension Reduction Techniques</strong></h3>
<p>The dimension reduction algorithms take a high dimensional representation of data as input, which consists of many features, and produce an output that summarizes the data by grouping essential characteristics and results into fewer factors. The two standard dimensionality reduction algorithms include principal component analysis and factor analysis. The principal component analysis replaces a large number of correlated variables with a smaller number of correlated variables. It is used to understand the data's structure, shape, and covariance, which is impossible with simple scatter plots. It is a method that rotates the dataset so that the rotated features are statistically uncorrelated. This method is used to summarize the data and reduce their dimensionality. In contrast, exploratory factor analysis can be used as a hypothesis-generating helpful tool for understanding the relationship between large numbers of variables.</p>
<p>When we deal with vast amounts of data, we are not sure about the usefulness of the information collected, and deriving helpful information becomes tedious. However, we cannot drop some variables to derive useful information, assuming they are not beneficial. For example, suppose the number of variables is more. Applying some tests, creating scatter plots, finding correlations between variables, and interpreting the data is not easy in that case. There would be too many pair-wise correlations between the variables to consider. It will also be challenging to comprehend the data through the graphical display. Hence, it is necessary to club these variables together and reduce the number of variables to a few interpretable linear combinations of the data to interpret the data in a more meaningful form. Each linear combination represents a principal component or a factor. Thus, dimensionality reduction is helpful when we have many variables in our dataset and we need to reduce this number or when responses for many questions tend to be highly correlated. This technique is generally used before performing t-test, ANOVA, regression, or cluster analysis on a dataset with correlated variables.</p>
<p><strong>Performance Appraisal Data</strong></p>
<p>The PerformanceAppraisal.csv file helps us understand KNIME usage. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder on the KNIME Community Hub.</p>
<blockquote>
<p><em>The</em> <a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj"><em>Identify Core Factors in Performance Appraisal – Principal Component Analysis</em></a> <em>workflow can be downloaded from the KNIME Community Hub.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738826326905/c6d8f168-eb62-42de-a4a3-3429c4252fa9.png" alt class="image--center mx-auto" /></p>
<p>After downloading the CSV file from the Data folder, you are ready.</p>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738826352076/e2bb41a6-4c62-459d-8962-eb91a7166deb.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the <strong>PerformanceAppraisal.csv</strong> CSV dataset. The above table shows that the employee dataset has 322 observations and 29 columns. Each column has values between one and five based on the Likert scale.</p>
<h3 id="heading-data-exploration"><strong>Data Exploration</strong></h3>
<p>The <strong>Statistics</strong> node primarily determines the descriptive summary statistics of the columns in the dataset. This node calculates statistical moments such as minimum, maximum, mean, standard deviation, variance, median, overall sum, number of missing values, and row count across all numeric columns. It counts all nominal values together with their occurrences. The node provides the following three output tables.</p>
<ol>
<li><p>Statistics Table: All statistic moments for all numeric columns,</p>
</li>
<li><p>Nominal Histogram Table: Nominal values for all selected categorical columns and</p>
</li>
<li><p>Occurrences Table: The most frequent/infrequent values from the categorical columns (Top/bottom)</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738826448522/b39cc989-eee8-4a51-a4a1-08c126264928.png" alt class="image--center mx-auto" /></p>
<p>The above table shows that each column has values between one and five based on the Likert scale.</p>
<h3 id="heading-data-visualization"><strong>Data Visualization</strong></h3>
<p>We will use the <strong>Linear Correlation</strong> node to generate a correlation matrix heatmap based on a selected set of columns.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738826487116/feccd4de-4849-4bb5-a8a6-d338c813face.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738826502330/9bf2ad13-f363-4122-8bbe-4342c9b74d05.png" alt class="image--center mx-auto" /></p>
<p>The squared table shows the pair-wise correlation values of all columns. The color range varies from dark red (strong negative correlation) to dark blue (strong positive correlation). If a correlation value for a pair of columns is unavailable, the corresponding cell contains a missing value (shown as a cross in the color view). Hovering the mouse over each box in the views window will display the corresponding pair-wise correlation value. It is clear from the chart that there is a correlation between many groups of variables.</p>
<h3 id="heading-determine-factors-of-performance-appraisal-system-using-exploratory-factor-analysis"><strong>Determine Factors of Performance Appraisal System Using Exploratory Factor Analysis</strong></h3>
<p>Objective: To determine factors of performance appraisal system using exploratory factor analysis</p>
<p>Factor analysis is an exploratory data analysis method used to search for critical underlying factors or latent variables from a set of observed variables. It helps in data interpretation by reducing the number of variables. It is widely utilized in nearly all specializations where we need to reduce the number of existing features, like market research, advertising, finance, etc. Factor analysis is a linear statistical model. It explains the variance among the observed variables and reduces a set of observed variables to unobserved variables called factors.</p>
<p>Factors are latent, hidden, unobserved, or hypothetical variables. A factor describes the association among the number of observed variables. The maximum number of factors is equal to the number of observed variables. Every factor explains a specific variance in observed variables with common patterns or responses. Each factor explains a particular amount of variance in the observed variables. It is a method for investigating whether the variables N1, N2,…, Nn are linearly related to a small number of unobserved factors F1, F2,…, Fn.</p>
<p>Some common assumptions that need to be fulfilled before applying factor analysis include the following: The data should not contain outliers, the sample size should be greater than the factor, and there should not be homoscedasticity among the variables.</p>
<p>There are two types of factor analysis:</p>
<ol>
<li><p><strong>Exploratory Factor Analysis:</strong> EFA is a commonly used approach for reducing the number of features. The basic assumption is that any observed variable is directly associated with any factor. EFA is a statistical technique for identifying latent relationships among sets of observed variables in a dataset. In particular, EFA seeks to model a large set of observed variables as linear combinations of some smaller unobserved latent factors.</p>
</li>
<li><p><strong>Confirmatory Factor Analysis:</strong> In CFA, the basic assumption is that each factor is associated with a particular set of observed variables.</p>
</li>
</ol>
<p>For our analysis, we will apply EFA using the “factor_analyzer” Python library in the <strong>Python Script</strong> node. Before applying factor analysis, it is critical to evaluate whether determining the factors in the dataset is possible. There are two methods to check the factorability or sampling adequacy:</p>
<ol>
<li><p><strong>Bartlett’s Test:</strong> Bartletts’ test of sphericity checks if the observed variables intercorrelate at all using the observed correlation matrix against the identity matrix. You should not use a factor analysis if the test is statistically insignificant. If the p-value is &lt;0.05, the test will be considered statistically significant, indicating that the observed correlation matrix is not an identity matrix.</p>
</li>
<li><p><strong>Kaiser-Meyer-Olkin (KMO) Test:</strong> The KMO test measures the suitability of data for factor analysis. It determines the adequacy for each variable and for the complete model. The KMO test estimates the proportion of variance among all the observed variables. A lower proportion is more suitable for factor analysis. The range of KMO values is between 0 and 1. A KMO value of less than 0.5 is considered inadequate for performing factor analysis.</p>
</li>
</ol>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Load the input data</span>
df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas()

<span class="hljs-comment"># Importing necessary libraries</span>
<span class="hljs-keyword">from</span> factor_analyzer.factor_analyzer <span class="hljs-keyword">import</span> calculate_bartlett_sphericity

chisquare,p_value=calculate_bartlett_sphericity(df)

print(<span class="hljs-string">"Chi Square value of Bartlett test: "</span>,chisquare.round(<span class="hljs-number">3</span>))
print(<span class="hljs-string">"p value of Brtlett test: "</span>,p_value.round(<span class="hljs-number">3</span>))

<span class="hljs-comment"># Applying KMO test for determining adequacy</span>
<span class="hljs-keyword">from</span> factor_analyzer.factor_analyzer <span class="hljs-keyword">import</span> calculate_kmo

kmo_values,kmo_model=calculate_kmo(df)

print(<span class="hljs-string">"KMO model:"</span>,kmo_model.round(<span class="hljs-number">3</span>))
print(<span class="hljs-string">"KMO values:\n"</span>,kmo_values.round(<span class="hljs-number">3</span>))

<span class="hljs-comment"># Convert datalist to a DataFrame for output</span>
output_df = pd.DataFrame(kmo_values)

<span class="hljs-comment"># Output the datalist as a table</span>
knio.output_tables[<span class="hljs-number">0</span>] = knio.Table.from_pandas(output_df)
</code></pre>
<p>The p-value of Bartlett’s test is 0, meaning it is statistically significant. The overall KMO value for our data is 0.786, which is excellent. The value of both tests indicates that factor analysis can be executed since the condition of adequacy is met.</p>
<h3 id="heading-exploratory-factor-analysis"><strong>Exploratory Factor Analysis</strong></h3>
<p>The primary objective of factor analysis is to reduce the number of observed variables and find unobservable variables. The factors with the lowest amount of variance should be dropped. Rotation, which can be orthogonal or oblique, is a tool for better interpretation of factor analysis. It redistributes the commonalities with a clear pattern of loadings.</p>
<p>We will apply EFA using the “factor_analyzer” Python library in the <strong>Python Script</strong> node. The eigenvalues are determined using the get_eigenvalues() function, which returns the eigenvalues for each variable. It tries to determine the optimum number of factors.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">from</span> factor_analyzer <span class="hljs-keyword">import</span> FactorAnalyzer

<span class="hljs-comment"># Load the input data</span>
df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas()

<span class="hljs-comment"># Perform factor analysis</span>
fa = FactorAnalyzer()
fa.fit(df)

<span class="hljs-comment"># Determining eigenvalues</span>
eigen_values, vectors = fa.get_eigenvalues()  <span class="hljs-comment"># Corrected unpacking of the returned values</span>
print(<span class="hljs-string">"Eigen values are: \n"</span>, eigen_values.round(<span class="hljs-number">3</span>))

<span class="hljs-comment"># Convert eigenvalues to a DataFrame for output</span>
EigenValues_df = pd.DataFrame(eigen_values, columns=[<span class="hljs-string">"EigenValues"</span>])

<span class="hljs-comment"># Output the eigenvalues as a table</span>
knio.output_tables[<span class="hljs-number">0</span>] = knio.Table.from_pandas(EigenValues_df)

<span class="hljs-comment"># Get factor loadings</span>
factor_loadings = fa.loadings_.round(<span class="hljs-number">4</span>)

<span class="hljs-comment"># Convert factor loadings to a DataFrame for output</span>
FactorLoadings_df = pd.DataFrame(factor_loadings, index=df.columns, columns=[<span class="hljs-string">f"Factor <span class="hljs-subst">{i+<span class="hljs-number">1</span>}</span>"</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(factor_loadings.shape[<span class="hljs-number">1</span>])])

<span class="hljs-comment"># Output the factor loadings as a table</span>
knio.output_tables[<span class="hljs-number">1</span>] = knio.Table.from_pandas(FactorLoadings_df)

<span class="hljs-comment"># Get factor variance (eigenvalues, proportion of variance, cumulative variance)</span>
fa_variance = fa.get_factor_variance()

<span class="hljs-comment"># Convert factor variance to a DataFrame for output</span>
FactorVariance_df = pd.DataFrame({
    <span class="hljs-string">"Eigenvalues"</span>: fa_variance[<span class="hljs-number">0</span>],
    <span class="hljs-string">"Proportion of Variance"</span>: fa_variance[<span class="hljs-number">1</span>],
    <span class="hljs-string">"Cumulative Variance"</span>: fa_variance[<span class="hljs-number">2</span>]
})

<span class="hljs-comment"># Output the eigenvalues as a table</span>
knio.output_tables[<span class="hljs-number">2</span>] = knio.Table.from_pandas(FactorVariance_df)
</code></pre>
<p>One of the difficult things to determine when conducting a factor analysis is to determine the number of factors. Different metrics such as eigenvalue, total percent variance explained, factor loadings, and line plots are used to decide the number of factors. The Kaiser criterion is an analytical approach based on selecting the factor with a more significant proportion of explained variance. The eigenvalue is a good criterion for determining the optimum number of factors. Eigenvalues represent variance explained by each factor from the total variance. Generally, an eigenvalue greater than one will be considered the feature's selection criteria. Eigenvalues are determined by using the get_eigenvalues() function. A line plot is a graphical approach based on visualizing factors and eigenvalues. It helps us to determine the number of factors where the curve makes an elbow.</p>
<p>One of the criteria is to decide the number of factors based on an eigenvalue greater than or equal to one. This is because a factor with an eigenvalue of 1 accounts for as much variance as a single variance, and the logic is that only factors that explain at least the same amount of variance as a single variable are worth keeping. However, it is observed that this sometimes results in more factors. From the results, we can observe that eigenvalues are more significant than one for eight variables, and for two variables, it is nearly 1.0. We will try to understand using another option, a line plot. A line plot shows the eigenvalues on the y-axis and the number of factors on the x-axis. It always displays a downward curve. The point where the slope of the curve is leveling off (the elbow) indicates the number of factors the analysis should generate. A chart depicting the number of factors and the eigenvalues ranges from 1 to the maximum number of variables. The curve shows a straight line for each factor and its eigenvalues. However, the optimum number of factors for this dataset might be six.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738826966332/9fa3cee7-2187-411e-9d54-fe3abea8ccc1.png" alt class="image--center mx-auto" /></p>
<p>It is clear from the results that both line plot and eigenvalues are yielding an unreasonably high number of factors. In our example, a cutoff of an eigenvalue greater than or equal to one would result in eight factors. And the line plot suggests six factors due to how the slope levels off. It is important to remember that one of the reasons for running a factor analysis is to reduce the large number of variables that describe a complex concept, such as a performance appraisal system, to a few interpretable latent variables. In other words, we would like to find fewer interpretable factors that explain the maximum variability in the data. Therefore, another essential metric to remember is the total variability of the original variables explained by each factor solution. For example, if three factors explain most of the variability in the original 12 variables, then those factors are a good, more straightforward substitute for all 12 variables. However, if it takes six factors to explain most of the variance in those 12 variables, then the purpose of factor analysis is not solved.</p>
<p>The matrix of weights, or factor loadings, generated from an EFA model describes the underlying relationships between each variable and the latent factors. Factor loadings are similar to standardized regression coefficients, and variables with higher loadings on a particular factor can be interpreted as explaining a more significant proportion of the variation in that factor. Factor loading matrices are often rotated after the factor analysis model is estimated to produce a more straightforward, more interpretable structure to identify which variables are loading on a particular factor. The factor loading is a matrix that shows the relationship of each variable to the underlying factor. It shows the correlation coefficient for the observed variable and factor. It is essential to determine the variance explained by each factor. The factor loadings are determined by loadings_, and the variance explained by the factors is determined by the get_factor_variances() function.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738827007866/b37985dd-4884-4932-83a8-4637befbb7bb.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738827023888/6d7a5ab8-c97f-4577-ba54-67cbe2698694.png" alt class="image--center mx-auto" /></p>
<p>It should be noted that each identified factor should have at least three variables with high factor loadings and that each variable should load highly on only one factor. The preceding result displays the factor loadings and variances of each factor. From the factor loadings matrix, we can observe the loading of each variable on each factor. We need to determine the highest loading of the variable in a particular factor. From the matrix, we can observe that there are six factors. The bold letters clearly show the highest loading on the respective factor. For this dataset, the optimum number of factors is six.</p>
<p>Factor analysis has some limitations. Its interpretation can be debatable because multiple interpretations of the same data factors can be made. Besides, factor identification and naming require domain knowledge.</p>
<h3 id="heading-determine-factors-of-performance-appraisal-system-using-principal-component-analysis"><strong>Determine Factors of Performance Appraisal System Using Principal Component Analysis</strong></h3>
<p>Objective: To determine factors of performance appraisal system using PCA</p>
<p>Most problems of interest to organizations are multivariate. They contain multiple dimensions that must be looked at simultaneously. Many statistical analysis techniques, such as machine learning algorithms, are sensitive to the number of dimensions in a problem. High dimensionality can render a problem computationally intractable in the significant data era. Hence, dimensionality reduction aims to replace a more extensive set of correlated variables with a smaller set of derived variables and lose the minimum amount of information. The best way to minimize information loss is to preserve variance. Principal Component Analysis (PCA) is a data reduction technique that transforms more correlated variables into a much smaller set of correlated variables called principal components. Simply put, PCA is a method of extracting essential variables (components) from a large set of variables available in a dataset. It extracts a low-dimensional set of features from a high-dimensional dataset to capture as much information as possible. It is always performed on a symmetric correlation and covariance matrix. This means the matrix should be numeric and have standardized data. The main idea of PCA is to reduce the dimensionality of a dataset consisting of many variables correlated with each other while retaining maximum information (variance) in the dataset. Transforming original variables to a new set of variables is called PCA.</p>
<p>PCA is used to overcome the redundancy of features in a dataset. These features are low-dimensional. The components aim to capture as much information as possible with high explained variance. The first component has the highest variance, followed by the second, third, and so on. The components must be uncorrelated. PCA is applied to a dataset with numeric variables. It is a tool that helps produce better visualizations of high-dimensional data.</p>
<p>The first principal component is a linear combination of original predictor variables, which captures the maximum variance in the data set. It determines the direction of the highest variability in the data. The larger the variability captured in the first component, the larger the information captured by the component. No other component can have variability higher than the first principal component. The first principal component results in a line closest to the data; that is, it minimizes the sum of the squared distance between a data point and the line.</p>
<p>The second principal component is also a linear combination of original predictors, which captures the remaining variance in the dataset and is uncorrelated with the first principal component. In other words, the correlation between the first and second components should be zero. All succeeding principal components follow a similar concept; they capture the remaining variation without correlating with the previous component. For n x p dimensional data, min (n-1,p) principal components can be constructed. The directions of these components are identified in an unsupervised way because the response variable is not used to determine the component direction. Therefore, it is an unsupervised approach.</p>
<p>It is a linear orthogonal transformation that transforms the data to a new coordinate system such that the most significant variance by any data projection lies on the first coordinate, the second most considerable variance on the next coordinate, and so on. The analysis uses an orthogonal projection of highly correlated variables to a set of values of linearly uncorrelated variables called principal components. The number of principal components is less than or equal to the number of original variables, and our objective is to maximize all the variance on the first principal component, then the second, and so on.</p>
<p>PCA components explain the maximum variance, while factor analysis explains the covariance in data. PCA components are entirely orthogonal to each other, whereas factor analysis does not require factors to be orthogonal. A PCA component is a linear combination of the observed variable, while in factor analysis, the observed variables are linear combinations of the unobserved variable or factor. PCA components are uninterpretable. In factor analysis, the underlying factors can be labeled and are interpretable.</p>
<p>PCA is a statistical procedure that transforms a dataset into a new dataset containing linearly uncorrelated variables, known as principal components. The basic idea is that the dataset is transformed into a set of components, each attempting to capture as much of the variance in data as possible. In the <strong>Python Script</strong> node, the PCA() function in the “sklearn.decomposition” library performs PCA by specifying the number of components.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">from</span> sklearn.decomposition <span class="hljs-keyword">import</span> PCA

<span class="hljs-comment"># Load the input data</span>
df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas()

<span class="hljs-comment"># Ensure the input data contains only numeric values</span>
df_numeric = df.select_dtypes(include=[<span class="hljs-string">'number'</span>])

<span class="hljs-comment"># Perform Principal Component Analysis</span>
pca = PCA(n_components=<span class="hljs-number">6</span>)
pca.fit(df_numeric)
df_transformed = pca.transform(df_numeric)

<span class="hljs-comment"># Convert the transformed data to a DataFrame</span>
df_transformed_df = pd.DataFrame(df_transformed, columns=[<span class="hljs-string">f"PC<span class="hljs-subst">{i+<span class="hljs-number">1</span>}</span>"</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(df_transformed.shape[<span class="hljs-number">1</span>])])

<span class="hljs-comment"># Output the transformed data as a table</span>
knio.output_tables[<span class="hljs-number">0</span>] = knio.Table.from_pandas(df_transformed_df)

<span class="hljs-comment"># Get principal components</span>
pca_components = pca.components_.round(<span class="hljs-number">3</span>)

<span class="hljs-comment"># Convert principal components to a DataFrame for output</span>
pca_components_df = pd.DataFrame(pca_components.T, index=df_numeric.columns, columns=[<span class="hljs-string">f"Factor <span class="hljs-subst">{i+<span class="hljs-number">1</span>}</span>"</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(pca_components.shape[<span class="hljs-number">0</span>])])

<span class="hljs-comment"># Output the factor loadings as a table</span>
knio.output_tables[<span class="hljs-number">1</span>] = knio.Table.from_pandas(pca_components_df)

<span class="hljs-comment"># Get principal component wise explained variance</span>
pca_variance = pca.explained_variance_ratio_.round(<span class="hljs-number">3</span>)

<span class="hljs-comment"># Convert factor variance to a DataFrame for output</span>
pca_variance_df = pd.DataFrame(pca_variance)

<span class="hljs-comment"># Output the eigenvalues as a table</span>
knio.output_tables[<span class="hljs-number">2</span>] = knio.Table.from_pandas(pca_variance_df)
</code></pre>
<p>Applying principal component analysis, 29 variables are reduced to six principal components using the command PCA(n_components=6) and <a target="_blank" href="http://pca.fit">pca.fit</a>(PerformanceAppraisal) functions.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738827072502/3672e9f4-ecef-4e0c-be89-6fccc5320658.png" alt class="image--center mx-auto" /></p>
<p>Thus, the reduced dataset has 322 rows and six columns, and the principal components dataset has 29 rows and six columns. The details of all components can be found using pca.components_. The resulting table displays the relationship of variables with the factors.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738827097950/e6ce57ef-5195-4cbc-bc2e-421245d72261.png" alt class="image--center mx-auto" /></p>
<p>The variance explained by each component is determined using explained_variance_ratio_.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738827119345/0c54b9c9-eb5a-4cb2-87f4-84edf1511d8e.png" alt class="image--center mx-auto" /></p>
<p>Thus, we can observe that the variance explained by the first component is 20.4%. The second principal component explains less variance than the first (10%), the third component explains 9% of the variance, the fourth component explains 6.3%, and the fifth component explains 5%. The sixth component explains 4.2% of the variance. Thus, the total variance explained by all the six components is nearly 55%.</p>
<p>It should be noted that since the principal component analysis and exploratory factor analysis derive their solutions from the correlation among the observed variables, we need to decide on the factor model that is the best fit for our research goals. We also need to determine how many component factors are required to extract. Then, we extract the components or factors and interpret the results. Finally, we compute the component or factor scores. We use the <strong>Python View</strong> node to create a color map depicting the components.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># This example script plots a heatmap using matplotlib and assigns it to the output view</span>
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Only use numeric columns</span>
data = knio.input_tables[<span class="hljs-number">0</span>].to_pandas().select_dtypes(<span class="hljs-string">'number'</span>)

<span class="hljs-comment"># Convert the data to a numpy array</span>
values = data.to_numpy()

<span class="hljs-comment"># Plot the heatmap</span>
fig, ax = plt.subplots(figsize=(<span class="hljs-number">15</span>, <span class="hljs-number">12</span>))  <span class="hljs-comment"># Adjusted figure size for better visualization</span>
cax = ax.matshow(values, cmap=<span class="hljs-string">'viridis'</span>)  <span class="hljs-comment"># Use a colormap for better visualization</span>
plt.colorbar(cax)

<span class="hljs-comment"># Set x-ticks and y-ticks</span>
ax.set_xticks(range(data.shape[<span class="hljs-number">1</span>]))
ax.set_xticklabels(data.columns, rotation=<span class="hljs-number">45</span>, ha=<span class="hljs-string">'left'</span>)  <span class="hljs-comment"># Rotate x-tick labels for better readability</span>
ax.set_yticks(range(data.shape[<span class="hljs-number">0</span>]))
ax.set_yticklabels(data.index)

<span class="hljs-comment"># Annotate each cell with the numeric value</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(values.shape[<span class="hljs-number">0</span>]):
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(values.shape[<span class="hljs-number">1</span>]):
        ax.text(j, i, <span class="hljs-string">f"<span class="hljs-subst">{values[i, j]:<span class="hljs-number">.3</span>f}</span>"</span>, ha=<span class="hljs-string">'center'</span>, va=<span class="hljs-string">'center'</span>, color=<span class="hljs-string">'white'</span>, fontsize=<span class="hljs-number">5</span>)

<span class="hljs-comment"># Set labels</span>
ax.set_ylabel(<span class="hljs-string">"Features"</span>)
ax.set_xlabel(<span class="hljs-string">"Principal Components"</span>)

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738827145522/c485591c-9a12-4f7b-921d-70c6482cd335.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738827162529/d2a269e4-f738-4ebf-8d43-7b002f315675.png" alt class="image--center mx-auto" /></p>
<p>From the table and chart, the highest loading of each variable on a particular factor is determined. It is clear from the table that.</p>
<ol>
<li><p><strong>Factor 1: Job-based Attitude:</strong> Efficiency, Commitment, Job Knowledge, Completeness, Quality, Quantity, Creativity, Appropriateness, Timeliness, and Flexibility contribute to the first factor. All these characteristics are related to job performance. Hence, this factor can be called a Job-based attitude.</p>
</li>
<li><p><strong>Factor 2: Behavioral Aspects:</strong> Attitude, Availability, and Communication. All these characteristics pertain to an employee's behavior. Hence, this factor can be called behavioral aspects.</p>
</li>
<li><p><strong>Factor 3: Leadership Quality:</strong> Responsibility, Focus, Decision Making, and Stress Tolerance. Since all these traits are traits of a leader, this factor can be called Leadership quality.</p>
</li>
<li><p><strong>Factor 4: Team-based Attitude:</strong> Interpersonal Relations, Share Ideas, Resourcefulness, Confidence, and Acceptability. These characteristics depict an employee's performance when working in a team. Hence, this factor can be called a team-based attitude.</p>
</li>
<li><p><strong>Factor 5: Planning:</strong> Receptive, Initiative, Strategic Approach, and Appropriateness. These qualities are required for planning, which is why this factor can be termed planning.</p>
</li>
<li><p><strong>Factor 6: Problem-solving Attitude:</strong> Solution-oriented, Logical Approach, Judgment, and Dependability. These characteristics emphasize a problem-solving attitude; hence, this factor can be termed a problem-solving attitude.</p>
</li>
</ol>
<p>Thus, 29 variables considered in the study related to performance appraisal can be reduced to six factors: problem-solving attitude, leadership quality, planning, behavioral aspects, team-based attitude, and job-based attitude.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In conclusion, performance appraisal is crucial for evaluating an employee's organizational contributions and effectiveness. Organizations can identify core factors that influence performance using techniques such as exploratory factor analysis and principal component analysis. These methods help reduce data’s complexity by grouping similar dimensions, making it easier to interpret and act upon. The study of performance appraisal data can reveal key factors such as job-based attitude, behavioral aspects, leadership quality, team-based attitude, planning, and problem-solving attitude. Understanding these factors allows organizations to provide more targeted feedback, improve decision-making regarding employee development, and enhance overall organizational performance.</p>
]]></content:encoded></item><item><title><![CDATA[Identify Absenteeism Patterns - Cluster Analysis]]></title><description><![CDATA[Introduction
Absenteeism is a habitual pattern of absence from a duty or obligation. Employee absenteeism is expensive and incurs a significant loss to an organization. It is essential to identify employees' characteristics according to their level o...]]></description><link>https://vijayv2k.com/identify-absenteeism-patterns-cluster-analysis</link><guid isPermaLink="true">https://vijayv2k.com/identify-absenteeism-patterns-cluster-analysis</guid><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[data analytics]]></category><category><![CDATA[clustering]]></category><category><![CDATA[K means Clustering ]]></category><category><![CDATA[#HierarchicalClustering ]]></category><category><![CDATA[confusion matrix]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Sat, 01 Feb 2025 07:15:46 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393076749/fef50af2-3265-49ad-8855-84a38620f1a1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction"><strong>Introduction</strong></h3>
<p>Absenteeism is a habitual pattern of absence from a duty or obligation. Employee absenteeism is expensive and incurs a significant loss to an organization. It is essential to identify employees' characteristics according to their level of absenteeism. This is done using cluster analysis techniques to group employees based on similar characteristics. There are two main techniques for doing cluster analysis: k-means clustering and hierarchical clustering.</p>
<h3 id="heading-unsupervised-machine-learning"><strong>Unsupervised Machine Learning</strong></h3>
<p>Unsupervised machine learning algorithms are used when the output is unknown, and no predefined instructions are available to the learning algorithms. In unsupervised learning, the learning algorithm only has input data, and knowledge is extracted from these data. These algorithms create a new representation of the data that is easier to comprehend than the original data and help improve the accuracy of advanced algorithms by consuming less time and reducing memory. Standard unsupervised machine learning algorithms include association rule mining, dimensionality reduction algorithms, and clustering.</p>
<h3 id="heading-clustering-techniques"><strong>Clustering Techniques</strong></h3>
<p>Clustering is the task of partitioning the data into groups called clusters in which members are similar in some way. A cluster is a collection of observations that are similar among themselves but are different from the observations belonging to other clusters. K-means clustering and hierarchical clustering are commonly used clustering algorithms. Clustering tries to find cluster centers that represent some areas of the data.</p>
<p>Clustering deals with finding a structure in a collection of unlabeled data. Data points inside a cluster are homogeneous and heterogeneous to other groups. The correct number of clusters is an essential issue because it becomes noise beyond the correct number, and you are not capturing any observations below the number. Generally, two forms of clustering, k-means and hierarchical clustering, are used for grouping employees or observations.</p>
<h3 id="heading-employee-absenteeism-data"><strong>Employee Absenteeism Data</strong></h3>
<p>The EmployeeAbsenteeism.csv file helps us understand KNIME usage. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder on the KNIME Community Hub.</p>
<blockquote>
<p><em>The</em> <a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj"><em>Identify Absenteeism Patterns – Cluster Analysis</em></a> <em>workflow can be downloaded from the KNIME Community Hub.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393094043/d15b2e3b-4f7f-4c00-86a8-06b5ee668b81.png" alt class="image--center mx-auto" /></p>
<p>After downloading the CSV file from the Data folder, you are ready.</p>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393112204/232cc349-9337-4021-a085-bfdcc0132f76.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the <strong>EmployeeAbsenteeism.csv</strong> CSV dataset. The above table shows that the employee dataset has 740 observations and 21 columns.</p>
<h3 id="heading-converting-continuous-column-to-categorical-using-binning"><strong>Converting Continuous Column to Categorical Using Binning</strong></h3>
<p>Since the clustering works on categorical columns, converting the <strong><em>AbsenteeismTimeInHours</em></strong> column into a categorical one is essential. We will use the <strong>Auto-Binner</strong> node to convert the <strong><em>AbsenteeismTimeInHours</em></strong> column into a categorical column by splitting it into three equal bins based on the frequency of the observations in the column. Subsequently, we will use the <strong>Rule Engine</strong> node to assign meaningful category values (low, avg, high) to the <strong><em>Absenteeism</em></strong> column for easy analysis and interpretation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393137858/a9f1e847-a224-4108-ba98-e41ed7be650b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393377744/df72628e-7485-4b24-9124-bc1a22d84e83.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-data-visualization"><strong>Data Visualization</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393211673/d8fd9978-e6fa-47d6-9d94-bb204679f7a9.png" alt class="image--center mx-auto" /></p>
<p>We will use the <strong>Python View</strong> node to generate multiple count plots between the <strong><em>Absenteeism</em></strong> column and the <strong><em>SocialDrinker</em></strong>, <strong><em>SocialSmoker</em></strong>*,* <strong><em>Son</em></strong>, <strong><em>Seasons</em></strong>, <strong><em>Pet</em></strong>, and <strong><em>DayOfTheWeek</em></strong> categorical columns.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Load your data (example) </span>
<span class="hljs-comment"># df = knio.input_tables[0].to_pandas() </span>

<span class="hljs-comment"># Count plot between employee absenteeism and categorical variables</span>
<span class="hljs-comment"># Importing libraries</span>
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO

<span class="hljs-comment"># Plotting </span>
fig = plt.figure(figsize=(<span class="hljs-number">15</span>,<span class="hljs-number">8</span>))
plt.suptitle(<span class="hljs-string">'Association between Absenteeism and Categorical Variables'</span>,
fontsize=<span class="hljs-number">20</span>, fontweight=<span class="hljs-string">'bold'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Social drinker</span>
plt.subplot(<span class="hljs-number">231</span>)
sns.countplot(x=<span class="hljs-string">'SocialDrinker'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'Absenteeism'</span>, palette=<span class="hljs-string">"Set1_r"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Social Drinker'</span>)
plt.ylabel(<span class="hljs-string">'Number of employees'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Social smoker</span>
plt.subplot(<span class="hljs-number">232</span>)
sns.countplot(x=<span class="hljs-string">'SocialSmoker'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'Absenteeism'</span>, palette=<span class="hljs-string">"Set2_r"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Social Smoker'</span>)
plt.ylabel(<span class="hljs-string">'Number of employees'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Son</span>
plt.subplot(<span class="hljs-number">233</span>)
sns.countplot(x=<span class="hljs-string">'Son'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'Absenteeism'</span>, palette=<span class="hljs-string">"Set3_r"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Son'</span>)
plt.ylabel(<span class="hljs-string">'Number of employees'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Seasons</span>
plt.subplot(<span class="hljs-number">234</span>)
sns.countplot(x=<span class="hljs-string">'Seasons'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'Absenteeism'</span>, palette=<span class="hljs-string">"Set1"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Seasons'</span>)
plt.ylabel(<span class="hljs-string">'Number of employees'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Pet</span>
plt.subplot(<span class="hljs-number">235</span>)
sns.countplot(x=<span class="hljs-string">'Pet'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'Absenteeism'</span>, palette=<span class="hljs-string">"Set2"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Pet'</span>)
plt.ylabel(<span class="hljs-string">'Number of employees'</span>)

<span class="hljs-comment"># Count plot for displaying number of employees for Day of the week</span>
plt.subplot(<span class="hljs-number">236</span>)
sns.countplot(x=<span class="hljs-string">'DayOfTheWeek'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'Absenteeism'</span>, palette=<span class="hljs-string">"Set3"</span>, legend=<span class="hljs-string">'auto'</span>)
plt.xlabel(<span class="hljs-string">'Day of the week'</span>)
plt.ylabel(<span class="hljs-string">'Number of employees'</span>)

<span class="hljs-comment"># Create buffer to write into</span>
buffer = BytesIO()

<span class="hljs-comment"># Create plot and write it into the buffer</span>
fig.savefig(buffer, format=<span class="hljs-string">'svg'</span>)

<span class="hljs-comment"># The output is the content of the buffer</span>
output_image = buffer.getvalue()

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393179497/19506577-803a-45c8-b7ad-de9033fb2842.png" alt class="image--center mx-auto" /></p>
<p>The chart clearly shows that employees generally have average absenteeism. A more significant number of employees have no pets. The day and season are not crucial for absenteeism because the number of absenteeism is uniform according to the day of the week and season. It can be observed that most of the absent employees do not smoke. Thus, smoking is not the reason for absenteeism. For the absentees, the number of employees who drink is the same as those who do not drink. It is also clear that more employees have no or one child.</p>
<p>We will use the <strong>Python View</strong> node to generate multiple count plots between the <strong><em>Absenteeism</em></strong> column and the <strong><em>BodyMassIndex</em></strong>, <strong><em>Age</em></strong>, and <strong><em>TransportationExpense</em></strong> continuous columns. Alternatively, we can use the <strong>Density Plot</strong> node to create an interactive plot with the <strong><em>Absenteeism</em></strong> column as the condition column and the <strong><em>BodyMassIndex</em></strong>, <strong><em>Age</em></strong>, and <strong><em>TransportationExpense</em></strong> as the dimension columns.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Load your data (example) </span>
df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas() 

<span class="hljs-comment"># Count plot between employee absenteeism and categorical variables</span>
<span class="hljs-comment"># Importing libraries</span>
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO

<span class="hljs-comment"># Association between employees absenteeism and continuous variables</span>
absent_low=df[df[<span class="hljs-string">"Absenteeism"</span>]==<span class="hljs-string">'Low'</span>]
absent_medium=df[df[<span class="hljs-string">"Absenteeism"</span>]==<span class="hljs-string">'Medium'</span>]
absent_high=df[df[<span class="hljs-string">"Absenteeism"</span>]==<span class="hljs-string">'High'</span>]

<span class="hljs-comment"># Creating and setting the new palette</span>
new_palette = [<span class="hljs-string">"#861B04"</span>, <span class="hljs-string">"#F86C4D"</span>, <span class="hljs-string">"#E5F803"</span>, <span class="hljs-string">"#4DB5F8"</span>, <span class="hljs-string">"#C4FC05"</span>, <span class="hljs-string">"#F30BF0"</span>, <span class="hljs-string">"#05FC93"</span>, <span class="hljs-string">"#FC0593"</span>, <span class="hljs-string">"#FC8F05"</span>]
sns.set_palette(palette=new_palette)

fig, (ax1, ax2, ax3) = plt.subplots(nrows=<span class="hljs-number">3</span>, figsize=(<span class="hljs-number">13</span>,<span class="hljs-number">9</span>))

<span class="hljs-comment"># Kernel density plot for employee attrition for body mass index</span>

sns.kdeplot(data=absent_low, x=<span class="hljs-string">"BodyMassIndex"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#861B04'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax1)

sns.kdeplot(data=absent_medium, x=<span class="hljs-string">"BodyMassIndex"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#F86C4D'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax1)

sns.kdeplot(data=absent_high, x=<span class="hljs-string">"BodyMassIndex"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#E5F803'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax1)
ax1.set_title(<span class="hljs-string">'Body Mass Index &amp; Absenteeism'</span>)
ax1.legend([<span class="hljs-string">'Low'</span>,<span class="hljs-string">'Medium'</span>,<span class="hljs-string">'High'</span>])

<span class="hljs-comment"># Kernel density plot for employee attrition for age</span>
sns.kdeplot(data=absent_low, x=<span class="hljs-string">"Age"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#4DB5F8'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax2)

sns.kdeplot(data=absent_medium, x=<span class="hljs-string">"Age"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#C4FC05'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax2)

sns.kdeplot(data=absent_high, x=<span class="hljs-string">"Age"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#F30BF0'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax2)
ax2.set_title(<span class="hljs-string">'Age &amp; Absenteeism'</span>)
ax2.legend([<span class="hljs-string">'Low'</span>,<span class="hljs-string">'Medium'</span>,<span class="hljs-string">'High'</span>])

<span class="hljs-comment"># Kernel density plot for employee attrition for transportation expense</span>
sns.kdeplot(data=absent_low, x=<span class="hljs-string">"TransportationExpense"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#05FC93'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax3)

sns.kdeplot(data=absent_medium, x=<span class="hljs-string">"TransportationExpense"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#FC0593'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax3)

sns.kdeplot(data=absent_high, x=<span class="hljs-string">"TransportationExpense"</span>, y=<span class="hljs-literal">None</span>, hue=<span class="hljs-literal">None</span>, weights=<span class="hljs-literal">None</span>, palette=<span class="hljs-literal">None</span>, hue_order=<span class="hljs-literal">None</span>, hue_norm=<span class="hljs-literal">None</span>, color=<span class="hljs-string">'#FC8F05'</span>, fill=<span class="hljs-literal">True</span>, 
multiple=<span class="hljs-string">"layer"</span>, common_norm=<span class="hljs-literal">True</span>, common_grid=<span class="hljs-literal">False</span>, cumulative=<span class="hljs-literal">False</span>, bw_method=<span class="hljs-string">"scott"</span>, bw_adjust=<span class="hljs-number">1</span>, warn_singular=<span class="hljs-literal">True</span>, 
log_scale=<span class="hljs-literal">None</span>, levels=<span class="hljs-number">10</span>, thresh=<span class="hljs-number">.05</span>, gridsize=<span class="hljs-number">200</span>, cut=<span class="hljs-number">3</span>, clip=<span class="hljs-literal">None</span>, legend=<span class="hljs-literal">True</span>, cbar=<span class="hljs-literal">False</span>, cbar_ax=<span class="hljs-literal">None</span>, cbar_kws=<span class="hljs-literal">None</span>, ax=ax3)
ax3.set_title(<span class="hljs-string">'Transportation Expense &amp; Absenteeism'</span>)
ax3.legend([<span class="hljs-string">'Low'</span>,<span class="hljs-string">'Medium'</span>,<span class="hljs-string">'High'</span>])

plt.tight_layout()

<span class="hljs-comment"># Create buffer to write into</span>
buffer = BytesIO()

<span class="hljs-comment"># Create plot and write it into the buffer</span>
fig.savefig(buffer, format=<span class="hljs-string">'svg'</span>)

<span class="hljs-comment"># The output is the content of the buffer</span>
output_image = buffer.getvalue()

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393326692/b7f96456-b8fb-4f67-b07e-8f8bf1837c79.png" alt class="image--center mx-auto" /></p>
<p>Since the different categories of absenteeism in the chart overlap considerably, it is clear that the level of absenteeism is not related to transportation expense, age, or body mass index.</p>
<h3 id="heading-assess-employee-absenteeism-using-k-means-clustering"><strong>Assess Employee Absenteeism Using K-Means Clustering</strong></h3>
<p>Objective: To cluster the employee records for absenteeism using K-means cluster analysis</p>
<p>K-means clustering is an unsupervised algorithm that solves the clustering problem by following a simple and easy way to classify a given dataset through a certain number of clusters. We must determine the number of clusters for practical analysis before applying the K-means algorithm. The number of clusters can differ depending on the initialization and the distance function. A better machine-learning algorithm can be created if effective initialization and better distance functions are defined.</p>
<p>The K-means picks K number f points for each cluster known as centroids. Each data point forms a cluster with the closest centroids, K clusters. We find the centroid of each cluster based on the existing cluster members. Here we have new centroids. As we have new centroids, we repeat the steps. We find the closest distance for each data point from the new centroids associated with new K clusters. We repeat this process until convergence occurs; centroids do not change. We need to determine the distances between data points without having any information on the features of these points. Clustering aims to minimize the distance between the points and their representatives. However, even if K-means clustering is carried out many times, we are not sure we will get a globally optimal solution. Hence, we need to try different initialization points to find the optima and consider the best among those local optima.</p>
<p>In K-means, we have clusters, each with its centroid. The sum of the squares differences between the centroid and the data points within a cluster constitutes the sum of the square values for that cluster. Also, when the sum of square values for all the clusters is done, it becomes the total within the sum of the square values for the cluster solution. We know that as the number of clusters increases, this value keeps on decreasing, but if we plot the result, you may see that the sum of squared distance decreases sharply up to some value of k and then much more slowly after that. This determines the optimum number of clusters.</p>
<h3 id="heading-using-the-elbow-method"><strong>Using the Elbow Method</strong></h3>
<p>Objective: To determine the optimal number of clusters using the elbow method.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393529493/87c4771e-211e-4d07-b562-71feb653382f.png" alt class="image--center mx-auto" /></p>
<p>Determining the optimum number of clusters is always recommended before applying the K-means algorithm. We will use the sklearn.cluster library in the <strong>Python Script</strong> node to iterate and determine the optimal K value. An empty data list is created. A for loop is made from 1 to 11, and the K-means algorithm is executed considering the values of K from 1 to 10. The command KMeans(n_clusters=I,random_state=42) applies the K-means algorithm, and the value of inertia is stored in the list corresponding to each value of K. The command datalist.append(kmeans.inertia_) adds the value of inertia to datalist. Subsequently, we will use the Line Plot (Plotly) node to plot the different values of the <strong><em>Number of Clusters</em></strong> and the corresponding value of <strong><em>Inertia</em></strong>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># This example script simply outputs the node's input table.</span>
<span class="hljs-comment"># Using the elbow method to find the optimal number of clusters</span>
<span class="hljs-keyword">from</span> sklearn.cluster <span class="hljs-keyword">import</span> KMeans
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Load the input data</span>
df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas()

<span class="hljs-comment"># Prepare the data for clustering (assuming all columns are used for clustering)</span>
AbsenteeismData = df.values

<span class="hljs-comment"># Initialize an empty list to store inertia values</span>
datalist = []

<span class="hljs-comment"># Loop through different numbers of clusters to calculate inertia</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, <span class="hljs-number">11</span>):
    kmeans = KMeans(n_clusters=i, random_state=<span class="hljs-number">42</span>)
    kmeans.fit(AbsenteeismData)
    datalist.append(kmeans.inertia_)

<span class="hljs-comment"># Convert datalist to a DataFrame for output</span>
output_df = pd.DataFrame({<span class="hljs-string">'Number of Clusters'</span>: range(<span class="hljs-number">1</span>, <span class="hljs-number">11</span>), <span class="hljs-string">'Inertia'</span>: datalist})

<span class="hljs-comment"># Output the datalist as a table</span>
knio.output_tables[<span class="hljs-number">0</span>] = knio.Table.from_pandas(output_df)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393546307/fe9002c9-91ac-4612-b90e-ed5357e55758.png" alt class="image--center mx-auto" /></p>
<p>From the line plot, we can observe that the optimum number of clusters is 3. So, we will start cluster analysis considering three clusters.</p>
<h3 id="heading-applying-k-means-clustering"><strong>Applying K-means Clustering</strong></h3>
<p>Before applying the K-means clustering, we will use the <strong>Normalizer</strong> node to normalize the continuous columns using the Z-score normalization method. We will then use the <strong>k-means</strong> node to apply the K-means algorithm to predict the cluster for each observation in the dataset. We will use the <strong>Rule Engine</strong> node to assign the clusters to the corresponding categories (low, avg, and high) of absenteeism. Finally, we will use the <strong>Scorer</strong> node to compare the actual (<strong><em>Absenteeism</em></strong>) and predicted cluster (<strong><em>AbsenteeismPred</em></strong>) columns by their attribute value pairs and show the confusion matrix. Additionally, the node provides several accuracy statistics such as True-Positives, False-Positives, True-Negatives, False-Negatives, Recall, Precision, Sensitivity, Specificity, and F-measures, as well as the overall accuracy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393580164/4f657a53-bb90-4654-a289-87aa62e1d0cf.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393633077/c5d10d27-bfd2-4f9f-a9a3-0b2b4102c019.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393661919/69bfccee-cefb-4231-b2f3-c730890d302a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393676880/5ce2d78d-9784-4b76-bde2-d42b4c2feba0.png" alt class="image--center mx-auto" /></p>
<p>The confusion matrix result shows that 77 observations belonging to the average cluster are grouped similarly in the predicted cluster. Similarly, the low cluster had 118 correctly classified employees, and the high cluster had 129 correctly classified employees. The accuracy score is 43.784%. However, forming proper categories of absenteeism after closely examining the data will help improve the accuracy.</p>
<h3 id="heading-assessing-employee-absenteeism-using-hierarchical-clustering"><strong>Assessing Employee Absenteeism Using Hierarchical Clustering</strong></h3>
<p>Objective: To cluster the employee records for absenteeism using hierarchical cluster analysis</p>
<p>Hierarchical clustering uses two approaches: top-down and bottom-up.</p>
<ul>
<li><p><strong>Top-down or divisive:</strong> The algorithm starts with all data points in one huge cluster. The most dissimilar data points are divided into subclusters until each cluster has exactly one data point.</p>
</li>
<li><p><strong>Bottom-up or agglomerative:</strong> The algorithm starts with every data point as one single cluster and tries to combine the most similar ones into superclusters until it reaches one huge cluster containing all subclusters.</p>
</li>
</ul>
<p>In the case of small observations, bottom-up or agglomerative hierarchical clustering provides better results since it helps us build clusters from n to 1 by merging the clusters bottom-up, obtaining all possible clusters between 1 and n.</p>
<p>A measure must be defined to determine the distance between clusters. There are three methods for comparing two clusters.</p>
<ul>
<li><p><strong>Single Linkage:</strong> This defines the distance between two clusters, c1, and c2, as the minimal distance between any two points, x, and y, with x in c1 and y in c2.</p>
</li>
<li><p><strong>Complete Linkage:</strong> Defines the distance between two clusters, c1 and c2, as the maximal distance between any two points x, y with x in c1 and y in c2.</p>
</li>
<li><p><strong>Average Linkage:</strong> Defines the distance between two clusters, c1, and c2, as the mean distance between all points in c1 and c2.</p>
</li>
</ul>
<p>A distance measure is necessary to measure the distance between two points. You can choose between the Manhattan and Euclidean distances, corresponding to the L1 and L2 norms.</p>
<p>The output of the <strong>Hierarchical Clustering</strong> node is the same data as the input, with one additional column containing the cluster name to which the data point is assigned. Since the hierarchical clustering algorithm produces a series of cluster results, the number of clusters for the output is defined as “three,” “Euclidean” as the distance function, and “complete” as the linkage type in the dialog. The production of the agglomerative clustering is depicted using a dendrogram. A dendrogram is a diagram that shows the hierarchical relationship between objects. A dendrogram's primary use is to find the best way to allocate objects to clusters.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393801600/744fc321-9596-4cc0-a1ae-d33e54a3c765.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393820721/a26736ec-87e9-4912-a735-082142dfa36c.png" alt class="image--center mx-auto" /></p>
<p>We will use the <strong>Rule Engine</strong> node to assign the clusters to the corresponding categories (low, avg, and high) of absenteeism. Finally, we will use the <strong>Scorer</strong> node to compare the actual (<strong><em>Absenteeism</em></strong>) and predicted cluster (<strong><em>AbsenteeismPred</em></strong>) columns by their attribute value pairs and show the confusion matrix. Additionally, the node provides several accuracy statistics such as True-Positives, False-Positives, True-Negatives, False-Negatives, Recall, Precision, Sensitivity, Specificity, and F-measures, as well as the overall accuracy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738393870878/01a57b5b-b4b0-47b4-97c2-ff02ae9fa18b.png" alt class="image--center mx-auto" /></p>
<p>The confusion matrix result shows that 35 observations belonging to the average cluster are grouped similarly in the predicted cluster. Similarly, the low cluster had 207 correctly classified employees, and the high cluster had 35 correctly classified employees. The accuracy score is 37.432%. However, forming proper categories of absenteeism after closely examining the data will help improve the accuracy.</p>
<h3 id="heading-summary">Summary</h3>
<p>In conclusion, identifying absenteeism patterns through cluster analysis is a valuable approach for organizations to understand and address employee absenteeism. By utilizing unsupervised machine learning techniques such as k-means and hierarchical clustering, organizations can group employees based on similar characteristics and identify patterns that may contribute to absenteeism. Analyzing employee absenteeism data, including converting continuous data to categorical data and visualization tools, provides insights into factors that may or may not influence absenteeism. While the accuracy of k-means and hierarchical clustering can vary, they offer a structured way to analyze absenteeism data. They can be improved by refining categories and examining data more closely. Ultimately, these techniques help organizations make informed decisions to reduce absenteeism and improve productivity.</p>
]]></content:encoded></item><item><title><![CDATA[Evaluating Job Satisfaction - Association Rule Mining]]></title><description><![CDATA[Introduction
Job or employee satisfaction, an unquantifiable metric, is a positive emotional response. It is a measure of how contented workers are with their jobs. It is important to remember that job satisfaction varies from employee to employee. I...]]></description><link>https://vijayv2k.com/evaluating-job-satisfaction-association-rule-mining</link><guid isPermaLink="true">https://vijayv2k.com/evaluating-job-satisfaction-association-rule-mining</guid><category><![CDATA[Data Science]]></category><category><![CDATA[data analytics]]></category><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[Association Rule- Apiori ]]></category><category><![CDATA[associationrule]]></category><category><![CDATA[job satisfaction]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Wed, 29 Jan 2025 08:40:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738201849610/2834bb47-3138-49d5-9673-cc088777c58d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction"><strong>Introduction</strong></h3>
<p>Job or employee satisfaction, an unquantifiable metric, is a positive emotional response. It is a measure of how contented workers are with their jobs. It is important to remember that job satisfaction varies from employee to employee. In the same workplace under the same conditions, the factors that help one employee feel good about their job may not apply to another employee. It is essential to have a multidimensional approach for measuring employee satisfaction. The parameters that should be considered for measuring job satisfaction include the challenging nature of work, flexible hours, regular appreciation, competitive pay, nature of the job, supervisor attitude, etc. This article focuses on determining the association of different levels of job satisfaction with different parameters. Association rule mining is adopted using the apriori algorithm to assess job satisfaction associations. The techniques discussed can be used to determine the association of different parameters according to the requirements of the HR department, such as attrition, performance levels, promotion, quality of work, employee attitude, etc.</p>
<h3 id="heading-unsupervised-machine-learning"><strong>Unsupervised Machine Learning</strong></h3>
<p>Unsupervised machine learning algorithms are used when the output is unknown, and no predefined instructions are available to the learning algorithms. In unsupervised learning, the learning algorithm only has input data, and knowledge is extracted from these data. These algorithms create a new representation of the data that is easier to comprehend than the original data and help improve the accuracy of advanced algorithms by consuming less time and reducing memory. Common unsupervised machine learning algorithms include association rule mining, dimensionality reduction algorithms, and clustering.</p>
<h3 id="heading-association-rule"><strong>Association Rule</strong></h3>
<p>Association rule mining is a data-mining technique that originated in the field of marketing and, more recently, has been used effectively in other fields, such as human resource management, organizational behavior, entrepreneurship, strategic management, bioinformatics, nuclear science, geophysics, etc. The goal is to identify relationships (i.e., association rules) between groups of products, items, factors, or categories, leading to insights into substantive management domains. The association rule mining is predominantly done using the apriori algorithm.</p>
<p>Association rules can be considered an IF-THEN relationship. Suppose factor A is the employee’s choice, and then the chances of factor B being considered by the employee are determined. These are two elements of these rules:</p>
<ul>
<li><p>Antecedent (IF): This factor is generally related to employee information, such as evaluation score, number of projects, training programs, work accident, department, etc.</p>
</li>
<li><p>Consequent (THEN): This comes along as a factor with an antecedent/group of antecedents. For example, job satisfaction is the consequence considering the number of projects, evaluation score, etc., as antecedents. Thus, many factors can be considered to be associated with the consequent (job satisfaction).</p>
</li>
</ul>
<h3 id="heading-job-satisfaction-data"><strong>Job Satisfaction Data</strong></h3>
<p>The JobSatisfaction.csv file helps us understand KNIME usage. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder on the KNIME Community Hub.</p>
<blockquote>
<p><em>The</em> <a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj"><em>Evaluating Job Satisfaction – Association Rule Mining</em></a> <em>workflow can be downloaded from the KNIME Community Hub.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141638998/oljFJzpw0.png?auto=format" alt class="image--center mx-auto" /></p>
<p>You are ready after downloading the CSV file from the Data folder.</p>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141673125/UIpDPCuNw.png?auto=format" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the <strong>JobSatisfaction.csv</strong> CSV dataset. The above table shows that the employee dataset has 14999 observations and 10 columns.</p>
<h3 id="heading-data-visualization"><strong>Data Visualization</strong></h3>
<p>We will use the Python View node to generate multiple count plots for the <strong><em>LeftCompany</em></strong>, <strong><em>Salary</em></strong>, <strong><em>TimeSpendCompany</em></strong>, <strong><em>PromotionLast5years</em></strong>, <strong><em>NumberProject</em></strong>, and <strong><em>WorkAccident</em></strong> categorical columns.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Visualization of employee details</span>
<span class="hljs-comment"># Importing libraries</span>
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO

<span class="hljs-comment"># Plotting </span>
fig = plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">10</span>)) 

<span class="hljs-comment">#Count plot for displaying number of employees who left/stayed</span>
plt.subplot(<span class="hljs-number">231</span>) 
sns.countplot(x=<span class="hljs-string">'LeftCompany'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'LeftCompany'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"viridis"</span>) 
plt.title(<span class="hljs-string">"Left Company"</span>)

<span class="hljs-comment">#Count plot for displaying number of employees with different salaries</span>
plt.subplot(<span class="hljs-number">232</span>)
sns.countplot(x=<span class="hljs-string">'Salary'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'Salary'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"mako"</span>)
plt.title(<span class="hljs-string">"Salary-wise Employees"</span>)

<span class="hljs-comment">#Count plot according to number of years spent in organization</span>
plt.subplot(<span class="hljs-number">233</span>)
sns.countplot(x=<span class="hljs-string">'TimeSpendCompany'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'TimeSpendCompany'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"vlag"</span>)
plt.title(<span class="hljs-string">"Time Spent"</span>)

<span class="hljs-comment">#Count plot for displaying number of employees according to promotion</span>
plt.subplot(<span class="hljs-number">234</span>)
sns.countplot(x=<span class="hljs-string">'PromotionLast5years'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'PromotionLast5years'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"rainbow"</span>)
plt.title(<span class="hljs-string">"Employees Promotions"</span>)

<span class="hljs-comment">#Count plot for displaying number of employees for number of projects</span>
plt.subplot(<span class="hljs-number">235</span>)
sns.countplot(x=<span class="hljs-string">'NumberProject'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'NumberProject'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"terrain"</span>)
plt.title(<span class="hljs-string">"Employees by Number of Projects"</span>)

<span class="hljs-comment">#Count plot for displaying number of employees for work accident</span>
plt.subplot(<span class="hljs-number">236</span>)
sns.countplot(x=<span class="hljs-string">'WorkAccident'</span>, data=knio.input_tables[<span class="hljs-number">0</span>].to_pandas(), hue=<span class="hljs-string">'WorkAccident'</span>, legend=<span class="hljs-literal">False</span>, palette=<span class="hljs-string">"prism"</span>)
plt.title(<span class="hljs-string">"Work Accident"</span>)

<span class="hljs-comment"># Create buffer to write into</span>
buffer = BytesIO()

<span class="hljs-comment"># Create plot and write it into the buffer</span>
fig.savefig(buffer, format=<span class="hljs-string">'svg'</span>)

<span class="hljs-comment"># The output is the content of the buffer</span>
output_image = buffer.getvalue()

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)  <span class="hljs-comment"># alternative: knio.view_matplotlib()</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141729248/i-L56CBj9.png?auto=format" alt class="image--center mx-auto" /></p>
<p>We can observe from the chart that employees leaving, promotion, and work accidents are binary variables. Nearly 30% of the employees have left the organization; very few employees have been given promotions in the organization in the last 5 years, and accidents have rarely happened at the workplace. More employees belonged to the low-salary group, more employees spent 3 years in the organization, and a maximum number of employees had three or four projects.</p>
<p>We will use the <strong>Bar Chart</strong> node to generate the occurrence count plot for the categories in the <strong><em>Department</em></strong> column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141765825/s7IBjo_lw.png?auto=format" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141785623/tyszNE1RU.png?auto=format" alt class="image--center mx-auto" /></p>
<p>The chart shows that the sales department had the most employees, followed by the technical and support departments. The accounting, HR, and management departments had the fewest employees.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141811514/UdkGgE14P.png?auto=format" alt class="image--center mx-auto" /></p>
<p>From the output of the Statistics node, we can observe that</p>
<ul>
<li><p>Two columns <strong><em>SatisfactionLevel</em></strong> (92 unique values) and <strong><em>LastEvaluation</em></strong> (65 unique values), are continuous,</p>
</li>
<li><p>Three columns, <strong><em>WorkAccident</em></strong>, <strong><em>LeftCompany</em></strong>, and <strong><em>PromotionLast5years</em></strong>, are binary,</p>
</li>
<li><p>Two columns, <strong><em>Department</em></strong> (10 categories) and <strong><em>Salary</em></strong> (3 categories), are categorical,</p>
</li>
<li><p>Three columns, <strong><em>AverageMonthlyHours</em></strong> (215 unique values), <strong><em>NumberProject</em></strong> (6 unique values), and <strong><em>TimeSpendCompany</em></strong> (8 unique values) are integers.</p>
</li>
</ul>
<h3 id="heading-converting-continuous-columns-to-categorical-using-binning"><strong>Converting Continuous Columns to Categorical Using Binning</strong></h3>
<p>Since the apriori algorithm works on categorical columns, converting each column into a categorical one is essential. We will use the <strong>Auto-Binner</strong> node to convert the <strong><em>SatisfactionLevel</em></strong>, <strong><em>LastEvaluation</em></strong>, and <strong><em>AverageMonthlyHours</em></strong> columns into categorical columns by splitting them into three equal bins based on the frequency of the observations in the column. Subsequently, we will use the <strong>Rule Engine</strong> node to assign meaningful category values (low, avg, high) to columns for easy analysis and interpretation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141839581/vrgnLBmpR.png?auto=format" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141866504/pIHn-zt-m.png?auto=format" alt class="image--center mx-auto" /></p>
<h3 id="heading-dummy-encoding"><strong>Dummy Encoding</strong></h3>
<p>Note that the apriori algorithm only accepts Boolean values. Hence, converting each category into different columns represented by binary values (0, 1) is essential. We will use the <strong>One to Many</strong> node to transform all possible category values in the selected columns into a new column. It is worth noting that the number of new columns created for a particular column is the same as the number of categories in the column. Subsequently, we will use the <strong>Column Filter</strong> node to retain only the necessary columns for further analysis.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141928685/b7cLg7rCM.png?auto=format" alt class="image--center mx-auto" /></p>
<p>The resultant dataset now has 14999 observations and 40 columns; all added columns have Boolean (0,1) values.</p>
<h3 id="heading-apriori-algorithm-for-association-rule-mining"><strong>Apriori Algorithm for Association Rule Mining</strong></h3>
<p>Using the <strong>Python Script</strong> node, the apriori algorithm is executed considering the apriori() and association_rules () functions available in the “mlxtrend” library. The apriori algorithm helps to determine the frequent factors based on their minimum support and maximum length. These factors are considered input to the association_rules() function with some conditions, and the data are filtered. The support and length of the factors play an essential role in the apriori algorithm.</p>
<p><strong>Syntax of apriori()</strong></p>
<p>Apriori(data, use_colnames=, min_support=, max_len=)</p>
<p>where</p>
<ul>
<li><p>data represents the data on which the algorithm is executed</p>
</li>
<li><p>use_colnames has a Boolean value representing whether colnames are considered or not</p>
</li>
<li><p>min_support is the minimum support required and has a value between 0 and 1</p>
</li>
<li><p>max_len specifies the maximum number of factors that will be considered</p>
</li>
</ul>
<p><strong>Syntax of association_rules()</strong></p>
<p>Association_rules(freq_fact, metric=, min_threshold=)</p>
<p>where</p>
<ul>
<li><p>freq_fact are frequent factors that are determined</p>
</li>
<li><p>metric specifies the measurement that needs to be considered</p>
</li>
<li><p>min_threshold specifies the threshold value that should be considered</p>
</li>
</ul>
<p>The code apriori(df, use_colnames=True, min_support=0.1, max_len=3) considers minimum support as 0.1 and maximum length of factors as 3. This means that until and unless the frequency factors are not 10%, these factors will not be considered for further analysis. This is a correct approach because considering factors that do not have an association is meaningless. At the same time, it is not preferred to have 500 factors left after filtering based on support. The lift metric is used as the filter criterion to avoid such cases. This is done using the association_rules() function, considering metric as a lift and minimum threshold as 1. Subsequently, we will use the <strong>Sorter</strong> node to order the resultant association rules in descending order of “confidence”.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738141966102/wwzcQ5Uvv.png?auto=format" alt class="image--center mx-auto" /></p>
<h3 id="heading-identify-the-association-of-low-satisfaction-using-apriori-algorithm"><strong>Identify the Association of Low Satisfaction Using Apriori Algorithm</strong></h3>
<p>Objective: To identify the association of low satisfaction level with different factors</p>
<p>We will determine the association between low satisfaction level and the factors of association. It is worth noting that the rule has more impact if there is more lift. The higher the value of the lift, the more the association. We will use the <strong>Row Filter</strong> node with the <strong><em>consequents</em></strong> column equal to “Low_SatisfactionLevel” as the filter criterion.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738142000855/H0HlyvkDH.png?auto=format" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738142022028/EoTUYQ2EC.png?auto=format" alt class="image--center mx-auto" /></p>
<p>A lift value greater than one means that all the antecedents displayed in different records are associated with the consequent (Low_SatisfactionLevel). Also, a confidence greater than 0.5 indicates that the occurrence of the records is greater than 50%. The first record indicates that the combination of a number of projects equal to 2 and low average monthly hours is associated with a low satisfaction level. The results also suggest that the number of projects is equal to 2, the time spent in the company is 3 years, and the last evaluation is low, which are some critical factors for low satisfaction. Thus, to increase satisfaction, the organization should change the number of projects and design unique strategies for employees who have completed 3 years. Steps should also be considered for employees whose last evaluation score is low.</p>
<h3 id="heading-identify-the-association-of-average-satisfaction-using-apriori-algorithm"><strong>Identify the Association of Average Satisfaction Using Apriori Algorithm</strong></h3>
<p>Objective: To identify the association of average satisfaction level with different factors</p>
<p>We will determine the association between average satisfaction level and the factors of association. As the filter criterion, we will use the <strong>Row Filter</strong> node with the <strong><em>consequents</em></strong> column equal to “Avg_SatisfactionLevel.”</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738142050073/qW28tMnFE.png?auto=format" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738142075294/1Gfs9LpzZ.png?auto=format" alt class="image--center mx-auto" /></p>
<p>A lift value greater than one means that all the antecedents displayed in different records are associated with the consequent (Avg_SatisfactionLevel). Also, a confidence greater than 0.4 indicates that the occurrence of the records is greater than 40%. The first record indicates that the number of projects equal to 3 is highly associated with an average satisfaction level. The results also suggest that the number of projects is equal to 3, there has been no promotion in the last five years, and the monthly hours belong to the average category, which are some critical factors for average satisfaction. Thus, to increase satisfaction, the organization should change the number of projects and design unique strategies for employees who have not been promoted. Steps should also be considered for employees whose monthly hours are average.</p>
<h3 id="heading-identify-the-association-of-high-satisfaction-using-apriori-algorithm"><strong>Identify the Association of High Satisfaction Using Apriori Algorithm</strong></h3>
<p>Objective: To identify the association of high satisfaction level with different factors</p>
<p>We will determine the association between high satisfaction level and the factors of association. As the filter criterion, we will use the <strong>Row Filter</strong> node with the <strong><em>consequents</em></strong> column equal to “High_SatisfactionLevel.”</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738142101694/S_j2Vf6l_.png?auto=format" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738142121685/y22qAtwRZ.png?auto=format" alt class="image--center mx-auto" /></p>
<p>A lift value greater than one means that all the antecedents displayed in different records are associated with the consequent (High_SatisfactionLevel). Also, a confidence greater than 0.38 indicates that the occurrence of the records is greater than 38%. The first record indicates that the number of projects equals four and that no workplace accidents are highly associated with high satisfaction. The results also suggest that the number of projects is equal to 4, the last evaluation score is high, and there are no workplace accidents, which are some critical factors for high satisfaction. Thus, to increase satisfaction, the organization should change the number of projects to four and formulate strategies to ensure the last evaluation score is high and no workplace accidents.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In conclusion, evaluating job satisfaction through association rule mining provides valuable insights into the factors influencing employee contentment. By utilizing the apriori algorithm, organizations can identify key associations between job satisfaction levels and various workplace parameters. This analysis helps in understanding the critical factors that contribute to low, average, and high satisfaction levels among employees. By addressing these factors, organizations can implement targeted strategies to enhance job satisfaction, leading to improved employee retention, performance, and overall workplace morale. The approach outlined in this article offers a systematic method for HR departments to assess and improve job satisfaction, ultimately contributing to a more positive and productive work environment.</p>
]]></content:encoded></item><item><title><![CDATA[Forecasting HR Cost - Time Series Modeling]]></title><description><![CDATA[Introduction
Cost in an organization is always a significant concern, and the management always wants to predict the cost before deciding on a future course of action. This article focuses on predicting cost using different time series models. Differ...]]></description><link>https://vijayv2k.com/forecasting-hr-cost-time-series-modeling</link><guid isPermaLink="true">https://vijayv2k.com/forecasting-hr-cost-time-series-modeling</guid><category><![CDATA[Data Science]]></category><category><![CDATA[data analytics]]></category><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[forecasting]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Tue, 28 Jan 2025 07:34:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738119973603/02891faa-3c4d-430f-a0f6-e061a4cbd22b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Cost in an organization is always a significant concern, and the management always wants to predict the cost before deciding on a future course of action. This article focuses on predicting cost using different time series models. Different models are used for predicting cost, such as autoregressive, moving average, and autoregressive integrated moving average (ARIMA) techniques, which are explained with examples. These techniques are used for any time series data existing in the organization. However, the methods discussed in this article can be used to extract different information according to an organization's requirements from any dataset in the human resource department.</p>
<h3 id="heading-hr-cost"><strong>HR Cost</strong></h3>
<p>HR cost is a key component of HR accounting. HR costs are mainly incurred from expenses related to salary, incentives, reimbursements, insurance, and fixed and miscellaneous costs. This includes total sot per hired employee across an entire company, the total compensation per employee, the total recruitment expenditures for every new hire across a particular time frame, expenses on job boards to draw valuable conclusions, the salary of recruiters, funds required to establish an employer brand like attending recruiting events, content writing, designing posters, and videos, social media, cost for partnerships with universities and institutions, cost of external recruiting agencies, recruiting technology costs like video interviewing tools, coding assessment tools.</p>
<p>Cost optimization continues to be a critical concern for many HR leaders. However, the HR professional should use different metrics that can be useful for determining an accurate assessment of total cost. For example, the quality of hire can be determined by comparing cost per hire and long-term performance evaluation. Different measures that an organization can take to reduce cost include restructuring the service delivery mechanism, incorporating flexibility for ensuring targeted utilization of capacities, redesigning processes to balance service delivery efficiency and effectiveness, developing the existing capacities to optimize services, balancing elements of the rewards model for effective cost optimization; structuring the workforce to align short-term business needs with long-term value; and achieving cost optimization effects through thoughtful layoff planning and execution.</p>
<p>Measure and forecast costs based on previous values are essential for smooth organizational functioning and effective strategy formulation.</p>
<h3 id="heading-time-series-modeling"><strong>Time Series Modeling</strong></h3>
<p>Forecasting helps formulate strategies in various businesses and is a basic need for managerial decision-making. Managers have to make decisions in uncertainty without knowing what will happen. Different methods, including qualitative and quantitative models, can obtain forecasting. Quantitative models include time series models and causal models. Causal models are used when one variable is dependent on the values of other variables. Time series data provide essential information related to time, and time series models attempt to predict the forecast demand (future values) using the past demand values (historical data). A time series is a series of data points in which each data point is associated with a timestamp. They play a significant role in understanding many details on specific factors over time. For example, stock price at different points of time on a given day, amount of sales in a region to varying months of the year.</p>
<p>Time series analysis can be used in many business applications to forecast a quantity into the future and explain its historical patterns. The ARIMA model is commonly used for time series forecasting. Exponential smoothing models were based on the data's description of trend and seasonality. At the same time, ARIMA models describe the autocorrelations in the data. Notably, every model is nonstationary, while ARIMA models can be stationary. ARIMA models use historical information to make predictions, which is a basis for complex models. ARIMA models support either no exponential or linear exponential smoothing but not nonlinear exponential smoothing. ARIMA is like a linear regression equation where the predictors depend on some parameters of the ARIMA model.</p>
<p>ARIMA models are a class of statistical models for analyzing and forecasting time series data. They explicitly cater to a suite of standard structures in time series data and, as such, provide a simple yet powerful method for making skillful time series forecasts. ARIMA generalizes the more straightforward autoregressive moving average and adds integration.</p>
<h3 id="heading-hr-cost-data"><strong>HR Cost Data</strong></h3>
<p>The HRCost file helps us understand KNIME usage. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder on the KNIME Community Hub.</p>
<blockquote>
<p><em>The</em> <a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj"><em>Forecast HR Cost – Time Series Modeling</em></a> <em>workflow can be downloaded from the KNIME Community Hub.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738119997148/a543aea5-77d7-473d-950f-11ba9f324307.png" alt class="image--center mx-auto" /></p>
<p>You are ready after downloading the CSV file from the Data folder.</p>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based Dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120014078/e5875008-aa9f-4842-901f-210d52a65c46.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the <strong>HRCost.csv</strong> CSV dataset. The above table shows that the employee dataset has 144 observations and 3 columns.</p>
<h3 id="heading-filter-subset-observations-for-the-hr-department"><strong>Filter / Subset observations for the HR Department</strong></h3>
<p>We will consider a subset of the dataset for our preliminary data exploration and visualization. Based on the <strong><em>MonthDate</em></strong> column, we can use the <strong>Date&amp;TimeBased Row Filter</strong> node to filter out the Jan 2016 to Dec 2019 observations. After that, we will use the <strong>Line Plot</strong> node to display the monthly expenses from the <strong><em>Cost</em></strong> column in a line chart.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120214390/35a3e080-2ff0-4d38-916e-c06f7242ff6f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120239367/23434389-2a18-4df0-a926-3b899fd825e3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120253874/3eafd6cd-869f-4638-99ea-299e3f1af2b6.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-testing-stationarity-of-time-series-data"><strong>Testing Stationarity of Time Series Data</strong></h3>
<p>It is essential to check the stationarity of the series before doing forecasting. A time series is considered stationary if it does not have a trend or seasonal effects and this has consistent statistical properties over time. These properties include mean, variance, and autocovariance. Before applying statistical modeling methods, the time series is required in stationery. This is necessary for easy modeling and proper series forecasts because it should be the same if we take a specific behavior over time. Observations from a nonstationary time series show seasonal effects, trends, and other structures that depend on the time index. We can determine whether the tied series is stationary or nonstationary by looking at plots and checking trends or seasonality or by using statistical tests such as the Dickey-Fuller test.</p>
<p>We will use the statsmodels.tsa.stattools package in the <strong>Python Script</strong> node to apply the Dickey-Fuller test. The test's null hypothesis is that a unit root can represent the time series. This means that it is nonstationary and has some time-dependent structure. The alternative hypothesis (rejecting the null hypothesis) is that the time series is stationary. It suggests the time series does not have a unit root and does not have a time-dependent structure. We interpret this result using the p-value from the test. If the p-value is less than or equal to 0.05, it suggests we reject the null hypothesis. This means the data are stationary and do not have a unit root. If the p-value is more significant than 0.05, we fail to reject the null hypothesis, and the data have a unit root and are nonstationary. For practical analysis, it is also recommended that the rolling mean of the series be created and plotted.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Importing necessary libraries</span>
<span class="hljs-keyword">from</span> statsmodels.tsa.stattools <span class="hljs-keyword">import</span> adfuller
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Load the input table as a pandas DataFrame</span>
df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas()

<span class="hljs-comment"># Ensure the series is extracted correctly</span>
<span class="hljs-keyword">if</span> <span class="hljs-string">"Cost"</span> <span class="hljs-keyword">in</span> df.columns:
    series = df[<span class="hljs-string">"Cost"</span>]
<span class="hljs-keyword">else</span>:
    <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"The column 'Cost' is not found in the input table."</span>)

<span class="hljs-comment"># Applying Dickey-Fuller Test</span>
<span class="hljs-comment"># Null hypothesis: The time series is nonstationary</span>
result = adfuller(series)

<span class="hljs-comment"># Prepare the results of the Dickey-Fuller test</span>
output_data = {
    <span class="hljs-string">"ADF Statistic"</span>: [result[<span class="hljs-number">0</span>]],
    <span class="hljs-string">"p-value"</span>: [result[<span class="hljs-number">1</span>]],
    <span class="hljs-string">"Critical Value 1%"</span>: [result[<span class="hljs-number">4</span>][<span class="hljs-string">"1%"</span>]],
    <span class="hljs-string">"Critical Value 5%"</span>: [result[<span class="hljs-number">4</span>][<span class="hljs-string">"5%"</span>]],
    <span class="hljs-string">"Critical Value 10%"</span>: [result[<span class="hljs-number">4</span>][<span class="hljs-string">"10%"</span>]]
}

<span class="hljs-comment"># Convert the results to a pandas DataFrame</span>
output_df = pd.DataFrame(output_data)

<span class="hljs-comment"># Save the output DataFrame to the KNIME output table</span>
knio.output_tables[<span class="hljs-number">0</span>] = knio.Table.from_pandas(output_df)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120277437/1a4f1055-233a-439a-818b-9e05226b0278.png" alt class="image--center mx-auto" /></p>
<p>We will use the <strong>Moving Average</strong> node to create a backward simple moving average, with 12 windows, of the <strong><em>Cost</em></strong> column. Subsequently, we use the <strong>Line Plot</strong> node to plot the <strong><em>Cost</em></strong> and <strong><em>MA(Cost)</em></strong> columns.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120290586/17011b13-985b-45ae-97d9-d362641214fa.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120304192/d1f6b627-86cd-491b-9bc2-56ddcd7c6732.png" alt class="image--center mx-auto" /></p>
<p>In our data, the p-value is 0.992, meaning the null hypothesis is accepted. This further implies that our series is nonstationary. This can be further interpreted by looking at the figure, which shows that the mean is increasing. It should be noted that for creating models, it is essential to make the series stationary before developing a model and doing forecasting.</p>
<h3 id="heading-smoothing-the-time-series-data"><strong>Smoothing the Time Series Data</strong></h3>
<p>When the time series data have significant irregular components, we want a smooth curve to reduce these fluctuations. Curve smoothing is generally achieved using a simple moving average method, which is the best method to accomplish this using the <strong>Moving Average</strong> node. To roll the mean, we first take some (k) consecutive values and define a parameter k value. Generally, as the value of k increases, the plot becomes increasingly smoothed. The major challenge is to find the appropriate value of k that highlights the significant patterns in the data without under or over-smoothing. In our data, the value of k depends on the frequency. Since it is one year, we will consider the value of k as 12. For our <strong><em>Cost</em></strong> data, we will use natural logarithmic transformation using the ln() function of the <strong>Math Formula</strong> node to get the <strong><em>LnCost</em></strong> column because there is a strong positive trend. Subsequently, we use the <strong>Line Plot</strong> node to plot the <strong><em>LnCost</em></strong> and <strong><em>MA(LnCost)</em></strong> columns.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120364994/73ece23a-6b69-4ae9-847f-6b03fdefc09a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120389222/2447614f-ad6a-49b5-a5ee-aba9d7c63a5e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120406973/6ee29f46-7723-4878-a05e-35d3397073a8.png" alt class="image--center mx-auto" /></p>
<p>We can observe that the <strong><em>MA(LnCost)</em></strong> starts from Dec 2009. This is because we take the average of the last 12 values, and the rolling mean is not defined for the first 11 months. Thus, the first 11 months will have missing values. Since we cannot analyze missing values, dropping these rows using the Row Filter node is essential. Subsequently, we will find the difference between the two columns, <strong><em>LnCost</em></strong> and <strong><em>MA(LnCost)</em></strong>, using the <strong>Math Formula</strong> node to create the <strong><em>Ln_MA_Diff</em></strong> column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120428766/205c869f-d25d-4257-b5f6-4bdee70f1da5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120452995/e87c1953-16d0-4383-935a-09ce10511aa6.png" alt class="image--center mx-auto" /></p>
<p>We will now determine the series' stationarity by performing the Dickey-Fuller test on the <strong><em>Ln_MA_Diff</em></strong> column and plotting its moving average series using the <strong>Line Plot</strong> node.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Importing necessary libraries</span>
<span class="hljs-keyword">from</span> statsmodels.tsa.stattools <span class="hljs-keyword">import</span> adfuller
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Load the input table as a pandas DataFrame</span>
df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas()

<span class="hljs-comment"># Ensure the series is extracted correctly</span>
<span class="hljs-keyword">if</span> <span class="hljs-string">"Ln_MA_Diff"</span> <span class="hljs-keyword">in</span> df.columns:
    series = df[<span class="hljs-string">"Ln_MA_Diff"</span>]
<span class="hljs-keyword">else</span>:
    <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"The column 'Ln_MA_Diff' is not found in the input table."</span>)

<span class="hljs-comment"># Applying Dickey-Fuller Test</span>
<span class="hljs-comment"># Null hypothesis: The time series is nonstationary</span>
result = adfuller(series)

<span class="hljs-comment"># Prepare the results of the Dickey-Fuller test</span>
output_data = {
    <span class="hljs-string">"ADF Statistic"</span>: [result[<span class="hljs-number">0</span>]],
    <span class="hljs-string">"p-value"</span>: [result[<span class="hljs-number">1</span>]],
    <span class="hljs-string">"Critical Value 1%"</span>: [result[<span class="hljs-number">4</span>][<span class="hljs-string">"1%"</span>]],
    <span class="hljs-string">"Critical Value 5%"</span>: [result[<span class="hljs-number">4</span>][<span class="hljs-string">"5%"</span>]],
    <span class="hljs-string">"Critical Value 10%"</span>: [result[<span class="hljs-number">4</span>][<span class="hljs-string">"10%"</span>]]
}

<span class="hljs-comment"># Convert the results to a pandas DataFrame</span>
output_df = pd.DataFrame(output_data)

<span class="hljs-comment"># Save the output DataFrame to the KNIME output table</span>
knio.output_tables[<span class="hljs-number">0</span>] = knio.Table.from_pandas(output_df)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120485312/b4d33ee3-f0d1-4c90-bd1a-384ea269bb62.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120503225/9d6084ee-0302-4732-941c-68e617930e0c.png" alt class="image--center mx-auto" /></p>
<p>The p-value of 0.009 is less than 0.05. This means that the series is stationary at the 95% confidence interval. We can also observe from the visual representation that the rolling values vary slightly, but there is no specific trend. Hence, we can assume the series' stationarity. Thus, in the following sections, we will consider the data after the natural logarithmic transformation <strong><em>LnCost</em></strong> for developing the ARIMA model.</p>
<h3 id="heading-forecast-hr-cost-using-auto-regressive-ar-model"><strong>Forecast HR Cost Using Auto-Regressive (AR) Model</strong></h3>
<p>Objective: To forecast the HR cost using the Auto-Regressive (AR) model</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120530416/85ca7fdd-6bfe-4fad-84c0-a7570be06b9a.png" alt class="image--center mx-auto" /></p>
<p>The AR model is created by considering the ARIMA function's third argument (moving average) to be zero. However, the value of the first argument denotes the lag value. For example, the ARIMA (5,1,0) creates an AR model, sets the lag value to 5 for autoregression, uses a difference order of 1 to make the time series stationary, and uses a moving average value of 0. Since the moving average component is 0, it can be considered as only an AR model.</p>
<p>Using the maximum likelihood estimation method, we will use the <strong>ARIMA Learner</strong> node to develop an AR (2,1,0) model of lag two on the <strong><em>LnCost</em></strong> column. We will then use the <strong>ARIMA Predictor</strong> node to apply the regression model and obtain fitted values in the “In-sample predictions” output table. Based on this model, we can get the subsequent five-month forecasted cost <strong><em>CostForecast</em></strong> column by using the forecast option in the <strong>ARIMA Predictor</strong> node. The “Forecast” output shows the result in standard error and forecast values.  Considering the forecasted values, the management of the organization can, thus, frame strategies and take decisions accordingly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120561524/53d1c806-ce43-4cba-bf18-96249120e3a4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120575116/3253df4e-17b5-491c-8e7e-973758407d05.png" alt class="image--center mx-auto" /></p>
<p>It should be noted that the fitted/forecast values need to be brought back to their original scale to predict actual values. The exp() function of the <strong>Math Formula</strong> node helps to determine the correct <strong><em>CostFitted</em></strong> values from the natural logarithmic <strong><em>LnCost(fitted values)</em></strong> values. It is essential to decide on the error of the developed model. This can be determined by observing the difference between the original and predicted values. The root mean squared function is one of the methods that can be used to determine the error (RMSE). Using multiple data manipulation nodes, the error in the developed AR model is 31.387. This means that there is a difference in the original and predicted values. It should be noted that the lower the value, the less the difference between the original and predicted values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120590201/a550dd1d-a0d2-4d4d-b2e7-5a012a595b1a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120604631/54d6c795-41e3-4f34-bc64-09cf1dd9ef36.png" alt class="image--center mx-auto" /></p>
<p>A visual display of the original <strong><em>Cost</em></strong> vs predicted <strong><em>CostFitted</em></strong> values uses the <strong>Line Plot</strong> node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120616924/6ee8cc7a-4e7f-4d43-9cad-db09a0912697.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-forecast-hr-cost-using-moving-average-ma-model"><strong>Forecast HR Cost Using Moving Average (MA) Model</strong></h3>
<p>Objective: To forecast the HR cost using the Moving Average (MA) model</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120696009/c04cead0-3dbc-40f8-a3de-e5652914d0f1.png" alt class="image--center mx-auto" /></p>
<p>The MA model is created by considering the ARIMA function's first argument (autoregressive) to be zero. However, the value of the first argument denotes the lag value. For example, the ARIMA (0,1,3) creates an MA model and sets the lag value to 3 for the moving average, uses a difference order of 1 to make the time series stationary, and uses an autoregressive value of 0. Since the autoregressive component is 0, it can be considered as only an MA model.</p>
<p>Using the maximum likelihood estimation method, we will use the <strong>ARIMA Learner</strong> node to develop an MA (0,1,2) on the <strong><em>LnCost</em></strong> column. We will then use the <strong>ARIMA Predictor</strong> node to apply the regression model and obtain fitted values in the “In-sample predictions” output table. Based on this model, we can get the subsequent five-month forecasted cost <strong><em>CostForecast</em></strong> column by using the forecast option in the <strong>ARIMA Predictor</strong> node. The “Forecast” output shows the result in standard error and forecast values.  Considering the forecasted values, the management of the organization can, thus, frame strategies and take decisions accordingly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120722232/4c484632-5020-4090-8334-30ac023a263f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120744576/f6fd5aff-7918-40fc-ac83-19f3bca5337e.png" alt class="image--center mx-auto" /></p>
<p>It should be noted that the fitted/forecast values need to be brought back to their original scale to predict actual values. The exp() function of the <strong>Math Formula</strong> node helps to determine the correct <strong><em>CostFitted</em></strong> values from the natural logarithmic <strong><em>LnCost(fitted values)</em></strong> values. It is essential to decide on the error of the developed model. This can be determined by observing the difference between the original and predicted values. The root mean squared function is one of the methods that can be used to determine the error (RMSE). Using multiple data manipulation nodes, the error in the developed AR model is 33.149. This means that there is a difference in the original and predicted values. It should be noted that the lower the value, the less the difference between the original and predicted values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120761118/da781827-97eb-4acc-8001-4cca1970982f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120776623/1ea49a15-889c-4344-bf3f-52408860f167.png" alt class="image--center mx-auto" /></p>
<p>A visual display of the original <strong><em>Cost</em></strong> vs predicted <strong><em>CostFitted</em></strong> values uses the <strong>Line Plot</strong> node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120792660/fdd4c011-23e9-4c98-b428-eab0c83586d4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120806801/eeaa3526-599f-4dc9-802d-2526f50d4f30.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-forecast-hr-cost-using-arima-model"><strong>Forecast HR Cost Using ARIMA Model</strong></h3>
<p>Objective: To forecast the HR cost using the ARIMA model.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120834459/9f5004d4-f187-4420-8c83-cf75634cb07e.png" alt class="image--center mx-auto" /></p>
<p>The ARIMA model is created by considering the first and third arguments as nonzero. For example, the ARIMA (3,1,3) creates an ARIMA model, sets the lag value to 3, and uses a difference order of 1 to make the time series stationary.</p>
<p>Using the maximum likelihood estimation method, we will use the <strong>ARIMA Learner</strong> node to develop an ARIMA (2,1,2) on the <strong><em>LnCost</em></strong> column. We will then use the <strong>ARIMA Predictor</strong> node to apply the regression model and obtain fitted values in the “In-sample predictions” output table. Based on this model, we can get the subsequent five-month forecasted cost <strong><em>CostForecast</em></strong> column by using the forecast option in the <strong>ARIMA Predictor</strong> node. The “Forecast” output shows the result in standard error and forecast values.  Considering the forecasted values, the management of the organization can, thus, frame strategies and take decisions accordingly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120850631/a419e281-b131-4946-a0f1-26abdbd4ba00.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120865202/3ce8fbb1-c698-4cb8-b9a8-859f57f48149.png" alt class="image--center mx-auto" /></p>
<p>It should be noted that the fitted/forecast values need to be brought back to their original scale to predict actual values. The exp() function of the <strong>Math Formula</strong> node helps to determine the correct <strong><em>CostFitted</em></strong> values from the natural logarithmic <strong><em>LnCost(fitted values)</em></strong> values. It is essential to decide on the error of the developed model. This can be determined by observing the difference between the original and predicted values. The root mean squared function is one of the methods that can be used to determine the error (RMSE). Using multiple data manipulation nodes, the error in the developed AR model is 34.5. This means that there is a difference in the original and predicted values. It should be noted that the lower the value, the less the difference between the original and predicted values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120887115/829ba59f-cde1-4d55-b29e-3578141ff47f.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120905598/5e4aecac-0303-499f-a3cb-5dcac35bf1c3.png" alt class="image--center mx-auto" /></p>
<p>A visual display of the original <strong><em>Cost</em></strong> vs predicted <strong><em>CostFitted</em></strong> values uses the <strong>Line Plot</strong> node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120922489/2c157e4e-f6c6-4dee-9ae3-109c8aeb1aa1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738120942453/8e9a97fb-18a2-4f9f-8cba-ac5d25da2ff7.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In conclusion, forecasting HR costs using time series modeling is valuable for organizations aiming to optimize their financial planning and decision-making processes. By employing models such as autoregressive (AR), moving average (MA), and autoregressive integrated moving average (ARIMA), organizations can effectively predict future HR expenses based on historical data. This enables management to make informed strategic decisions, align resources with business objectives, and implement cost-saving measures. The process involves ensuring data stationarity, applying appropriate smoothing techniques, and selecting the best-fitting model to achieve accurate forecasts. Ultimately, these predictive insights contribute to more efficient HR operations and overall organizational success.</p>
]]></content:encoded></item><item><title><![CDATA[Evaluate Training Effectiveness - Comparative Statistics]]></title><description><![CDATA[Introduction
The HR department organizes training and development programs for employees. These programs instill a global mindset in budding talent and help them acquire comprehensive business knowledge to enhance their performance and deliver better...]]></description><link>https://vijayv2k.com/evaluate-training-effectiveness-comparative-statistics</link><guid isPermaLink="true">https://vijayv2k.com/evaluate-training-effectiveness-comparative-statistics</guid><category><![CDATA[Data Science]]></category><category><![CDATA[data analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Tue, 28 Jan 2025 05:48:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121695044/c8557f1a-6563-4eaa-b9f8-c6505ee52e7a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>The HR department organizes training and development programs for employees. These programs instill a global mindset in budding talent and help them acquire comprehensive business knowledge to enhance their performance and deliver better values to clients. Moreover, development programs prepare future business leaders to develop leadership in thoughts and actions, besides grooming them to lead big and small teams efficiently at different levels.</p>
<p>The compare means technique is generally used to compare the means of continuous variables for different categories of categorical variables. The compare means techniques can be used to compare the means of continuous variables such as salary, performance score, recruitment expenses, satisfaction level, and general expenses of employees with different categorical variables such as demographic variables (gender, age, income group) and other variables such as departments, region, manager name, and recruitment sources. Specific examples include a comparison of expenses from different recruitment sources, a comparison of salary from different departments, regions, age groups, etc.; a comparison of performance scores from different age and gender groups; a comparison of general expenses from the different areas, a comparison of employee satisfaction level concerning different managers, etc. This article, however, focuses on measuring the effectiveness of training programs according to different demographic variables; besides, compare means techniques like independent sample t-test, ANOVA, etc., are also used.</p>
<h3 id="heading-compare-means"><strong>Compare Means</strong></h3>
<p>A common problem in research is comparing the central tendency of one group to a value or another group or groups. A test compares sample means to see if sufficient proof exists to predict that the means of the corresponding population distributions also differ. Standard statistical tools for assessing these comparisons are t-tests, analysis of variance, and general linear models. Parametric techniques are used when some assumptions are not met. The general goal for most of these tools is to use the estimate of the means (or another central measure), assess the variation based on sample estimates, and use this information to provide the amount of evidence of a difference in means or central tendency.</p>
<p>T-test and analysis of variance (abbreviated as ANOVA) are two parametric statistical techniques used to test the hypothesis when the dependent variable is continuous and the independent variable is categorical. The sample is taken from different populations. The different samples are measured on some variable of interest. For example, a t-test will determine if the means of the two sample distributions differ significantly. At the same time, ANOVA will decide if the means of more than two sample distributions vary considerably from each other. Both these tests are based on the three common assumptions:</p>
<ol>
<li><p>The sample drawn from the population should be normally distributed,</p>
</li>
<li><p>There should be homogeneity of variances and</p>
</li>
<li><p>The independence of observations should exist.</p>
</li>
</ol>
<p>There is a thin line of demarcation between the t-test and ANOVA. When the categorical variable has two groups, the t-test is used, while ANOVA is preferred if there are more than two groups. Thus, when the population means of only two groups are to be compared, the t-test is used, but when the means of more than two groups are to be compared, ANOVA is preferred. Three common assumptions need to be fulfilled before applying a t-test or ANOVA. However, it should be noted that a one-sample t-test should fulfill only the normality assumption since only one sample is involved.</p>
<ol>
<li><p><strong>Normally distributed:</strong> Non-normally distributed variables (highly skewed or kurtotic variables or with substantial outliers) can distort relationships and significance tests. Before applying a t-test or ANOVA, it is assumed that variables are normally distributed (symmetric bell-shaped distribution).</p>
</li>
<li><p><strong>Independent samples:</strong> If we randomly sample each set of items separately, under different conditions, the samples are independent. The measurements in one sample have no bearing on the measurements in the other sample. For example, consider randomly sampling two groups of people based on gender to test their online shopping behavior. Let's take one random sample from a group of males and record their perception and another sample from a group of females and record their perception. We know that the measurement in one sample does not affect the other sample.</p>
</li>
<li><p><strong>Homogeneity of variances:</strong> The assumption of homogeneity of variance is an assumption of the independent samples t-test and ANOVA, which states that the variance within each population is equal. However, the independent samples t-test and ANOVA can handle this assumption if the group sizes are equal. Equal group sizes may be defined by the ratio of the largest to the smallest group being less than 1.5. If group sizes are vastly unequal, the homogeneity of variance is violated, then the result will be biased when significant sample variances are associated with small group sizes. When this occurs, the significance level will be underestimated, which can cause the null hypothesis to be falsely rejected. The result will also be biased in the opposite direction if significant variances are associated with large group sizes. This would mean that the significance level will be overestimated. This does not cause the same problems as falsely rejecting the null hypothesis; however, it can cause a decrease in the power of the test.</p>
</li>
</ol>
<p>A test is a process for comparing sample means of different groups. While comparing the means of different groups, we frame a hypothesis in which the dependent variable is continuous, and the independent variable is categorical. For example, in determining the effect of gender on job satisfaction, gender (a categorical variable) will be considered the independent variable, and job satisfaction will be viewed as the dependent variable.</p>
<h3 id="heading-training-score-data"><strong>Training Score Data</strong></h3>
<p>The TrainingScore.csv file helps us understand KNIME usage. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder on the KNIME Community Hub.</p>
<blockquote>
<p><em>The</em> <a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj"><em>Evaluate Training Effectiveness - Comparative Statistics</em></a> <em>workflow can be downloaded from the KNIME Community Hub.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121715175/8fbc2a49-7591-4d27-abbf-6cf99446a8cf.png" alt class="image--center mx-auto" /></p>
<p>You are ready after downloading the CSV file from the Data folder.</p>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based Dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121729964/b88a12d1-ece0-40ea-ba09-e8613c1a6c11.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the <strong>TrainingScore.csv</strong> CSV dataset. The above table shows that the employee dataset has 220 observations and 5 columns.</p>
<h3 id="heading-data-exploration-and-visualization"><strong>Data Exploration and Visualization</strong></h3>
<p>We will now try to understand the dataset related to organizational training. The training dataset is created based on surveys conducted before and after training is conducted in an organization.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121747066/2337a344-7c43-472d-b402-ce73684655ff.png" alt class="image--center mx-auto" /></p>
<p>There are 220 observations and five columns. <strong><em>PostTrainingScore</em></strong> and <strong><em>PreTrainingScore</em></strong> are continuous columns, while <strong><em>Gender</em></strong>, <strong><em>Age</em></strong>, and <strong><em>Department</em></strong> are categorical.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121759066/32d7ed5b-915f-4145-a20c-b664775b9eac.png" alt class="image--center mx-auto" /></p>
<p>The occurrences table from the <strong>Statistics</strong> node shows four unique categories for the <strong><em>Department</em></strong> column: ‘Finance’, ‘Human Resource’, ‘Marketing’, and ‘Operations’. Similarly, there are three <strong><em>Age</em></strong> groups: ’21-30’, ’41-60’, and ’31-40’, and two gender groups: ‘Male’ and ‘Female’.</p>
<h3 id="heading-visualizing-categorical-columns"><strong>Visualizing Categorical Columns</strong></h3>
<p>We will use the <strong>Bar Chart</strong> node to generate a count plot for the <strong><em>Department</em></strong>, <strong><em>Age</em></strong>, and <strong><em>Gender</em></strong> columns. The results clearly show that there are more female employees than male employees, most of the employees belong to the 41-60 age group, and all the departments have approximately the same number of employees.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121771277/786ce67a-fa65-46da-ae6e-dfceed492f88.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121783423/1d8bfecb-22b6-4e2d-a268-2f35976d5040.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121798235/a6809aae-4329-497f-9cd1-d94e2278a498.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121811401/33b1eb04-76b7-4977-bb75-39010f3df879.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-visualizing-continuous-columns"><strong>Visualizing Continuous Columns</strong></h3>
<p>We will use the <strong>Line Chart</strong> node to display the <strong><em>PostTrainingScore</em></strong> and <strong><em>PreTrainingScore</em></strong> columns. The results show that the minimum scores of an employee pretraining and post-training are 10 and 12, respectively. The maximum scores of an employee pretraining and post-training are 17 and 20, respectively. The mean scores of employees pretraining and post-training are 14.13 and 16.31, respectively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121824576/ef1a85a7-75bd-4cf5-b6af-dd764ba86cc3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121835772/fd8cfec9-7dd5-4300-b916-f8a9da138439.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-compare-training-effectiveness-using-one-sample-t-test"><strong>Compare Training Effectiveness Using One Sample T-Test</strong></h3>
<p>Objective: To determine the difference between the training score of employees and the desired score</p>
<p>The t-test is a statistical test that compares the sample mean of one group with a standard value. Since only one sample is involved, only the normality assumption must be fulfilled for this test.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121848636/bad3e75d-9538-4ed4-81b2-7df9d09d2507.png" alt class="image--center mx-auto" /></p>
<p>We consider a situation in which an organization has conducted a training program for its employees. It records the scores of employees before and after training. The maximum score is considered to be 20. The organization wants its employees to score 20 after the training. The organization wants to know if there is any significant difference between the actual score of the employees after training and the desired maximum score of 20.</p>
<p>We will first display the observations of the <strong><em>PostTrainingScore</em></strong> column using the <strong>Histogram</strong> node with 10 bins.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121863813/bd90fa51-7cc5-481b-8b63-f2001038d1a2.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121875436/5db86889-bc70-4452-b25c-a2c80f8943f5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121886702/26056f7d-d941-49cf-bba3-6c834ed5ed83.png" alt class="image--center mx-auto" /></p>
<p>The chart shows that the score after training ranges mainly between 12 and 20. The maximum number of employees achieves a score of 16-18. Skewness and kurtosis functions measure the normality of the data. The data are considered normal if skewness and kurtosis coefficients lie between -1 and +1. Since the skewness value is -0.242 and that of kurtosis is -0.63, as obtained from the <strong>Statistics</strong> node, we can say that the data are normal.</p>
<p>The probability plot is generated for observations in the <strong><em>PostTrainingScore</em></strong> column using the <strong>Continuous Probability Distribution</strong> component or <strong>Python View</strong> node using the “scipy.probplot” package. The chart shows that the data can be assumed normal since nearly all the dots lie on the line.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121900389/b8d9445d-e703-45a8-9994-456d793f2c4b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121919948/f2cb904c-3cd6-4834-8d84-fa5140cce0b7.png" alt class="image--center mx-auto" /></p>
<p>We will use the <strong>Single-sample t-test</strong> node to perform a one-sample t-test on the <strong><em>PostTrainingScore</em></strong> column with a test value of 20.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121933925/522ec252-382f-4140-84ad-09ed3109e06d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121950802/262388eb-d634-4fce-bf8d-1baccb995472.png" alt class="image--center mx-auto" /></p>
<p>Since the normality assumption has been met, we can apply the test to the data. To determine whether the two distributions differ significantly from each other, the test that measures the probability associated with the difference between the groups may be either a one-tailed test or a two-tailed test of significance. The test examines whether the mean of one distribution differs significantly from the standard value. We reject the null hypothesis since the p-value equals 0.000, less than 0.05. This means that the value does vary substantially from the value 20.</p>
<p>This means that the employees' scores are significantly different from the 20. Thus, the training could not show a 100% score for all the employees. Based on the results, the organization can design strategies and act accordingly.</p>
<h3 id="heading-compare-training-effectiveness-using-independent-t-test"><strong>Compare Training Effectiveness Using Independent T-Test</strong></h3>
<p>Objective: To determine the difference between training scores of employees of different genders.</p>
<p>The t-test helps compare the population means of only two groups. Thus, it can be conducted to examine whether the population means of the two samples significantly differ. We will evaluate whether there is any difference between the scores of male and female employees.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121963884/a41c350f-7c76-4c2c-a53f-8d7dd6134bee.png" alt class="image--center mx-auto" /></p>
<p>We will use the <strong>Independent group's t-test</strong> node to perform the test on the <strong><em>PostTrainingScore</em></strong> column with <strong><em>Gender</em></strong> as the grouping column. We will also use the <strong>Density Plot</strong> node to create an interactive plot with <strong><em>PostTrainingScore</em></strong> as the dimension column and <strong><em>Gender</em></strong> (male and female) as the condition column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121977066/dfd7dd90-fbd5-40f5-924f-a14c6098dfc4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738121987462/bfb3f5e2-880b-4600-8174-a61afe21718d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122001309/e1826a6c-89e1-448b-afe0-1489efd0d0cc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122013738/4041fcc2-1297-4840-a5fa-4faccc198359.png" alt class="image--center mx-auto" /></p>
<p>We assume the data we have taken in the example above are independent. Thus, the assumption of independent samples is fulfilled. We use Levene’s test to check the homogeneity of variances. If the p-value of the test is greater than 0.05, the assumption of homogeneity of variance is met. From the preceding output, we can see that the p-value is more than the significance level of 0.05 using Levene’s test. This means that the variance across groups is statistically insignificant. Therefore, we assume the homogeneity of variances (equal variances assumed) in the different groups.</p>
<p>A null hypothesis is rejected if the p-value is less than 0.05 at a 5% significance level. Since, in our example, the p-value (0.1842) is greater than 0.05, the null hypothesis is not rejected. This means that the actual difference in the means of male and female groups is equal to 0, which implies that there is no significant difference in the scores of male and female groups.</p>
<h3 id="heading-compare-training-effectiveness-using-dependent-t-test"><strong>Compare Training Effectiveness Using Dependent T-Test</strong></h3>
<p>Objective: To determine the difference between the scores of employees obtained before and after training.</p>
<p>A dependent (paired) t-test is used for dependent samples. If we collect two measurements on each item, person, or experimental unit, each pair of observations is closely related or matched. In this scenario, we apply the paired t-test using the <strong>Paired t-test</strong> node to compare the pre-training and post-training scores.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122030135/73247998-b714-43e5-b4b1-77b9743fef90.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122041467/9b2a0b6a-255c-4104-98e9-7379d4adc33d.png" alt class="image--center mx-auto" /></p>
<p>In our use case, we try to understand whether any significant difference occurred after the training was given. The columns <strong><em>PreTrainingScore</em></strong> and <strong><em>PostTrainingScore</em></strong> represent the scores of employees before and after the training. Since the p-value is 0.000, which is less than 0.05, we failed to reject the null hypothesis, which means that there is a significant difference in the scores of the employees after the training. This further implies that training impacts employees and can be considered helpful.</p>
<h3 id="heading-compare-training-effectiveness-using-one-way-anova"><strong>Compare Training Effectiveness Using One-Way ANOVA</strong></h3>
<p>Objective: To determine the difference between the training scores of employees belonging to different departments</p>
<p>ANOVA (analysis of variance) is a statistical method commonly used in situations where a comparison is made between more than two population means. In ANOVA, the total variation in a dataset is split into two types:  the amount allocated to chance and the amount assigned to particular causes. Its basic principle is to test the variances among population means by assessing the variation within group items proportionate to the variation between groups. It should be noted that within the sample, the variance exists because of the random, unexplained disturbance. However, different reasons may cause a variance between the samples. Using this technique, we test the null hypothesis (H0), wherein all population means are the same, or the alternative hypothesis (H1), wherein at least one population mean is different.</p>
<p>We will now evaluate whether there is any significant difference between employees' scores in different departments.</p>
<p>We will first use the <strong>Color Manager</strong> node to assign specific colors for the categories in the <strong><em>Department</em></strong> column. Subsequently, we will use the <strong>Violin Plot (Plotly)</strong> node to create an interactive plot based on the <strong><em>PostTrainingScore</em></strong> grouped by <strong><em>Department</em></strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122061180/e1b307ab-a296-4387-a824-4e630a1030ea.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122073076/b35040dd-ee80-4f39-a10d-598f810c72aa.png" alt class="image--center mx-auto" /></p>
<p>We will use the <strong>One-way ANOVA</strong> node to test the <strong><em>PostTrainingScore</em></strong> column with <strong><em>Department</em></strong> as the grouping column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122091566/ff3fbc64-f701-45a2-96c3-f463604afb0d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122102959/b2662d01-8963-4056-88bd-892108ac78a5.png" alt class="image--center mx-auto" /></p>
<p>The violin chart shows that the score is nearly the same for employees belonging to all departments. For the ANOVA test, the data are filtered according to the categorical variable from the primary data set and stored in different groups. According to various departments, different groups, namely ‘Finance’, ‘Human Resource’, ‘Marketing’, and ‘Operations’, are formed. The one-way ANOVA result shows that the p-value is 0.2112; hence, we failed to reject the null hypothesis. This means there is no significant difference between the scores of employees belonging to different departments after training.</p>
<h3 id="heading-compare-training-effectiveness-using-anova-with-tukeys-test"><strong>Compare Training Effectiveness Using ANOVA with Tukey’s Test</strong></h3>
<p>Objective: To determine the difference between the training scores of employees belonging to different age groups</p>
<p>From the previous results of the ANOVA test, we can observe that a significant p-value indicates that some of the group means are different, but we do not know which pairs of groups are different. Multiple pairwise comparisons can also determine if the mean difference between specific pairs of groups is statistically significant. We can apply Tukey HSD (Honest Significant Difference) to perform multiple pair-wise comparisons between the means of groups from the “statsmodel.stats” package.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122115341/c0576f3b-dca9-4a1e-826e-f489774d7cf2.png" alt class="image--center mx-auto" /></p>
<p>We will evaluate whether there is any difference between the scores of employees of different age groups. We will use the <strong>Python Script</strong> node with “statsmodels.stats.multicomp” package to test the <strong><em>PostTrainingScore</em></strong> column with <strong><em>Age</em></strong> as the grouping column. We will also use the <strong>Density Plot</strong> node to create an interactive plot with <strong><em>PostTrainingScore</em></strong> as the dimension column and <strong><em>Age</em></strong> as the condition column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122127317/51b82e5f-4e47-4a2a-a527-71146277dc09.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122140181/884b24c3-2a8b-4cb2-84ac-d67f08539384.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122153710/4dd1f22e-d562-4772-a715-4b39faf13ed5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122168448/0169a4b7-fb08-4b39-be40-27f9879f52c3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122180347/485c4c4b-6806-4f06-b869-00ecfa4b916d.png" alt class="image--center mx-auto" /></p>
<p>For the ANOVA test, the data are filtered according to the categorical variable from the primary dataset and stored in different groups. For example, according to different age groups, different groups, namely, first, second, and third, are formed for various age groups. The plot shows that most of the employees belonging to the 21-30 age group had a score of 18. The one-way ANOVA result from the <strong>One-way ANOVA</strong> node shows that the p-value is 0.0058; hence, we reject the null hypothesis. This means that there is a significant difference between the three groups.</p>
<p>Tukey’s test determines individual differences between the different groups formed. For Tukey’s test, the various groups are formed automatically after the information on categorical and continuous variables is collected. The function itself forms groups depending on the values of the categorical variable. For example, the dataset has only 21-30, 31-40, and 41-60 age groups. Tukey’s test shows that since there are three groups representing different age groups, three pairs are formed: (21-30 and 31-40), (21-30 and 41-60), and (31-40 and 41-60). The mean difference values for the three groups are -1.207, -0.957, and 0.25, respectively. The result shows that the null hypothesis is rejected for the last group but not for the first two groups.</p>
<p>This means there is no significant difference in the training scores of the people in age groups 31-40 and 41-60. Thus, the employees of these age groups show similar scores after training. However, the employees in age groups 21-30 and 31-40 show different scores.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In conclusion, evaluating the effectiveness of training programs through comparative statistics is crucial for organizations aiming to enhance employee performance and development. By utilizing statistical techniques such as t-tests and ANOVA, organizations can assess the impact of training across various demographic variables, including gender, age, and department. The analysis of training scores before and after training and comparisons across different groups provides valuable insights into the success of training initiatives. These insights enable organizations to tailor their training strategies to meet desired outcomes and effectively contribute to employee growth and organizational success.</p>
]]></content:encoded></item><item><title><![CDATA[Structuring Employee Rewards Package - Conjoint Analysis]]></title><description><![CDATA[Introduction
Employee psychology is a branch involved in studying employees' behavior and the cognitive process behind how employees perceive various issues. Understanding employee psychology related to the compensation and benefits plans organizatio...]]></description><link>https://vijayv2k.com/structuring-employee-rewards-package-conjoint-analysis</link><guid isPermaLink="true">https://vijayv2k.com/structuring-employee-rewards-package-conjoint-analysis</guid><category><![CDATA[Data Science]]></category><category><![CDATA[data analytics]]></category><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[conjoint]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Tue, 28 Jan 2025 04:54:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122627715/7e420ff8-0daa-40b2-87e5-ab6f58391c16.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Employee psychology is a branch involved in studying employees' behavior and the cognitive process behind how employees perceive various issues. Understanding employee psychology related to the compensation and benefits plans organizations provide is essential. The HR professional needs to understand the utility of different policies for health benefits, flexible schedules, retirement benefits, performance rewards, etc. The objective is to understand what employees consider the most critical benefits elements by individual, group, or segment. A key outcome is determining the relative importance of these benefits, as they impact attraction, retention, and performance levels, and identifying which elements can be cut back or minimized in building benefit programs.</p>
<p>Conjoint analysis is a statistical technique used in research to determine how people value different attributes (features, functions, benefits) related to any concept. It is used to understand the weight of the various attributes related to any plan. Conjoint analysis is generally used to determine which attributes are essential to a person (employee in HR, customer in marketing) and the importance of each attribute.</p>
<p>Conjoint analysis is a technique used to understand the preference or relative importance of various proposed plans related to any particular area. Four important attributes are considered when designing an adequate compensation and benefits plan: work-life balance, performance reward, retirement benefits, and health care benefits. In this article, we will see how conjoint analysis can be used to answer the following questions:</p>
<ol>
<li><p>Which type of retirement benefits is preferred by employees?</p>
</li>
<li><p>What is employees' preference for flexibility in working hours?</p>
</li>
<li><p>Which type of health care benefit is employees’ preference?</p>
</li>
<li><p>Which performance reward system is preferred by employees?</p>
</li>
</ol>
<p>Efforts are being made to understand the weightage given by the employees to each of the attributes and the level related to the compensation and benefits plan. An in-depth analysis of the utility of every combination of compensation and benefits is carried out to determine the importance of each combination.</p>
<h3 id="heading-conjoint-analysis"><strong>Conjoint Analysis</strong></h3>
<p>Conjoint analysis is a valuable approach to measure the value that individuals place on features of a plan or policy. It combines real-life scenarios and statistical techniques with modeling actual decisions. Companies can ask employees to evaluate various factors such as wages, health benefits, flexible schedules, retirement benefits, wellness programs, life insurance, health savings accounts, and medical insurance to implement this approach in rewards.</p>
<p>Conjoint analysis is an excellent tool for answering these types of questions. However, it is essential to understand that conjoint analysis differs from surveys. A survey provides answers related to percentage analysis, such as “47% of employees have a preference for plan A,” “42% want plan B,” and “11% want plan C.”</p>
<p>The objective is to understand what employees consider the most critical benefits elements by individual, group, or segment. A key outcome is determining the relative importance of these benefits, as they impact attraction, retention, and performance levels, and identifying which elements can be cut back or minimized in building benefit programs. These are four types of conjoint analysis:</p>
<ul>
<li><p><strong>Rating-based conjoint:</strong> The respondents are asked to rate the alternatives they are shown. This can be on a scale of 0 to 100. They may be required to allocate scores so that the scores sum to a certain number (e.g., all scores in each question must add up to 100).</p>
</li>
<li><p><strong>Best-worst conjoint:</strong> In each question, the respondents are asked to indicate which option is best and which is the worst among three or more alternatives.</p>
</li>
<li><p><strong>Ranking-based conjoint:</strong> The respondents are asked to rank alternatives from best to worst. It is similar to the best-worst scaling, but the respondents must also allocate rankings to the intermediate options.</p>
</li>
<li><p><strong>Choice-based conjoint:</strong> The respondents are asked which option they will choose. However, this is the most theoretically sound, practical, and popular method of conjoint analysis in the marketing domain.</p>
</li>
</ul>
<h3 id="heading-data-exploration-and-visualization"><strong>Data Exploration and Visualization</strong></h3>
<p>All the employees' data regarding their preference for compensation and benefits were collected. Each employee was asked to give his or her preference for work-life balance for flexible and inflexible hours; for the type of performance rewards related to incentive system, pay plan, and commission; for retirement benefits related to benefits plan and contribution plan; and for health care benefits related to life insurance, medical insurance, and health savings account. Since there were two categories for work-life balance, three for performance rewards, two for retirement benefits, and three for medical benefits, 36 (2x3x2x3) combinations were created.</p>
<p>A conjoint model exposes respondents to combinations described in terms of the same attributes (with varying levels). The employees were asked to rank 36 different compensation and benefits schemes based on their preferences on an ordinal scale from 1 to 10. The rating column corresponds to the average score of all the employees. It should be noted that since there were only 36 different combinations, the employees were requested to evaluate all 36 combinations. However, if there had been more combinations, only the selected and preferred combinations would have been considered for getting the employees' choice.</p>
<h3 id="heading-compensation-benefits-data"><strong>Compensation Benefits Data</strong></h3>
<p>The CompensationBenefits.csv file helps us understand KNIME usage. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder on the KNIME Community Hub.</p>
<blockquote>
<p><em>The</em> <a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj"><em>Structuring Employee Rewards Package - Conjoint Analysis</em></a> <em>workflow can be downloaded from the KNIME Community Hub.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122645945/39eb32af-d311-43a4-bb91-c452d01bc961.png" alt class="image--center mx-auto" /></p>
<p>You are ready after downloading the CSV file from the Data folder.</p>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122841442/2fdbc984-c3ea-4928-a398-8a77d124d28a.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the <strong>CompensationBenefits.csv</strong> CSV dataset. The above table shows that the employee dataset has 36 observations and 5 columns. The names of the five columns are ‘Rating’, ‘WorkLifeBalance’, ‘PerformanceReward’, ‘RetirementBenefits’, and ‘HealthCareBenefits’. It should be understood that the experimental design consists of four attributes: work-life balance, performance reward, retirement benefits, and health benefits. The occurrences table from the <strong>Statistics</strong> node shows that there are two categories in work-life balance: ‘InflexibleHours’, ‘FlexibleHours’; three categories in performance reward: ‘IncentiveSystem’, ‘PayPlan’, ‘Commission’; two categories in retirement benefits: ‘BenefitPlan, ‘ContributionPlan’; and three categories in health benefits: ‘LifeInsurance’, ‘MedicalInsurance’, ‘HealthSavingAccount’.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122859950/9ef00c01-1d06-4041-be02-102011f28991.png" alt class="image--center mx-auto" /></p>
<p>The dataset has 36 combinations, showing the rating for every combination. The highest rating is given to the scheme that has flexible hours and commission for performance rewards. However, retirement benefits can be either a benefit plan or a contribution plan, and health care benefits can be a health savings account or medical insurance.</p>
<h3 id="heading-measure-part-worth-utilities-of-each-level-using-conjoint-analysis"><strong>Measure Part-Worth Utilities of Each Level Using Conjoint Analysis</strong></h3>
<p>Objective: To determine the importance of each level using conjoint analysis</p>
<p>Conjoint analysis is carrying out linear regression where the target variable could be binary (choice-based conjoint analysis) 1-10 Likert scale (rating conjoint analysis), or ranking (rank-based conjoint analysis). The part-worth utilities measure both attribute importance score and level preference score. The beta coefficient of the regression equation helps to calculate the part-worth utility (PWU) of the variants of variables for the attribute importance scores. It should be noted that large part-worth utilities are assigned to the most preferred levels, and small part-worth utilities are assigned to the least preferred levels. In this section, the importance of every predictor variable is determined using the ordinary least squares regression method considering rank-based conjoint analysis.</p>
<p>Part-worth utilities (conjoint analysis utilities) measure attribute importance and level values. The utilities are numerical scores that measure how much each feature influences the decision to make that choice. It should be noted here that the part-worth utilities allow us to have a deeper understanding of which specific features within an attribute influence the choice. Strongly preferred levels are assigned higher scores compared to the less preferred ones.</p>
<p>In this section, conjoint analysis is used to assign utility values for each sublevel of each attribute: performance reward, health care benefits, retirement benefits, and work-life balance. It should be noted that the sublevel getting the highest utility value is the one that the employee most favors for that attribute.</p>
<p>It is known that the ordinary least squares (OLS) model cannot be created on categorical variables. Also, the OLS model works well on binary data; hence, binary dummy data are made using the <strong>One to Many</strong> node. This will create new independent variables for all the categories of independent variables.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122881581/e078d502-0e5c-401b-9922-e8204a6b64d3.png" alt class="image--center mx-auto" /></p>
<p>The <strong>One to Many</strong> node creates new columns according to the number of categories for each variable. Three columns are made since there are three categories for health care benefits (health savings account, life insurance, and medical insurance). Similarly, three new columns are designed for performance rewards, and two are for retirement benefits and work-life balance. The result clearly shows that there are 36 observations with 15 columns. Among these, 10 new columns have binary integer values.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122896819/50d96383-6f37-435c-98fb-00ac30b1a77a.png" alt class="image--center mx-auto" /></p>
<p>In conjoint analysis, one category for each categorical variable is considered a reference, and others are considered dummy variables. For this process, the following dummy and reference variables are created for each attribute:</p>
<ol>
<li><p>“InflexibleHours” is a dummy variable for work-life balance, and “FlexibleHours” is the reference variable.</p>
</li>
<li><p>For health care benefits, “LifeInsurance” and “MedicalInsurance” are dummy variables, and “HealthSavingsAccount” is a reference variable.</p>
</li>
<li><p>For performance reward, “IncentiveSystem” and “PayPlan” are dummy variables, and “Commission” is a reference variable.</p>
</li>
<li><p>“ContributionPlan” is a dummy variable for retirement benefits, and “BenefitPlan” is the reference variable.</p>
</li>
</ol>
<h3 id="heading-dropping-reference-variables"><strong>Dropping Reference Variables</strong></h3>
<p>It is essential to retain only requirement columns for the analysis. Hence, the reference and categorical variables are removed using the <strong>Column Filter</strong> node before creating the regression model. Rating is considered the dependent variable.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122912967/c8610a86-d005-4063-9768-d501041de104.png" alt class="image--center mx-auto" /></p>
<p>After dropping the unwanted columns, the table has 36 rows and 7 columns.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122927265/256b8469-8e12-4a6e-a6c8-f5aaebc6f7a2.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-creating-the-linear-regression-model"><strong>Creating the Linear Regression Model</strong></h3>
<p>The regression model uses the <strong>Linear Regression Learner</strong> node with six independent variables and considers the <strong>Rating</strong> column the dependent variable.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122940950/15514884-342f-47dd-9454-4d1a419d655a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122953634/362eb7f5-66a8-410c-9805-16af3a336452.png" alt class="image--center mx-auto" /></p>
<p>Since we have created one variable as a reference for each category, the value of the coefficients will be considered concerning the base variable. Thus, the results can be interpreted as follows:</p>
<p>Coefficients of independent variables from the regression model and their interpretation</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Independent Variable</strong></td><td><strong>Coefficients</strong></td><td><strong>Interpretation</strong></td></tr>
</thead>
<tbody>
<tr>
<td>InflexibleHours</td><td>-2.1984</td><td>The utility of InflexibleHours is 2.1984 utils less than FlexibleHours.</td></tr>
<tr>
<td>IncentiveSystem</td><td>0.7024</td><td>The utility of the IncentiveSystem is 0.7024 utils more than that of the Commission.</td></tr>
<tr>
<td>PayPlan</td><td>2.2024</td><td>The utility of PayPlan is 2.2024 utils more than the Commission.</td></tr>
<tr>
<td>ContributionPlan</td><td>2.6905</td><td>The ContributionPlan utility is 2.6905 utils more than the BenefitPlan.</td></tr>
<tr>
<td>LifeInsurance</td><td>3.3690</td><td>The utility of LifeInsurance is 3.3690 utils more than the HealthSavingsAccount</td></tr>
<tr>
<td>MedicalInsurance</td><td>3.785</td><td>The utility of MedicalInsurance is 3.785 utils more than the HealthSavingsAccount.</td></tr>
</tbody>
</table>
</div><p>It should be understood that the predictor variable's importance depends on the coefficient's value. Large part-worth utilities are assigned to the most preferred levels, and small part-worth utilities are transferred to the least preferred levels. However, since these coefficients are for the base variable, the next step is determining the utilities of each level of the attributes. This is done by selecting the relative utility of each level separately for each attribute.</p>
<p><strong>Utility of Levels of Work-Life Balance</strong></p>
<p>It is clear from the model that the coefficient of InflexibleHours is -2.1984. Thus, the utilities for both the levels of the work-life balance will be:</p>
<ul>
<li><p>Utility of FlexibleHours = 0 – Average(0,-2.1984) = 0-(-1.0992) = 1.0992</p>
</li>
<li><p>Utility of InflexibleHours = -2.1984 – Average(0,-2.1984) = -2.1984-(-1.0992) = -1.0992</p>
</li>
</ul>
<p>Thus, it is clear that the utility of FlexibleHours + utility of InflexibleHours = 0.</p>
<p><strong>Utility of Levels of Performance Reward</strong></p>
<p>The model shows that the coefficients of IncentiveSystem and PayPlan are 0.7024 and 2.2024, respectively. Thus, the utilities for all the levels of performance reward will be:</p>
<ul>
<li><p>Utility of Commission: 0-Average(0.7024, 2.2024) = 0-0.968 = -0.968</p>
</li>
<li><p>Utility of IncentiveSystem: 0.7024-Average(0, 0.7024, 2.2024) = 0.7024-0.968 = -0.265</p>
</li>
<li><p>Utility of PayPlan: 2.2024-Average(0,0.7024,2.2024) = 2.2024-0.968 = 1.234</p>
</li>
</ul>
<p>Thus, it is clear that the utility of PayPlan + the utility of IncentivePlan + the utility of Commission = 0.</p>
<p><strong>Utility of Levels of Retirement Benefits</strong></p>
<p>The model shows that the coefficients of BenefitPlan and ContributionPlan are 0 and 2.690, respectively. Thus, the equations that can be framed for determining the utilities for both the levels of retirement benefits will be:</p>
<ul>
<li><p>Utility of BenefitPlan: 0-Average(0,2.690) = 0-2.690 = -1.345</p>
</li>
<li><p>Utility of ContributionPlan: 2.690-Average(0,2.690) = 0-2.690 = 1.345</p>
</li>
</ul>
<p>Thus, it is clear that utility of BenefitPlan + utility of ContributionPlan = 0.</p>
<p><strong>Utility of Levels of Health Care Benefits</strong></p>
<p>The model shows that HealthSavingsAccount, LifeInsurance, and MedicalInsurance coefficients are 0, 3.369, and 3.7857, respectively. Thus, the utilities for all the levels of the health care benefits will be:</p>
<ul>
<li><p>Utility of HealthSavingsAccount: 0-Average(0,3.369,3.7857) = 0-2.3849 = -2.3849</p>
</li>
<li><p>Utility of LifeInsurance: 3.369-Average(0,3.369,3.7857) = 3.369-2.3849 = 0.9841</p>
</li>
<li><p>Utility of MedicalInsurance: 3.7857-Average(0,3.369,3.7857) = 3.7857-2.3849 = 1.4008</p>
</li>
</ul>
<p>Thus, it is clear that the utility of HealthSavingsAccount + utility of LifeInsurance + utility of MedicalInsurance = 0.</p>
<p>The above calculations are performed using various data manipulation nodes, which are then combined into the <strong>Utility Value of Levels</strong> meta node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122972594/2d1956b5-00bb-4bca-9103-92f83efbdac4.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738122988617/ceac1c3d-b28e-4891-aaec-c5fd4cddaf5f.png" alt class="image--center mx-auto" /></p>
<p>The resultant table provides the <strong><em>Utility</em></strong> value of each <strong><em>Level</em></strong> of the <strong><em>Attribute</em></strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123002262/ef44d888-8379-464c-a934-4ae20163de8e.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-utility-of-all-the-levels-of-each-attribute"><strong>Utility of All the Levels of Each Attribute</strong></h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Attribute</strong></td><td><strong>Level</strong></td><td><strong>Beta Coefficient</strong></td><td><strong>Utility</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Work-life Balance</td><td>FlexibleHours</td><td>0</td><td>1.0992</td></tr>
<tr>
<td></td><td>InflexibleHours</td><td>-2.1984</td><td>-1.0992</td></tr>
<tr>
<td>Performance Reward</td><td>Commission</td><td>0</td><td>-0.968</td></tr>
<tr>
<td></td><td>IncentiveSystem</td><td>0.7024</td><td>-0.266</td></tr>
<tr>
<td></td><td>PayPlan</td><td>2.2024</td><td>1.234</td></tr>
<tr>
<td>Retirement Benefits</td><td>BenefitsPlan</td><td>0</td><td>-1.345</td></tr>
<tr>
<td></td><td>ContributionPlan</td><td>2.6905</td><td>1.345</td></tr>
<tr>
<td>Healthcare Benefits</td><td>HealthSavingsAccount</td><td>0</td><td>-2.385</td></tr>
<tr>
<td></td><td>LifeInsurance</td><td>3.369</td><td>0.984</td></tr>
<tr>
<td></td><td>MedicalInsurance</td><td>3.7857</td><td>1.401</td></tr>
</tbody>
</table>
</div><h3 id="heading-displaying-the-utilities-of-each-category"><strong>Displaying the Utilities of Each Category</strong></h3>
<p>We will use the <strong>Python View</strong> node to generate a subplot chart displaying the utility of different plans/levels of each attribute.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># This script plots a histogram using matplotlib and assigns it to the output view</span>
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO

<span class="hljs-comment"># Creating subplot chart for displaying the utilities of each category</span>
fig = plt.figure(figsize=(<span class="hljs-number">20</span>,<span class="hljs-number">20</span>))
plt.subplot(<span class="hljs-number">221</span>)
plt.bar([<span class="hljs-string">"Flexible Hours"</span>,<span class="hljs-string">"Inflexible Hours"</span>],[<span class="hljs-number">1.0992</span>,<span class="hljs-number">-1.0992</span>])
plt.title(<span class="hljs-string">"Work Life Balance"</span>)
plt.subplot(<span class="hljs-number">222</span>)
plt.bar([<span class="hljs-string">"Commission"</span>,<span class="hljs-string">"Incentive System"</span>,<span class="hljs-string">"Pay Plan"</span>],[<span class="hljs-number">-0.968</span>,<span class="hljs-number">-0.266</span>,<span class="hljs-number">1.234</span>])
plt.title(<span class="hljs-string">"Performance Reward"</span>)
plt.subplot(<span class="hljs-number">223</span>)
plt.bar([<span class="hljs-string">"Benefits Plan"</span>,<span class="hljs-string">"Contribution Plan"</span>],[<span class="hljs-number">-1.345</span>,<span class="hljs-number">1.345</span>])
plt.title(<span class="hljs-string">"Retirement Benefits"</span>)
plt.subplot(<span class="hljs-number">224</span>)
plt.bar([<span class="hljs-string">"Health Saving Account"</span>,<span class="hljs-string">"Life Insurance"</span>,<span class="hljs-string">"Medical Insurance"</span>],[<span class="hljs-number">-2.385</span>,<span class="hljs-number">0.984</span>,<span class="hljs-number">1.401</span>])
plt.title(<span class="hljs-string">"Health Care"</span>)
plt.suptitle(<span class="hljs-string">"Utility of Different Plans"</span>)

<span class="hljs-comment"># Create buffer to write into</span>
buffer = BytesIO()

<span class="hljs-comment"># Create plot and write it into the buffer</span>
fig.savefig(buffer, format=<span class="hljs-string">'svg'</span>)

<span class="hljs-comment"># The output is the content of the buffer</span>
output_image = buffer.getvalue()

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)  <span class="hljs-comment"># alternative: knio.view_matplotlib()</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123021010/2eca1a36-933f-42f2-88dc-34a09872838d.png" alt class="image--center mx-auto" /></p>
<p>It is clear from the chart and summary of the model that the utility of flexible hours is more than that of inflexible hours; the utility pay plan is more than that of the commission and incentive system; the utility of the contribution plan is more than that of benefits plan; and the utility of medical insurance is more than that of life insurance and health savings account. Hence, these are considered preferred variables by the employees. The higher the value, the higher the importance of that attribute in employees' perception. Since, for the work-life balance attribute, the flexible hours level has the maximum utility, and for the performance reward attribute, the pay plan level has the maximum utility, this means that when selecting compensation and benefits plan by the employees, the highest preference is given to flexible hours and pay plan.</p>
<p>It should be noted that the HR professional will prefer a scheme that maximizes utility. This will lead to employee satisfaction with the organization. The figures show that performance rewards with incentive systems, pay plans, and health care benefits with health savings accounts and life insurance are the least preferred approaches.</p>
<h3 id="heading-measure-part-worth-utilities-of-each-attribute-using-conjoint-analysis"><strong>Measure Part-Worth Utilities of Each Attribute Using Conjoint Analysis</strong></h3>
<p>Objective: To determine the importance of each attribute using conjoint analysis</p>
<p>We need to determine to what extent each component (attribute) contributes to the total utility of the plan. What is more important for the employees should be known- health care benefits, performance rewards, work-life balance, or retirement benefits- and how much weight should be given to these attributes. It provides us with an idea about which attribute is most important. In this section, we will first determine the utility values for each attribute (performance reward, retirement benefits, work-life balance, and health care benefits). The utility per attribute is the range of coefficients in a feature. The difference between the maximum and minimum utility of variants calculates the range. The total utility is computed by determining the sum of all partial utilities. The relative importance per feature is calculated by dividing the utility of each level by the total utilities. Thus,</p>
<ul>
<li><p>Range = Maximum(Utility of variants) – Minimum(Utility of variants)</p>
</li>
<li><p>Importance of attribute = Range of attribute/Total range of all attributes</p>
</li>
</ul>
<p>The above calculations are performed using various data manipulation nodes, which are then combined into the <strong>Attribute Importance</strong> meta-node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123035978/afb0e469-dcbc-4c6a-b39b-0f2a0f1f485c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123048596/67f94ce1-61f9-421d-8c00-f2d66bec8720.png" alt class="image--center mx-auto" /></p>
<p>The resultant table provides the Relative importance of all attributes as shown in the <strong><em>AttributeImportance</em></strong> column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123064867/aab1a0c7-8350-4084-963a-0f43d8c4ff0e.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-pie-chart-depicting-the-significance-of-attributes"><strong>Pie Chart Depicting the Significance of Attributes</strong></h3>
<p>We will use the <strong>PieChart</strong> node to generate an interactive chart depicting the importance of the attributes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123077235/51dc5e6f-2ea7-430d-8472-3da60b4043d3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123091444/5b7ae254-a5f8-4e3d-9094-f3a44fee1bbb.png" alt class="image--center mx-auto" /></p>
<p>The total range of all attributes is 10.877. Hence, the importance of work-life balance, performance rewards, retirement benefits, and health care benefits is 20%, 20%, 24.7%, and 34.8%, respectively. The results clearly show that the employees gave the maximum preference to health care benefits.</p>
<h3 id="heading-compare-different-compensation-and-benefits-plans"><strong>Compare Different Compensation and Benefits Plans</strong></h3>
<p>Objective: To determine the total utilities of different plans for compensation and benefits</p>
<p>To arrive at the total utility value of all 36 plans, we perform the calculations using various data manipulation nodes combined into the <strong>Total Utility</strong> meta-node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123104609/a028632a-620f-4cd5-acf0-9ab93dcdba40.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123117117/98e61870-edfc-425f-92c2-6806c37252d3.png" alt class="image--center mx-auto" /></p>
<p>This section determines the total utility, as represented by the <strong><em>TotalUtility</em></strong> column, of all 36 plans related to compensation and benefits that can be executed. It should be noted that the attribute and sublevel getting the highest utility value will be most favored by employees. The total utility of each plan is the sum of the utilities of each criterion. Thus, the total utility of the plan with inflexible hours, incentive system, benefit plan, and life insurance is the sum of their utilities.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123130758/dccd199f-8467-49a8-889b-c39bf1530214.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-listing-top-five-plans"><strong>Listing Top Five Plans</strong></h3>
<p>We will use the <strong>Top k-row Filter</strong> node to find the top 5 plans by <strong><em>TotalUtility</em>.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123148342/de97efd0-9ef4-4d31-b6f4-02d40c4db032.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738123160977/0c6d3317-10d2-4ec1-a4dd-c2777f40b5af.png" alt class="image--center mx-auto" /></p>
<p>It is clear from the results that the highest utility (5.079) is for flexible hours choice in work-life balance, pay plan in performance reward, contribution plan in retirement, and medical insurance in health care benefits. The second highest utility (4.663) is for flexible hours choice in work-life balance, pay plan in performance reward, contribution plan in retirement, and life insurance in health care benefits. The lowest utility (-5.798) is for inflexible hours, choice in work-life balance, commission in performance reward, benefit plan in retirement, and health savings account in health care benefits. Hence, the organization can decide strategies accordingly. This will help improve employees' satisfaction level and make them happy with the organization’s policies, thereby contributing to their better performance and finally fulfilling the organization’s objectives.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In conclusion, structuring an employee rewards package using conjoint analysis provides a comprehensive understanding of employee preferences regarding compensation and benefits. By evaluating attributes such as work-life balance, performance rewards, retirement benefits, and health care benefits, organizations can identify which elements are most valued by employees. This approach allows HR professionals to design benefit programs that maximize employee satisfaction and retention. The analysis reveals that employees highly prefer flexible working hours, pay plans, contribution plans, and medical insurance. By aligning reward packages with these preferences, organizations can effectively enhance employee satisfaction, improve performance, and achieve organizational objectives.</p>
]]></content:encoded></item><item><title><![CDATA[Reviewing Employee Details – Data Visualization]]></title><description><![CDATA[Introduction
The HR department needs to frame strategies that benefit the employees and do not create complexity in understanding data. The HR professional must understand the data before making decisions or performing advanced analysis. Thus, employ...]]></description><link>https://vijayv2k.com/reviewing-employee-details-data-visualization</link><guid isPermaLink="true">https://vijayv2k.com/reviewing-employee-details-data-visualization</guid><category><![CDATA[Data Science]]></category><category><![CDATA[data analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[DataVisualization]]></category><category><![CDATA[dataviz]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Mon, 27 Jan 2025 17:34:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124050247/77004b8a-f1ba-4905-aea5-1cb8d1bc23cf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>The HR department needs to frame strategies that benefit the employees and do not create complexity in understanding data. The HR professional must understand the data before making decisions or performing advanced analysis. Thus, employee data exploration starts with organizing data into a highly usable and valuable resource and extracting information to improve the functioning of the HR department. Through data visualization, the HR professional can better understand the dynamics of the employee data across multiple dimensions. This chapter discusses different visualization techniques in KNIME that help to analyze and visualize data according to the requirement.</p>
<h3 id="heading-employee-data"><strong>Employee Data</strong></h3>
<p>To understand the usage of KNIME, the IBMdata.csv data for HR Analytics is considered. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder on the KNIME Community Hub.</p>
<blockquote>
<p><a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj"><em>The Reviewing Employee Details – Data Visualization</em></a> <em>workflow can be downloaded from the KNIME Community Hub.</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124086164/f67ec3ae-4fb6-4c73-8c56-8314754fc106.png" alt class="image--center mx-auto" /></p>
<p>You are ready after downloading the CSV file from the Data folder.</p>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124101400/971a0c91-ca8a-4d12-bb3d-f4ed2c261cca.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the IBMdata CSV dataset. The above table shows that the employee dataset has 1470 observations and 35 columns. Most columns are integers, and some, such as <strong>Gender</strong>, <strong>JobRole</strong>, <strong>MaritalStatus</strong>, etc., are string columns.</p>
<h3 id="heading-distribution-of-employees-by-department"><strong>Distribution of Employees by Department</strong></h3>
<p>Objective: To create a pie chart corresponding to the department</p>
<p>Pie charts visualize the absolute and relative frequencies. A pie chart is a circle partitioned into segments where each of the segments represents a category. The size of each segment depends upon the relative frequency and is determined by the angle. A pie chart represents values as slices of a circle with different colors.</p>
<p>We will use the <strong>Pie Chart</strong> node to plot the number &amp; percentage of employees in each <strong><em>Department</em></strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124121529/048b405e-8853-4420-a50a-cfa3f9d4a9d6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124137013/52dbe375-d599-4733-a99a-5ef766609d27.png" alt class="image--center mx-auto" /></p>
<p>The interactive pie chart shows the employee distribution of the three different departments.</p>
<h3 id="heading-filter-subset-observations-for-the-hr-department"><strong>Filter / Subset observations for the HR Department</strong></h3>
<p>For our data visualization, we will consider only employees belonging to the HR department. We can use the <strong>Row Filter</strong> node to filter out the observations for the “Human Resources” <strong><em>Department</em></strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124150677/7fc706cb-8d2b-45cd-8622-9b09bd10921c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124170737/f5124495-8d4d-4544-84a8-8c23aaabc662.png" alt class="image--center mx-auto" /></p>
<p>The filtered table shows that the employee dataset for the HR department has 63 observations and 35 columns.</p>
<h3 id="heading-data-visualization-using-bar-chart"><strong>Data Visualization using Bar Chart</strong></h3>
<p>Objective: To create an interactive bar chart to display category-wise count for the number of years since the last promotion</p>
<p>The count function of the bar chart is used to show the number of observations corresponding to the different values of the specified column. To begin with, we will use the <strong>Number to String</strong> node to convert the <strong><em>YearsSinceLastPromotion</em></strong> from integer to string. Then, we will use the <strong>Sorter</strong> node to order the table in ascending order of the <strong><em>YearsSinceLastPromotion</em></strong> column. Subsequently, we will use the <strong>Bar Chart</strong> node to create charts showing count (aggregation) values for <strong><em>YearsSinceLastPromotion</em></strong> for HR department employees.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124186373/abb3ba32-b534-4d89-8546-635ba9ed7079.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124199809/31d3d0a1-b593-4b70-a297-8ffcfc30e13e.png" alt class="image--center mx-auto" /></p>
<p>The figure shows 24 observations corresponding to 0 years, 17 observations corresponding to 1 year, eight observations corresponding to 2 years, three observations corresponding to 3, 4, 5, and 7 years, and one observation for 10 and 12 years. The higher value of categorical columns corresponding to the maximum frequency of observations is displayed at the top. The chart shows that the organization has effective promotion policies because most employees are given promotions within 1 year.</p>
<h3 id="heading-data-visualization-using-line-plot"><strong>Data Visualization using Line Plot</strong></h3>
<p>Objective: To create a line chart corresponding to the hourly rate</p>
<p>We will use the <strong>Line Plot</strong> node to create an interactive line chart based on the <strong><em>HourlyRate</em></strong> of employees in the HR department.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124215547/d0d76198-e535-44f9-885a-063e055f554e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124231206/98ec606b-96c2-407f-9f7d-20ab04427aa3.png" alt class="image--center mx-auto" /></p>
<p>The line chart shows employees' hourly rates range from 30 to 100. However, it should be noted that the line chart is effective for time series data. Here, it is drawn based on row number, which does not signify any vital meaning. The intention is to familiarize the user with the concept of a line chart.</p>
<h3 id="heading-data-visualization-using-multiple-bar-chart"><strong>Data Visualization using Multiple Bar Chart</strong></h3>
<p>Objective: To create an interactive bar chart for different continuous columns according to gender</p>
<p>We will use the <strong>Bar Chart</strong> node to create multiple charts showing average (aggregation) values for <strong><em>Age</em></strong>, <strong><em>HourlyRate</em></strong>, <strong><em>TotalWorkingYears</em></strong>, and <strong><em>YearsAtCompany</em></strong>, with <strong><em>Gender</em></strong> as the category dimension column for HR department employees.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124245293/4a089875-d2f0-423a-b35d-9deeafbc2b4d.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124261254/9ff7e9e4-db80-49a3-b2dc-4eda8d3e38b5.png" alt class="image--center mx-auto" /></p>
<p>The output shows a pair of four-bar charts corresponding to four columns, one bar for each category. The chart shows that male and female employees have nearly the same average total experience and age. The average hourly rate of males is higher than that of female employees. Male employees have spent more years with the company than female employees.</p>
<h3 id="heading-data-visualization-using-correlation-matrix"><strong>Data Visualization using Correlation Matrix</strong></h3>
<p>Objective: To create a correlation matrix plot for multiple columns</p>
<p>We will use the <strong>Linear Correlation</strong> node to generate a correlation matrix heatmap based on a selected set of columns for HR department employees.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124274700/f2511427-83fb-4fb3-8ca4-d1238b6d37d7.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124290895/843ffa1d-2f08-4d92-9886-c544af964506.png" alt class="image--center mx-auto" /></p>
<p>The squared table shows the pair-wise correlation values of all columns. The color range varies from dark red (strong negative correlation) to dark blue (strong positive correlation). If a correlation value for a pair of columns is unavailable, the corresponding cell contains a missing value (shown as a cross in the color view). Hovering the mouse over each box in the views window will display the corresponding pair-wise correlation value.</p>
<h3 id="heading-data-visualization-using-box-plot"><strong>Data Visualization using Box Plot</strong></h3>
<p>Objective: To create an interactive box plot for daily rate by education field</p>
<p>We will use the <strong>Box Plot</strong> node to create an interactive plot based on the<strong><em>DailyRate</em></strong>, with <strong><em>EducationField</em></strong> as the condition column for HR department employees.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124309004/4828e1ca-4655-4d7d-97c6-c10990337d77.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124324578/5598bb7f-ccd5-46bb-8994-9c9c31d6e7a3.png" alt class="image--center mx-auto" /></p>
<p>A box plot describes the distribution of a continuous variable by plotting the summary of the following statistical terms: The box itself goes from the lower quartile (Q1) to the upper quartile (Q3). The median is drawn as a horizontal bar inside the box. The distance between Q1 and Q3 is called interquartile range (IQR). Above and below the box are the so-called whiskers. They are drawn at the minimum and maximum value as horizontal bars and are connected with the box with a line.</p>
<p>The figure shows the general structure of an interactive box plot. The box plot is drawn for daily rate for education fields. There are five categories in education: medical, human resources, life sciences, technical degree, and others. Hence, five boxes are shown in the figure corresponding to these five categories. We can determine the minimum and maximum values along with the first and third quartiles. It is clear from the chart that the median value of the daily rate is highest for “other” while it is the least for “Technical Degree”. The interquartile range of daily rate is highest in “Life Sciences”. The lowest daily rate is for “Human Resources”.</p>
<h3 id="heading-data-visualization-using-violin-plot"><strong>Data Visualization using Violin Plot</strong></h3>
<p>Objective: To create an interactive violin plot for gender for years in the current role</p>
<p>We will first use the <strong>Color Manager</strong> node to assign specific colors for the categories (male and female) in the <strong><em>Gender</em></strong> column. Subsequently, we will use the <strong>Violin Plot (Plotly)</strong> node to create an interactive plot based on the<strong><em>YearsInCurrentRole</em></strong> grouped by <strong>Gender</strong> (male and female) for employees in the HR department.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124338365/7674710d-6859-4cc0-969f-9e35d6cf4ed9.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124351180/b7c0913c-96d2-441d-81ba-20f4368b3ba3.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124364714/ffa47687-754f-4b12-aff2-19ebf26ef8b4.png" alt class="image--center mx-auto" /></p>
<p>The violin plot combines a box plot and a kernel density plot. The violin chart draws a shape depending on the frequency. Like a box plot, an interactive violin plot can produce multiple violins corresponding to different values of a categorical column. We can observe from the chart's shape that the maximum number of female employees spent 2 years in their current role, while the maximum number of male employees spent 3 years in their current role.</p>
<h3 id="heading-data-visualization-using-density-plot"><strong>Data Visualization using Density Plot</strong></h3>
<p>Objective: To create an interactive density plot for years at the company by gender</p>
<p>We will use the <strong>Color Manager</strong> node configured earlier to assign specific colors for the categories (male and female) in the <strong><em>Gender</em></strong> column. Subsequently, we will use the <strong>Density Plot</strong> node to create an interactive plot with <strong><em>YearsAtCompany</em></strong> as the dimension column and <strong><em>Gender</em></strong> (male and female) as the condition column for employees in the HR department.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124376412/81a467e9-8dbe-49ec-8f11-6659c45de3ad.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124389999/ea1c789f-342f-4599-b483-cdaef487243f.png" alt class="image--center mx-auto" /></p>
<p>A kernel density estimate plot is a method for visualizing the distribution of observations in a dataset analogous to a histogram. KDE represents the data using a continuous probability density curve in one or more dimensions. The plot shows that male employees have spent more years in the HR department.</p>
<h3 id="heading-data-visualization-using-scatter-plot"><strong>Data Visualization using Scatter Plot</strong></h3>
<p>Objective: To create an interactive scatter plot for age and total working years by gender</p>
<p>We will use the <strong>Color Manager</strong> node configured earlier to assign specific colors for the categories (male and female) in the <strong><em>Gender</em></strong> column. Subsequently, we will use the <strong>Scatter Plot</strong> node to create an interactive plot based on <strong><em>Age</em></strong> and <strong><em>TotalWorkingYears</em></strong> with <strong><em>Gender</em></strong> (male and female) as the color dimension for employees in the HR department.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124402197/50c23884-a212-4ca4-96c3-855516abd9e6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124413814/b872301f-faf8-4bd1-8c74-cee53b629ee4.png" alt class="image--center mx-auto" /></p>
<p>The figure shows a scatter plot for age to total working years. The pattern indicates that a line covers the maximum points. The other points lie near the line. The chart shows that working years also increase with increasing age.</p>
<h3 id="heading-data-visualization-using-scatter-plot-matrix"><strong>Data Visualization using Scatter Plot Matrix</strong></h3>
<p>Objective: To create a scatter plot matrix for age, hourly rate, daily rate, and distance from home.</p>
<p>We will use the <strong>Color Manager</strong> node configured earlier to assign specific colors for the categories (male and female) in the <strong><em>Gender</em></strong> column. Subsequently, we will use the <strong>Scatter Plot Matrix</strong> node to create a pair-wise scatter plot matrix of <strong><em>Age</em></strong>, <strong><em>DailyRate</em></strong>, <strong><em>HourlyRate</em></strong>, and <strong><em>DistanceFromHome</em></strong> columns with <strong><em>Gender</em></strong> (male and female) as the color dimension for employees in the HR department.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124426668/7ab06fa4-a86d-4d4d-9b59-a34b4264d952.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124439020/fb286ad4-5ff7-43ff-b7aa-7147b5efcbc2.png" alt class="image--center mx-auto" /></p>
<p>The figure shows a pair plot considering all the possible combinations for the four columns. Since there are four variables (n), a matrix of 3x3 images (n-1) is created. The scatter plot is drawn for every combination of two variables.</p>
<h3 id="heading-data-visualization-using-matplotlib"><strong>Data Visualization using Matplotlib</strong></h3>
<p>Objective: To create a shape chart corresponding to monthly income.</p>
<p>For this purpose, we will create a table with the <strong>Table Creator</strong> node containing four series of monthly income data. We will use the Matplotlib visualization library in the <strong>Python View</strong> node to create a custom chart. In the figure, we plot multiple lines with different shapes and colors. We can observe that for every x, y pair of arguments, there is an optional third argument, which is the format string that indicates the concatenation of a color string with a line-style string. Thus, the first line, <strong><em>Series1</em></strong>, is drawn using green triangles (g^); the second line, <strong><em>Series2</em></strong>, is drawn using blue squares (bs); the third line, <strong><em>Series3</em></strong>, is drawn using red dashes (r--); the fourth line, <strong><em>Series4</em></strong>, is drawn using magenta dots (mo).</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> knime.scripting.io <span class="hljs-keyword">as</span> knio

<span class="hljs-comment"># Code to display multiple lines with different shapes and colors</span>
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> io <span class="hljs-keyword">import</span> BytesIO

df = knio.input_tables[<span class="hljs-number">0</span>].to_pandas() 

<span class="hljs-comment"># Plotting </span>
fig = plt.figure(figsize=(<span class="hljs-number">15</span>,<span class="hljs-number">8</span>))
plt.suptitle(<span class="hljs-string">'Multiple Lines with Different Shapes and Colors'</span>,
fontsize=<span class="hljs-number">20</span>, fontweight=<span class="hljs-string">'bold'</span>)


<span class="hljs-comment"># Creating a chart with different colors and effects for different series</span>
plt.plot(df[<span class="hljs-string">'List'</span>], df[<span class="hljs-string">'Series1'</span>], <span class="hljs-string">'g^'</span>, 
         df[<span class="hljs-string">'List'</span>], df[<span class="hljs-string">'Series2'</span>], <span class="hljs-string">'bs'</span>,
         df[<span class="hljs-string">'List'</span>], df[<span class="hljs-string">'Series3'</span>], <span class="hljs-string">'r--'</span>, 
         df[<span class="hljs-string">'List'</span>], df[<span class="hljs-string">'Series4'</span>], <span class="hljs-string">'mo'</span>)

plt.xlabel(<span class="hljs-string">'List'</span>)
plt.ylabel(<span class="hljs-string">'Values'</span>)
plt.title(<span class="hljs-string">'Multiple Series Plot'</span>)
plt.show()


<span class="hljs-comment"># Setting limits of x-axis</span>
plt.xlim(<span class="hljs-number">0</span>,<span class="hljs-number">10</span>)

<span class="hljs-comment"># Setting limits for y-axis</span>
plt.ylim(<span class="hljs-number">0</span>,<span class="hljs-number">220</span>)

<span class="hljs-comment"># Displaying grid in chart</span>
plt.grid(<span class="hljs-literal">True</span>,color=<span class="hljs-string">'k'</span>)

<span class="hljs-comment"># Create buffer to write into</span>
buffer = BytesIO()

<span class="hljs-comment"># Create plot and write it into the buffer</span>
fig.savefig(buffer, format=<span class="hljs-string">'svg'</span>)

<span class="hljs-comment"># The output is the content of the buffer</span>
output_image = buffer.getvalue()

<span class="hljs-comment"># Assign the figure to the output_view variable</span>
knio.output_view = knio.view(fig)  <span class="hljs-comment"># alternative: knio.view_matplotlib()</span>
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124455439/fca13292-f4f6-4038-be17-7d2dd0efa8de.png" alt class="image--center mx-auto" /></p>
<p>Alternatively, we can plot the four series of monthly income using the Line Plot node, with each series in a different color line.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124467857/73d8912b-0d8b-4aa8-874e-833539ac5c24.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124479432/9d7b3224-791a-49f5-9336-73be6da89e92.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-data-visualization-using-stacked-area-chart"><strong>Data Visualization using Stacked Area Chart</strong></h3>
<p>Objective: To create an area chart for expenses of different months in four years.</p>
<p>For this purpose, we will create a table with the <strong>Table Creator</strong> node containing four years of monthly expense data. Subsequently, we will use the <strong>Stacked Area Chart</strong> node to create a stacked area chart visualization of the monthly expense data, with each year stacked one above the other. The difference between a stacked bar chart and an area chart is that the values are represented as cumulative values in a stacked bar chart. In contrast, an area chart defines them as individual values. These charts can track changes over time for two or more related groups that comprise one whole category.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124492890/51b55dc4-ece0-46d8-a137-7ae04dc3e000.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738124504580/77207922-98ae-4133-9b80-95a77f1462e1.png" alt class="image--center mx-auto" /></p>
<p>The chart shows the total expenses for 12 months and each year. Thus, we can observe that the costs for 2013 are the highest since the area occupied is more than the expenses of any other year.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In this example, we explored using KNIME for hands-on data visualization. Working with the IBMdata.csv dataset and various KNIME charting and plotting nodes enabled us to interpret data for better understanding and extracting crucial insights.</p>
]]></content:encoded></item><item><title><![CDATA[Analyzing Employee Details – Data Exploration & Manipulation]]></title><description><![CDATA[Introduction
Organizations have a vast amount of employee data. The HR personnel in these organizations must understand these data and use basic statistical techniques to formulate effective strategies. They can use statistical methods such as mean, ...]]></description><link>https://vijayv2k.com/analyzing-employee-details-data-exploration-manipulation</link><guid isPermaLink="true">https://vijayv2k.com/analyzing-employee-details-data-exploration-manipulation</guid><category><![CDATA[Data Science]]></category><category><![CDATA[dataanalytics]]></category><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[exploratory data analysis]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Mon, 27 Jan 2025 16:22:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125180683/c8253e0f-b122-448d-b5a8-ba77b3b77c34.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>Organizations have a vast amount of employee data. The HR personnel in these organizations must understand these data and use basic statistical techniques to formulate effective strategies. They can use statistical methods such as mean, median, correlation, etc.; mathematical techniques such as minimum, maximum, etc.; and string operations such as concatenating data, modifying/updating records, etc. These basic techniques help the HR professional to have a better understanding of the data. This chapter discusses different functions in KNIME that help to analyze and manipulate data according to the requirement.</p>
<h3 id="heading-employee-data"><strong>Employee Data</strong></h3>
<p>To understand the usage of KNIME, the IBMdata.csv for HR Analytics is considered. This dataset can be downloaded from the “<a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Hands-on%20HR%20Analytics%20with%20KNIME/Data~gLvY8lmS5x6DT7Ag/">Data</a>” folder from the KNIME Community Hub.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125196524/c395237f-723f-4182-984b-bfb83f8cb9e5.png" alt class="image--center mx-auto" /></p>
<p>You are ready after downloading the CSV file from the Data folder.</p>
<blockquote>
<p><em>You can download the</em> <a target="_blank" href="https://hub.knime.com/s/fe-9EOmBKCzvK-Lj">02 Analyzing Employee Details - Data Exploration &amp; Manipulation</a> <em>workflow from the KNIME Community Hub</em></p>
</blockquote>
<h3 id="heading-reading-the-csv-based-dataset"><strong>Reading the CSV-based dataset</strong></h3>
<p>The first step in our analysis will be to load the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our analysis in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125212344/6b4f6d56-d485-4ccf-9b64-477df8dfff56.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the IBMdata CSV dataset.</p>
<p>The above table shows that the employee dataset has 1470 observations and 35 columns. Most columns are integers, and some, such as <strong><em>Gender</em></strong>, <strong><em>JobRole</em></strong>, <strong><em>MaritalStatus</em></strong>, etc., are string columns.</p>
<h3 id="heading-data-exploration-and-descriptive-summary-statistics"><strong>Data Exploration and Descriptive Summary Statistics</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125227721/b71a1212-a84b-4370-afbf-de6bc6b75096.png" alt class="image--center mx-auto" /></p>
<p>The <strong>Statistics</strong> node primarily determines the descriptive summary statistics of the columns in the dataset. This node calculates statistical moments such as minimum, maximum, mean, standard deviation, variance, median, overall sum, number of missing values, and row count across all numeric columns. It counts all nominal values together with their occurrences. The node provides the following three output tables</p>
<ol>
<li><p>Statistics Table: All statistic moments for all numeric columns,</p>
</li>
<li><p>Nominal Histogram Table: Nominal values for all selected categorical columns and</p>
</li>
<li><p>Occurrences Table: The most frequent/infrequent values from the categorical columns (Top/bottom)</p>
</li>
</ol>
<p>The <strong>Data Explorer</strong> node offers various options for displaying the properties of the input data in an interactive view.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125241418/3183ea2e-c193-492d-8d89-558e6dbef3c7.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125254335/1681abd7-a56c-43b7-8789-c26d618be744.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-data-manipulation-of-string-columns"><strong>Data Manipulation of String Columns</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125267168/5d7232df-3884-41a2-bbc9-a611d959309c.png" alt class="image--center mx-auto" /></p>
<p><strong>Joining of Strings</strong></p>
<p>Objective: To display the employee details using concatenation of <strong><em>Department</em></strong> and <strong><em>EducationField</em></strong> string columns</p>
<p>A new <strong><em>CombinedString</em></strong> column can be created by concatenation (combining) of different strings. The strings can be combined by using the <strong>Join</strong> function of the <strong>String Manipulation</strong> node.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125282720/1ff3fbdc-1695-4f60-8fd0-b73be247eaab.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125296709/00c5a533-7257-41dd-8bce-27c6dbe294e6.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-case-conversion-of-strings"><strong>Case Conversion of Strings</strong></h3>
<p>Objective: To display the employee details in capitalized, uppercase, and lowercase format.</p>
<p>In the <strong>String Manipulation</strong> node, the <strong>capitalize (str)</strong> function capitalizes all whitespace-separated words in a string so that each word comprises a title-case character and then a series of lowercase characters.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125310808/4109df1d-bee5-444e-8f7b-98bb86370045.png" alt class="image--center mx-auto" /></p>
<p>We apply the capitalize function on the <strong><em>CombinedString</em></strong> column to create the <strong><em>CapCombinedString</em></strong> column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125328053/c4ae26b0-6fdd-4e1c-abcd-3533992275d6.png" alt class="image--center mx-auto" /></p>
<p>The <strong>uppercase(str)</strong> and <strong>lowercase(str)</strong> functions convert all the characters in a string into uppercase and lowercase, respectively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125341236/2c18c7e3-72fe-45ed-9598-658ef59a88a5.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125354840/43806262-5e14-4aca-abdb-258d13644323.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-search-and-replace-of-string"><strong>Search and Replace of String</strong></h3>
<p>Objective: To search for a particular string and replace it with another</p>
<p>The <strong>replace(str, search, replace)</strong> function of the String Manipulation node replaces all occurrences of a String within another String. In our <strong><em>CombinedString</em></strong> column, we search for the word “Employee” and replace it with “Staff” in the appended <strong><em>RepCombinedString</em></strong> column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125369649/ea90f024-76f4-4838-b34d-ab2d3ee1e0cd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125383863/9df65d9d-3505-4665-b743-9a6b4ec69253.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-search-and-match-of-string"><strong>Search and Match of String</strong></h3>
<p>Objective: To determine and indicate whether the employee belongs to the Sales department</p>
<p>We use the <strong>LIKE</strong> function of the <strong>Rule Engine</strong> node to search for “Sales” in the <strong><em>CombinedString</em></strong> column and create a new column, <strong><em>Sales</em></strong>, with “Yes” or “No,” to indicate whether the employee belongs to the Sales department.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125397837/65cd47db-ae1a-4eb8-a15a-cc3ecebe7b8b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125412151/aca5b51c-fffc-43ed-94eb-e723560a6715.png" alt class="image--center mx-auto" /></p>
<p>The <strong>Like</strong> function helps locate the string “Sales” in the given string column. If the department has a “Sales” word, the corresponding <strong>Sales</strong> column is populated with a “Yes” value and a “No” value otherwise. The above results show that the first employee belongs to the sales department, and the subsequent four do not.</p>
<h3 id="heading-aggregated-statistics-using-group-by-operation"><strong>Aggregated Statistics using Group by Operation</strong></h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125428948/f5671960-46bd-4104-8349-fd03400fe7e9.png" alt class="image--center mx-auto" /></p>
<p>The <strong>GroupBy</strong> node helps group observations based on a categorical column. After grouping observations, we can apply multiple aggregation functions, such as mean, median, minimum, maximum, count, sum, covariance, variance, standard deviation, etc.</p>
<p>We will use the <strong>GroupBy</strong> node to get the aggregated statistics for multiple columns across each <strong><em>Gender</em></strong> (male and female).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125445517/e394b479-8183-42ea-b978-1904ee60fe33.png" alt class="image--center mx-auto" /></p>
<ul>
<li><p>Mean of <strong><em>DistanceFromHome</em></strong></p>
</li>
<li><p>Median of <strong><em>DistanceFromHome</em></strong></p>
</li>
<li><p>Minimum <strong><em>Age</em></strong></p>
</li>
<li><p>Maximum <strong><em>Age</em></strong></p>
</li>
<li><p>Count of <strong><em>EmployeeCount</em></strong></p>
</li>
<li><p>Sum of <strong><em>DailyRate</em></strong></p>
</li>
<li><p>Covariance of <strong><em>HourlyRate</em></strong></p>
</li>
<li><p>Variance of <strong><em>HourlyRate</em></strong></p>
</li>
<li><p>Standard deviation of <strong><em>HourlyRate</em></strong></p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125466138/b32f4e4b-34ce-4778-a0b1-1b372d0a8f2f.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-group-by-with-sorting"><strong>Group by with Sorting</strong></h3>
<p>Objective: To determine the employee count and percent for different marital status</p>
<p>We will use the <strong>GroupBy</strong> node to get the distinct employee count and percentage across each marital status (group by <strong><em>MaritalStatus</em></strong>, aggregate count, and percent by <strong><em>EmployeeNumber</em></strong>). Subsequently, we use the <strong>Sorter</strong> node to order the resultant table in descending order of count.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125478552/807d847f-186d-42db-bb68-77213f237a7e.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125490711/0ee9fe8e-373a-4872-a09d-515995cdea53.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125502391/64e040ff-80b4-4d33-9512-6962b8d20241.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125513739/9f252c3e-facc-490a-aadf-99b1386f7ac0.png" alt class="image--center mx-auto" /></p>
<p>We can observe three distinct values of <strong><em>Marital Status</em></strong>: Single, Married, and Divorced. The number of observations of married employees is maximum (673, 45.782%) and displayed at the top; followed by the number of observations of single employees (470, 31.973%), and observations having divorced employees is minimum (327, 22.245%) and displayed at the bottom.</p>
<h3 id="heading-data-filtering-subset-using-and-and-or-operation"><strong>Data Filtering (subset) using AND and OR operation</strong></h3>
<p>Objective: To filter the data of female employees belonging to the sales department</p>
<p>We will use the <strong>Row Filter</strong> node and add the criterion1 filter column as <strong><em>Gender</em></strong> (value = “Female”) and the criterion2 filter column as <strong><em>Department</em></strong> (value = “Sales”). By selecting the “All criteria” option, the “AND” filter condition is applied (189 rows in the resultant filtered table). On the other hand, by choosing the “Any criteria” option, the “OR” filter condition is applied (845 rows in the resultant filtered table).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125530388/3aef6756-ad4d-43f7-abd0-fd0a0d61872e.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-determine-correlation-using-spearman-correlation-coefficient"><strong>Determine Correlation Using Spearman Correlation Coefficient</strong></h3>
<p>Objective: To determine the correlation between hourly rate and job satisfaction</p>
<p>We will use the <strong>Rank Correlation</strong> node to determine the Spearman correlation coefficient of the <strong><em>HourlyRate</em></strong> and <strong><em>JobSatisfaction</em></strong> columns. The node calculates a correlation coefficient for each pair of selected columns, i.e., a measure of the correlation of the two variables. All measures are based on the rank of the cells. By executing the node, we get three outputs for statistical inference. Correlation measure contains correlation variables, p-values, and degrees of freedom. The correlation matrix displays the correlation variables in a matrix representation. The Rank table contains the fractional ranks of the columns where the rank corresponds to the position of the value in a sorted table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125550029/d05c4469-aac3-4d48-be2f-35f50b9986ec.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125561097/e8751972-5829-40de-970e-7578c734373a.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125571679/39383296-29e9-46da-ab72-13fce95564c8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125583258/5e449e92-383f-43d3-8708-e1d253b6b003.png" alt class="image--center mx-auto" /></p>
<p>The correlation between the two groups lies between -1 and +1. The value -1 denotes a perfect negative correlation, and +1 denotes a perfect positive correlation. The value 0 denotes no correlation. The value between 0 and 1 denoted the extent of correlation. A lesser value denotes a lower correlation, and a higher value denotes a higher correlation. From the output, we can see that the Spearman correlation is -0.06; this means a low correlation between the two groups. We know the null hypothesis is rejected if the p-value is &lt;0.05. Our data shows that the p-value is less than 0.05, which means the null hypothesis is rejected. This means there exists a negative correlation between hourly rate and job satisfaction.</p>
<h3 id="heading-determine-correlation-using-pearson-correlation-coefficient"><strong>Determine Correlation Using Pearson Correlation Coefficient</strong></h3>
<p>Objective: To determine the correlation between monthly rate and job satisfaction</p>
<p>We will use the <strong>Linear Correlation</strong> node to determine the Spearman correlation coefficient of the <strong><em>MonthlyRate</em></strong> and <strong><em>JobSatisfaction</em></strong> columns. The node calculates a correlation coefficient for each pair of selected columns, i.e., a measure of the correlation of the two variables. By executing the node, we get two outputs for statistical inference. The correlation measure contains correlation variables, p-values, and degrees of freedom. The correlation matrix displays the correlation variables in a matrix representation.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125597231/1596f871-8976-4a7d-82f4-ea21d8c747a7.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125609894/e69ac5e9-88ca-4139-b8d4-9fe79d7a84cd.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738125621319/2237d2bd-0392-4aab-9f80-d52abc039e16.png" alt class="image--center mx-auto" /></p>
<p>The correlation coefficient is 0.001, which is very low. Also, the p-value (0.98) is more than 0.05, which means the null hypothesis failed to be rejected. This means no significant correlation exists between monthly rate and job satisfaction.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In conclusion, this article demonstrated the effective use of KNIME for data exploration and manipulation, specifically in HR analytics using the IBMdata.csv dataset. By leveraging various KNIME nodes, we performed a comprehensive exploratory data analysis, including reading and summarizing data, manipulating string columns, and conducting statistical analyses such as correlation. These techniques provide HR professionals with valuable insights into employee data, enabling them to make informed decisions and develop strategic initiatives. The hands-on approach with KNIME showcases its versatility and power in handling complex data tasks, making it an essential tool for data-driven decision-making in organizations.</p>
]]></content:encoded></item><item><title><![CDATA[Human Resource Analytics Using KNIME – An Introduction]]></title><description><![CDATA[HR Analytics

What gets measured gets managed. What gets managed gets executed. -Peter Drucker
Global organizations with workforce analytics and planning outperform all other organizations by 30% more sales per employee. -CedarCrestone Research Surve...]]></description><link>https://vijayv2k.com/human-resource-analytics-using-knime-an-introduction</link><guid isPermaLink="true">https://vijayv2k.com/human-resource-analytics-using-knime-an-introduction</guid><category><![CDATA[associationrule]]></category><category><![CDATA[Data Science]]></category><category><![CDATA[dataanalytics]]></category><category><![CDATA[HR]]></category><category><![CDATA[HR analytics]]></category><category><![CDATA[KNIME]]></category><category><![CDATA[DataVisualization]]></category><category><![CDATA[dataviz]]></category><category><![CDATA[conjoint]]></category><category><![CDATA[timeseries]]></category><category><![CDATA[forecasting]]></category><category><![CDATA[cluster]]></category><category><![CDATA[clustering]]></category><category><![CDATA[Principal Component Analysis (PCA) ]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Mon, 27 Jan 2025 14:53:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737989474879/70e51bb7-d1ba-48aa-a2ac-b9314559b516.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-hr-analytics">HR Analytics</h3>
<blockquote>
<p><strong><em>What gets measured gets managed. What gets managed gets executed.</em></strong> -Peter Drucker</p>
<p><strong><em>Global organizations with workforce analytics and planning outperform all other organizations by 30% more sales per employee.</em></strong> -CedarCrestone Research Survey</p>
<p><strong><em>The corporate world is slowly evolving its practice of HR analytics toward a ‘model of predictive management’ for human resources because to be successful, HR analytics must extend beyond reporting what is (the present) or what was (the past) to predicting and analyzing what will be (the future).</em></strong> -Center for Advanced Human Resource Studies</p>
<p><strong><em>The global HR analytics market will grow at a CAGR of around 12% during the 2019-2025 forecast period.</em></strong> -World HR Analytics Market</p>
<p><strong><em>Companies using a portfolio of HR analytics solutions could realize an increase of 275 basis points in profit margins, on average, by 2025.</em></strong> -McKinsey Global Institute</p>
</blockquote>
<h3 id="heading-hr-metrics-and-hr-analytics"><strong>HR Metrics and HR Analytics</strong></h3>
<p>The core responsibility of the HR department is to provide a high return on the business’s investment in its employees by effectively aligning with corporate culture, organizational values, vision, and mission. It provides organizations with insight and feedback on the contribution of HR initiatives to meeting operational goals and strategic business objectives.</p>
<p>HR Metrics are measurements used to determine the value and effectiveness of HR initiatives and help track key HR department activities by reporting numbers. These indicators allow businesses to measure performance, efficiency, and impact of business processes and change. While HR metrics act as a barometer for business performance, they can only track events but do not provide in-depth information about the event, which can be used for making strategic decisions and uncovering areas of improvement. On the other hand, HR analytics aims to provide insight into each process after gathering data and then use them to make relevant decisions about improving these processes. Thus, when used for HR analytics, HR metrics can pave the way toward effectively meeting organizational objectives.</p>
<h3 id="heading-what-is-hr-analytics"><strong>What is HR Analytics?</strong></h3>
<p>HR analytics, also known as people analytics, talent analytics, or workforce analytics, can be defined as follows:</p>
<ul>
<li><p>The systematic identification and quantification of the people drivers of business outcomes.</p>
</li>
<li><p>The process of collecting and analyzing human resources data to improve employee performance.</p>
</li>
<li><p>Applying sophisticated data mining and business analytics techniques to human resources data.</p>
</li>
</ul>
<p>The field of analytics refers to using analytics in an organization's HR department processes to improve workforce performance and result in a better return on investment.</p>
<p>HR analytics can be used to explore and examine the data and then transform their findings into insights that will help executives, managers, and operational employees of the HR department to make better and more informed decisions. These are three types of analytics:</p>
<ul>
<li><p>Descriptive analytics – What has happened?</p>
</li>
<li><p>Predictive analytics – What could happen?</p>
</li>
<li><p>Prescriptive analytics – What should happen?</p>
</li>
</ul>
<p>The data-driven insights that HR analytics provides help identify existing and required outcomes. This will further improve productivity and efficiency, generating increased revenue for the organization.</p>
<p>Artificial Intelligence (AI) and machine learning help streamline the HR department's significant and essential functions. The latest developments in HR analytics use AI tools for text and image data analysis. AI helps measure employee behavior and hire the most suitable candidate for the job during recruitment by filtering resumes and recognizing and analyzing facial expressions and voice in the organization.</p>
<h3 id="heading-hr-analytics-for-professional-challenges"><strong>HR Analytics for Professional Challenges</strong></h3>
<p>To meet organizational objectives, HR professionals must recruit the right person, experience less attrition, utilize employees' best capabilities, improve the recruitment process, provide competitive salaries, launch successful employee training programs, etc. The organization's leaders can make consistently better decisions using facts supported by data. The key to finding the correct data for the organization is identifying the overall business needs, as every organization may differ in data collection, formulating strategies, and decision-making. According to the requirement, the data for doing HR analytics can be collected from the Human Resource Information System (HRIS) and through the customized survey portals.</p>
<h3 id="heading-why-knime-for-hr-analytics"><strong>Why KNIME for HR Analytics?</strong></h3>
<p>This series intends to encourage more ‘data-driven’ decisions in HR. HR Analytics is no longer a nice-to-have add-on; it is how HR practitioners should conduct HR decision-making in the future. Where applicable, human judgment is ‘added’ onto a rigorous data analysis done in the first place.</p>
<p>To achieve this ideal world, I need to equip you with some fundamental knowledge of KNIME, an open-source tool for data scientists. I am well aware that, on one side, you want to do something for your career in HR. However, you are most likely completely new to data analytics and coding.</p>
<p><a target="_blank" href="https://www.knime.com/"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1737990101357/4d03aff1-e423-49e7-8bb5-2140f98db9e8.jpeg" alt="KNIME Analytics Platform" class="image--center mx-auto" /></a></p>
<p>KNIME is a data science platform for data analytics and machine learning. It is an open-source tool businesses can use to automate repetitive tasks, analyze data, and build AI models. The visual workflow representation of each node makes it easy to use and understand, even for people without a data analytics or programming background.</p>
<h3 id="heading-topics-covered-in-hr-analytics-series"><strong>Topics Covered in HR Analytics Series</strong></h3>
<p>This series of articles on “HR Analytics with KNIME“ covers the role of HR analytics in the following functional areas.</p>
<p><a target="_blank" href="https://vijayv2k.com/analyzing-employee-details-data-exploration-manipulation"><strong>Analyzing Employee Details – Data Exploration &amp; Manipulation</strong></a></p>
<p>It illuminates the available data exploration and manipulation nodes in KNIME, familiarizes them with their functions, and educates them on using them in different HR data analysis scenarios.</p>
<p><a target="_blank" href="https://vijayv2k.com/reviewing-employee-details-data-visualization"><strong>Reviewing Employee Details – Data Visualization</strong></a></p>
<p>Educating on the various visualization techniques and their relevant nodes in the KNIME provides knowledge of charts for categorical and continuous variables, demonstrates the use of charts to solve real-world problems, and encourages effective decision-making regarding selecting a chart related to the data type.</p>
<h3 id="heading-hr-analytics-using-statistical-techniques">HR Analytics Using Statistical Techniques</h3>
<p><a target="_blank" href="https://vijayv2k.com/structuring-employee-rewards-package-conjoint-analysis"><strong>Structuring Employee Rewards Package – Conjoint Analysis</strong></a></p>
<p>The article mentions the organization's flexible compensation and benefits plan and discusses how to perform conjoint analysis to determine the preference of different attributes and levels. It helps evaluate conjoint analysis results and determine the utility of varying compensation and benefits plans.</p>
<p><a target="_blank" href="https://vijayv2k.com/evaluate-training-effectiveness-comparative-statistics"><strong>Evaluate Training Effectiveness – Comparative Statistics</strong></a></p>
<p>It helps you understand the importance of employee training and development programs, provides knowledge of different comparison techniques, assesses the results of comparison techniques used for evaluating training programs, and elaborates on familiarity with applications of comparison techniques in other areas of HR analytics.</p>
<p><a target="_blank" href="https://vijayv2k.com/forecasting-hr-cost-time-series-modeling"><strong>Forecasting HR Cost – Time Series Modeling</strong></a></p>
<p>Educated on the importance of time series analysis, it helps determine the series’ stationarity and assists in constructing different models using ARIMA modeling techniques. It also mentions how to forecast using ARIMA modeling techniques.</p>
<h3 id="heading-hr-analytics-using-unsupervised-machine-learning"><strong>HR Analytics Using Unsupervised Machine Learning</strong></h3>
<p>Unsupervised machine learning algorithms are used when the output is unknown, and no predefined instructions are available to the learning algorithms. In unsupervised learning, the learning algorithm only has input data, and knowledge is extracted from these data. These algorithms create a new representation of the data that is easier to comprehend than the original data and help improve the accuracy of advanced algorithms by consuming less time and reducing memory. Standard unsupervised machine learning algorithms include association rule mining, dimensionality reduction algorithms, and clustering.</p>
<p><a target="_blank" href="https://vijayv2k.com/evaluating-job-satisfaction-association-rule-mining"><strong>Evaluating Job Satisfaction – Association Rule Mining</strong></a></p>
<p>It helps determine the factors associated with job satisfaction, educates people to understand the methodology of association rule mining, and shares knowledge on implementing the apriori algorithm for determining factors impacting job satisfaction. It also facilitates the evaluation of the results of association rule mining for job satisfaction.</p>
<p><a target="_blank" href="https://vijayv2k.com/identify-absenteeism-patterns-cluster-analysis"><strong>Identify Absenteeism Patterns – Cluster Analysis</strong></a></p>
<p>It helps to understand the importance of clustering and mentions different clustering techniques. You will also be able to analyze the results of various clustering techniques and implement them in a real-world situation.</p>
<p><a target="_blank" href="https://vijayv2k.com/identify-core-factors-in-performance-appraisal-principal-component-analysis"><strong>Identify Core Factors in Performance Appraisal – Principal Component Analysis</strong></a></p>
<p>It helps to understand the factors of the performance appraisal system and helps in applying dimension reduction algorithms. It also educates on implementing algorithms to determine performance appraisal factors and analyze the results of these algorithms.</p>
<h3 id="heading-hr-analytics-using-supervised-classification-machine-learning">HR Analytics Using Supervised Classification Machine Learning</h3>
<p>Classification is a machine learning technique for solving problems predicting a dependent categorical variable. The classification problem occurs when the dependent variable has two or multiple categories and is predicted by a set of independent variables. Most of the data in real-world problems require the concept of classification. It should be specified that any number of dependent variable categories can exist in classification. However, logistic regression applies only to two categories (binary classification). Logistic regression predicts binary values, such as whether the customer will buy or not, Pass/Fail, Yes/No, 0/1. It measures the probability of event=success and event=failure.</p>
<p><a target="_blank" href="https://vijayv2k.com/predicting-employee-attrition-supervised-classification-machine-learning"><strong>Predicting Employee Attrition - Supervised Classification Machine Learning</strong></a></p>
<p>It helps to understand the importance of attrition for employees and gain knowledge of different classification techniques. You can use classification techniques to predict employee attrition and familiarize yourself with classification techniques applied in other areas of HR analytics.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In conclusion, HR analytics is a transformative approach that empowers organizations to make data-driven decisions, enhancing workforce performance and aligning HR initiatives with strategic business objectives. By leveraging tools like KNIME, HR professionals can efficiently analyze and visualize data, leading to improved recruitment processes, optimized employee training programs, and better overall organizational outcomes. Integrating advanced technologies such as AI and machine learning will further streamline HR functions as the field evolves, ensuring that companies remain competitive in a rapidly changing global market. Embracing HR analytics is a trend and a necessity for future-ready organizations aiming to maximize their human capital investment.</p>
]]></content:encoded></item><item><title><![CDATA[Hands-On Exploratory Data Analysis with KNIME]]></title><description><![CDATA[KNIME is particularly well-suited to data analysis workflows due to its versatility and highly optimized performance. It allows practitioners to scale data analysis workflows beyond what they would otherwise achieve on their local machine. This artic...]]></description><link>https://vijayv2k.com/hands-on-exploratory-data-analysis-with-knime</link><guid isPermaLink="true">https://vijayv2k.com/hands-on-exploratory-data-analysis-with-knime</guid><category><![CDATA[Data Science]]></category><category><![CDATA[dataanalytics]]></category><category><![CDATA[Dataanalysis]]></category><category><![CDATA[visualization]]></category><category><![CDATA[Low Code]]></category><category><![CDATA[nocode]]></category><category><![CDATA[KNIME]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Thu, 12 Dec 2024 18:10:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1734026924195/2e611e65-e54d-4d96-a468-f15d14b17c9d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>KNIME is particularly well-suited to data analysis workflows due to its versatility and highly optimized performance. It allows practitioners to scale data analysis workflows beyond what they would otherwise achieve on their local machine. This article will use the data analysis workflow to perform some hands-on exploratory dataset analysis, allowing us to explore different approaches for performing practical data analysis with KNIME.</p>
<p>More specifically, in this article, we will cover the following topics:</p>
<ul>
<li><p>Loading our dataset from a CSV file and applying data-cleaning steps for our analysis.</p>
</li>
<li><p>Using the Pivot &amp; GroupBy for convenient aggregation operations.</p>
</li>
<li><p>Using the data visualization nodes to create interactive data visualizations.</p>
</li>
<li><p>Perform exploratory data analysis of pedestrian traffic counts using a public dataset in Melbourne City.</p>
</li>
</ul>
<p>By the end of this article, you will be able to assemble workflows for practical data analysis with KNIME that work for your needs.</p>
<h3 id="heading-downloading-the-dataset-and-workflow"><strong>Downloading the dataset and workflow</strong></h3>
<p>We will be working with one of the pedestrian counting-system datasets produced and made public by the city of Melbourne. This <a target="_blank" href="https://data.melbourne.vic.gov.au/explore/dataset/pedestrian-counting-system-monthly-counts-per-hour/information/">dataset</a> contains hourly pedestrian counts from sensors in and around Melbourne. We will use a historical snapshot of this dataset covering May 2009 to December 2022.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734023923511/3ed933f5-d656-4874-8db2-d5bce2b6f5c7.png" alt class="image--center mx-auto" /></p>
<p>You are ready once you have extracted the CSV file from the ZIP archive.</p>
<blockquote>
<p><em>You can download the</em> <a target="_blank" href="https://hub.knime.com/vijayv2k/spaces/Projects/Melbourne%20Pedestrian%20Sensor%20Data%20Analysis~LMZ28LKTVv2DAga7/current-state">Melbourne Pedestrian Sensor Data Analysis</a> workflow <em>from the KNIME Community Hub.</em></p>
</blockquote>
<h3 id="heading-reading-and-transforming-the-csv-based-dataset"><strong>Reading and transforming the CSV-based dataset</strong></h3>
<p>The first step in our analysis will be to identify the data loading and transformation steps we will use to prepare the data for our exploratory analyses. We will do this first step using the <strong>CSV Reader</strong> node before we persist our transformation in a KNIME table.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024036594/c8856c7b-24bb-4130-929c-1d405e1b5546.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024054309/a9a7c502-98f8-41d7-ad1b-38833ef2b0fc.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table is created by loading the pedestrian CSV dataset without cleaning.</p>
<p>As we can see, each record in this dataset (4,562,230 rows &amp; 10 columns) contains the number of pedestrian counts passing through a given sensor for a specific hour, along with other information about the hourly reading, such as the sensor name and timestamp of the record and date and time components extracted from the timestamp.</p>
<p>The primary data issue you might have noticed is that the <strong>Date_Time</strong> field is of the String type. We must convert this column to a Date&amp;Time type for some time series analysis and visualizations. Let us address this by using the <strong>String to Date&amp;Time</strong> node. We can see that the <strong>Date_Time</strong> column now has the correct date &amp; time format.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024110251/f8b5be26-ec2e-47db-8e52-7a18223fa649.png" alt class="image--center mx-auto" /></p>
<p>Given that we will be performing a range of time series analyses, we will almost certainly need these records ordered by Date, so the other transformation we will perform involves sorting the records by the <strong>Date_Time</strong> column.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024151744/1c547f5a-5e4f-40cf-8932-0f18dd74a83e.png" alt class="image--center mx-auto" /></p>
<p>The KNIME table that is produced after applying the transformations</p>
<p>Our data format is now suitable for performing our analysis. Of course, the nature of data analysis is iterative, and we may need to come back to tune our data processing steps after working with the dataset. But for now, we are ready to proceed with the data analysis.</p>
<h3 id="heading-practical-data-analysis-using-knime"><strong>Practical data analysis using KNIME</strong></h3>
<p>We will briefly cover two sets of tools that will assist us in performing our data analysis. The first is aggregation nodes like <strong>GroupBy</strong> and <strong>Pivot</strong>, which provide a convenient way to perform aggregate operations on the data. The second is comprehensive data visualization nodes (<strong>Views</strong> and <strong>JavaScript</strong>) that produce interactive visualizations. Let us get started.</p>
<h3 id="heading-total-number-of-pedestrians-for-every-sensor-across-the-years"><strong>Total number of pedestrians for every sensor across the years</strong></h3>
<p>Say we wanted to count the total number of pedestrian readings for every sensor aggregated across all years. We can use the <strong>Pivot</strong> node to perform this aggregation using the following column settings: group by <strong>Sensor_Name</strong>, pivot by <strong>Year</strong>, and sum by <strong>Hourly_Counts</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024270425/7f6a2dc6-aac3-41d5-aa03-56aa3d96cbbc.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024286604/9102aa16-c410-4440-b059-22051beccfd0.png" alt class="image--center mx-auto" /></p>
<p>The resulting pivot table is produced after performing the aggregation. Note that some sensors have not captured data for some years, which are aptly represented as missing values.</p>
<p>Taking it further, say we wanted to count the total number of pedestrian readings for the <em>Melbourne Central</em> sensor alone. We can use the <strong>Row Filter</strong> node to filter out the aggregated count for this sensor.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024331018/45444093-0660-4982-a2b6-a7e5e2a11629.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-visualize-the-number-of-active-sensors-across-each-year"><strong>Visualize the number of active sensors across each year</strong></h3>
<p>First, we will use the <strong>GroupBy</strong> node to get the distinct number of sensor names seen across each year (group by <strong>Year</strong> and unique count by <strong>Sensor_Name</strong>). Before we proceed with the visualization, we will convert the <strong>Year</strong> column from <strong>Number to String.</strong> Subsequently, we will use the <strong>Line Plot</strong> node to plot the unique count of sensors across each year.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024372992/80602727-d983-4d12-aeff-c065ac88ed61.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024399393/3bd25400-0610-48c2-ae09-cb7a25f29232.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024424271/92812065-ce4e-464e-b316-92f5b0c4b73f.png" alt class="image--center mx-auto" /></p>
<p>The resultant interactive line plot shows the number of active sensors each year.</p>
<h3 id="heading-top-10-sensors-by-traffic-in-2022"><strong>Top 10 sensors by traffic in 2022</strong></h3>
<p>First, we will use the <strong>Row Filter</strong> node to filter out the dataset for the year 2022. Then, we will use the <strong>GroupBy</strong> node on the resultant dataset to get the total number of pedestrians across each sensor (group by <strong>Sensor_Name</strong> and sum of <strong>Hourly_Counts</strong>). Before the visualization, we will use the <strong>Top k-row Filter</strong> node to find the top 10 sensors. Subsequently, we will use the <strong>Bar Chart</strong> node to get an interactive bar chart of the top 10 sensors by traffic in 2022.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024609744/deb881a8-7232-498a-bfcd-f54a767e48c1.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024619076/b638f106-7b78-42c5-8ce3-59069ea44625.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024670529/cbe90437-5aff-4c6a-8c4d-d4c3338b1b80.png" alt class="image--center mx-auto" /></p>
<p>Table with the top 10 sensors by total pedestrian counts for 2022</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024702548/d37a9ac6-3cbc-4434-a7c7-acf1950b4a8d.png" alt class="image--center mx-auto" /></p>
<p>The resultant interactive bar chart shows the top 10 sensors by traffic in 2022.</p>
<h3 id="heading-visualizing-total-pedestrian-counts-over-time"><strong>Visualizing total pedestrian counts over time</strong></h3>
<p>Let us understand how the dataset's total number of pedestrian counts registered by the sensor network has changed over the years. We will use the <strong>GroupBy</strong> node to get the total number of pedestrians across all sensors by year (group by <strong>Year</strong> and sum by <strong>Hourly_Counts</strong>). Before we proceed with the visualization, we will convert the <strong>Year</strong> column from <strong>Number to String.</strong> Subsequently, we will use the <strong>Line Plot</strong> node to plot the total number of pedestrians yearly.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024754337/7f95d261-41ac-415d-87ec-8810f16a3259.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024762463/519260c2-b9c3-41a0-964e-b1e80548f765.png" alt class="image--center mx-auto" /></p>
<p>The resultant line chart shows the total pedestrian counts recorded annually across the entire pedestrian counting system.</p>
<p>This plot shows a steady increase over the years in the number of total pedestrians recorded moving across Melbourne city, with a rather pronounced crash in 2020, which is almost certainly due to the impact that COVID-19 lockdown restrictions had on the number of people walking through the city. However, we must be careful about the conclusions we draw from this plot. As we saw in the previous section, the number of active sensors in the system has increased, resulting in some pedestrians being counted more times over the same route than in previous years.</p>
<h3 id="heading-pedestrian-count-over-time-for-sensors-active-across-all-years"><strong>Pedestrian count over time for sensors active across all years</strong></h3>
<p>To address the confounding impact of the changing number of sensors over the years, let us filter down our dataset to only records from sensors that have readings across every year before repeating the same analysis. We will do this in two steps:</p>
<ol>
<li><p>Extract the sensor names with readings for every year in the dataset.</p>
</li>
<li><p>Repeat our sum aggregation of pedestrian counts by year while retaining only those rows with sensor names in the above table (#1).</p>
</li>
</ol>
<p>We can achieve the first step by grouping our dataset by sensor name and selecting only sensor names whose group of records includes at least one record for each year that our dataset covers. Our dataset contains data from 2009 to 2022, covering 14 years. We will use the <strong>GroupBy</strong> node (unique count by <strong>Year</strong>) to confirm that this is the distinct number of years seen in our dataset.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024850962/0746763e-6640-41f1-9d64-0793818cb0c9.png" alt class="image--center mx-auto" /></p>
<p>We will leverage the observation that each sensor needs to have 14 distinct <strong>Year</strong> values across its readings to be considered. We will use the <strong>GroupBy</strong> node to get the number of distinct years for every sensor (group by <strong>Sensor_Name</strong> and unique count by <strong>Year</strong>). Using the <strong>Table Row to Variable</strong> node, we will pass the distinct count value 14 as a flow variable for the <strong>Row Filter</strong> node. This gives us the list of 15 sensors with readings for all 14 years.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024936603/b55ce0b8-50ba-4e69-beef-92f4b08906e8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024949630/e43bfad2-747e-4767-9874-28d4e882bf63.png" alt class="image--center mx-auto" /></p>
<p>A distinct year count is passed to the row filter node as a flow variable.</p>
<p>We can perform the next step now that we know which sensors were active across all years in the dataset. Here, we will replicate the previous set of nodes we used to plot the total number of pedestrian counts for each year (yearly traffic across all sensors). However, this time, we will restrict pedestrian counts to only those active sensors for all years. We will use the <strong>Reference Row Filter</strong> node for this purpose.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734024996407/aee28876-2f58-4aff-aff5-026eccdbb19b.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025005976/efbe77b8-baad-4607-9f37-3234d2f22922.png" alt class="image--center mx-auto" /></p>
<p>A resultant line chart shows the total pedestrian counts by year across only active sensors yearly.</p>
<p>Comparing this with the previous plot, we can see that the trend regarding the increasing number of pedestrian counts over the years is less pronounced. This is what we expect to see when controlling the growing number of sensors. We can still see the dramatic drop in sensor counts due to the COVID-19 lockdowns, which, if anything, now looks even more pronounced compared to the previous years.</p>
<h3 id="heading-monthly-pedestrian-count-for-sensors-active-in-2019-2020-and-2021"><strong>Monthly pedestrian count for sensors active in 2019, 2020, and 2021</strong></h3>
<p>To finish our investigation into pedestrian counts through the city over time, let us drill down a bit deeper into the impact of the lockdowns on Melbourne pedestrian traffic by looking at the month-to-month changes for 2019, 2020, and 2021. For this, we will need a new data extract, which we group by years and months and then aggregate the total counts for each combination of year and month. Continuing our previous analysis, we will filter this down to only readings from active sensors across all years.</p>
<p>First, we will convert the <strong>Year</strong> column from <strong>Number to String</strong> and use the <strong>Nominal Value Row Filter</strong> node to restrict the dataset for 2019, 2020, and 2021. We can then use the <strong>Pivot</strong> node to perform the monthly aggregation using the following column settings: group by <strong>Num_Month</strong>, pivot by <strong>Year</strong>, and sum by <strong>Hourly_Counts.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025074646/c55d2db3-1b6c-4e28-b857-25971e115da6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025085942/ef979162-f1ad-4f4a-963f-66721f36e916.png" alt class="image--center mx-auto" /></p>
<p>The resulting pivot table contains the aggregated pedestrian counts for each month and year combination.</p>
<p>Subsequently, we will use the <strong>Line Plot</strong> node to plot the monthly total number of pedestrians for sensors active in 2019, 2020, and 2021.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025188448/bf0c6696-04b7-439a-bb16-7a50ef2a3be2.png" alt class="image--center mx-auto" /></p>
<p>A resultant line chart shows the monthly traffic for sensors active in 2019, 2020, and 2021.</p>
<p>This visualization allows us to compare the month-by-month total counts for each target year readily. By hovering over the markers of different lines, we can gather that in April 2019, there were 8.2 million pedestrian counts, which dropped to 1.1 million for the same month in 2020, when the initial lockdown was in full effect.</p>
<h3 id="heading-creating-time-series-plots-of-sensor-readings"><strong>Creating time series plots of sensor readings</strong></h3>
<p>We will now move on to a finer level of analysis and explore how the hourly pedestrian traffic changes over a range of days for specific sensors. Let us start by creating a plot of hourly traffic for the <em>Flinders La-Swanston St (West)</em> sensor across all of 2020. First, we will use the Row Filter node to extract only the records corresponding to our target sensor and year. Then, we will use the <strong>Line Plot</strong> node to plot the hourly pedestrian count.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025246268/1f6d5b61-0223-4b45-94e5-a15c9d0db6ab.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025256205/880a4026-375b-4a8b-bf95-cc5af79f8bf0.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025266129/861eeccd-625a-4eba-8605-8fef5e389588.png" alt class="image--center mx-auto" /></p>
<p>A resultant line chart shows the hourly pedestrian counts for the Flinders La-Swanston St (West) sensor for 2020.</p>
<p>This is a very dense line plot since we have visualized every hour throughout the year. It provides a striking visualization of the impact the COVID-19 lockdowns had on pedestrian traffic across this sensor:</p>
<ul>
<li><p>Traffic dropped around the middle of March as restrictions were applied, leading up to the first complete lockdown on March 31.</p>
</li>
<li><p>Traffic starts to increase in mid-May as restrictions are relaxed.</p>
</li>
<li><p>A massive spike on June 6 coincided with a protest close to the central business district.</p>
</li>
<li><p>Traffic drops off again, with a second lockdown being put in place on July 7</p>
</li>
<li><p>We start seeing traffic increase again from October through to the end of the year, corresponding to the ongoing lifting of restrictions, which began in mid-September</p>
</li>
</ul>
<p>This is a perfect time to take advantage of another of the interactive features the <strong>Line Plot</strong> node visualizations offer. We can zoom in on specific regions of the x and y axes by left-clicking and dragging over the desired area. Selecting the region from January 16 to 31 gives us the following time series:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025578878/3cdcb6b6-ebdb-49d0-bf62-26117ecde960.gif" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025627791/42f97978-3e14-4279-b1bd-f78a3a3e7186.png" alt class="image--center mx-auto" /></p>
<p>A zoomed-in view of the same time series plot</p>
<p>We can now easily discern the periodic changes in pedestrian traffic for this sensor, corresponding to the daily rhythm of people’s activities. You can click on the zoom reset icon to reset the zoom level.</p>
<h3 id="heading-comparing-time-series-plots-of-three-sensor-readings"><strong>Comparing time series plots of three sensor readings</strong></h3>
<p>It might be interesting to compare the daily traffic rhythms across three different sensors to see whether there are variations. We can use a combination of <strong>Row Filter</strong> (for September 2019), and <strong>Rule-based Row Filter</strong> (for <strong>Sensor_Name</strong> in "Flinders St-Spark La", "Bourke Street Mall (North)", "Southern Cross Station"). We can thenuse the <strong>Pivot</strong> node to perform the aggregation using the following column settings: group by <strong>Date_Time</strong>, pivot by <strong>Sensor_Name</strong>, and sum by <strong>Hourly_Counts)</strong>. Subsequently, we will use the <strong>Line Plot</strong> node to plot the hourly pedestrian count for the chosen three sensors in September 2019.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025693851/a6b39bec-50d1-481f-a606-c025215563c6.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025700489/0cee9040-9dac-45dd-9c9c-fdd1d1276f5f.png" alt class="image--center mx-auto" /></p>
<p>A resultant line chart shows the hourly pedestrian counts for three different sensors in Sep 2019.</p>
<p>By plotting the hourly traffic of these three sensors, we can readily compare pedestrian traffic patterns across them for September 2019. Comparing these three sensors, we can see that while they all have daily peaks and troughs, there is a noticeable variation:</p>
<ul>
<li><p>The Southern Cross Station sensor time series plot is striking. It reveals a pronounced difference in weekday traffic versus weekend traffic, with the weekend daytime peaks being much lower than those on the weekdays. This suggests that much pedestrian traffic comes from commuting to and from work.</p>
</li>
<li><p>The daily peaks for the Bourke Street Mall (North) sensor look similar in range but with less pronounced variation between weekday and weekend traffic.</p>
</li>
<li><p>Lastly, the Flinders St-Spark La sensor has a much lower range of daily traffic counts, with discernible drops over the weekend. We can also see a significant spike in pedestrian traffic on September 20.</p>
</li>
</ul>
<p>In the context of exploratory data analysis, the particularly convenient interactive feature of these plots allows us to easily compare traffic through these sensors across narrower time windows using the zoom function without modifying the configuration.</p>
<h3 id="heading-visualizing-the-distribution-of-daily-pedestrian-traffic-for-a-sensor"><strong>Visualizing the distribution of daily pedestrian traffic for a sensor</strong></h3>
<p>To gain deeper insights into how pedestrian traffic varies across a particular sensor location, we must move away from visualizing individual data points (time series plots) and instead visualize aggregated statistics (box plots) across multiple data points. Let us create a box plot set that compares the distributions of daily pedestrian count for a single sensor across various years. We will look at traffic across the <em>Bourke Street Mall (North)</em> sensor, comparing 2019, 2020, and 2021 distributions.</p>
<p>We start by using a <strong>Rule-based Row Filter</strong> (for <strong>Sensor_Name</strong> in "Bourke Street Mall (North)" and <strong>Year</strong> in 2019, 2020, 2021). We will then use the <strong>GroupBy</strong> node to get the daily pedestrian count across each year (group by <strong>Year</strong> and <strong>Date</strong> and sum by <strong>Hourly_Counts</strong>) and convert the <strong>Year</strong> column from <strong>Number to String</strong>. After that, we will use the <strong>Box Plot</strong> node to plot the daily pedestrian count distribution across the <strong>Year</strong> dimension (Condition column).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025814977/1e30feb4-c5c7-423b-acc9-ca69d1df372c.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025822172/58e24482-ee6c-4642-a83b-915c821110d5.png" alt class="image--center mx-auto" /></p>
<p>A resultant interactive box plot with three box plots comparing the distributions of daily pedestrian counts from 2019 to 2021 for the Bourke Street Mall (North) sensor.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1734025869922/8a693a29-6483-4092-919b-f3b4f61a74e1.png" alt class="image--center mx-auto" /></p>
<p>A resultant conditional box plot (JavaScript) with three box plots comparing the distributions of daily pedestrian counts from 2019 to 2021 for the Bourke Street Mall (North) sensor.</p>
<p>These three box plots provide us with a rich set of information about the distribution of daily pedestrian counts across the three years. Hovering over each box plot informs us of the value of key summary statistics, including that they include the median daily count (the horizontal line inside the box), the first and third quartiles (the bottom and top of the boxes, enclosing 50% of the data points), and the lower and upper fence values (the horizontal lines bounding the whiskers extending from the box), which indicate sentinel data points, below or above which any data points are considered outliers.</p>
<p>Unsurprisingly, the pre-COVID-19 distribution of daily counts for 2019 sits much higher than the next two years. We can also see that this year has a lower degree of spread than the other years, with the shorter box indicating a lower interquartile range – within which 50% of all the daily counts occur. 2020 and 2021 saw a greater spread of values, consistent with alternative lockdown periods in both years. We can also see that 2020 has a slight skew toward lower values, and 2021 has a more significant skew toward higher numbers. This, as well as the slightly lower interquartile range for 2021, is consistent with 2021 having fewer days of lockdown than 2020.</p>
<p>As you can see, this dataset provides a wealth of possible insights into changes and variability in pedestrian traffic through Melbourne. We will have to leave our exploratory analysis of the dataset here. Still, while going through these analyses, you might have thought about different lines of exploration and questions that we could have pursued. You can continue the analysis now that you have all the necessary ingredients.</p>
<h3 id="heading-summary"><strong>Summary</strong></h3>
<p>In this example, we explored how to use KNIME in the context of hands-on data analysis. Working with the Melbourne Pedestrian Counting System dataset, various KNIME data manipulation and visualization features enabled us to perform exploratory data analysis, in which we uncovered a range of insights into pedestrian traffic through Melbourne City.</p>
]]></content:encoded></item><item><title><![CDATA[Analysing Olympic games medal table]]></title><description><![CDATA[Introduction & pre-processing

Stacked & grouped bar chart

Bubble chart


Introduction
In this short KNIME tutorial, we visualize the Olympic dataset derived from the  Wikipedia  entry on All-time Olympic games medals, as of the 2016 Summer Olympics...]]></description><link>https://vijayv2k.com/analysing-olympic-games-medal-table</link><guid isPermaLink="true">https://vijayv2k.com/analysing-olympic-games-medal-table</guid><category><![CDATA[Data Science]]></category><category><![CDATA[#data visualisation]]></category><dc:creator><![CDATA[Vijaykrishna]]></dc:creator><pubDate>Wed, 14 Apr 2021 05:55:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1618378817433/xXY231ikZ.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<ul>
<li><p>Introduction &amp; pre-processing</p>
</li>
<li><p>Stacked &amp; grouped bar chart</p>
</li>
<li><p>Bubble chart</p>
</li>
</ul>
<h3 id="introduction">Introduction</h3>
<p>In this short KNIME tutorial, we visualize the Olympic dataset derived from the  <a target="_blank" href="https://en.wikipedia.org/wiki/All-time_Olympic_Games_medal_table">Wikipedia</a>  entry on All-time Olympic games medals, as of the 2016 Summer Olympics and 2018 Winter Olympics. All changes in medal standings due to doping cases and medal redistributions, including 25-Nov-2020, are considered.</p>
<p>The KNIME workflow along with the data can be downloaded  <a target="_blank" href="https://kni.me/w/ygFoTj1DHF_c3uv7">here</a> </p>
<p>Using the CSV reader node, we read the CSV file containing the dataset into the KNIME table. Then perform data cleaning and preprocessing operations to get a more usable data table to meet the desired purpose. </p>
<h3 id="top-ten-countries">Top ten countries</h3>
<p>Get the top ten countries that have the most medals in the summer and winter games.</p>
<p>We use the Top k Selector node to select the top ten countries with the most medals</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618379024637/HyrnH3aSA.png" alt="2021-04-14_9-41-41.png" /></p>
<h3 id="bar-chart">Bar chart</h3>
<p>We use the JavaScript Bar Chart node to create an interactive stacked and grouped bar chart representing the top ten countries in terms of the total number of medals in the winter and summer games.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618379220182/XPtQ-bW7G.gif" alt="2021-04-14_9-46-16.gif" /></p>
<h3 id="bubble-chart">Bubble chart</h3>
<p>We use JavaScript Bubble Chart (Plotly) node to create an interactive bubble chart showing the value of adjusted gold medals (no. of total gold / no. of total games) vs. the rank concerning the number of total medals won.</p>
<p>The size of the bubble corresponds to an adjusted value of total medals (no. of medals / no. of total games) won, and the color corresponds to the continent (North America, Europe, or Asia) or brown for NA – Not Applicable in case of Soviet Union.</p>
<p>The bubble chart shows that the United States has the most number of total medals in summer and winter games, as indicated by the x-axis (rank). Norway has the least number of combined medals among the top ten.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1618379308762/Iok31Qs7L.gif" alt="2021-04-14_9-48-01.gif" /></p>
<p>Based on the values of the adjusted gold medals represented by the y-axis, the Soviet Union won the most gold medals relative to the number of Olympic games in which they participated, followed by the US and Russia, respectively.</p>
<p>The sizes of the bubbles suggest that the top three countries that won the most medals relative to the number of games they were part of are respectively, the Soviet Union, the US, and Russia.</p>
<p>To put it in perspective, by comparing France and China, the latter won fewer total medals overall (position on the x-axis). But taking into account the number of Olympic games played, China did win more gold medals (position on the y-axis) and total medals (bubble-size).</p>
]]></content:encoded></item></channel></rss>