<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kendi</title>
    <description>The latest articles on DEV Community by Kendi (@kendixy).</description>
    <link>https://dev.to/kendixy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3843192%2Fd6c04fe7-e604-408d-938a-3af520fd81d1.png</url>
      <title>DEV Community: Kendi</title>
      <link>https://dev.to/kendixy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kendixy"/>
    <language>en</language>
    <item>
      <title>From Straight Lines to Smarter Models: Understanding Regression and Regularization in Machine Learning</title>
      <dc:creator>Kendi</dc:creator>
      <pubDate>Tue, 21 Jul 2026 11:55:03 +0000</pubDate>
      <link>https://dev.to/kendixy/from-straight-lines-to-smarter-models-understanding-regression-and-regularization-in-machine-48e6</link>
      <guid>https://dev.to/kendixy/from-straight-lines-to-smarter-models-understanding-regression-and-regularization-in-machine-48e6</guid>
      <description>&lt;h2&gt;
  
  
  Part 1: Linear Regression — What the Model Actually Does
&lt;/h2&gt;

&lt;p&gt;Linear regression is one of the simplest predictive models in machine learning. Its job is straightforward: learn the relationship between a set of input features and a continuous target by fitting the best possible line through the data. If you have many features, that "line" becomes a hyperplane, but the underlying idea stays the same.&lt;/p&gt;

&lt;p&gt;For multiple features, the model can be written as:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ŷ = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Where ŷ is the predicted value, β₀ is the intercept, and β₁ through βₙ are coefficients that quantify how much each feature contributes to the prediction.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Coefficients Are Found: Ordinary Least Squares
&lt;/h3&gt;

&lt;p&gt;The model finds the coefficients that minimise the &lt;strong&gt;Residual Sum of Squares (RSS)&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RSS = Σ(yᵢ - ŷᵢ)²&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each term (yᵢ - ŷᵢ) is the residual — the difference between the actual value and the model's prediction for observation i. Squaring serves two purposes: it prevents positive and negative errors from cancelling each other out, and it penalises large errors more heavily than small ones.&lt;/p&gt;

&lt;p&gt;This approach is called &lt;strong&gt;Ordinary Least Squares (OLS)&lt;/strong&gt;. It has a closed-form analytical solution, meaning the optimal coefficients can be calculated directly rather than estimated iteratively. This makes OLS computationally efficient and, importantly, it produces the Best Linear Unbiased Estimator (BLUE) when the five classical regression assumptions hold.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Five Assumptions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Linearity.&lt;/strong&gt; The relationship between predictors and target must be approximately linear. A model cannot capture a curve by drawing a straight line.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Independence of errors.&lt;/strong&gt; Residuals for different observations should not be correlated. This assumption is most frequently violated in time series data, where prediction errors in one period predict errors in the next.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No multicollinearity.&lt;/strong&gt; Predictor variables should not be highly correlated with each other. When they are, the model cannot reliably separate their individual effects. Coefficients become unstable — small changes in the data produce wildly different estimates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No influential outliers.&lt;/strong&gt; A single extreme observation can pull the regression line toward it, distorting coefficients for all other rows. The model minimises squared errors, so large errors have disproportionate influence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Normality of residuals.&lt;/strong&gt; Errors should be approximately normally distributed. This matters primarily for hypothesis testing on coefficients — calculating p-values and confidence intervals. It is less critical for prediction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Detecting Multicollinearity: VIF
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Variance Inflation Factor (VIF)&lt;/strong&gt; quantifies how much the variance of a coefficient is inflated due to multicollinearity:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;VIF = 1 / (1 - R²ⱼ)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Where R²ⱼ is the R² obtained when predicting feature j from all other features. If feature j can be predicted well from its peers, it is nearly redundant, and VIF will be high. A VIF above 10 is a serious signal; above 5 warrants attention.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;statsmodels.stats.outliers_influence&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;variance_inflation_factor&lt;/span&gt;

&lt;span class="n"&gt;X_with_constant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;X_numeric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;X_with_constant&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;constant&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="n"&gt;vif_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;VIF&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;variance_inflation_factor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_with_constant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_numeric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Part 2: Evaluating Model Performance
&lt;/h2&gt;

&lt;p&gt;Training a model is only half the work. The other half is understanding how well it performs — and, critically, whether that performance will hold on data the model has never seen.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Four Core Metrics
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mean Absolute Error (MAE)&lt;/strong&gt; is the average of the absolute prediction errors. It is easy to interpret — an MAE of 5,000 means predictions are off by approximately 5,000 units on average. It treats all errors equally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mean Squared Error (MSE)&lt;/strong&gt; squares the errors before averaging. This penalises large errors disproportionately. The units are squared, making direct interpretation difficult.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Root Mean Squared Error (RMSE)&lt;/strong&gt; is the square root of MSE, returning the metric to the original units. RMSE will always be equal to or larger than MAE. When the gap is large, outlier predictions exist. RMSE is appropriate when large errors are especially costly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;R² (Coefficient of Determination)&lt;/strong&gt; measures the proportion of variance in the target variable explained by the model:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;R² = 1 - (SS_residual / SS_total)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An R² of 0.96 means the model explains 96% of the variation in the target. The remaining 4% is attributable to factors outside the model or genuine randomness.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A critical limitation of R²:&lt;/strong&gt; adding any predictor — even a completely irrelevant one — will never decrease R². A model with shoe size as a feature will have equal or higher R² than one without it. This makes R² unreliable for comparing models with different numbers of features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Adjusted R²&lt;/strong&gt; corrects for this by applying a penalty for adding predictors that do not genuinely improve the model. It decreases when an irrelevant predictor is added and increases when a useful one is. Use Adjusted R² whenever comparing models with different feature counts.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Train-Test Split
&lt;/h3&gt;

&lt;p&gt;Performance metrics calculated on training data are meaningless as evaluation tools — the model has already seen that data and optimised itself against it. True evaluation requires testing on data the model has never encountered.&lt;/p&gt;

&lt;p&gt;The standard approach is to hold out a portion of data before training:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.model_selection&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;train_test_split&lt;/span&gt;

