<?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: Antonina Wambui</title>
    <description>The latest articles on DEV Community by Antonina Wambui (@analystnina).</description>
    <link>https://dev.to/analystnina</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%2F4084610%2F507903d0-90c1-46a7-8862-59fed3c355c8.jpg</url>
      <title>DEV Community: Antonina Wambui</title>
      <link>https://dev.to/analystnina</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/analystnina"/>
    <language>en</language>
    <item>
      <title>Turning Vehicle Sales Data into Actionable Business Intelligence: A Power BI Analysis of JCars Logistics</title>
      <dc:creator>Antonina Wambui</dc:creator>
      <pubDate>Wed, 30 Sep 2026 14:05:58 +0000</pubDate>
      <link>https://dev.to/analystnina/turning-vehicle-sales-data-into-actionable-business-intelligence-a-power-bi-analysis-of-jcars-2dp7</link>
      <guid>https://dev.to/analystnina/turning-vehicle-sales-data-into-actionable-business-intelligence-a-power-bi-analysis-of-jcars-2dp7</guid>
      <description>&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;Business data is only useful when it can support better decisions.&lt;/p&gt;

&lt;p&gt;For JCars Logistics, vehicle sales records contain information about customers, vehicles, branches, payments, deliveries, revenue and costs. However, the original dataset contained inconsistencies that could affect the reliability of analysis.&lt;/p&gt;

&lt;p&gt;This project uses &lt;strong&gt;Power BI&lt;/strong&gt; to transform the raw vehicle-sales data into a structured business intelligence solution.&lt;/p&gt;

&lt;p&gt;The analysis focuses on four main areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sales performance&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Financial performance&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operational efficiency&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customer and market behaviour&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rather than looking only at total sales, the project investigates where revenue is coming from, where costs are affecting profitability, how branches are performing, and which transactions require further attention.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Project Objective:&lt;/strong&gt;&lt;br&gt;
To transform raw vehicle sales data into an interactive Power BI solution that helps management understand performance, identify operational issues and make data-informed decisions.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Understanding the Dataset
&lt;/h2&gt;

&lt;p&gt;The original dataset contained &lt;strong&gt;276 transaction records and 32 columns&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Each row represents &lt;strong&gt;one vehicle sold in one sales transaction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The dataset contained information from several areas of the business:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Business Area&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Transactions&lt;/td&gt;
&lt;td&gt;Order ID, Order Date, Delivery Date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customers&lt;/td&gt;
&lt;td&gt;Customer Name, Customer Type, Age&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vehicles&lt;/td&gt;
&lt;td&gt;Make, Model, Vehicle Type, Fuel Type&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geography&lt;/td&gt;
&lt;td&gt;Region, County, City, Branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sales&lt;/td&gt;
&lt;td&gt;Sales Representative, Lead Source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finance&lt;/td&gt;
&lt;td&gt;Selling Price, Cost, Discount, Revenue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operations&lt;/td&gt;
&lt;td&gt;Delivery, Logistics, Payment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customer Experience&lt;/td&gt;
&lt;td&gt;Rating, Reviews&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The transaction-level grain was retained during the transformation process.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Data Quality Assessment
&lt;/h2&gt;

&lt;p&gt;Before creating the Power BI model, the dataset was assessed for data-quality problems.&lt;/p&gt;

&lt;p&gt;Several issues were identified, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inconsistent Order ID formats&lt;/li&gt;
&lt;li&gt;Multiple date formats&lt;/li&gt;
&lt;li&gt;Invalid customer ages&lt;/li&gt;
&lt;li&gt;Multiple currencies&lt;/li&gt;
&lt;li&gt;Inconsistent category names&lt;/li&gt;
&lt;li&gt;Incorrect or questionable zero values&lt;/li&gt;
&lt;li&gt;Invalid vehicle years&lt;/li&gt;
&lt;li&gt;Inconsistent discount formats&lt;/li&gt;
&lt;li&gt;Invalid customer ratings&lt;/li&gt;
&lt;li&gt;Branch and yard naming differences&lt;/li&gt;
&lt;li&gt;Spelling errors in sales representative names&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, customer ages included unrealistic values such as &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;5&lt;/code&gt;, &lt;code&gt;121&lt;/code&gt; and &lt;code&gt;-5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The dataset also contained financial values in &lt;strong&gt;KES, USD, EUR and ZAR&lt;/strong&gt;, making currency standardisation necessary before financial analysis.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Data Cleaning Approach
&lt;/h2&gt;

&lt;p&gt;The cleaning process was based on the business meaning of each field rather than applying one rule to every column.&lt;/p&gt;

&lt;h3&gt;
  
  
  Examples of Cleaning Decisions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data Issue&lt;/th&gt;
&lt;th&gt;Action Taken&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Inconsistent Order IDs&lt;/td&gt;
&lt;td&gt;Standardised the identifier format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid dates&lt;/td&gt;
&lt;td&gt;Converted valid dates and changed unrecoverable values to null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unrealistic ages&lt;/td&gt;
&lt;td&gt;Changed unreliable values to null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple currencies&lt;/td&gt;
&lt;td&gt;Converted monetary values to KES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Category inconsistencies&lt;/td&gt;
&lt;td&gt;Standardised spelling, casing and abbreviations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid vehicle years&lt;/td&gt;
&lt;td&gt;Corrected values where evidence existed; otherwise used null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid discounts&lt;/td&gt;
&lt;td&gt;Unreliable values were changed to null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid ratings&lt;/td&gt;
&lt;td&gt;Converted valid text formats and removed unreliable values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sales representative spelling errors&lt;/td&gt;
&lt;td&gt;Matched names against the available representative list&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The objective was not simply to make the dataset look clean, but to make the cleaned values &lt;strong&gt;suitable for analysis&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Currency Standardisation
&lt;/h2&gt;

&lt;p&gt;All monetary values were converted to &lt;strong&gt;Kenya Shillings (KES)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The exchange rates used were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Currency&lt;/th&gt;
&lt;th&gt;Rate to KES&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;USD&lt;/td&gt;
&lt;td&gt;129.54&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EUR&lt;/td&gt;
&lt;td&gt;147.84&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ZAR&lt;/td&gt;
&lt;td&gt;7.93&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The corrupted &lt;code&gt;?&lt;/code&gt; currency symbol was investigated by comparing the affected values with related financial information. The values were treated as USD where the surrounding evidence supported that interpretation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example Power Query Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fnMoneyKES = (v as any) as nullable number =&amp;gt;
    let
        raw = Text.Trim(Text.From(v) ?? ""),
        upperRaw = Text.Upper(raw),

        currency =
            if Text.Contains(upperRaw, "KES") 
                or Text.Contains(upperRaw, "KSH") then "KES"

            else if Text.Contains(raw, "$") 
                or Text.Contains(upperRaw, "USD") then "USD"

            else if Text.Contains(upperRaw, "EUR") then "EUR"

            else if Text.Contains(upperRaw, "ZAR") 
                or Text.StartsWith(Text.Trim(raw), "R ") then "ZAR"

            else if Text.Contains(raw, "?") then "USD"

            else "KES",

        numText = Text.Select(raw, {"0".."9", "."}),
        numVal = try Number.From(numText) otherwise null

    in
        if numVal = null then null
        else if currency = "USD" then numVal * 129.54
        else if currency = "EUR" then numVal * 147.84
        else if currency = "ZAR" then numVal * 7.93
        else numVal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Data Validation
&lt;/h2&gt;

&lt;p&gt;After cleaning, additional checks were performed to identify inconsistencies that could affect the analysis.&lt;/p&gt;

&lt;p&gt;One important validation involved comparing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Payment Status
       ↓
Delivery Status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This identified &lt;strong&gt;14 inconsistent records&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;10&lt;/strong&gt; records were marked as &lt;code&gt;Paid&lt;/code&gt; but had &lt;code&gt;Delivery Cancelled&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4&lt;/strong&gt; records were marked as &lt;code&gt;Payment Cancelled&lt;/code&gt; but had &lt;code&gt;Delivered&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These records were not automatically changed because there was insufficient evidence to determine which field was incorrect.&lt;/p&gt;

&lt;p&gt;Instead, they were flagged for further investigation.&lt;/p&gt;

&lt;p&gt;Other validation checks included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comparing Car Model with Vehicle Type&lt;/li&gt;
&lt;li&gt;Checking Branch and City relationships&lt;/li&gt;
&lt;li&gt;Checking Sales Representative and Branch relationships&lt;/li&gt;
&lt;li&gt;Investigating missing Vehicle Type values&lt;/li&gt;
&lt;li&gt;Reviewing financial values across related columns&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Data Model
&lt;/h2&gt;

&lt;p&gt;The cleaned flat table was transformed into a &lt;strong&gt;Star Schema&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The model contains:&lt;/p&gt;

&lt;h3&gt;
  
  
  Fact Table
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FactSales&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DimDate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DimCustomer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DimVehicle&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DimLocation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DimSalesRep&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DimPayment&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DimLeadSource&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DimDeliveryStatus&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. Model Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  DimDate
                     |
                     |
DimCustomer ---- FactSales ---- DimVehicle
                     |
                     |
               DimLocation
                     |
                     |
               DimSalesRep
                     |
                     |
                DimPayment
                     |
                     |
              DimLeadSource
                     |
                     |
           DimDeliveryStatus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The relationships were configured mainly as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dimension [1] ───────── [*] FactSales
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where &lt;code&gt;[1]&lt;/code&gt; represents the &lt;strong&gt;one&lt;/strong&gt; side and &lt;code&gt;[*]&lt;/code&gt; represents the &lt;strong&gt;many&lt;/strong&gt; side.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. FactSales Table
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;FactSales&lt;/code&gt; table contains transaction-level information.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Column&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OrderID&lt;/td&gt;
&lt;td&gt;Transaction identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OrderDate&lt;/td&gt;
&lt;td&gt;Transaction date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeliveryDate&lt;/td&gt;
&lt;td&gt;Delivery date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CustomerID&lt;/td&gt;
&lt;td&gt;Foreign Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VehicleID&lt;/td&gt;
&lt;td&gt;Foreign Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LocationID&lt;/td&gt;
&lt;td&gt;Foreign Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SalesRepID&lt;/td&gt;
&lt;td&gt;Foreign Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PaymentID&lt;/td&gt;
&lt;td&gt;Foreign Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LeadSourceID&lt;/td&gt;
&lt;td&gt;Foreign Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeliveryStatusID&lt;/td&gt;
&lt;td&gt;Foreign Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Returned&lt;/td&gt;
&lt;td&gt;Transaction attribute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UnitsSold&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UnitSellingPrice&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UnitCost&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DiscountPct&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeliveryFee&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LogisticsCost&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RevenueRecorded&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CustomerRating&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ReviewCount&lt;/td&gt;
&lt;td&gt;Measure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  10. Dimension Tables
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Primary Key&lt;/th&gt;
&lt;th&gt;Main Attributes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DimDate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Year, Quarter, Month, MonthYear&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DimCustomer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;CustomerID&lt;/td&gt;
&lt;td&gt;Customer Name, Type, Age&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DimVehicle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VehicleID&lt;/td&gt;
&lt;td&gt;Make, Model, Type, Year, Fuel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DimLocation&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;LocationID&lt;/td&gt;
&lt;td&gt;Region, County, City, Branch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DimSalesRep&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SalesRepID&lt;/td&gt;
&lt;td&gt;Sales Representative&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DimPayment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PaymentID&lt;/td&gt;
&lt;td&gt;Payment Method, Status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DimLeadSource&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;LeadSourceID&lt;/td&gt;
&lt;td&gt;Lead Source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DimDeliveryStatus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;DeliveryStatusID&lt;/td&gt;
&lt;td&gt;Delivery Status&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  11. Customer Data Limitation
&lt;/h2&gt;