&lt;span class="n"&gt;X_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X_test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random_state&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;test_size=0.2&lt;/code&gt; reserves 20% for testing. &lt;code&gt;random_state=42&lt;/code&gt; makes the split reproducible. You train on &lt;code&gt;X_train&lt;/code&gt; and &lt;code&gt;y_train&lt;/code&gt;, then evaluate predictions on &lt;code&gt;X_test&lt;/code&gt; against &lt;code&gt;y_test&lt;/code&gt; — data the model never touched during training.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3: The Overfitting Problem
&lt;/h2&gt;

&lt;p&gt;On a salary prediction project using the job_salary_prediction_dataset, my plain linear regression model produced:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Training R²: 0.9634&lt;/li&gt;
&lt;li&gt;Test R²: 0.9635&lt;/li&gt;
&lt;li&gt;Gap: 0.0001&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a well-behaved model. The near-identical scores on training and test data indicate the model learned genuine patterns rather than memorising the training data's noise.&lt;/p&gt;

&lt;p&gt;But this result is not always guaranteed. The gap between training and test performance tells the real story.&lt;/p&gt;

&lt;h3&gt;
  
  
  Overfitting Defined
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Overfitting&lt;/strong&gt; occurs when a model learns the training data too specifically — including its noise, outliers, and dataset-specific quirks — and fails to generalise to new observations. It manifests as high training performance and substantially lower test performance.&lt;/p&gt;

&lt;p&gt;At the coefficient level, overfitting produces very large values. The model assigns extreme weights to certain features to minimise training error, at the expense of generalisation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Underfitting&lt;/strong&gt; is the opposite failure: the model is too simple to capture the underlying pattern and performs poorly on both training and test data.&lt;/p&gt;

&lt;p&gt;The tension between the two is formalised as the &lt;strong&gt;bias-variance tradeoff&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;High bias&lt;/strong&gt; (underfitting): the model consistently misses the true pattern. Rigid, makes systematic errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High variance&lt;/strong&gt; (overfitting): the model is too sensitive to the specific training data. Small changes in training data produce large changes in predictions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reducing bias typically increases variance, and vice versa. The goal is to find the model complexity that balances both.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 4: Regularization — Adding a Penalty
&lt;/h2&gt;

&lt;p&gt;Regularization addresses overfitting by modifying the cost function. Instead of minimising only the prediction error, the model simultaneously minimises prediction error and a penalty on the size of the coefficients. Large coefficients are discouraged, producing a simpler, more generalisable model.&lt;/p&gt;

&lt;p&gt;Three regularization techniques are widely used in practice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lasso Regression (L1)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cost = RSS + α × Σ|βⱼ|&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Lasso adds a penalty proportional to the &lt;strong&gt;sum of absolute values&lt;/strong&gt; of the coefficients. The parameter α controls the strength of the penalty: α = 0 reduces to plain linear regression, and increasing α progressively shrinks coefficients.&lt;/p&gt;

&lt;p&gt;The critical property of Lasso — a consequence of the geometry of the L1 penalty — is that it can push coefficients to &lt;strong&gt;exactly zero&lt;/strong&gt;. When a coefficient reaches zero, that feature is removed from the model entirely. Lasso performs &lt;strong&gt;automatic feature selection&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This makes Lasso valuable in high-dimensional settings where many features are suspected to be irrelevant. In the salary prediction project, running Lasso with α = 1 zeroed out &lt;code&gt;industry_Education&lt;/code&gt;, identifying it as a non-contributor to salary prediction. Increasing α to 1000 zeroed out 23 features — but at the cost of dropping the R² from 0.9635 to 0.7719. This is the bias-variance tradeoff made visible: the stronger the penalty, the simpler the model, and beyond a point, too simple to capture genuine patterns.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.linear_model&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Lasso&lt;/span&gt;

&lt;span class="n"&gt;lasso&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Lasso&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;lasso&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train_encoded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;lasso_pred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lasso&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_test_encoded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Lasso when:&lt;/strong&gt; you suspect many features are irrelevant and want the model to identify and remove them automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitation:&lt;/strong&gt; when two features are highly correlated, Lasso tends to arbitrarily select one and zero out the other, which may not reflect the true underlying structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ridge Regression (L2)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cost = RSS + α × Σβⱼ²&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ridge uses the &lt;strong&gt;sum of squared coefficients&lt;/strong&gt; as its penalty. The structure is nearly identical to Lasso, but the geometry of squaring means Ridge shrinks coefficients close to zero without ever reaching it exactly. Every feature remains in the model — only with reduced influence.&lt;/p&gt;

&lt;p&gt;This behaviour makes Ridge more appropriate when all features are expected to contribute something meaningful, and particularly when predictors are correlated. Ridge distributes the weight between correlated features more gracefully than Lasso's winner-take-all approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.linear_model&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Ridge&lt;/span&gt;

&lt;span class="n"&gt;ridge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Ridge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ridge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train_encoded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ridge_pred&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ridge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_test_encoded&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Ridge when:&lt;/strong&gt; all features are genuinely relevant, or when multicollinearity between predictors is a concern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Elastic Net (L1 + L2)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Cost = RSS + λ[α × Σ|βⱼ| + ((1-α)/2) × Σβⱼ²]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Elastic Net combines both penalties. The parameter &lt;code&gt;l1_ratio&lt;/code&gt; (α in the formula above) controls the blend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;l1_ratio = 1.0&lt;/code&gt; → pure Lasso&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;l1_ratio = 0.0&lt;/code&gt; → pure Ridge&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;l1_ratio = 0.5&lt;/code&gt; → equal mix&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This flexibility resolves the individual weaknesses of each: Elastic Net can zero out genuinely irrelevant features while handling correlated features more gracefully than Lasso alone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.linear_model&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ElasticNet&lt;/span&gt;

&lt;span class="n"&gt;elastic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ElasticNet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l1_ratio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;elastic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X_train_encoded&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use Elastic Net when:&lt;/strong&gt; you are uncertain whether Lasso or Ridge is more appropriate. It is a reliable default in high-dimensional problems.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 5: When to Use Each Approach
&lt;/h2&gt;

&lt;p&gt;The choice of regularization is not arbitrary — it should follow from what you know about your data and the problem structure.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Technique&lt;/th&gt;
&lt;th&gt;Penalty&lt;/th&gt;
&lt;th&gt;Zeros coefficients?&lt;/th&gt;
&lt;th&gt;Best suited for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Plain OLS&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No overfitting present&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lasso (L1)&lt;/td&gt;
&lt;td&gt;Absolute values&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Many irrelevant features&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ridge (L2)&lt;/td&gt;
&lt;td&gt;Squared values&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;All features relevant; high correlation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Elastic Net&lt;/td&gt;
&lt;td&gt;Both&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Uncertain — safe default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A practical workflow: always start with plain linear regression and evaluate the training-to-test gap. If the gap is small, regularization adds little value. If the gap is large, overfitting is present — try Lasso first if feature selection is desirable, Ridge if all features are believed to contribute, and Elastic Net when the situation is ambiguous.&lt;/p&gt;

&lt;p&gt;The strength of regularization (α) is a &lt;strong&gt;hyperparameter&lt;/strong&gt; — it is not learned from data but set by the analyst. Finding the optimal value requires cross-validation, a technique that evaluates model performance across multiple held-out subsets of the training data to identify the α that generalises best.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Regression is deceptively simple to implement and genuinely difficult to implement well. The gap between running &lt;code&gt;LinearRegression().fit(X_train, y_train)&lt;/code&gt; and building a model you can trust for decision-making lies in understanding what the model is doing, what assumptions it relies on, and where it will fail.&lt;/p&gt;

&lt;p&gt;Regularization is not a correction applied when something goes wrong — it is a deliberate modelling choice that encodes prior knowledge about the problem: that coefficients should be small, that some features are likely irrelevant, or that the training data is noisy. Making that choice thoughtfully, rather than defaulting to whatever produces the highest R², is the difference between fitting data and building models that work.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>datascience</category>
      <category>machinelearning</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why Statistics Is the Backbone of Data Science</title>
      <dc:creator>Kendi</dc:creator>
      <pubDate>Fri, 26 Jun 2026 05:55:28 +0000</pubDate>
      <link>https://dev.to/kendixy/why-statistics-is-the-backbone-of-data-science-33g0</link>
      <guid>https://dev.to/kendixy/why-statistics-is-the-backbone-of-data-science-33g0</guid>
      <description>&lt;p&gt;One of the biggest surprises I had while learning data science was realizing that Python isn't the hard part.&lt;/p&gt;

&lt;p&gt;You can learn Python in a few weeks. You can become comfortable with pandas pretty quickly. You can even train a machine learning model by following a tutorial.&lt;/p&gt;

&lt;p&gt;But none of that means you understand your data.&lt;/p&gt;

&lt;p&gt;That's where statistics comes in.&lt;/p&gt;

&lt;p&gt;A lot of beginners (myself included) focus on learning tools first because they're exciting. New libraries, dashboards, machine learning models. Statistics often feels like something you can come back to later.&lt;/p&gt;

&lt;p&gt;In reality, it's the opposite.&lt;/p&gt;

&lt;p&gt;Statistics isn't a side topic in data science. It's the reason the tools work in the first place.&lt;/p&gt;




&lt;h2&gt;
  
  
  Data only becomes useful when you understand what it represents
&lt;/h2&gt;

&lt;p&gt;Before running any analysis, the first question isn't &lt;em&gt;"Which model should I use?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It's &lt;em&gt;"What kind of data am I looking at?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Broadly speaking, data falls into two groups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Numerical data&lt;/strong&gt; consists of values you can measure or count. Sales, age, height, temperature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Categorical data&lt;/strong&gt; represents labels or groups. Blood type, product category, education level.&lt;/p&gt;

&lt;p&gt;That distinction matters more than most beginners realize.&lt;/p&gt;

&lt;p&gt;For example, calculating the average blood group doesn't make sense. Treating education levels as though the gap between each level is identical can also lead to misleading conclusions.&lt;/p&gt;

&lt;p&gt;Python won't stop you from making those mistakes.&lt;/p&gt;

&lt;p&gt;Statistics teaches you when a calculation actually makes sense.&lt;/p&gt;




&lt;h2&gt;
  
  
  A single number rarely tells the whole story
&lt;/h2&gt;

&lt;p&gt;Imagine two classes that both have an average score of 50.&lt;/p&gt;

&lt;p&gt;At first glance, you'd think they performed similarly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;class_A&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;52&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;class_B&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both classes have exactly the same mean.&lt;/p&gt;

&lt;p&gt;But they're clearly very different.&lt;/p&gt;

&lt;p&gt;In Class A, almost everyone performed similarly.&lt;/p&gt;

&lt;p&gt;In Class B, performance varied dramatically.&lt;/p&gt;

&lt;p&gt;That's why summary statistics come in pairs.&lt;/p&gt;

&lt;p&gt;Measures like the &lt;strong&gt;mean, median, and mode&lt;/strong&gt; tell you where the center of the data lies.&lt;/p&gt;

&lt;p&gt;Measures like &lt;strong&gt;standard deviation, variance, range, and IQR&lt;/strong&gt; tell you how spread out the data is.&lt;/p&gt;

&lt;p&gt;Looking at only one is like reading only half the sentence.&lt;/p&gt;




&lt;h2&gt;
  
  
  The median isn't a backup plan
&lt;/h2&gt;

&lt;p&gt;When people first learn statistics, they often think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Use the mean whenever possible. If it doesn't work, use the median."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not really how it works.&lt;/p&gt;

&lt;p&gt;The mean uses every value in the dataset, which makes it powerful—but also sensitive to extreme values.&lt;/p&gt;

&lt;p&gt;Imagine 99 people earn KES 30,000 each month, while one person earns KES 10 million.&lt;/p&gt;

&lt;p&gt;The average income suddenly becomes much higher than what almost everyone actually earns.&lt;/p&gt;

&lt;p&gt;The median ignores those extremes and simply finds the middle value.&lt;/p&gt;

&lt;p&gt;Sometimes that's a much better description of what's "typical."&lt;/p&gt;

&lt;p&gt;Choosing between the mean and median isn't about memorizing rules.&lt;/p&gt;

&lt;p&gt;It's about understanding your data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Outliers aren't always mistakes
&lt;/h2&gt;

&lt;p&gt;One of the first instincts many people have is to delete values that look unusual.&lt;/p&gt;

&lt;p&gt;Sometimes that's the right decision.&lt;/p&gt;

&lt;p&gt;If someone accidentally entered 250 instead of 25, that's probably a data entry error.&lt;/p&gt;