&lt;p&gt;The source dataset did not contain a unique customer identifier.&lt;/p&gt;

&lt;p&gt;Therefore, the customer dimension was created using a combination of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customer Name
      +
Customer Type
      +
Customer Age
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that customer-level findings should be interpreted carefully because the dataset does not provide a verified master customer list.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. DAX Measures
&lt;/h2&gt;

&lt;p&gt;Several DAX measures were created to support the analysis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Total Revenue
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total Revenue =
SUM(FactSales[RevenueRecorded])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Total Gross Profit
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Total Gross Profit =
SUMX(
    FactSales,
    FactSales[RevenueRecorded]
        - (FactSales[UnitsSold] * FactSales[UnitCost])
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Gross Profit Margin
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gross Profit Margin % =
DIVIDE(
    [Total Gross Profit],
    [Total Revenue]
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Return Rate
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Return Rate % =
DIVIDE(
    CALCULATE(
        COUNTROWS(FactSales),
        FactSales[Returned] = "Yes"
    ),
    COUNTROWS(FactSales)
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Logistics Cost Percentage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Logistics Cost % of Revenue =
DIVIDE(
    [Total Logistics Cost],
    [Total Revenue]
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  13. Business Questions
&lt;/h2&gt;

&lt;p&gt;Instead of designing the dashboard around visuals first, the analysis was driven by specific business questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Question 1
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Which vehicle categories generate high revenue but weak profitability?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Question 2
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Which regions and branches contribute the most revenue?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Question 3
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Is there an observable relationship between customer ratings and transaction value?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Question 4
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Which locations experience higher delivery times or logistics costs?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Question 5
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Which transactions contain conflicting payment and delivery information?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Question 6
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How concentrated is revenue among high-value customers?&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  14. Dashboard Structure
&lt;/h2&gt;

&lt;p&gt;The Power BI report was divided into five analytical pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Page 1 — Business Overview
&lt;/h2&gt;

&lt;p&gt;The first page provides a high-level summary of the business.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key visuals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Total Revenue&lt;/li&gt;
&lt;li&gt;Gross Profit&lt;/li&gt;
&lt;li&gt;Gross Profit Margin&lt;/li&gt;
&lt;li&gt;Return Rate&lt;/li&gt;
&lt;li&gt;Revenue Trend&lt;/li&gt;
&lt;li&gt;Revenue by Region&lt;/li&gt;
&lt;li&gt;Revenue by Vehicle Make&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Main question
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How is the business performing overall?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Page 2 — Product &amp;amp; Sales Performance
&lt;/h2&gt;

&lt;p&gt;This page focuses on vehicle sales.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analysis includes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Vehicle Make&lt;/li&gt;
&lt;li&gt;Vehicle Model&lt;/li&gt;
&lt;li&gt;Vehicle Type&lt;/li&gt;
&lt;li&gt;Units Sold&lt;/li&gt;
&lt;li&gt;Revenue&lt;/li&gt;
&lt;li&gt;Gross Profit&lt;/li&gt;
&lt;li&gt;Gross Profit Margin&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Main question
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What are we selling, and are those sales profitable?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Page 3 — Regional &amp;amp; Branch Analysis
&lt;/h2&gt;

&lt;p&gt;This page examines geographical performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hierarchy
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Region
   ↓
County
   ↓
City
   ↓
Branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Metrics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Revenue&lt;/li&gt;
&lt;li&gt;Gross Profit&lt;/li&gt;
&lt;li&gt;Logistics Cost&lt;/li&gt;
&lt;li&gt;Delivery Time&lt;/li&gt;
&lt;li&gt;Units Sold&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Main question
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Where is the business performing well, and where are operational issues appearing?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Page 4 — Customers &amp;amp; Sales Channels
&lt;/h2&gt;

&lt;p&gt;This page focuses on customer and sales performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analysis includes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Customer Revenue&lt;/li&gt;
&lt;li&gt;Customer Ratings&lt;/li&gt;
&lt;li&gt;Lead Sources&lt;/li&gt;
&lt;li&gt;Sales Representatives&lt;/li&gt;
&lt;li&gt;Payment Methods&lt;/li&gt;
&lt;li&gt;Customer Type&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Main question
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Who is generating value and how are customers reaching the business?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Page 5 — Operations &amp;amp; Exceptions
&lt;/h2&gt;

&lt;p&gt;This page focuses on records that require further investigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Analysis includes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Payment/Delivery mismatches&lt;/li&gt;
&lt;li&gt;Delivery duration&lt;/li&gt;
&lt;li&gt;Logistics Cost %&lt;/li&gt;
&lt;li&gt;Returned vehicles&lt;/li&gt;
&lt;li&gt;Cancelled transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Main question
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Which operational records require management attention?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  15. Key Findings
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Revenue Concentration
&lt;/h2&gt;

&lt;p&gt;The cleaned dataset recorded approximately:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;KSh 1.48 Billion in total revenue&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Toyota contributed the largest share among vehicle makes.&lt;/p&gt;

&lt;p&gt;Rift Valley and Central were also major contributors to regional revenue.&lt;/p&gt;

&lt;p&gt;This indicates that overall revenue is influenced by both &lt;strong&gt;vehicle demand and regional performance&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Customer Revenue Concentration
&lt;/h2&gt;

&lt;p&gt;The top 10 customers generated approximately:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;KSh 299.3 Million&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This represents approximately &lt;strong&gt;20% of total revenue&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This provides an opportunity to monitor high-value customers separately from the wider customer base.&lt;/p&gt;




&lt;h2&gt;
  
  
  Revenue vs Profitability
&lt;/h2&gt;

&lt;p&gt;High revenue did not always translate into positive profitability.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vehicle Type&lt;/th&gt;
&lt;th&gt;Gross Profit Margin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SUV&lt;/td&gt;
&lt;td&gt;8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sedan&lt;/td&gt;
&lt;td&gt;-9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Crossover&lt;/td&gt;
&lt;td&gt;-6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Van&lt;/td&gt;
&lt;td&gt;-28%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Truck&lt;/td&gt;
&lt;td&gt;-66%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;SUVs generated the highest revenue among the vehicle types at approximately &lt;strong&gt;KSh 845 Million&lt;/strong&gt;, while some categories recorded negative margins.&lt;/p&gt;

&lt;p&gt;These results should be interpreted alongside the data-quality limitations identified during cleaning.&lt;/p&gt;




&lt;h2&gt;
  
  
  16. Delivery Performance
&lt;/h2&gt;

&lt;p&gt;The analysis identified a noticeable difference in average delivery time.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Days&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nairobi Average Delivery Time&lt;/td&gt;
&lt;td&gt;26.29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Overall Average Delivery Time&lt;/td&gt;
&lt;td&gt;15.18&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Nairobi therefore requires additional operational investigation, particularly when delivery time is considered alongside logistics costs.&lt;/p&gt;




&lt;h2&gt;
  
  
  17. Exception Analysis
&lt;/h2&gt;

&lt;p&gt;One of the most important findings was the presence of conflicting payment and delivery statuses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;14 Inconsistent Transactions
│
├── 10 → Paid + Delivery Cancelled
│
└── 4 → Payment Cancelled + Delivered
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These records were not changed automatically.&lt;/p&gt;

&lt;p&gt;Instead, they were flagged for investigation because the available information did not establish which status was incorrect.&lt;/p&gt;




&lt;h2&gt;
  
  
  18. Vehicle Profitability Concerns
&lt;/h2&gt;

&lt;p&gt;Several vehicle categories and makes showed negative margins.&lt;/p&gt;

&lt;p&gt;Examples identified in the analysis include:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Vehicle Make&lt;/th&gt;
&lt;th&gt;Gross Profit Margin&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BMW&lt;/td&gt;
&lt;td&gt;-37%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Isuzu&lt;/td&gt;
&lt;td&gt;-31%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The results should be investigated against:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unit Cost&lt;/li&gt;
&lt;li&gt;Selling Price&lt;/li&gt;
&lt;li&gt;Currency Conversion&lt;/li&gt;
&lt;li&gt;Discounts&lt;/li&gt;
&lt;li&gt;Missing Financial Values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is important because data-quality issues can influence profitability calculations.&lt;/p&gt;




&lt;h2&gt;
  
  
  19. Management Focus Areas
&lt;/h2&gt;

&lt;p&gt;Based on the analysis, several areas deserve further investigation.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Vehicle Pricing
&lt;/h3&gt;

&lt;p&gt;Review vehicle categories recording negative margins to understand whether acquisition costs, discounts or selling prices are contributing to the results.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Payment and Delivery Reconciliation
&lt;/h3&gt;

&lt;p&gt;Review the 14 inconsistent transactions against the original business records.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Nairobi Delivery Operations
&lt;/h3&gt;

&lt;p&gt;Investigate the reasons behind the relatively long average delivery time and associated logistics costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. High-Value Customers
&lt;/h3&gt;

&lt;p&gt;Monitor the contribution of high-value customers to understand customer concentration.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Data Collection
&lt;/h3&gt;

&lt;p&gt;Improve future data capture by introducing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unique Customer IDs&lt;/li&gt;
&lt;li&gt;Standardised currencies&lt;/li&gt;
&lt;li&gt;Validated dates&lt;/li&gt;
&lt;li&gt;Controlled category fields&lt;/li&gt;
&lt;li&gt;Consistent payment and delivery statuses&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  20. Project Limitations
&lt;/h2&gt;

&lt;p&gt;The analysis has several limitations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customer Identification
&lt;/h3&gt;

&lt;p&gt;There was no unique customer identifier in the source data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Missing Financial Information
&lt;/h3&gt;

&lt;p&gt;Some Unit Cost and Unit Selling Price values could not be reliably recovered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conflicting Operational Records
&lt;/h3&gt;

&lt;p&gt;Some payment and delivery statuses were inconsistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source Dataset
&lt;/h3&gt;

&lt;p&gt;The analysis represents the information available in the supplied dataset and may not capture every factor affecting actual business performance.&lt;/p&gt;




&lt;h2&gt;
  
  
  21. Lessons Learned
&lt;/h2&gt;

&lt;p&gt;This project reinforced an important principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Data cleaning is part of data analysis, not a separate task.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A value cannot always be judged as incorrect simply because it looks unusual.&lt;/p&gt;

&lt;p&gt;Sometimes another column provides the context needed to understand it.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Unclear Currency
       ↓
Compare Financial Fields
       ↓
Determine Most Supported Interpretation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vehicle Type Missing
       ↓
Check Car Model
       ↓
Compare With Similar Records
       ↓
Determine Whether Inference Is Supported
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Payment Status
       ↓
Compare With Delivery Status
       ↓
Identify Possible Exceptions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project therefore highlighted the importance of making cleaning decisions based on evidence.&lt;/p&gt;

&lt;p&gt;When there was not enough evidence to confidently correct a value, it was safer to use &lt;code&gt;null&lt;/code&gt; or flag the record for investigation.&lt;/p&gt;




&lt;h2&gt;
  
  
  22. Conclusion
&lt;/h2&gt;

&lt;p&gt;The JCars Logistics dataset provided an opportunity to examine the business from several perspectives.&lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;Power Query, Power BI data modelling, DAX and interactive visualisations&lt;/strong&gt;, the raw transaction data was transformed into a structured analytical solution.&lt;/p&gt;

&lt;p&gt;The final report connects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sales
  ↓
Revenue
  ↓
Costs
  ↓
Profitability
  ↓
Operations
  ↓
Customer Experience
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The project demonstrates how Power BI can transform raw business records into an interactive decision-support tool.&lt;/p&gt;

&lt;p&gt;More importantly, it shows that meaningful analytics depends not only on creating attractive dashboards, but also on &lt;strong&gt;understanding the data, documenting assumptions, validating relationships and questioning unusual results&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ninadavid4/JCars-Logistics-Analysis.git" rel="noopener noreferrer"&gt;Github Repository&lt;/a&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>data</category>
      <category>software</category>
    </item>
    <item>
      <title>Understanding Data Modelling, Relationships and Joins in Power BI</title>
      <dc:creator>Antonina Wambui</dc:creator>
      <pubDate>Thu, 24 Sep 2026 08:55:49 +0000</pubDate>
      <link>https://dev.to/analystnina/understanding-data-modelling-relationships-and-joins-in-power-bi-3eh8</link>
      <guid>https://dev.to/analystnina/understanding-data-modelling-relationships-and-joins-in-power-bi-3eh8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When working with Power BI, importing data is only the beginning. The real challenge comes when you have multiple tables and need to make sure they work together correctly.&lt;/p&gt;

&lt;p&gt;This is where data modelling, relationships, and joins become important.&lt;/p&gt;

&lt;p&gt;For example, imagine a retail company that wants to analyse its sales. It may have information about customers, products, dates, locations, and individual sales transactions stored in different tables.&lt;/p&gt;

&lt;p&gt;If these tables are not structured properly, reports can become difficult to build and DAX calculations may produce unexpected results.&lt;/p&gt;

&lt;p&gt;In this articles, I will explain how data modelling works in Power BI, the different modelling schemas, relationship and cardinality, filter directions, and the different types of joins available in Power Query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. What is Data Modelling in Power BI?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Modelling&lt;/strong&gt; is the process of organising tables, columns, and relationships so that data can be analysed correctly in Power BI.&lt;/p&gt;

&lt;p&gt;Instead of putting every piece of information into one large table, we can separate the data into tables based on their purpose and then connect them using relationships.&lt;/p&gt;

&lt;p&gt;A good data model is important because it can help with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Better report performance&lt;/li&gt;
&lt;li&gt;Simpler DAX calculations&lt;/li&gt;
&lt;li&gt;Easier filtering &lt;/li&gt;
&lt;li&gt;Reduced data redundancy&lt;/li&gt;
&lt;li&gt;Easier maintenance&lt;/li&gt;
&lt;li&gt;Scalability as the amount of data increases&lt;/li&gt;
&lt;li&gt;Better understanding of the report structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a sales model might contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FactSales&lt;/li&gt;
&lt;li&gt;DimCustomer&lt;/li&gt;
&lt;li&gt;DimProduct&lt;/li&gt;
&lt;li&gt;DimDate&lt;/li&gt;
&lt;li&gt;DimLocation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tables can then be connected using keys.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Data Modelling Approaches&lt;/strong&gt;&lt;br&gt;
There are several ways of structuring data.&lt;br&gt;
Three common approaches are &lt;strong&gt;flat table, star schema, and snowflake schema&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flat Table&lt;/strong&gt;&lt;br&gt;
A flat table keeps most or all information in a single table.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SalesID&lt;/th&gt;
&lt;th&gt;Customers&lt;/th&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Location&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Quantity&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;S001&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;Maize Flour&lt;/td&gt;
&lt;td&gt;Food&lt;/td&gt;
&lt;td&gt;Nairobi&lt;/td&gt;
&lt;td&gt;10/09/26&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S002&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;Cooking Oil&lt;/td&gt;
&lt;td&gt;Food&lt;/td&gt;
&lt;td&gt;Mombasa&lt;/td&gt;
&lt;td&gt;10/09/26&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S003&lt;/td&gt;
&lt;td&gt;Carol&lt;/td&gt;
&lt;td&gt;Soap&lt;/td&gt;
&lt;td&gt;Household&lt;/td&gt;
&lt;td&gt;Nairobi&lt;/td&gt;
&lt;td&gt;11/09/26&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;450&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────┐
│         Sales Table         │
├─────────────────────────────┤
│ SaleID                      │
│ Customer                    │
│ Product                     │
│ Category                    │
│ Location                    │
│ Date                        │
│ Quantity                    │
│ Revenue                     │
└─────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to understand &lt;/li&gt;
&lt;li&gt;Easy to create&lt;/li&gt;
&lt;li&gt;Useful for small datasets&lt;/li&gt;
&lt;li&gt;Requires fewer relationships&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeated information creates data redundancy&lt;/li&gt;
&lt;li&gt;The table can become very large &lt;/li&gt;
&lt;li&gt;Changes to descriptive information may need to be made in many rows&lt;/li&gt;
&lt;li&gt;Can make the model harder to maintain&lt;/li&gt;
&lt;li&gt;It may not be ideal for large analytical solutions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A flat table can be useful for a small project or simple anaylsis, especially when the dataset does not contain many different entities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Star Schema&lt;/strong&gt;&lt;br&gt;
A star schema separates business transactions from descriptive information.&lt;/p&gt;

&lt;p&gt;The central table is normally a fact table, while the surrounding tables are &lt;strong&gt;dimension tables&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 ┌───────────────┐
                 │ DimCustomer   │
                 └───────┬───────┘
                         │
                         ▼
┌───────────────┐  ┌───────────────┐  ┌───────────────┐
│  DimProduct   │──│   FactSales   │──│    DimDate    │
└───────────────┘  └───────┬───────┘  └───────────────┘
                           │
                           ▼
                    ┌───────────────┐
                    │  DimLocation  │
                    └───────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fact table stores events or transactions, while the dimension tables provide context about those events.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to understand&lt;/li&gt;
&lt;li&gt;Works well with Power BI&lt;/li&gt;
&lt;li&gt;Usually produces simpler DAX&lt;/li&gt;
&lt;li&gt;Makes filtering easier&lt;/li&gt;
&lt;li&gt;Reduces unnecessary repetition&lt;/li&gt;
&lt;li&gt;Easier to maintain and expand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires relationships between tables&lt;/li&gt;
&lt;li&gt;More tables can initially seem complicated&lt;/li&gt;
&lt;li&gt;Poorly designed relationships can cause incorrect results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For many Power BI reporting projects, a star schema is a practical way of organising analytical data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Snowflake schema&lt;/strong&gt;&lt;br&gt;
A snowflake schema is similar to a star schema, but some dimension tables are further divided into related tables&lt;/p&gt;

&lt;p&gt;For example, instead of storing the category directly in DimProduct, we could create a separate DimCategory table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 ┌─────────────────┐
                 │   DimCategory   │
                 └────────┬────────┘
                          │
                          ▼
                 ┌─────────────────┐
                 │   DimProduct    │
                 └────────┬────────┘
                          │
                          ▼
                 ┌─────────────────┐
                 │    FactSales    │
                 └─────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces repeated information&lt;/li&gt;
&lt;li&gt;Can be useful when dimensions have multiple levels&lt;/li&gt;
&lt;li&gt;Can represent complex organizational structures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More tables and relationships&lt;/li&gt;
&lt;li&gt;More complex model&lt;/li&gt;
&lt;li&gt;Can make DAX and filtering harder to understand&lt;/li&gt;
&lt;li&gt;More joins/relationships may be required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A snowflake schema can be useful when the source data naturally contains hierarchical dimensions, but unnecessary splitting can add complexity&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Fact Tables and Dimension Tables&lt;/strong&gt;&lt;br&gt;
Understanding fact and dimension tables is one of the most important parts of data modelling.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fact Table&lt;/strong&gt;&lt;br&gt;
A fact table normally contains business events or transactions.&lt;/p&gt;

&lt;p&gt;For a retail company, FactSales could contain:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SaleID&lt;/th&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;ProductID&lt;/th&gt;
&lt;th&gt;DateID&lt;/th&gt;
&lt;th&gt;Quantity&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;S001&lt;/td&gt;
&lt;td&gt;C001&lt;/td&gt;
&lt;td&gt;P001&lt;/td&gt;
&lt;td&gt;D001&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S002&lt;/td&gt;
&lt;td&gt;C002&lt;/td&gt;
&lt;td&gt;P002&lt;/td&gt;
&lt;td&gt;D001&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;S003&lt;/td&gt;
&lt;td&gt;C001&lt;/td&gt;
&lt;td&gt;P003&lt;/td&gt;
&lt;td&gt;D002&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;450&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table contains numerical values that can be used for calculations, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quantity&lt;/li&gt;
&lt;li&gt;Revenue&lt;/li&gt;
&lt;li&gt;Cost&lt;/li&gt;
&lt;li&gt;Profit&lt;/li&gt;
&lt;li&gt;Discount&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What is grain?&lt;/strong&gt;&lt;br&gt;
The grain tells us what one row in the fact table represents.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
One row in the FactSales represents one product sold in one sales transaction.&lt;/p&gt;

&lt;p&gt;Defining grain before creating a model is important because it helps determine what information belongs in the fact table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dimension Table&lt;/strong&gt;&lt;br&gt;
Dimension tables contain descriptive information that gives context to the facts.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;strong&gt;DimCustomer&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;th&gt;City&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C001&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;Nairobi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C002&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;Mombasa&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;DimProduct&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ProductID&lt;/th&gt;
&lt;th&gt;ProductName&lt;/th&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;P001&lt;/td&gt;
&lt;td&gt;Maize Flour&lt;/td&gt;
&lt;td&gt;Food&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;P002&lt;/td&gt;
&lt;td&gt;Cooking Oil&lt;/td&gt;
&lt;td&gt;Food&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;DimDate&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;DateID&lt;/th&gt;
&lt;th&gt;Date&lt;/th&gt;
&lt;th&gt;Month&lt;/th&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;D001&lt;/td&gt;
&lt;td&gt;10/09/26&lt;/td&gt;
&lt;td&gt;September&lt;/td&gt;
&lt;td&gt;2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D002&lt;/td&gt;
&lt;td&gt;11/09/26&lt;/td&gt;
&lt;td&gt;September&lt;/td&gt;
&lt;td&gt;2026&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Dimension tables answer questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who brought the product?&lt;/li&gt;
&lt;li&gt;What product was sold?&lt;/li&gt;
&lt;li&gt;When was it sold?&lt;/li&gt;
&lt;li&gt;Where did the sale happen?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fact table tells us what happened, while dimensions help explain who, what, when, and where.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Relationships in Power BI&lt;/strong&gt;&lt;br&gt;
A relationship connects tables through a common column.&lt;/p&gt;

&lt;p&gt;For example, CustomerID can connect DimCustomer to FactSales.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension Table&lt;/th&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Fact Table&lt;/th&gt;
&lt;th&gt;Foreign Key&lt;/th&gt;
&lt;th&gt;Relationship&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DimCustomer&lt;/td&gt;
&lt;td&gt;CustomerID&lt;/td&gt;
&lt;td&gt;FactSales&lt;/td&gt;
&lt;td&gt;CustomerID&lt;/td&gt;
&lt;td&gt;1:*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DimProduct&lt;/td&gt;
&lt;td&gt;ProductID&lt;/td&gt;
&lt;td&gt;FactSales&lt;/td&gt;
&lt;td&gt;ProductID&lt;/td&gt;
&lt;td&gt;1:*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DimDate&lt;/td&gt;
&lt;td&gt;DateID&lt;/td&gt;
&lt;td&gt;FactSales&lt;/td&gt;
&lt;td&gt;DateID&lt;/td&gt;
&lt;td&gt;1:*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DimLocation&lt;/td&gt;
&lt;td&gt;LocationID&lt;/td&gt;
&lt;td&gt;FactSales&lt;/td&gt;
&lt;td&gt;LocationID&lt;/td&gt;
&lt;td&gt;1:*&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  One-to-One (1:1)
&lt;/h3&gt;

&lt;p&gt;One row in one table corresponds to one row in another table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| Table A | Relationship | Table B |
|---|---|---|
| A001 | 1 : 1 | A001 |
| A002 | 1 : 1 | A002 |
| A003 | 1 : 1 | A003 |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  One-to-Many (1:*)
&lt;/h3&gt;

&lt;p&gt;One row in one table can be related to many rows in another table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| DimCustomer | Relationship | FactSales |
|---|---|---|
| C001 | 1 : &lt;span class="err"&gt;*&lt;/span&gt; | C001 |
| C001 | 1 : &lt;span class="err"&gt;*&lt;/span&gt; | C001 |
| C001 | 1 : &lt;span class="err"&gt;*&lt;/span&gt; | C001 |
| C002 | 1 : &lt;span class="err"&gt;*&lt;/span&gt; | C002 |
| C002 | 1 : &lt;span class="err"&gt;*&lt;/span&gt; | C002 |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This relationship can be useful when information belonging to the same entity has been separated into two tables.&lt;/p&gt;

&lt;p&gt;However, if the tables always need to be used together, it may be worth considering whether they really need to remain separate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Many-to-Many (&lt;em&gt;:&lt;/em&gt;)
&lt;/h3&gt;

&lt;p&gt;Many rows in one table can be related to many rows in another table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;| Students | Relationship | Courses |
|---|---|---|
| S001 | &lt;span class="ge"&gt;* : *&lt;/span&gt; | C001 |
| S001 | &lt;span class="ge"&gt;* : *&lt;/span&gt; | C002 |
| S002 | &lt;span class="ge"&gt;* : *&lt;/span&gt; | C001 |
| S002 | &lt;span class="ge"&gt;* : *&lt;/span&gt; | C003 |
| S003 | &lt;span class="ge"&gt;* : *&lt;/span&gt; | C002 |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many-to-many relationship should be designed carefully because they can make filtering and calculations more complicated.&lt;/p&gt;

&lt;p&gt;Where possible, a bridge or intermediate table can help create a clearer model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Examples:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1:1&lt;/strong&gt; → One employee ↔ One employee profile&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1:&lt;/strong&gt;* → One customer ↔ Many sales&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;:&lt;/em&gt;&lt;/strong&gt; → Many students ↔ Many courses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Active and Inactive Relationships&lt;/strong&gt;&lt;br&gt;
Power BI can have relationships that are either active or inactive.&lt;/p&gt;

&lt;p&gt;An active relationship is normally used automatically when filters and calculations are performed.&lt;/p&gt;

&lt;p&gt;An inactive relationships exists in the model but is not automatically used for filtering.&lt;/p&gt;

&lt;p&gt;For example, a sales table may contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OrderDate&lt;/li&gt;
&lt;li&gt;ShipDate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both dates could connect to the same DimDate table, but only one relationship can normally be active between the same two tables for a given path.&lt;/p&gt;

&lt;p&gt;Inactive relationships can be used in specific DAX calculations when needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7.Filter Direction&lt;/strong&gt;&lt;br&gt;
Relationships also determine how filters move between tables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single-direction filtering&lt;/strong&gt;&lt;br&gt;
 With single-direction filtering, a filter normally moves from the dimension table towards the fact table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DimProduct  ───────────────→  FactSales
              Filter

Suppose I select **maize flour** in a report.

Power BI can use the relationship to filter fact sales and show only sales involving Maize Flour.

This is commonly used in star schemas because it creates a clear filtering path.

**Bidirectional filtering**
Bidirectional filtering allows filters to travel in both directions.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
text&lt;br&gt;
DimProduct  ◄──────────────►  FactSales&lt;br&gt;
              Filter&lt;/p&gt;

&lt;p&gt;Although this can be useful in certain scenarios, it should be used carefully.&lt;/p&gt;

&lt;p&gt;Using bidirectional relationships unnecessarily can create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ambiguous filter paths&lt;/li&gt;
&lt;li&gt;Unexpected results&lt;/li&gt;
&lt;li&gt;More complicated models&lt;/li&gt;
&lt;li&gt;Difficulty troubleshooting calculations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this reason, single-direction filtering is often preferred unless there is a clear reason to use both directions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Joins in Power Query&lt;/strong&gt;&lt;br&gt;
Relationships are not the only way to work with multiple tables.&lt;/p&gt;

&lt;p&gt;Power Query  provides &lt;strong&gt;Merge Queries&lt;/strong&gt;, which allows us to join tables based on matching columns.&lt;/p&gt;

&lt;p&gt;Imagine we have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customers&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C001&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C002&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C003&lt;/td&gt;
&lt;td&gt;Carol&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Orders&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;|CustomerID | OrderID  |&lt;br&gt;
|C001       | O101     |&lt;br&gt;
|C002       | O102     |&lt;br&gt;
|C004       | 0103     |&lt;/p&gt;

&lt;p&gt;Here, CustomerID is the matching column.&lt;/p&gt;

&lt;p&gt;Power Query provides several join types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9.Left Outer Join&lt;/strong&gt;&lt;br&gt;
A left outer join keeps all rows from the first/left table and matching rows from the second/right table.&lt;/p&gt;

&lt;p&gt;Expected result:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C001&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C002&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C003&lt;/td&gt;
&lt;td&gt;Carol&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Carol is retained even though she has no matching order.&lt;/p&gt;

&lt;p&gt;This is useful when we want to keep every customer and see whether they have corresponding orders.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10.Right Outer Join&lt;/strong&gt;&lt;br&gt;
A right outer join keeps all rows from the second/right table and matching rows from the first/left table.&lt;/p&gt;

&lt;p&gt;Expected results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C001&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C002&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C004&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;O103&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;C004 is retained even though that customer does not exist in the Customers table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. Full Outer Join&lt;/strong&gt;&lt;br&gt;
A full outer join keeps all rows from both tables, whether or not there is a match.&lt;/p&gt;

&lt;p&gt;Expected results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C001&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C002&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C003&lt;/td&gt;
&lt;td&gt;Carol&lt;/td&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C004&lt;/td&gt;
&lt;td&gt;Null&lt;/td&gt;
&lt;td&gt;O103&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This can be useful when identifying records that exist in one table but not the other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;12. Inner Join&lt;/strong&gt;&lt;br&gt;
An inner join keeps only records that have a match in both tables.&lt;/p&gt;

&lt;p&gt;Expected results:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C001&lt;/td&gt;
&lt;td&gt;Amina&lt;/td&gt;
&lt;td&gt;O101&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C002&lt;/td&gt;
&lt;td&gt;Brian&lt;/td&gt;
&lt;td&gt;O102&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;C003 and C004 are removed because they do not have matching records on both sides.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;13. Left Anti Join&lt;/strong&gt;&lt;br&gt;
A left anti join returns records that exist in the left table but have no matching record in the right table.&lt;/p&gt;

&lt;p&gt;Expected result:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;CustomerName&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C003&lt;/td&gt;
&lt;td&gt;Carol&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is useful when finding customers who have never placed an order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;14. Right Anti Join&lt;/strong&gt;&lt;br&gt;
A  right anti join returns records that exist in the right table but have no matching record in the left table.&lt;/p&gt;

&lt;p&gt;Expected result:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;CustomerID&lt;/th&gt;
&lt;th&gt;OrderID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C004&lt;/td&gt;
&lt;td&gt;O103&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This can help identify orders whose customer information is missing from the Customers table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;15. Power Query Joins vs Power BI Relationships&lt;/strong&gt;&lt;br&gt;
One thing I found important when learning Power BI that a join and a relationship are not the same thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Power Query Merge&lt;/strong&gt;&lt;br&gt;
A merge happens during the data preparation stage.&lt;/p&gt;

&lt;p&gt;It can bring columns from one table into another table.&lt;/p&gt;

&lt;p&gt;For example, we could merge Customers and Orders using CustomersID.&lt;/p&gt;

&lt;p&gt;The resulting table contains information from both tables.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Power BI Relationship&lt;/strong&gt;&lt;br&gt;
A relationship happens in the data modelling stage.&lt;/p&gt;

&lt;p&gt;It does not physically combine the tables.&lt;/p&gt;

&lt;p&gt;Instead, Power BI keeps the tables separate and uses the relationship to allow filters and calculations to work across them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Merge&lt;/strong&gt; combines data. &lt;strong&gt;Relationship&lt;/strong&gt; connects data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should I merge?&lt;/strong&gt;&lt;br&gt;
A merge can make sense when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You genuinely need columns from another table in the same table&lt;/li&gt;
&lt;li&gt;You are cleaning or preparing data &lt;/li&gt;
&lt;li&gt;The resulting structure is simpler and appropriate for the analysis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, excessive merging can create very wide tables, duplicate information, and make a model harder to maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should I use a relationship?&lt;/strong&gt;&lt;br&gt;
Relationships are useful when the tables represent different business entities.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;And for the second illustration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
text&lt;br&gt;
DimCustomer&lt;br&gt;
DimProduct&lt;br&gt;
DimDate&lt;br&gt;
DimLocation&lt;br&gt;
     ↓&lt;br&gt;
 FactSales&lt;/p&gt;

&lt;p&gt;Keeping these tables separate makes the model easier to understand and allows dimensions to be reused for different analyses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;16. My Recommended Power BI Model&lt;/strong&gt;&lt;br&gt;
For a typical business intelligence project, I would generally structure the model around a star schema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌─────────────────┐
                    │  DimCustomer    │
                    │   CustomerID    │
                    └────────┬────────┘
                             │ 1:*
                             ▼
┌─────────────────┐   ┌─────────────────┐   ┌─────────────────┐
│   DimProduct    │──►│    FactSales    │◄──│     DimDate     │
│   ProductID     │   │     SaleID      │   │     DateID      │
└─────────────────┘   │     Quantity    │   └─────────────────┘
                      │     Revenue     │
                      └────────┬────────┘
                               │ 1:*
                               ▼
                    ┌─────────────────┐
                    │   DimLocation   │
                    │   LocationID    │
                    └─────────────────┘

The reason I would use this structure is that it provides a good balance between simplicity, performance, scalability, and maintainability.

The fact table contains measurable business events, while the dimension tables provide descriptive information.

I would normally use:
- One-to-many relationships
- Dimension tables on the 1 side
- Fact tables on the * side
- Single-direction filtering from dimensions to facts
- Unique primary keys in dimension tables
- Foreign keys in fact tables

For example:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
text&lt;br&gt;
DimProduct [1] ───────── [*] FactSales&lt;/p&gt;

&lt;p&gt;This allows selecting a product to filter the corresponding sales records.&lt;/p&gt;

&lt;p&gt;A star schema also makes it easier to write and understand DAX measures because the model has clear relationships and predictable filter paths.&lt;/p&gt;

&lt;p&gt;A flat table can still be useful for a small or simple dataset, while a snowflake schema can be appropriate when dimensions naturally contain several levels of hierarchy. However, adding unnecessary tables and relationships can increase model complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Data modelling is an important part of building a Power BI solution. It is not simply about importing tables and creating charts. The way tables are structured and connected affects how easily we can analyse the data and how reliable our results will be.&lt;/p&gt;

&lt;p&gt;Understanding fact tables, dimension tables, schemas, relationships, cardinality, filter direction, and joins makes it easier to build models that can handle real business questions.&lt;/p&gt;

&lt;p&gt;One of the biggest distinctions to remember is the difference between a Power Query merge and Power BI relationship. A merge combines data during data preparation, while a relationship connects separate tables during modelling.&lt;/p&gt;

&lt;p&gt;For many business intelligence projects, a well-designed star schema with clear one-to-many relationships and appropriate filter directions provides a strong foundation for building Power BI reports.&lt;/p&gt;

&lt;p&gt;Ultimately, the goals of data modelling is simple: &lt;strong&gt;organise data in the way that makes analysis accurate, understandable, and easier to maintain&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>powerbi</category>
      <category>powerquery</category>
      <category>datamodelling</category>
      <category>techstudent</category>
    </item>
    <item>
      <title>Building an Interactive Excel Dashboard for E-commerce Product Analysis: A Case Study of Jumia Products</title>
      <dc:creator>Antonina Wambui</dc:creator>
      <pubDate>Wed, 09 Sep 2026 16:56:45 +0000</pubDate>
      <link>https://dev.to/analystnina/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-case-study-of-jumia-ckl</link>
      <guid>https://dev.to/analystnina/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-case-study-of-jumia-ckl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;One thing I have started learning during my journey into data analytics is that data rarely arrives ready for analysis.&lt;/p&gt;

&lt;p&gt;After working through Excel as part of the LuxDevHQ Data Science and Analytics, I wanted to put the skills I had learned into practice. For this project, I worked with dataset containing product listing from Jumia and challenged myself to go beyond simply creating charts.&lt;/p&gt;

&lt;p&gt;The goal was to take messy e-commerce data, understand what was wrong with it clean and transform it, analyze the patterns, and finally present the result through an interactive Excel dashboard.&lt;/p&gt;

&lt;p&gt;The dataset contained 115 product records with information about products, prices, discounts, reviews and ratings. At first glance, it looked fairly simple. However, after inspecting it more closely, I discovered missing values, duplicate records, negative review counts, inconsistent data formats and a product with prices recorded as ranges.&lt;/p&gt;

&lt;p&gt;That made the project much more interesting.&lt;/p&gt;

&lt;p&gt;Instead of jumping straight into visualization, I followed a complete analytics workflow: &lt;br&gt;
Raw Data → Data Audit → Data Cleaning → Data Transformation → Analysis → Visualization → Dashboard → Insights&lt;/p&gt;

&lt;p&gt;This article walks through that process and some of the lessons I learned along the way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding the Dataset&lt;/strong&gt;&lt;br&gt;
The original dataset contained six main columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product&lt;/li&gt;
&lt;li&gt;Current Price&lt;/li&gt;
&lt;li&gt;Old Price&lt;/li&gt;
&lt;li&gt;Discount &lt;/li&gt;
&lt;li&gt;Review&lt;/li&gt;
&lt;li&gt;Ratingd&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Ratingd column was simply a naming error, so I standardized it to Rating.&lt;/p&gt;

&lt;p&gt;One One important limitation became clear very early: the dataset did not contain actual sales information.&lt;/p&gt;

&lt;p&gt;Because of this, I could not honestly claim that a product with more reviews was necessarily selling more.&lt;/p&gt;

&lt;p&gt;Instead, I treated the number of reviews are not the same thing as sales. A product could have more reviews because it has been available for a longer period, for example.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question I wanted the Data to Answer&lt;/strong&gt;&lt;br&gt;
With that limitation in mind, I focused my analysis around questions such as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do longer discounts appear to attract more customer engagement?&lt;/li&gt;
&lt;li&gt;Is there a relationship between product ratings and reviews?&lt;/li&gt;
&lt;li&gt;Does product price appear to influence ratings?&lt;/li&gt;
&lt;li&gt;Which product price appears to influence ratings?&lt;/li&gt;
&lt;li&gt;Are there products that deserve further investigation?&lt;/li&gt;
&lt;li&gt;What patterns can be communicated effectively through an Excel dashboard?
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Auditing the Raw Data&lt;/strong&gt;&lt;br&gt;
Before cleaning anything, I wanted to understand the condition of the dataset.&lt;/p&gt;

&lt;p&gt;The initial audit revealed several interesting problems:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data Quality Issue&lt;/th&gt;
&lt;th&gt;Finding&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Total records&lt;/td&gt;
&lt;td&gt;115&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Original columns&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing Reviews&lt;/td&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Missing Ratings&lt;/td&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exact duplicate rows&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Repeated product names&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Negative review values&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price ranges&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid rating range&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid discount range&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One of the biggest red flags was the Review column.&lt;/p&gt;

&lt;p&gt;There were 57 non-blank review values and all 57 were negative.&lt;/p&gt;

&lt;p&gt;That immediately raised a question: &lt;br&gt;
How can a product have a negative number of review?&lt;/p&gt;

&lt;p&gt;Obviously, a review count cannot realistically be negative. Since the issue affected every non-blank value rather than only a few records, I treated it as a systematic data-quality problem that needed investigation.&lt;/p&gt;

&lt;p&gt;This was a good reminder that data cleaning isn't just about fixing errors; it is about understanding why something looks wrong before changing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Cleaning the Data&lt;/strong&gt;&lt;br&gt;
Once I understood the problems, I started cleaning the dataset.&lt;br&gt;
I tried to make each cleaning decision based on the information available rather than simply forcing the data to look perfect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Correcting Negative Review&lt;/strong&gt;&lt;br&gt;
For the negative review counts, I created a helper column and used:&lt;/p&gt;

&lt;p&gt;=IF(E2="","",ABS(VALUE(E2)))&lt;/p&gt;

&lt;p&gt;The ABS () function converts the negative values into positive values while the IF () statement ensures that blank cells remain blank.&lt;/p&gt;

&lt;p&gt;After verifying the results, I converted the corrected values to static values.&lt;br&gt;
 This gave me realistic positive review counts without turning missing information into fake data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handling Missing Values&lt;/strong&gt;&lt;br&gt;
Both the review and rating columns contained 58 blank cells.&lt;br&gt;
I decided not to replace these blanks with zero.&lt;/p&gt;

&lt;p&gt;Why?&lt;br&gt;
Because:&lt;/p&gt;

&lt;p&gt;Blank ≠ Zero&lt;/p&gt;

&lt;p&gt;A blank review count means the review information was not captured.&lt;/p&gt;

&lt;p&gt;A zero means the product actually had zero reviews.&lt;/p&gt;

&lt;p&gt;Those two situations carry different meanings.&lt;/p&gt;

&lt;p&gt;Replacing all blanks with zero could therefore distort averages, rankings and other calculations.&lt;br&gt;
So, in this case, leaving the missing values untouched was the more honest choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Dealing With the Price Range&lt;/strong&gt;&lt;br&gt;
One particularly interesting record belonged to a 1/2/3 Seater Elastic Sofa Cover.&lt;/p&gt;

&lt;p&gt;It's prices were recorded as ranges:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Current Price&lt;/strong&gt;: Ksh 1,620-1980&lt;br&gt;
&lt;strong&gt;Old Price&lt;/strong&gt;: Ksh 2,200-3,200&lt;/p&gt;

&lt;p&gt;I considered three possible approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the minimum price&lt;/li&gt;
&lt;li&gt;Remove the record&lt;/li&gt;
&lt;li&gt;Calculate the midpoint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I chose the midpoint approach.&lt;/p&gt;

&lt;p&gt;This allowed me to retain the product instead of throwing away an otherwise useful record.&lt;/p&gt;

&lt;p&gt;The original price range was retained separately so that the transformation could be traced.&lt;/p&gt;

&lt;p&gt;However, this decision also produced an interesting result.&lt;/p&gt;

&lt;p&gt;Using the midpoint prices gave me a calculated discount of approximately 33%, while the advertised discount in the dataset was 38%.&lt;/p&gt;

&lt;p&gt;Rather than changing one value to make them agree, I kept both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Removing duplicates&lt;/strong&gt;&lt;br&gt;
The dataset contained three completely identical rows.&lt;br&gt;
Since every field matched, I removed those records as exact duplicates.&lt;/p&gt;

&lt;p&gt;However, I also found six products with repeated product names.&lt;br&gt;
I did not automatically remove those.&lt;/p&gt;

&lt;p&gt;Why?&lt;br&gt;
Because the repeated product names had differences in things such as price discount or review count. Since Jumia is a marketplace with multiple sellers, these could represent separate listings for similar products.&lt;/p&gt;

&lt;p&gt;Removing them simply because the product names matched could therefore introduce another form of data error.&lt;/p&gt;

&lt;p&gt;So my rule was:&lt;br&gt;
Exact duplicate → Remove&lt;/p&gt;

&lt;p&gt;Same product name but different listing information → Keep&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Standardizing the Dataset&lt;/strong&gt;&lt;br&gt;
After dealing with the major data-quality issues, I standardized the remaining fields.&lt;/p&gt;

&lt;p&gt;Some of the changes included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Renaming Ratingd to Rating&lt;/li&gt;
&lt;li&gt;Removing "out of 5" from rating values&lt;/li&gt;
&lt;li&gt;Converting ratings into numerical values&lt;/li&gt;
&lt;li&gt;Converting prices from text into numbers&lt;/li&gt;
&lt;li&gt;Standardizing column names&lt;/li&gt;
&lt;li&gt;Formatting prices as Kenyan Shillings&lt;/li&gt;
&lt;li&gt;Applying consistent number formatting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cleaned data was then structured as Excel table so that formulas, PivotTables and charts could work more efficiently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating New Analytical Fields&lt;/strong&gt;&lt;br&gt;
After cleaning the data, I created additional fields to make the dataset more useful for analysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discount Analysis&lt;/strong&gt;&lt;br&gt;
I calculated the discount amount by finding the difference between the old and current prices. I also calculated the percentage discount and kept it alongside the original advertised discount.&lt;/p&gt;

&lt;p&gt;This allowed me to compare the seller's advertised discount with the discount calculated from the actual prices.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rating Categories&lt;/strong&gt;&lt;br&gt;
To make ratings easier to analyze, I grouped them into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Poor&lt;/strong&gt;: Below 3&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Average&lt;/strong&gt;: 3-4.5&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Excellent&lt;/strong&gt;: Above 4.5&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ratings between 4.1 and 4.5 were included in the Average category as a documented working assumption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discount Categories&lt;/strong&gt;&lt;br&gt;
Discounts were grouped into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Low&lt;/strong&gt;: Below 20%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Medium&lt;/strong&gt;: 20%- 40%&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High&lt;/strong&gt;: 40%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Price Categories&lt;/strong&gt;&lt;br&gt;
Instead of choosing price ranges arbitrarily, I used quartiles from the dataset.&lt;/p&gt;

&lt;p&gt;Using QUARTILE.INC(), I obtained&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Q1: Ksh 493&lt;/li&gt;
&lt;li&gt;Q3: Ksh 1,669.50&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These thresholds were then used to classify products into Low, Medium and High price categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Engagement Strength&lt;/strong&gt;&lt;br&gt;
Since review count was being used as a proxy foe customer engagement, I used the 75th percentile as the threshold.&lt;/p&gt;

&lt;p&gt;The Review Q3 was 13 reviews, so products with 13 or more reviews were classified as having strong engagement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Status and Combination Flags&lt;/strong&gt;&lt;br&gt;
I also created a Data Status field to identify products as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete&lt;/li&gt;
&lt;li&gt;Missing Rating&lt;/li&gt;
&lt;li&gt;Missing Review&lt;/li&gt;
&lt;li&gt;Missing Both&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, I created four combination flags to highlight products requiring further attention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High discount + Low Rating&lt;/li&gt;
&lt;li&gt;High discount + Low Engagement&lt;/li&gt;
&lt;li&gt;Many Reviews + Average Rating&lt;/li&gt;
&lt;li&gt;Strong Engagement + Excellent Rating&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Where the required data was missing, the result was marked "&lt;strong&gt;missing&lt;/strong&gt;" rather than making an assumption.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Analysis Using PivotTables and Excel Functions&lt;/strong&gt;&lt;br&gt;
With the dataset cleaned and enriched, I moved on to analysis using &lt;strong&gt;PivotTables&lt;/strong&gt;, &lt;strong&gt;PivotCharts&lt;/strong&gt;, &lt;strong&gt;formulas&lt;/strong&gt;, FILTER(), &lt;strong&gt;correlation&lt;/strong&gt; and &lt;strong&gt;scatter plots&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I focused on three relationships:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discount vs. Reviews&lt;/li&gt;
&lt;li&gt;Rating vs. Reviews&lt;/li&gt;
&lt;li&gt;Current Price vs. Rating&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because Review and Rating contained missing values, I used FILTER () to create helper ranges containing only complete pairs before calculating correlations.&lt;/p&gt;

&lt;p&gt;The results were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Relationship&lt;/th&gt;
&lt;th&gt;Pearson r&lt;/th&gt;
&lt;th&gt;R²&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Discount vs. Reviews&lt;/td&gt;
&lt;td&gt;-0.111&lt;/td&gt;
&lt;td&gt;0.002&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rating vs. Reviews&lt;/td&gt;
&lt;td&gt;0.043&lt;/td&gt;
&lt;td&gt;0.002&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Current Price vs. Rating&lt;/td&gt;
&lt;td&gt;0.110&lt;/td&gt;
&lt;td&gt;0.012&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;All three relationships were very weak.&lt;/p&gt;

&lt;p&gt;For example, the -0.111 correlation between discount and reviews is very close to zero, while the R² values show that these variables explained very little of the variation in one another.&lt;/p&gt;

&lt;p&gt;This doesn't mean that price, ratings or discounts never influence customer behavior. It simply means that this dataset did not show a strong relationship between them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product Ranking&lt;/strong&gt;&lt;br&gt;
I also created PivotTables to identify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Top 10 products by Rating&lt;/li&gt;
&lt;li&gt;Bottom 10 products by Rating&lt;/li&gt;
&lt;li&gt;Top 10 products by Discount&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For rating rankings, products without ratings were excluded. Where products has the same rating, review count was used as the tie-breaker.&lt;/p&gt;

&lt;p&gt;This gave the rankings a consistent and transparent approach.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building the Interactive Dashboard&lt;/strong&gt;&lt;br&gt;
After completing the analysis, I brought the most important findings together into a single-screen interactive dashboard.&lt;/p&gt;

&lt;p&gt;The dashboard contains:&lt;br&gt;
&lt;strong&gt;KPI Cards&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total Products&lt;/li&gt;
&lt;li&gt;Average Price&lt;/li&gt;
&lt;li&gt;Average Discount&lt;/li&gt;
&lt;li&gt;Average Rating&lt;/li&gt;
&lt;li&gt;Total Reviews&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Products Performance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Top 10 by Rating&lt;/li&gt;
&lt;li&gt;Top 10 by Reviews&lt;/li&gt;
&lt;li&gt;Top 10 by Discount&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Relationship Analysis&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Discount vs. Reviews&lt;/li&gt;
&lt;li&gt;Rating vs. Reviews&lt;/li&gt;
&lt;li&gt;Price vs. Rating
The scatter plots include trendlines and R² values to help interpret the relationship.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Category Analysis&lt;/strong&gt;&lt;br&gt;
I also included charts showing by the distribution of products by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rating Category&lt;/li&gt;
&lt;li&gt;Discount Category&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Interactive Slicers&lt;/strong&gt;&lt;br&gt;
To make the dashboard easier to explore, I added slicers for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rating Category&lt;/li&gt;
&lt;li&gt;Discount Category&lt;/li&gt;
&lt;li&gt;Price Category&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These allow users to filter the dashboard and explore different groups of products interactively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Findings&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1. Bigger Discounts Did Not Mean More Engagement&lt;/strong&gt;&lt;br&gt;
The correlation between discount and reviews was -0.111, indicating an extremely weak relationship.&lt;/p&gt;

&lt;p&gt;In this dataset, products with larger discounts did not necessarily receive more reviews.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Price Was Barely Related to Rating&lt;/strong&gt;&lt;br&gt;
The correlation between current price and rating was 0.110, also a very weak relationship.&lt;/p&gt;

&lt;p&gt;This suggests that higher-priced products were not necessarily rated better.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Some Highly Discounted Products Still Had Weak Performance&lt;/strong&gt;&lt;br&gt;
Some products combined high discounts with low ratings or low engagement.&lt;/p&gt;

&lt;p&gt;These products may require more than simply another price reduction. Their product description, images, listing quality or customer expectations could be worth investigating.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Some Products Had Strong Engagement and Excellent Ratings&lt;/strong&gt;&lt;br&gt;
I also identified five products with both strong engagement and excellent ratings.&lt;/p&gt;

&lt;p&gt;These products could provide useful examples for understanding what appears to work well, although the available data isn't enough to explain exactly why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommendations&lt;/strong&gt;&lt;br&gt;
Based on the analysis, I would recommend:&lt;br&gt;
Don't rely on discounts alone to drive engagement. Sellers could also improve product images, descriptions and overall listing quality.&lt;/p&gt;

&lt;p&gt;Investigate highly discounted products with weak ratings or engagement before offering even larger discounts.&lt;/p&gt;

&lt;p&gt;Study high-performing products with strong engagement and excellent ratings to identify patterns worth replicating.&lt;/p&gt;

&lt;p&gt;Interpret the results carefully. Correlation shows relationships, but it does not prove that one variable causes another.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitations&lt;/strong&gt;&lt;br&gt;
The analysis had several limitations.&lt;/p&gt;

&lt;p&gt;The most important was the lack of sales, revenue, units sold, and listing-age data. Therefore, review count was only used as a proxy for engagement and should not be treated as actual sales performance.&lt;/p&gt;

&lt;p&gt;Other limitations included:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;One product had a price range that required midpoint estimation.&lt;/li&gt;
&lt;li&gt;Many products had missing ratings and reviews.&lt;/li&gt;
&lt;li&gt;The rating categories included a working assumption for ratings between 4.1 and 4.5.&lt;/li&gt;
&lt;li&gt;The dataset contained only 115 original records.&lt;/li&gt;
&lt;li&gt;Correlation does not imply causation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These limitations are important because they define how far the findings can reasonably be generalized.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Learned&lt;/strong&gt;&lt;br&gt;
The biggest lesson from this project was that data analysis starts before the charts.&lt;/p&gt;

&lt;p&gt;What initially looked like a simple dataset turned out to contain several issues that could have affected the analysis if they had gone unnoticed.&lt;/p&gt;

&lt;p&gt;I learned to question unusual values, handle missing information carefully, document assumptions, and avoid making changes without understanding the impact.&lt;/p&gt;

&lt;p&gt;I also got to experience the complete analytics workflow:&lt;/p&gt;

&lt;p&gt;Data Auditing → Cleaning → Transformation → Analysis → Visualization → Dashboard → Insights&lt;/p&gt;

&lt;p&gt;Most importantly, this project showed me that Excel can be much more than a spreadsheet. With the right approach, it can be used to turn messy data into meaningful information and communicate insights through an interactive dashboard.&lt;/p&gt;

&lt;p&gt;And honestly, seeing a few raw columns turn into a complete analytical dashboard was one of my favorite parts of this project.&lt;/p&gt;

&lt;p&gt;I'm really enjoying this data analytics journey.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>data</category>
      <category>datascience</category>
      <category>excel</category>
    </item>
    <item>
      <title>Getting Started with Excel for Data Analytics: From the Basics to Cleaning Data.</title>
      <dc:creator>Antonina Wambui</dc:creator>
      <pubDate>Wed, 09 Sep 2026 09:31:35 +0000</pubDate>
      <link>https://dev.to/analystnina/getting-started-with-excel-for-data-analytics-from-the-basics-to-cleaning-data-3bhd</link>
      <guid>https://dev.to/analystnina/getting-started-with-excel-for-data-analytics-from-the-basics-to-cleaning-data-3bhd</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;When I first started learning data analytics, I thought working with data was mainly about creating charts, finding patterns and presenting insights.&lt;br&gt;
I quickly realised there is an important step that comes before all that: &lt;strong&gt;making sure the data is actually ready to be analysed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Raw datasets can contain missing values, duplicate records, inconsistent text, incorrect data types, and formatting problems. If these issues are ignored, they can affect the results of the analysis and eventually lead to misleading conclusions.&lt;/p&gt;

&lt;p&gt;During my Excel training at &lt;strong&gt;LuxDevHQ&lt;/strong&gt;, I was introduced to some of the tools and techniques Excel provides for preparing data for analysis. This included sorting and filtering, formatting, handling missing values, removing duplicates and text functions such as &lt;strong&gt;TRIM&lt;/strong&gt;, &lt;strong&gt;PROPER&lt;/strong&gt; and &lt;strong&gt;CONCAT&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For my practice, I worked with a synthetic dataset that allowed me to simulate a real-world data-cleaning task. Rather than jumping into analysis, I focused on understanding the dataset first and gradually transforming it into a cleaner and more consistent version.&lt;/p&gt;

&lt;p&gt;In this article, I'll share my process, the Excel tools I used, and some of the lessons I picked up along the way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Starting With the Raw Dataset&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first step in any data analysis project is understanding what you're working with.&lt;br&gt;
I imported my dataset into Excel and took some time to look through the columns and rows before making any changes.&lt;/p&gt;

&lt;p&gt;At this stage, I wasn't trying to fix anything yet. I wanted to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What information does each column contain?&lt;/li&gt;
&lt;li&gt;Which columns contain numbers?&lt;/li&gt;
&lt;li&gt;Which contain text?&lt;/li&gt;
&lt;li&gt;Are there dates?&lt;/li&gt;
&lt;li&gt;Are there missing values?&lt;/li&gt;
&lt;li&gt;Are there values that look inconsistent?&lt;/li&gt;
&lt;li&gt;Could any columns have duplicates?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This simple inspection helped me realise that data cleaning shouldn't begin with immediately changing things. You first need to understand what the data represents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Creating a Safe Copy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One thing I learned early was the importance of protecting the original dataset.&lt;/p&gt;

&lt;p&gt;Instead of working directly on my original data, I created a duplicate worksheet and used the copy for my cleaning process.&lt;br&gt;
This gave me a backup that I could return to whenever I made a mistake.&lt;/p&gt;

&lt;p&gt;It might seem like a small step, but when you're experimenting with Excel for the first time, it's easy to accidentally delete a column, change a value or apply formatting to the wrong range.&lt;br&gt;
Having an untouched copy made the process much safer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Making the Dataset Easier to Work With&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before looking for errors, I first made the spreadsheet easier to read.&lt;br&gt;
I adjusted the column widths using Excel's &lt;strong&gt;AutoFit&lt;/strong&gt; feature so that the values and column headings were visible.&lt;/p&gt;

&lt;p&gt;I also converted the dataset into an Excel table.&lt;br&gt;
This was useful because tables make it easier to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Filter information&lt;/li&gt;
&lt;li&gt;Sort records&lt;/li&gt;
&lt;li&gt;Navigate through large datasets&lt;/li&gt;
&lt;li&gt;Keep formatting consistent&lt;/li&gt;
&lt;li&gt;Work with formulas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I then enabled filters on the columns so I could inspect specific categories instead of manually going through every row.&lt;/p&gt;

&lt;p&gt;For example, filtering a column allowed me to quickly identify blank cells or check whether the same category had been entered in different ways. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Checking Data Types&lt;/strong&gt;&lt;br&gt;
One of the most interesting things I learned was that how a value looks isn't always the same as how Excel understands it.&lt;/p&gt;

&lt;p&gt;A column containing numbers doesn't necessarily mean it should be treated as a numerical field.&lt;/p&gt;

&lt;p&gt;For example, an ID such as:&lt;/p&gt;

&lt;p&gt;10001&lt;/p&gt;

&lt;p&gt;may look like a number, but if it is simply identifying a transaction or customer, there is no reason to calculate an average or total from it.&lt;/p&gt;

&lt;p&gt;The same applies to phone numbers.&lt;/p&gt;

&lt;p&gt;I therefore checked my columns and made sure they were using appropriate formats.&lt;/p&gt;

&lt;p&gt;Some of the common data types I worked with included:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data&lt;/th&gt;
&lt;th&gt;Appropriate Format&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Transaction/Customer ID&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Names&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Phone Numbers&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dates&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quantity&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prices/Revenue&lt;/td&gt;
&lt;td&gt;Currency or Number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Categories&lt;/td&gt;
&lt;td&gt;Text&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This was a good reminder that data types should be based on what the data means, not just what it looks like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Looking for Missing Data&lt;/strong&gt;&lt;br&gt;
Next, I checked the dataset for missing values.&lt;br&gt;
Missing data is not automatically an error. Sometimes a value is genuinely unavailable.&lt;/p&gt;

&lt;p&gt;The important thing is deciding what to do with the missing value based on the context.&lt;/p&gt;

&lt;p&gt;For example, if a category such as location was missing, I could use a value such as "Unknown" where appropriate.&lt;/p&gt;

&lt;p&gt;However, I wouldn't randomly replace a missing numerical value with zero.&lt;/p&gt;

&lt;p&gt;A blank amount and an amount of zero do not necessarily mean the same thing.&lt;/p&gt;

&lt;p&gt;This made me realise that data cleaning isn't simply about making every cell look complete. It's about making appropriate decisions about what each value represents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Finding Duplicates&lt;/strong&gt;&lt;br&gt;
Another important check was identifying duplicate records.&lt;/p&gt;

&lt;p&gt;I used Excel's &lt;br&gt;
Data → Remove Duplicates&lt;br&gt;
feature to check whether the dataset contained repeated records.&lt;/p&gt;

&lt;p&gt;Even when duplicates aren't found performing the check is still useful.&lt;br&gt;
It confirms that you've considered one of the common problems that can affect analysis.&lt;/p&gt;

&lt;p&gt;For example, if the same transaction appeared twice and I calculated total revenue without noticing it the final result could be higher than the actual revenue.&lt;/p&gt;

&lt;p&gt;This showed me why data validation should happen before analysis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Cleaning Inconsistent Text&lt;/strong&gt;&lt;br&gt;
Text data can look simple, but it can create some interesting problems.&lt;/p&gt;

&lt;p&gt;For example, Excel may treat these as different values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nairobi&lt;/li&gt;
&lt;li&gt;nairobi&lt;/li&gt;
&lt;li&gt;NAIROBI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To a person, they all appear to mean the same thing. To a computer, however, differences in formatting or extra spaces can affect how values are grouped and analysed.&lt;/p&gt;

&lt;p&gt;This is where some of Excel's text functions became useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TRIM&lt;/strong&gt;&lt;br&gt;
I used TRIM to remove unnecessary spaces from text.&lt;br&gt;
=TRIM(A2)&lt;/p&gt;

&lt;p&gt;This is particularly useful when data has been copied from another source and contains unwanted space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PROPER&lt;/strong&gt;&lt;br&gt;
I also explored PROPER for standardising names.&lt;br&gt;
=PROPER(A2)&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;JOHN KAMAU&lt;/p&gt;

&lt;p&gt;can become:&lt;/p&gt;

&lt;p&gt;John Kamau&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CONCAT&lt;/strong&gt;&lt;br&gt;
Another function I practised was &lt;strong&gt;CONCAT&lt;/strong&gt;,which can be used to join pieces of text together.&lt;/p&gt;

&lt;p&gt;=CONCAT(A2,B2)&lt;/p&gt;

&lt;p&gt;These functions showed me that Excel isn't only useful for calculations. It can also be used to transform and standardise text.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Using Find and Replace&lt;/strong&gt;&lt;br&gt;
Not every cleaning problem requires a formula.&lt;/p&gt;

&lt;p&gt;Excel's &lt;strong&gt;Find and Replace&lt;/strong&gt; feature can be much quicker when dealing with specific inconsitencies.&lt;/p&gt;

&lt;p&gt;The shortcut:&lt;br&gt;
Ctrl + H&lt;br&gt;
Opens Find and Replace&lt;/p&gt;

&lt;p&gt;For example, if one category had been entered several times incorrectly, I could search for the incorrect version and replace it with the correct one.&lt;/p&gt;

&lt;p&gt;This was one of those small Excel features that I initially overlooked but found surprisingly useful during the cleaning process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9. Helper Columns: A Simple but Useful Technique&lt;/strong&gt;&lt;br&gt;
Something else I learned was the use of helper columns.&lt;/p&gt;

&lt;p&gt;Instead of changing the original values immediately, I could create a temporary column containing a formula such as:&lt;br&gt;
=TRIM(A2)&lt;/p&gt;

&lt;p&gt;Then I could fill the formula down the dataset, check the result and, once satisfied, copy the result and use Paste Special → Values.&lt;/p&gt;

&lt;p&gt;This allowed me to compare the original values with the cleaned ones before replacing anything.&lt;/p&gt;

&lt;p&gt;For a beginner, I found this approach much less intimidating because I could see exactly what the formula was doing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;10. What This Exercise Taught Me&lt;/strong&gt;&lt;br&gt;
This exercise changed the way I look at spreadsheets.&lt;br&gt;
Before, I thought cleaning data mainly meant removing duplicates and filling blank cells.&lt;br&gt;
Now I understand that it involves several different decisions, including:&lt;/p&gt;

&lt;p&gt;Understanding → Checking → Cleaning → Validating → Preparing&lt;/p&gt;

&lt;p&gt;I also learned that there isn't always one correct way to clen a dataset.&lt;/p&gt;

&lt;p&gt;The right approach depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The type of data&lt;/li&gt;
&lt;li&gt;What each column represents&lt;/li&gt;
&lt;li&gt;Why values are missing&lt;/li&gt;
&lt;li&gt;The type of inconsistency&lt;/li&gt;
&lt;li&gt;What the data will eventually be used for&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a missing text value might reasonably be labelled "Unknown", while a missing financial value may need further investigation rather than simply being replaced with zero.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11. From Cleaning to Analysis&lt;/strong&gt;&lt;br&gt;
The biggest lesson for me was that data cleaning is part of data analysis, not something separate from it.&lt;/p&gt;

&lt;p&gt;A dashboard may look beautiful, but if the data behind it contains errors, the visualization can still communicate the wrong story.&lt;/p&gt;

&lt;p&gt;The process therefore becomes: &lt;br&gt;
Raw Data → Cleaning → Validation → Analysis → Visualization → Insights&lt;/p&gt;

&lt;p&gt;Excel can support several of these stages, which makes it a useful starting point for someone learning data analytics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
My first hands-on experience with Excel data cleaning gave me a better understanding of what happens before the charts and dashboards are created.&lt;/p&gt;

&lt;p&gt;I learned how to inspect a dataset, protect the original data, work with tables, check data types, identify missing values and duplicates, standardise text and use Excel functions such as &lt;strong&gt;TRIM, PROPER, and CONCAT&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;More importantly, I learned that cleaning data isn't about making a spreadsheet look perfect. It's about making sure the information is consistent, meaningful and reliable enough to support analysis.&lt;/p&gt;

&lt;p&gt;I'm still at the beginning of my data analytics journey, but this exercise has given me a stronger foundation in Excel and a better appreciation for the work that happens behind the scenes before we can confidently say:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Let's analyse the data"&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>excel</category>
      <category>dataanalytics</category>
      <category>datacleaning</category>
      <category>beginners</category>
    </item>
    <item>
      <title>My First GitHub Project</title>
      <dc:creator>Antonina Wambui</dc:creator>
      <pubDate>Fri, 21 Aug 2026 12:06:11 +0000</pubDate>
      <link>https://dev.to/analystnina/-my-first-github-project-2lol</link>
      <guid>https://dev.to/analystnina/-my-first-github-project-2lol</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;When working on a project, you may make many changes to your files. It can become difficult to keep track of what you changed. Git helps you solve this by allowing you to record your changes and keep a history of your work. GitHub provides a place where the project can be stored online.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Git?
&lt;/h3&gt;

&lt;p&gt;Git is a tool used to keep track of changes made to files in a project. It helps you have different versions of your work so that you can see how your project has changed over time. This can be useful when working on a project because you can keep track of your progress and go back to an earlier version if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is GitHub?
&lt;/h3&gt;

&lt;p&gt;GitHub is the online platform where you can store and share that Git project. &lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Repository?
&lt;/h3&gt;

&lt;p&gt;A (repo) is a place where your project is stored and git keeps track of it's history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Local Folder
&lt;/h2&gt;

&lt;p&gt;The first step is to create a folder on my computer where I will keep my project in my files. &lt;br&gt;
This is called a &lt;strong&gt;local folder&lt;/strong&gt; because it is stored in my computer.&lt;/p&gt;

&lt;p&gt;For example, I can create a folder called &lt;code&gt;my-first-project&lt;/code&gt;. I can then open Git Bash and move into the folderusing the &lt;code&gt;cd&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-first-project
&lt;span class="nb"&gt;cd &lt;/span&gt;my-first-project

The &lt;span class="k"&gt;**&lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt;&lt;span class="k"&gt;**&lt;/span&gt; &lt;span class="nb"&gt;command &lt;/span&gt;is used to create a new folder, &lt;span class="k"&gt;while &lt;/span&gt;the &lt;span class="k"&gt;**&lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="k"&gt;**&lt;/span&gt; &lt;span class="nb"&gt;command &lt;/span&gt;is used to move into that folder.

So &lt;span class="nb"&gt;local &lt;/span&gt;folder - is basically my project&lt;span class="s1"&gt;'s home on my computer.
You create folder first, then git comes later when you 

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
git init&lt;/p&gt;

&lt;p&gt;so the order is &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create folder&lt;/li&gt;
&lt;li&gt;Enter folder&lt;/li&gt;
&lt;li&gt;Git init&lt;/li&gt;
&lt;li&gt;Git starts tracking the project&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Staging with git add
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Staging&lt;/strong&gt; is the process of preparing changes before a commit.&lt;/p&gt;

&lt;p&gt;After creating or changing a file, I need to tell git which changes I want to include in my next commit.&lt;br&gt;
This is done by using the &lt;code&gt;git add&lt;/code&gt; command. &lt;/p&gt;

&lt;p&gt;Example, I can use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;

The &lt;span class="nb"&gt;.&lt;/span&gt; means that Git should stage all the changes &lt;span class="k"&gt;in &lt;/span&gt;the current folder.

Also can stage one specific file by using its name:
Bash
git add README.md

After using git add, the changes are placed &lt;span class="k"&gt;in &lt;/span&gt;the staging area and are ready to be committed.

&lt;span class="k"&gt;**&lt;/span&gt;Committing with git commit&lt;span class="k"&gt;**&lt;/span&gt;
After staging my changes, the next step is to commit them. 
A &lt;span class="k"&gt;**&lt;/span&gt;commit&lt;span class="k"&gt;**&lt;/span&gt; is like a saving version or checkpoint of my project. It allows Git to keep a record of the changes I have made.

To create commit, I use the following &lt;span class="nb"&gt;command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
git commit -m "Initial commit"&lt;/p&gt;

&lt;p&gt;the &lt;strong&gt;-m&lt;/strong&gt; allows me to add a message describing what I have committed. The message should briefly explain what the changes are&lt;br&gt;
For example&lt;br&gt;
Bash&lt;br&gt;
git commit -m "Add README file"&lt;/p&gt;

&lt;h3&gt;
  
  
  What is SSH
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;SSH&lt;/strong&gt; stands for Secure Shell. &lt;br&gt;
It is a secure way of connecting my computer to git hub. In Git, SSH can be used to connect my local repository to a GitHub repository. &lt;br&gt;
It uses SSH keys to verify the connection between my computer and GitHub.&lt;/p&gt;

&lt;p&gt;Once the connection is set up you can use commands such as&lt;br&gt;
Bash&lt;br&gt;
git push &lt;br&gt;
to send your GitHub securely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connecting the project to GitHub&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After creating a repository on GitHub, I need to connect it to the project on my computer. This allows Git to know where my project should be sent when i want to upload my work.&lt;br&gt;
I can connect my local repository to GitHub by using the &lt;code&gt;git remote add&lt;/code&gt; command. Example:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
bash
git remote add origin git@github.com:ninadavid4/my-first-project.git
Here, **origin** is the name given to the GitHub repository. The SSH address after origin tells git where the remote repository is located.
I can check if the connection has been added by using 
Bash
git remote -v
This shows the GitHub repository connected to my local project.

Then later, when you use:
Bash 
git push

Git knows where to send your commits.

##Conclusion
In this project, I learned how to take a project from a local folder on my computer and connect it GitHub using Git and SSH. I learned how to create a Git repository, stage changes using `git add`, save them using `git commit`, and connect the project to a remote GitHub repository. I also learned that SSH provides a secure way for my computer to communicate with GitHub.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>beginners</category>
      <category>git</category>
      <category>github</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