&lt;p&gt;But sometimes the unusual value is exactly what you're looking for.&lt;/p&gt;

&lt;p&gt;If you're building a fraud detection system, the suspicious transactions are the most valuable observations in your dataset.&lt;/p&gt;

&lt;p&gt;Statistics gives us a systematic way to flag potential outliers using the IQR rule.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lower fence = Q1 − (1.5 × IQR)

Upper fence = Q3 + (1.5 × IQR)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anything outside those boundaries is flagged for investigation.&lt;/p&gt;

&lt;p&gt;Notice the wording.&lt;/p&gt;

&lt;p&gt;Flagged—not automatically deleted.&lt;/p&gt;

&lt;p&gt;Statistics helps identify unusual observations.&lt;/p&gt;

&lt;p&gt;Context tells you what to do with them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Machine learning doesn't replace statistics
&lt;/h2&gt;

&lt;p&gt;Every machine learning algorithm makes assumptions.&lt;/p&gt;

&lt;p&gt;Linear regression assumes linear relationships and normally distributed residuals.&lt;/p&gt;

&lt;p&gt;Naive Bayes assumes features are conditionally independent.&lt;/p&gt;

&lt;p&gt;K-Means works best when clusters are reasonably compact and roughly spherical.&lt;/p&gt;

&lt;p&gt;If those assumptions don't hold, your model may still produce predictions.&lt;/p&gt;

&lt;p&gt;They just won't be reliable.&lt;/p&gt;

&lt;p&gt;Understanding statistics helps you know when to trust a model—and when not to.&lt;/p&gt;




&lt;h2&gt;
  
  
  The part of data science that doesn't become obsolete
&lt;/h2&gt;

&lt;p&gt;Libraries change.&lt;/p&gt;

&lt;p&gt;Frameworks change.&lt;/p&gt;

&lt;p&gt;The code you write today may look outdated in a few years.&lt;/p&gt;

&lt;p&gt;But the important questions stay the same.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does this distribution tell me?&lt;/li&gt;
&lt;li&gt;Is this difference meaningful or just random variation?&lt;/li&gt;
&lt;li&gt;Is this outlier important or just an error?&lt;/li&gt;
&lt;li&gt;Can I trust this result?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are statistical questions.&lt;/p&gt;

&lt;p&gt;And they're the questions that separate someone who can write code from someone who can genuinely analyze data.&lt;/p&gt;

&lt;p&gt;If you're starting your journey into data science, don't treat statistics as something to learn later.&lt;/p&gt;

&lt;p&gt;It's the foundation that makes everything else make sense.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>datascience</category>
      <category>learning</category>
    </item>
    <item>
      <title>Power BI Data Modeling Explained Simply: Joins, Relationships, and Schemas</title>
      <dc:creator>Kendi</dc:creator>
      <pubDate>Sat, 28 Mar 2026 20:43:42 +0000</pubDate>
      <link>https://dev.to/kendixy/power-bi-data-modeling-explained-simply-joins-relationships-and-schemas-b0a</link>
      <guid>https://dev.to/kendixy/power-bi-data-modeling-explained-simply-joins-relationships-and-schemas-b0a</guid>
      <description>&lt;p&gt;Here is something nobody tells you when you start learning Power BI: the visuals are the easy part. Anyone can drag a bar chart onto a canvas. What separates a report that works from one that lies to you is what happens before you touch a single visual — the data model.&lt;/p&gt;

&lt;p&gt;Get the model right and your numbers are accurate, your reports are fast, and your DAX measures are simple. Get it wrong and no amount of formatting or fancy visuals will fix it. You will just have a beautifully designed wrong answer.&lt;/p&gt;

&lt;p&gt;This article covers everything you need to build models that actually work.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Data Modeling?
&lt;/h2&gt;

&lt;p&gt;Data modeling is the process of organizing your tables and defining how they connect to each other so that analysis is accurate, efficient, and scalable.&lt;/p&gt;

&lt;p&gt;In Power BI specifically, your data model determines three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Whether your calculations are correct&lt;/li&gt;
&lt;li&gt;How fast your report runs&lt;/li&gt;
&lt;li&gt;How easily someone can explore the data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A weak model produces incorrect aggregations, duplicate counts, and reports that take forever to load. A strong model makes all of that disappear.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 1: SQL Joins — Combining Tables in Power Query
&lt;/h2&gt;

&lt;p&gt;Joins are how you physically combine two tables into one based on a shared column called a key. In Power BI, joins happen in &lt;strong&gt;Power Query&lt;/strong&gt; during data preparation — before anything reaches your model.&lt;/p&gt;

&lt;p&gt;Let us use a consistent example throughout. You have two tables:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Staff Table&lt;/strong&gt;&lt;br&gt;
| StaffID | StaffName |&lt;br&gt;
|---------|-----------|&lt;br&gt;
| S01 | James |&lt;br&gt;
| S02 | Amina |&lt;br&gt;
| S03 | Peter |&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Training Table&lt;/strong&gt;&lt;br&gt;
| StaffID | Course |&lt;br&gt;
|---------|--------|&lt;br&gt;
| S01 | Excel |&lt;br&gt;
| S02 | Power BI |&lt;br&gt;
| S04 | SQL |&lt;/p&gt;

&lt;p&gt;Notice: Peter (S03) has no training record. The SQL course (S04) has no matching staff member. This mismatch is exactly what each join type handles differently.&lt;/p&gt;


&lt;h3&gt;
  
  
  INNER JOIN — Only What Matches in Both
&lt;/h3&gt;

&lt;p&gt;Returns rows that have a match in &lt;strong&gt;both&lt;/strong&gt; tables. Anything without a match on either side is excluded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
| StaffID | StaffName | Course |&lt;br&gt;
|---------|-----------|--------|&lt;br&gt;
| S01 | James | Excel |&lt;br&gt;
| S02 | Amina | Power BI |&lt;/p&gt;

&lt;p&gt;Peter is excluded — no training record. The SQL course is excluded — no matching staff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; A clean attendance report showing only staff with confirmed training records.&lt;/p&gt;


&lt;h3&gt;
  
  
  LEFT JOIN — Keep Everything on the Left
&lt;/h3&gt;

&lt;p&gt;Returns all rows from the left table. Rows from the right table are included only where a match exists. No match means null.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
| StaffID | StaffName | Course |&lt;br&gt;
|---------|-----------|--------|&lt;br&gt;
| S01 | James | Excel |&lt;br&gt;
| S02 | Amina | Power BI |&lt;br&gt;
| S03 | Peter | null |&lt;/p&gt;

&lt;p&gt;Peter stays — but his Course is null because no training record exists for him.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; All staff members, flagging those who have not yet completed any training.&lt;/p&gt;


&lt;h3&gt;
  
  
  RIGHT JOIN — Keep Everything on the Right
&lt;/h3&gt;

&lt;p&gt;Mirror of the LEFT JOIN. All rows from the right table are kept. Left table rows are included only where a match exists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
| StaffID | StaffName | Course |&lt;br&gt;
|---------|-----------|--------|&lt;br&gt;
| S01 | James | Excel |&lt;br&gt;
| S02 | Amina | Power BI |&lt;br&gt;
| S04 | null | SQL |&lt;/p&gt;

&lt;p&gt;The SQL course stays — but StaffName is null because S04 does not exist in the Staff table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; All training courses offered, identifying any assigned to staff members who no longer exist in the system.&lt;/p&gt;


&lt;h3&gt;
  
  
  FULL OUTER JOIN — Everything from Both Tables
&lt;/h3&gt;

&lt;p&gt;Returns every row from both tables. Where there is no match, nulls fill the gap on the missing side. Nothing is excluded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
| StaffID | StaffName | Course |&lt;br&gt;
|---------|-----------|--------|&lt;br&gt;
| S01 | James | Excel |&lt;br&gt;
| S02 | Amina | Power BI |&lt;br&gt;
| S03 | Peter | null |&lt;br&gt;
| S04 | null | SQL |&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; A full audit comparing your HR system against your training system — surfacing every mismatch in both directions at once.&lt;/p&gt;


&lt;h3&gt;
  
  
  LEFT ANTI JOIN — Only the Unmatched Left Rows
&lt;/h3&gt;

&lt;p&gt;Returns only rows from the left table that have &lt;strong&gt;no match&lt;/strong&gt; in the right table. The opposite of an INNER JOIN in a sense.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
| StaffID | StaffName |&lt;br&gt;
|---------|-----------|&lt;br&gt;
| S03 | Peter |&lt;/p&gt;

&lt;p&gt;Only Peter — the staff member with no training record.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Finding staff members who have not attended any training. A compliance check.&lt;/p&gt;


&lt;h3&gt;
  
  
  RIGHT ANTI JOIN — Only the Unmatched Right Rows
&lt;/h3&gt;

&lt;p&gt;Returns only rows from the right table that have no match in the left table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;br&gt;
| StaffID | Course |&lt;br&gt;
|---------|--------|&lt;br&gt;
| S04 | SQL |&lt;/p&gt;

&lt;p&gt;Only the SQL course — assigned to a StaffID that does not exist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use case:&lt;/strong&gt; Identifying orphaned records in a system — training records pointing to staff members who no longer exist.&lt;/p&gt;


&lt;h3&gt;
  
  
  How to Create Joins in Power Query
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Home tab → Transform Data&lt;/strong&gt; to open Power Query Editor&lt;/li&gt;
&lt;li&gt;Select the table you want as your left table&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Home tab → Merge Queries&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select the second table from the dropdown&lt;/li&gt;
&lt;li&gt;Click the matching column in each table to set the key&lt;/li&gt;
&lt;li&gt;Choose your &lt;strong&gt;Join Kind&lt;/strong&gt; from the dropdown&lt;/li&gt;
&lt;li&gt;Click OK&lt;/li&gt;
&lt;li&gt;Click the expand icon on the new merged column to select which columns to bring in&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  Join Summary Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Join Type&lt;/th&gt;
&lt;th&gt;Keeps from Left&lt;/th&gt;
&lt;th&gt;Keeps from Right&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Inner&lt;/td&gt;
&lt;td&gt;Matching only&lt;/td&gt;
&lt;td&gt;Matching only&lt;/td&gt;
&lt;td&gt;Clean matched data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Left&lt;/td&gt;
&lt;td&gt;All rows&lt;/td&gt;
&lt;td&gt;Matching only&lt;/td&gt;
&lt;td&gt;Enrich left, flag gaps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Right&lt;/td&gt;
&lt;td&gt;Matching only&lt;/td&gt;
&lt;td&gt;All rows&lt;/td&gt;
&lt;td&gt;Enrich right, flag gaps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Full Outer&lt;/td&gt;
&lt;td&gt;All rows&lt;/td&gt;
&lt;td&gt;All rows&lt;/td&gt;
&lt;td&gt;Full system audit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Left Anti&lt;/td&gt;
&lt;td&gt;Unmatched only&lt;/td&gt;
&lt;td&gt;Nothing&lt;/td&gt;
&lt;td&gt;Find missing references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Right Anti&lt;/td&gt;
&lt;td&gt;Nothing&lt;/td&gt;
&lt;td&gt;Unmatched only&lt;/td&gt;
&lt;td&gt;Find orphaned records&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  Part 2: Power BI Relationships — Joins vs Relationships
&lt;/h2&gt;

&lt;p&gt;This distinction trips up almost everyone starting out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A join physically merges two tables into one.&lt;/strong&gt; The result is a single flat table. You use this during data preparation in Power Query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A relationship keeps tables separate and creates a logical filter connection between them.&lt;/strong&gt; The data stays in its own table. Power BI uses the relationship to know how filters should flow when someone interacts with a report.&lt;/p&gt;

&lt;p&gt;In most professional Power BI models, relationships handle the core structure. Joins are reserved for specific data preparation steps where you genuinely need to flatten or enrich a table before loading it into the model.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Joins&lt;/th&gt;
&lt;th&gt;Relationships&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Where&lt;/td&gt;
&lt;td&gt;Power Query&lt;/td&gt;
&lt;td&gt;Model View&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tables&lt;/td&gt;
&lt;td&gt;Physically combined&lt;/td&gt;
&lt;td&gt;Stay separate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Heavier&lt;/td&gt;
&lt;td&gt;More efficient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flexibility&lt;/td&gt;
&lt;td&gt;Static&lt;/td&gt;
&lt;td&gt;Dynamic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use for&lt;/td&gt;
&lt;td&gt;Data preparation&lt;/td&gt;
&lt;td&gt;Analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h3&gt;
  
  
  How to Create Relationships in Power BI
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Method 1 — Drag and drop in Model View:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click the &lt;strong&gt;Model View&lt;/strong&gt; icon on the left sidebar&lt;/li&gt;
&lt;li&gt;Find the key column in one table&lt;/li&gt;
&lt;li&gt;Drag it onto the matching key column in the other table&lt;/li&gt;
&lt;li&gt;A relationship line connects the two tables&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Method 2 — Manage Relationships:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Modeling tab → Manage Relationships&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select both tables and their matching columns&lt;/li&gt;
&lt;li&gt;Set cardinality and cross-filter direction&lt;/li&gt;
&lt;li&gt;Click OK&lt;/li&gt;
&lt;/ol&gt;


&lt;h3&gt;
  
  
  Cardinality — What Kind of Relationship Is It?
&lt;/h3&gt;
&lt;h4&gt;
  
  
  One-to-Many (1:M) — Use This as Your Default
&lt;/h4&gt;

&lt;p&gt;One row in the first table matches many rows in the second.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; One Department can have many Employees. The Departments table lists each department once. The Employees table has that department ID repeated across many rows.&lt;/p&gt;

&lt;p&gt;This is the most common, most efficient, and most reliable relationship type in Power BI. Build your model around 1:M relationships wherever possible. In Model View it shows as &lt;strong&gt;1&lt;/strong&gt; on one side and ***** on the other.&lt;/p&gt;
&lt;h4&gt;
  
  
  Many-to-Many (M:M) — Use With Real Caution
&lt;/h4&gt;

&lt;p&gt;Many rows in both tables can match each other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Doctors and Hospitals. One doctor works at multiple hospitals. One hospital employs multiple doctors.&lt;/p&gt;

&lt;p&gt;Power BI supports M:M natively but it introduces ambiguous filtering and can produce incorrect totals. Where possible, resolve M:M by introducing a bridge table — a third table that breaks the relationship into two clean 1:M relationships.&lt;/p&gt;
&lt;h4&gt;
  
  
  One-to-One (1:1) — Rare and Usually Unnecessary
&lt;/h4&gt;

&lt;p&gt;Each row in one table matches exactly one row in the other.&lt;/p&gt;

&lt;p&gt;If you have a 1:1 relationship, ask yourself honestly whether these tables should just be merged. They usually should.&lt;/p&gt;


&lt;h3&gt;
  
  
  Active vs Inactive Relationships
&lt;/h3&gt;

&lt;p&gt;Power BI allows only &lt;strong&gt;one active relationship&lt;/strong&gt; between any two tables. Active relationships are what visuals and DAX measures use by default. Additional relationships between the same tables must be inactive — shown as dashed lines in Model View.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When do you need inactive relationships?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Date table connected to a fact table with multiple date columns is the classic case. Say your Orders table has OrderDate, ShipDate, and DeliveryDate. You can only have one active relationship to your Date table. The others are inactive.&lt;/p&gt;

&lt;p&gt;To use an inactive relationship in a measure, activate it temporarily with USERELATIONSHIP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sales by Ship Date = CALCULATE(
    SUM(Orders[Revenue]),
    USERELATIONSHIP(Orders[ShipDate], Calendar[Date])
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This measure calculates revenue filtered by ShipDate instead of the default OrderDate — without permanently changing the model.&lt;/p&gt;




&lt;h3&gt;
  
  
  Cross-Filter Direction — Which Way Do Filters Flow?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Single direction:&lt;/strong&gt; Filters flow from the "one" side to the "many" side only. This is the default and the right choice for most relationships.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Both directions (bidirectional):&lt;/strong&gt; Filters flow both ways simultaneously.&lt;/p&gt;

&lt;p&gt;Bidirectional sounds helpful but it creates real problems — ambiguous filter paths, performance degradation, and measures that produce incorrect results in ways that are very hard to diagnose. Start with single direction always. Only consider bidirectional after testing confirms you genuinely need it and the behavior is correct.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 3: Fact Tables and Dimension Tables
&lt;/h2&gt;

&lt;p&gt;Every professional data model is built around this distinction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fact Tables
&lt;/h3&gt;

&lt;p&gt;A fact table stores &lt;strong&gt;measurable events&lt;/strong&gt; — things that happened. Each row is one transaction or event.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contains numbers you want to measure: revenue, quantity, duration, count&lt;/li&gt;
&lt;li&gt;Contains foreign keys that point to dimension tables&lt;/li&gt;
&lt;li&gt;Typically long — many rows&lt;/li&gt;
&lt;li&gt;Typically narrow — few columns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt; Hospital admissions, e-commerce orders, bank transactions, flight bookings&lt;/p&gt;

&lt;h3&gt;
  
  
  Dimension Tables
&lt;/h3&gt;

&lt;p&gt;A dimension table stores &lt;strong&gt;descriptive context&lt;/strong&gt; about those events — the who, what, where, and when.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contains descriptive attributes: names, categories, locations, dates&lt;/li&gt;
&lt;li&gt;Contains a primary key that the fact table references&lt;/li&gt;
&lt;li&gt;Typically short — few rows&lt;/li&gt;
&lt;li&gt;Typically wide — many columns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt; Patients, Products, Branches, Calendar&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The practical rule:&lt;/strong&gt; Your slicers and filters come from dimension tables. Your aggregations and measures come from fact tables. Keep them separate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 4: Schemas — The Overall Shape of Your Model
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Star Schema — Start Here Every Time
&lt;/h3&gt;

&lt;p&gt;A central fact table connects directly to surrounding dimension tables. One hop from any dimension to the fact. No chains.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              [Calendar]
                  |
[Customer] — [Sales Fact] — [Product]
                  |
              [Branch]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean, fast, easy to maintain. Power BI's calculation engine is specifically optimized for this structure. Your DAX measures will be simpler and your reports will be faster on a star schema than any other structure. This is the recommended starting point for almost every Power BI model.&lt;/p&gt;




&lt;h3&gt;
  
  
  Snowflake Schema — Normalized but Complex
&lt;/h3&gt;

&lt;p&gt;Dimension tables are broken into sub-dimensions connected in chains.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Region] ← [Branch] — [Sales Fact] — [Product] → [Category] → [Department]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of a single Branch dimension with Region included as a column, Region becomes its own separate table connected to Branch.&lt;/p&gt;

&lt;p&gt;This reduces data redundancy — useful in enterprise data warehouses where storage and integrity matter. In Power BI reporting however, the additional complexity adds joins, slows queries, and makes the model harder to navigate. If your source data arrives in a snowflake structure, consider flattening dimension chains in Power Query before loading into the model.&lt;/p&gt;




&lt;h3&gt;
  
  
  Flat Table (Denormalized) — Simple but Limited
&lt;/h3&gt;

&lt;p&gt;Everything — facts and dimensions — in a single table. No relationships needed.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;OrderDate&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;th&gt;City&lt;/th&gt;
&lt;th&gt;ProductName&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Revenue&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;01/03/2026&lt;/td&gt;
&lt;td&gt;James&lt;/td&gt;
&lt;td&gt;Nairobi&lt;/td&gt;
&lt;td&gt;Laptop&lt;/td&gt;
&lt;td&gt;Electronics&lt;/td&gt;
&lt;td&gt;85000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;02/03/2026&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;Mombasa&lt;/td&gt;
&lt;td&gt;Phone&lt;/td&gt;
&lt;td&gt;Electronics&lt;/td&gt;
&lt;td&gt;42000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Fast to build, easy to understand. But "Electronics" is repeated in every electronics row. Change a category name and you are updating thousands of cells. Performance degrades quickly as row count grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use flat tables for:&lt;/strong&gt; Quick one-off analysis, very small datasets, early prototyping before building a proper model. Avoid them for anything that will be maintained, updated, or scaled.&lt;/p&gt;




&lt;h3&gt;
  
  
  Schema Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Schema&lt;/th&gt;
&lt;th&gt;Structure&lt;/th&gt;
&lt;th&gt;Performance&lt;/th&gt;
&lt;th&gt;Complexity&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Star&lt;/td&gt;
&lt;td&gt;Fact + direct dimensions&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Most Power BI reporting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snowflake&lt;/td&gt;
&lt;td&gt;Fact + chained dimensions&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Medium&lt;/td&gt;
&lt;td&gt;Enterprise warehouses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flat&lt;/td&gt;
&lt;td&gt;Single table&lt;/td&gt;
&lt;td&gt;Poor at scale&lt;/td&gt;
&lt;td&gt;Very low&lt;/td&gt;
&lt;td&gt;Small, simple, one-off&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Part 5: Role-Playing Dimensions
&lt;/h2&gt;

&lt;p&gt;A role-playing dimension is one dimension table used multiple times in the same model, each time in a different context.&lt;/p&gt;

&lt;p&gt;The Date table is the most common example. A Hospital fact table might have AdmissionDate, DischargeDate, and SurgeryDate — all referencing the same Calendar dimension but each representing a different point in time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution 1 — One active, rest inactive:&lt;/strong&gt;&lt;br&gt;
Create one active relationship between Calendar and AdmissionDate. Create inactive relationships to DischargeDate and SurgeryDate. Use USERELATIONSHIP in DAX when you need the inactive ones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Discharges This Month = CALCULATE(
    COUNT(Admissions[PatientID]),
    USERELATIONSHIP(Admissions[DischargeDate], Calendar[Date])
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution 2 — Duplicate the dimension table:&lt;/strong&gt;&lt;br&gt;
Create three separate Calendar tables — AdmissionCalendar, DischargeCalendar, SurgeryCalendar — each with its own active relationship. More relationships to maintain but no inactive relationship complexity in DAX.&lt;/p&gt;

&lt;p&gt;For most scenarios, Solution 1 is cleaner.&lt;/p&gt;




&lt;h2&gt;
  
  
  Part 6: Common Modeling Issues
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Many-to-Many without a bridge table&lt;/strong&gt;&lt;br&gt;
Connecting two fact tables directly produces unreliable totals. Fix by introducing a shared dimension table that both relate to through 1:M relationships.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bidirectional filtering everywhere&lt;/strong&gt;&lt;br&gt;
Slows the model and creates ambiguous results. Default to single direction. Only use Both direction after deliberate testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Circular relationships&lt;/strong&gt;&lt;br&gt;
Table A → Table B → Table C → Table A creates a loop Power BI cannot resolve. Fix by identifying and removing the redundant relationship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No dedicated Date table&lt;/strong&gt;&lt;br&gt;
Using date columns from fact tables directly breaks time intelligence functions. Always create a continuous Date dimension table, mark it as a Date table in Power BI (right-click table in Model View → Mark as Date Table), and use it as the single source for all date filtering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Loading unnecessary columns&lt;/strong&gt;&lt;br&gt;
Every column you load into the model consumes memory. In Power Query, remove columns you will not use before loading. Keep the model lean.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Recommended Workflow
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1 — Load your data&lt;/strong&gt; into Power Query&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2 — Clean and prepare&lt;/strong&gt; using joins and transformations in Power Query&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3 — Build the model&lt;/strong&gt; in Model View using 1:M relationships in a star schema&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4 — Create a Date table&lt;/strong&gt; and mark it appropriately&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5 — Write DAX measures&lt;/strong&gt; on top of the clean model&lt;/p&gt;

&lt;p&gt;Following this sequence means your measures are built on a solid foundation. Skipping to DAX before the model is right is the most common reason Power BI reports produce numbers nobody trusts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;The most important insight in data modeling is also the simplest one: &lt;strong&gt;keep facts and dimensions separate, connect them with 1:M relationships, and structure them as a star.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Everything else in this article — the join types, cardinality options, schema variations, role-playing dimensions — is either building on that foundation or explaining what happens when you deviate from it.&lt;/p&gt;

&lt;p&gt;Master the star schema with clean 1:M relationships first. You will handle 90% of real-world Power BI modeling scenarios with that alone.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Part of my data science learning journey.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>beginners</category>
      <category>data</category>
      <category>database</category>
    </item>
    <item>
      <title>How Excel is Used in Real-World Data Analysis</title>
      <dc:creator>Kendi</dc:creator>
      <pubDate>Wed, 25 Mar 2026 13:10:38 +0000</pubDate>
      <link>https://dev.to/kendixy/how-excel-is-used-in-real-world-data-analysis-db4</link>
      <guid>https://dev.to/kendixy/how-excel-is-used-in-real-world-data-analysis-db4</guid>
      <description>&lt;h2&gt;
  
  
  How Excel is Used in Real-World Data Analysis
&lt;/h2&gt;

&lt;p&gt;Excel is a spreadsheet application by Microsoft that organizes data into a grid of rows and columns. Each box in that grid is called a cell, and each cell can hold a number, text, a date, or a formula that calculates something automatically.&lt;/p&gt;

&lt;p&gt;On top of that grid, Excel gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hundreds of built-in functions for math, text, dates, and logic&lt;/li&gt;
&lt;li&gt;Power Query for importing and transforming data from any source&lt;/li&gt;
&lt;li&gt;PivotTables that summarize thousands of rows in seconds&lt;/li&gt;
&lt;li&gt;Charts and visualizations that turn numbers into stories&lt;/li&gt;
&lt;li&gt;Data validation to control what gets entered into cells&lt;/li&gt;
&lt;li&gt;Conditional formatting that highlights patterns automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Excel is used in finance, healthcare, logistics, marketing, research, and government — basically anywhere data exists and decisions need to be made. It sits at a sweet spot between accessibility and depth. A beginner can use it on day one. An expert can still find new things to learn after years.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Used Excel in a Real Project
&lt;/h2&gt;

&lt;p&gt;For a recent project I analyzed product performance data from Jumia — one of Africa's largest e-commerce platforms — covering product prices, discounts, customer reviews, and ratings. Here is exactly how I approached it.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Make a Copy of Your Original Data
&lt;/h3&gt;

&lt;p&gt;Before touching anything, I created a copy of the raw data and kept the original sheet untouched. Data cleaning is destructive — you delete rows, overwrite values, change formats. Without a backup, there is no going back.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Understand Your Data Before Changing Anything
&lt;/h3&gt;

&lt;p&gt;I used &lt;strong&gt;CTRL + END&lt;/strong&gt; to see how many rows and columns I had, then scrolled through to spot obvious problems — price columns with "KSh" symbols, ratings stored as text like "4.5 out of 5", negative review counts, and blank cells scattered throughout.&lt;/p&gt;

&lt;p&gt;Understanding your data first tells you exactly what needs fixing and in what order. It prevents you from applying the wrong solution to the wrong problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Data Cleaning — Where the Real Work Happens
&lt;/h3&gt;

&lt;p&gt;Data cleaning is unglamorous but it is the foundation everything else stands on. In professional data work it takes 60 to 80 percent of total project time. The key steps I worked through were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Removing duplicates&lt;/strong&gt; — ensuring each product appeared only once using Data tab → Remove Duplicates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixing data types&lt;/strong&gt; — converting price columns from text to numbers, extracting numeric ratings from text like "4.5 out of 5"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Handling missing values&lt;/strong&gt; — replacing blank cells with the column average rather than deleting rows and losing data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardizing text&lt;/strong&gt; — making sure category values like "Nairobi" and "nairobi" were consistent using PROPER, UPPER, and LOWER functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is exciting. All of it is essential.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Formulas That Fascinated Me
&lt;/h2&gt;

&lt;h3&gt;
  
  
  XLOOKUP — The Lookup Function Excel Should Have Had From the Start
&lt;/h3&gt;

&lt;p&gt;Before XLOOKUP, the standard way to look up data was VLOOKUP — and it had serious limitations. It could only search left to right, broke silently when columns were inserted, and required hardcoded column numbers that made formulas fragile.&lt;/p&gt;

&lt;p&gt;XLOOKUP fixes all of that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=XLOOKUP(lookup_value, lookup_range, return_range, if_not_found)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It searches in any direction, handles missing values natively, uses column names instead of numbers, and can return multiple columns at once. One formula replaces what used to require complex workarounds.&lt;/p&gt;

&lt;p&gt;The one caveat — XLOOKUP is only available in Excel 2021 and Microsoft 365. If you are on an older version, INDEX/MATCH is the next best alternative.&lt;/p&gt;

&lt;h3&gt;
  
  
  IFS — Replacing Messy Nested IFs
&lt;/h3&gt;

&lt;p&gt;IFS checks multiple conditions in sequence and returns the first match. It replaced what would otherwise be deeply nested IF statements that are almost impossible to read or debug.&lt;/p&gt;

&lt;p&gt;For example, classifying products by rating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=IFS(F2&amp;gt;=4.5, "Excellent", F2&amp;gt;=3, "Average", F2&amp;lt;3, "Poor")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean, readable, and easy to update. Nesting three IFs inside each other to do the same thing is a maintenance nightmare.&lt;/p&gt;

&lt;h3&gt;
  
  
  PivotTables — Summarizing Data Without a Single Formula
&lt;/h3&gt;

&lt;p&gt;A PivotTable takes your raw data and lets you summarize it any way you want — by category, by date, by product — without writing a single formula. You drag fields into rows, columns, and values, and Excel does the rest.&lt;/p&gt;

&lt;p&gt;One tip that makes PivotTables significantly more reliable: convert your clean data into an Excel Table first using &lt;strong&gt;CTRL + T&lt;/strong&gt;. Tables expand automatically when new rows are added, so your PivotTable always captures the full dataset on refresh.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Dashboard — Making Data Usable for Everyone
&lt;/h3&gt;

&lt;p&gt;The final step was bringing everything together in an interactive dashboard — a single sheet where any business stakeholder could explore the data without touching the underlying numbers. KPI cards at the top, charts in the middle, and slicers that filter every chart simultaneously with a single click.&lt;/p&gt;

&lt;p&gt;This is the difference between data analysis and data communication. The numbers only matter if the right people can read them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The formulas are learnable. The functions have documentation. What nobody tells you is that the hardest part of data analysis is not the technical side — it is the discipline.&lt;/p&gt;

&lt;p&gt;The discipline to make a backup before touching anything. The discipline to understand your data before changing it. The discipline to clean thoroughly before analyzing. The discipline to question your results before presenting them.&lt;/p&gt;

&lt;p&gt;Excel gave me powerful tools. But the two steps that made the biggest difference were the simplest ones — making a copy of the original data and actually reading through it before writing a single formula.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Written as part of a data science learning program at LuxDev HQ.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>datascience</category>
      <category>analytics</category>
    </item>
  </channel>
</rss>
