<?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: Nesta Munene</title>
    <description>The latest articles on DEV Community by Nesta Munene (@nesta_munene_5f710317bb2e).</description>
    <link>https://dev.to/nesta_munene_5f710317bb2e</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%2F4071727%2Ff44059a8-ffe5-45a5-b98b-d97457daf26b.png</url>
      <title>DEV Community: Nesta Munene</title>
      <link>https://dev.to/nesta_munene_5f710317bb2e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nesta_munene_5f710317bb2e"/>
    <language>en</language>
    <item>
      <title>Data Modelling, Relationships &amp; Joins</title>
      <dc:creator>Nesta Munene</dc:creator>
      <pubDate>Sun, 13 Sep 2026 20:03:46 +0000</pubDate>
      <link>https://dev.to/nesta_munene_5f710317bb2e/data-modelling-relationships-joins-5h1j</link>
      <guid>https://dev.to/nesta_munene_5f710317bb2e/data-modelling-relationships-joins-5h1j</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A Power BI report is only as good as the data model sitting underneath it. For instance, two analysts can start with identical raw data and end up with wildly different reports; one fast, easy to extend, and simple to write DAX against; the other slow, tangled, and fragile the moment a new requirement shows up. The difference almost always comes down to data modelling decisions made before a single visual was ever placed on a canvas.&lt;/p&gt;

&lt;p&gt;This article will walks you through how Power BI models data using flat tables versus star and snowflake schemas, the role of fact and dimension tables, how relationships and filter direction actually work, the difference between a Power Query join and a Power BI relationship, and finally, a justified recommendation for how to structure a typical BI project.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Data Modelling in Power BI
&lt;/h2&gt;

&lt;p&gt;Data modelling is the process of organizing your tables and the connections between them before you start building visuals. It answers questions like: should this be one big table, or several smaller ones? How do they relate to each other? Which table holds the numbers you want to measure, and which tables hold the descriptive context around those numbers?&lt;/p&gt;

&lt;p&gt;This matters for several practical reasons:&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;DAX simplicity:&lt;/strong&gt; a well-structured model lets a single measure like &lt;code&gt;SUM(Sales[Amount])&lt;/code&gt; work correctly across every report filter, without needing to be rewritten for each new chart.&lt;br&gt;
2.&lt;strong&gt;Performance:&lt;/strong&gt; Power BI's engine (VertiPaq) is optimized to compress and query well-structured, related tables far more efficiently than one enormous flat table.&lt;br&gt;
3.&lt;strong&gt;Scalability:&lt;/strong&gt; adding a new dimension (say, a Promotions table) to a well-modelled star schema is a five-minute job; retrofitting it into a flat table can mean rebuilding half your columns.&lt;br&gt;
4.&lt;strong&gt;Maintainability:&lt;/strong&gt; when business logic changes (e.g., a new way of categorizing customers), a well-modelled table only needs updating in one place, not duplicated across every report.&lt;/p&gt;
&lt;h3&gt;
  
  
  Flat Table
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; a single, wide table containing every piece of data-transactional facts and descriptive attributes in one place. This is the Excel-style approach: one row per transaction, with customer name, product name, region, date, and sales amount all sitting in the same row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure:&lt;/strong&gt; no separate tables, no relationships, just one table with many columns.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    SALES_FLAT {
        int OrderID
        date OrderDate
        string CustomerName
        string CustomerCity
        string ProductName
        string ProductCategory
        string Region
        int Quantity
        decimal SalesAmount
    }&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;br&gt;
1.Simple to understand at a glance.&lt;br&gt;
2.No relationships to configure, so it's fast to build for very small, one-off analyses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;br&gt;
1.Massive data redundancy: if "Nairobi" appears as a customer's city on 500 orders, that text is repeated 500 times instead of stored once.&lt;br&gt;
2.Poor performance at scale: a wide, repetitive table compresses far worse than normalized tables, and Power BI's engine has to do more work per query.&lt;br&gt;
3.Difficult to maintain: updating a customer's city means finding and updating every row that customer appears in, rather than one row in a dimension table.&lt;br&gt;
4.DAX becomes harder to reuse across contexts once a table conflates multiple grains (e.g., "one row per order" and "one row per customer" living together).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When appropriate:&lt;/strong&gt; small, static datasets, quick one-time analyses, or genuinely simple use cases with no plans to scale. It's a reasonable starting point, but not something to scale a serious BI solution on.&lt;/p&gt;
&lt;h3&gt;
  
  
  Star Schema
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; a central &lt;strong&gt;fact table&lt;/strong&gt; (holding measurable business events such as; sales, orders, transactions) surrounded by multiple dimension tables (holding descriptive context such as customers, products, dates, locations), each connected directly to the fact table by a relationship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure:&lt;/strong&gt; the fact table sits in the middle; each dimension connects to it independently, with no dimension connecting to another dimension.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    DimCustomer ||--o{ FactSales : "CustomerID"
    DimProduct ||--o{ FactSales : "ProductID"
    DimDate ||--o{ FactSales : "DateKey"
    DimLocation ||--o{ FactSales : "LocationID"

    DimCustomer {
        int CustomerID PK
        string CustomerName
        string Segment
    }
    DimProduct {
        int ProductID PK
        string ProductName
        string Category
    }
    DimDate {
        int DateKey PK
        date FullDate
        string Month
        int Year
    }
    DimLocation {
        int LocationID PK
        string City
        string Region
    }
    FactSales {
        int OrderID
        int CustomerID FK
        int ProductID FK
        int DateKey FK
        int LocationID FK
        decimal SalesAmount
        int Quantity
    }&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;br&gt;
1.Eliminates redundancy: "Nairobi" is stored once in DimLocation, not once per transaction.&lt;br&gt;
2.Fast query performance: Power BI's VertiPaq engine is specifically optimized for this shape.&lt;br&gt;
3.Simple, predictable DAX: filters flow cleanly from dimension to fact in one hop.&lt;br&gt;
4.Easy for report builders to understand and navigate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;br&gt;
1.Requires upfront design work: you need to identify your facts and dimensions before building, rather than just dumping in a flat export.&lt;br&gt;
2.Slightly less intuitive for someone used to reading a single spreadsheet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When appropriate:&lt;/strong&gt; the default choice for the vast majority of real world Power BI projects: sales analysis, product performance dashboards, operational reporting, and anything expected to grow over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance and complexity implications:&lt;/strong&gt; star schemas are what Power BI is built to perform best on. Model complexity is low and predictable, one hop from any dimension to the fact table and this directly keeps DAX formulas simple, since Power BI's automatic filter propagation does most of the work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A worked example, built from a real dataset:&lt;/strong&gt; to make this concrete, I took a Kenya crop production dataset that originally arrived as a single flat table — one row per crop record, with County, Crop Type, Season, Planting Date, Harvest Date, and a set of numeric measures (Revenue, Profit, Yield, Production Cost, Market Price) all sitting in the same wide table. I rebuilt it into a proper star schema in Power Query, splitting it into a fact table and four dimensions:&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;Kenya_Crops_Dataset (Fact)&lt;/strong&gt; - Planted Area, Yield, Market Price, Production Cost, Revenue, Profit, plus Planting Date and Harvest Date&lt;br&gt;
2.&lt;strong&gt;DimCounty&lt;/strong&gt; - County&lt;br&gt;
3.&lt;strong&gt;DimCropType&lt;/strong&gt; - Crop Type&lt;br&gt;
4.&lt;strong&gt;DimSeason&lt;/strong&gt; - Season&lt;br&gt;
5.&lt;strong&gt;Calendar&lt;/strong&gt; - Date&lt;/p&gt;

&lt;p&gt;Each dimension was created by referencing the original fact query, keeping only it's one relevant column, and removing duplicates, turning a flat table into a normalized set of tables ready to be related.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9cqt156jesrzas3kqsbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9cqt156jesrzas3kqsbw.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1: The finished star schema in Power BI's Model View. Note the two lines running to Calendar one solid, one dashed&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Snowflake Schema
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Definition:&lt;/strong&gt; an extension of the star schema where dimension tables are further broken down into related sub-dimensions, rather than each dimension being a single flat table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Structure:&lt;/strong&gt; instead of DimProduct holding both product details &lt;em&gt;and&lt;/em&gt; category details in one table, a snowflake schema splits this into DimProduct → DimCategory, connected to each other before either connects back to the fact table.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;erDiagram
    DimCategory ||--o{ DimProduct : "CategoryID"
    DimProduct ||--o{ FactSales : "ProductID"
    DimCity ||--o{ DimLocation : "CityID"
    DimLocation ||--o{ FactSales : "LocationID"

    DimCategory {
        int CategoryID PK
        string CategoryName
    }
    DimProduct {
        int ProductID PK
        string ProductName
        int CategoryID FK
    }
    DimCity {
        int CityID PK
        string CityName
        string Country
    }
    DimLocation {
        int LocationID PK
        int CityID FK
        string Region
    }
    FactSales {
        int OrderID
        int ProductID FK
        int LocationID FK
        decimal SalesAmount
    }&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;br&gt;
1.Further reduces redundancy in cases where a dimension itself has repeating descriptive data (e.g., many products sharing the same category name and description).&lt;br&gt;
2.Can better reflect a genuinely hierarchical business structure (Category → Sub-category → Product).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;br&gt;
1.More tables means more relationships, meaning more "hops" a filter has to travel through to reach the fact table, this adds query overhead and can slow report performance compared to a star schema.&lt;br&gt;
2.More complex DAX and more places for a broken relationship to hide.&lt;br&gt;
3.Harder for report builders to navigate, finding the right field means knowing which of several linked tables it lives in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When appropriate:&lt;/strong&gt; large enterprise models with genuinely deep, reused hierarchies, or where a dimension is large enough that normalizing it meaningfully reduces storage and improves maintainability. It's a deliberate trade-off, not a "better" version of a star schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance and complexity implications:&lt;/strong&gt; every additional join level is an additional cost. It is good to default to a star schema and only snowflake a specific dimension when there's a clear, measurable reason to.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Fact Tables and Dimension Tables
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fact tables&lt;/strong&gt; store the measurable, numeric events of a business; the things you want to sum, average, or count. Think of sales transactions, orders placed, website clicks, or support tickets logged. A fact table is typically long with many rows and narrow few columns: mostly foreign keys pointing to dimensions, plus a handful of numeric measures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dimension tables&lt;/strong&gt; store the descriptive context that explains &lt;em&gt;who, what, where,&lt;/em&gt; and &lt;em&gt;when&lt;/em&gt; around those facts - customer names, product details, dates, locations. Dimension tables are typically wide with many descriptive columns but short rows than the fact table.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Fact Table&lt;/th&gt;
&lt;th&gt;Dimension Table&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stores&lt;/td&gt;
&lt;td&gt;Measurable business events&lt;/td&gt;
&lt;td&gt;Descriptive attributes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Example content&lt;/td&gt;
&lt;td&gt;SalesAmount, Quantity, OrderID&lt;/td&gt;
&lt;td&gt;CustomerName, ProductCategory, City&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical shape&lt;/td&gt;
&lt;td&gt;Many rows, few columns&lt;/td&gt;
&lt;td&gt;Fewer rows, many columns&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Examples&lt;/td&gt;
&lt;td&gt;FactSales, FactOrders, FactTransactions&lt;/td&gt;
&lt;td&gt;DimCustomer, DimProduct, DimDate, DimLocation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Measures vs. descriptive attributes:&lt;/strong&gt; a &lt;em&gt;measure&lt;/em&gt; is a number you aggregate &lt;code&gt;SUM(FactSales[SalesAmount])&lt;/code&gt;. A &lt;em&gt;descriptive attribute&lt;/em&gt; is something you group or filter by, but never sum. Grouping sales &lt;code&gt;by Region&lt;/code&gt; makes sense; summing "Region" does not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grain / granularity:&lt;/strong&gt; this is one of the most important and most overlooked concepts in fact table design. Grain describes what a single row in the fact table represents. Is one row "one order" or "one line item within an order" or "one day's total sales for one product"? Every measure and every relationship depends on this being clearly defined and consistent - mixing grains in one fact table (some rows representing an order, others representing a daily summary) breaks aggregations silently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical example, the Kenya Crops model:&lt;/strong&gt; in the star schema built for Section 1, the grain of the fact table is one row per crop production record. Its numeric measures - Yield, Revenue, Profit, Production Cost, Market Price, are the facts. County, Crop Type, and Season are descriptive attributes, which is exactly why they were pulled out into their own dimension tables rather than left as repeating text in every fact row. Each dimension connects directly to the fact table - the star shape from Section 1 - letting a report slice total revenue or yield by any combination of county, crop type, season, or date, without duplicating that descriptive text across every row the way the original flat table did.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0mxb2w6lqjr88pxvsvwd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0mxb2w6lqjr88pxvsvwd.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2: The fact table's grain, one row per production record visible here before it was split into the star schema. This single, wide table is the "before" state Section 1's flat-table discussion refers to.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Relationships in Power BI
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;relationship&lt;/strong&gt; is a defined connection between two tables, based on a shared column, that tells Power BI how rows in one table relate to rows in another. Relationships are necessary because splitting data into multiple tables (as a star or snowflake schema does) only works if Power BI has a way to reassemble the connections between them at query time - this is the direct successor to the manual &lt;code&gt;XLOOKUP&lt;/code&gt; work in Excel, done once structurally instead of formula-by-formula.&lt;/p&gt;
&lt;h3&gt;
  
  
  One-to-Many (1:*)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; one row in Table A can relate to many rows in Table B, but each row in Table B relates back to only one row in Table A. This is by far the most common relationship type in a star schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; one row in &lt;code&gt;DimCustomer&lt;/code&gt; (a single customer) relates to many rows in &lt;code&gt;FactSales&lt;/code&gt; (that customer's many orders). In the Kenya Crops model, the same pattern holds between DimCounty and the fact table: one county (e.g. "Nakuru") relates to many crop production records.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fprhjs74mq31mwjawvy9c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fprhjs74mq31mwjawvy9c.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
*Figure 3: Power BI's relationship dialog, showing the County relationship's cardinality.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it:&lt;/strong&gt; this is the default, expected relationship between any dimension and its fact table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When not to use it:&lt;/strong&gt; it shouldn't be used to connect two tables that both hold transactional-level data with no clear "one side" - that usually signals you actually have a many-to-many situation being modelled incorrectly.&lt;/p&gt;
&lt;h3&gt;
  
  
  One-to-One (1:1)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; one row in Table A relates to exactly one row in Table B, and vice versa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; a &lt;code&gt;DimCustomer&lt;/code&gt; table split into &lt;code&gt;DimCustomerProfile&lt;/code&gt; (name, segment) and &lt;code&gt;DimCustomerContact&lt;/code&gt; (email, phone), where each customer has exactly one matching row in each.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it:&lt;/strong&gt; rare in practice - usually only when a table has genuinely been split for organizational or security reasons (e.g., separating sensitive contact details from general profile data).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When not to use it:&lt;/strong&gt; if you find yourself creating a 1:1 relationship as a workaround, it's almost always a sign those two tables should simply be merged into one - a 1:1 relationship adds model complexity without a real modelling benefit in most cases.&lt;/p&gt;
&lt;h3&gt;
  
  
  Many-to-Many (&lt;em&gt;:&lt;/em&gt;)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; rows in Table A can relate to many rows in Table B, and rows in Table B can relate to many rows in Table A.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; a &lt;code&gt;DimProduct&lt;/code&gt; table and a &lt;code&gt;DimPromotion&lt;/code&gt; table, where one promotion can apply to many products, and one product can be part of many different promotions at once.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to use it:&lt;/strong&gt; when the real-world business relationship genuinely has no "one" side - this does happen, but it should be a deliberate modelling decision, often resolved with a bridge table in between rather than a direct many-to-many link.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When not to use it:&lt;/strong&gt; many-to-many relationships are harder for Power BI to filter through efficiently and can produce ambiguous or unexpectedly duplicated results if used casually. Most textbook "many-to-many" cases are better modelled with an intermediate bridge table that breaks the relationship into two clean one-to-many hops.&lt;/p&gt;
&lt;h3&gt;
  
  
  Keys, Cardinality, and Integrity
&lt;/h3&gt;

&lt;p&gt;1.&lt;strong&gt;Primary Key:&lt;/strong&gt; a column that uniquely identifies each row in a table. e.g., &lt;code&gt;CustomerID&lt;/code&gt; in &lt;code&gt;DimCustomer&lt;/code&gt;, where every value appears exactly once.&lt;br&gt;
2.&lt;strong&gt;Foreign Key:&lt;/strong&gt; a column in another table that refers back to a primary key. e.g., &lt;code&gt;CustomerID&lt;/code&gt; in &lt;code&gt;FactSales&lt;/code&gt;, where the same customer's ID can (and should) appear many times, once per order.&lt;br&gt;
3.&lt;strong&gt;Unique values:&lt;/strong&gt; a primary key's defining requirement, no duplicates. &lt;code&gt;CustomerID&lt;/code&gt; in &lt;code&gt;DimCustomer&lt;/code&gt; must be unique for the relationship to behave correctly.&lt;br&gt;
4.&lt;strong&gt;Cardinality:&lt;/strong&gt; describes how many times a key value can repeat on each side of the relationship - this is what defines whether a relationship is 1:1, 1:&lt;em&gt;, or *:&lt;/em&gt;.&lt;br&gt;
5.&lt;strong&gt;Referential integrity:&lt;/strong&gt; the guarantee that every foreign key value in the fact table actually has a matching row in the dimension table - an order referencing &lt;code&gt;CustomerID = 507&lt;/code&gt; should only exist if a customer with ID 507 actually exists in &lt;code&gt;DimCustomer&lt;/code&gt;. Broken referential integrity (an order with no matching customer) shows up as blank or "unknown" values in reports.&lt;br&gt;
6.&lt;strong&gt;Active vs. inactive relationships:&lt;/strong&gt; Power BI allows only one &lt;em&gt;active&lt;/em&gt; relationship between two tables at a time. Any additional relationship between the same two tables must be marked &lt;em&gt;inactive&lt;/em&gt;, and can only be invoked deliberately inside a DAX measure using &lt;code&gt;USERELATIONSHIP()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I ran into this directly while building the Kenya Crops model: the fact table has both a &lt;strong&gt;Planting Date&lt;/strong&gt; and a &lt;strong&gt;Harvest Date&lt;/strong&gt;, and both logically need to relate to the same &lt;strong&gt;Calendar&lt;/strong&gt; dimension. Power BI let the Planting Date relationship save as active (visible as the solid line to Calendar in Figure 1), but automatically marked the second relationship, to Harvest Date, as inactive - drawn as the dashed line in that same diagram the moment I tried to create it, because a Calendar table can only actively filter a fact table through one date column at a time.&lt;/p&gt;

&lt;p&gt;To actually use the inactive relationship, it has to be explicitly invoked inside a measure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  Total Yield by Harvest Date = 
  CALCULATE(
      SUM('Kenya_Crops_Dataset'[Yield]),
      USERELATIONSHIP(Calendar[Date], 'Kenya_Crops_Dataset'[Harvest Date])
  )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without &lt;code&gt;USERELATIONSHIP()&lt;/code&gt;, any measure placed on a Calendar-based visual would default to filtering by Planting Date only - Harvest Date would simply be ignored by the model unless specifically activated this way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why CustomerID is unique in DimCustomer but repeats in FactSales:&lt;/strong&gt; this is the cardinality relationship in action. &lt;code&gt;DimCustomer&lt;/code&gt; describes each customer once - the "one" side. &lt;code&gt;FactSales&lt;/code&gt; records every transaction that customer made - the "many" side. The same CustomerID legitimately appears multiple times in FactSales because that customer placed multiple orders, while it can only appear once in DimCustomer because a customer is only described once.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Filter Direction
&lt;/h2&gt;

&lt;p&gt;Filter direction controls which way a selection in one table affects another related table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single-direction filtering&lt;/strong&gt; (the Power BI default for most relationships): a filter applied to the "one" side (a dimension) flows down to the "many" side (the fact table), but not the other way around. Selecting "Nairobi" in &lt;code&gt;DimLocation&lt;/code&gt; filters &lt;code&gt;FactSales&lt;/code&gt; down to only Nairobi's transactions - but filtering &lt;code&gt;FactSales&lt;/code&gt; some other way (say, only orders over KSh 5,000) does not, by default, filter which cities show up in &lt;code&gt;DimLocation&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bidirectional filtering:&lt;/strong&gt; the filter can travel both directions - a selection in the fact table can also filter back up into a connected dimension.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; selecting "Electronics" in &lt;code&gt;DimProduct&lt;/code&gt; filters &lt;code&gt;FactSales&lt;/code&gt; down to only electronics sales - this is standard single-direction behaviour and is exactly what powered the slicers in my earlier Jumia Excel dashboard (clicking "Excellent" on the Rating Category slicer filtered the connected pie charts the same way a dimension filter flows down to a fact table in Power BI).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why bidirectional filtering should be used carefully:&lt;/strong&gt; turning on both-direction filtering can create &lt;strong&gt;ambiguous filter paths&lt;/strong&gt; - situations where Power BI has more than one possible route a filter could travel to reach a table, and can't determine which one should win. This is especially risky in models with multiple relationships between the same tables, or several dimensions connected to more than one fact table. It also adds real query overhead, since the engine now has to evaluate filter propagation in both directions across every calculation. The general guidance is to leave relationships single-direction by default and only switch to bidirectional when a specific, well-understood use case genuinely requires it - not as a default "just in case" setting.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Joins in Power Query
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;join&lt;/strong&gt; (called a &lt;strong&gt;Merge Query&lt;/strong&gt; in Power Query) combines two tables based on matching values in a shared column - this happens during data preparation, before the model is even built, unlike a relationship which connects already-loaded tables inside the model.&lt;/p&gt;

&lt;p&gt;Consider two example tables:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customers&lt;/strong&gt;&lt;br&gt;
| CustomerID | Name |&lt;br&gt;
|---|---|&lt;br&gt;
| 1 | Asha |&lt;br&gt;
| 2 | Brian |&lt;br&gt;
| 3 | Carol |&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Orders&lt;/strong&gt;&lt;br&gt;
| OrderID | CustomerID | Amount |&lt;br&gt;
|---|---|---|&lt;br&gt;
| 101 | 1 | 500 |&lt;br&gt;
| 102 | 1 | 300 |&lt;br&gt;
| 103 | 4 | 750 |&lt;/p&gt;

&lt;p&gt;Notice CustomerID 4 appears in Orders but not Customers, and Carol (CustomerID 3) has no orders - these gaps are exactly what each join type handles differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  Left Outer Join
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; keeps every row from the left table (Customers), and matches in any corresponding rows from the right table (Orders) where they exist.&lt;br&gt;
&lt;strong&gt;Retained:&lt;/strong&gt; all rows from the left table; matched rows from the right, or blanks where there's no match.&lt;br&gt;
&lt;strong&gt;Example output:&lt;/strong&gt; Asha's two orders appear twice (once per order); Brian is unmatched - wait, Brian has no order in this data, so Brian would appear once with blank Order fields; Carol appears once with blank Order fields. CustomerID 4's order is dropped, since it's not in the left table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Right Outer Join
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; the mirror image - keeps every row from the right table (Orders), matching in Customer data where it exists.&lt;br&gt;
&lt;strong&gt;Retained:&lt;/strong&gt; all rows from the right table; matched rows from the left, or blanks where there's no match.&lt;br&gt;
&lt;strong&gt;Example output:&lt;/strong&gt; all three orders appear (101, 102, 103); the first two show Asha's name, the third (CustomerID 4) shows a blank Customer name, since no matching customer exists.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full Outer Join
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; keeps every row from both tables, matching where possible and leaving blanks where there's no match on either side.&lt;br&gt;
&lt;strong&gt;Retained:&lt;/strong&gt; everything - matched and unmatched rows from both tables.&lt;br&gt;
&lt;strong&gt;Example output:&lt;/strong&gt; Asha's two orders, Brian with blanks, Carol with blanks, and CustomerID 4's order with a blank customer name - nothing from either table is dropped.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inner Join
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; keeps only rows where a match exists in both tables.&lt;br&gt;
&lt;strong&gt;Retained:&lt;/strong&gt; only the overlapping, matched rows.&lt;br&gt;
&lt;strong&gt;Example output:&lt;/strong&gt; just Asha's two orders (101 and 102) - Brian and Carol are dropped (no orders), and order 103 is dropped (no matching customer).&lt;/p&gt;

&lt;h3&gt;
  
  
  Left Anti Join
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; keeps only rows from the left table that have &lt;em&gt;no&lt;/em&gt; match in the right table - effectively the opposite of an inner join.&lt;br&gt;
&lt;strong&gt;Retained:&lt;/strong&gt; unmatched left-table rows only.&lt;br&gt;
&lt;strong&gt;Example output:&lt;/strong&gt; Brian and Carol - customers with no orders at all. Useful for finding "customers who have never ordered anything."&lt;/p&gt;

&lt;h3&gt;
  
  
  Right Anti Join
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt; the mirror of a left anti join - keeps only rows from the right table with no match in the left.&lt;br&gt;
&lt;strong&gt;Retained:&lt;/strong&gt; unmatched right-table rows only.&lt;br&gt;
&lt;strong&gt;Example output:&lt;/strong&gt; order 103 - an order that references a customer who doesn't exist in the Customers table. Useful for finding orphaned or data-quality-flagged records, similar to the negative Review values I had to catch and fix in my Jumia Excel dataset.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Power Query Joins vs. Power BI Relationships
&lt;/h2&gt;

&lt;p&gt;These solve a similar-sounding problem - combining related data - but they work at completely different stages and in fundamentally different ways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does a Power Query merge physically combine data?&lt;/strong&gt; Yes. A merge in Power Query happens during data loading/transformation, and it produces a genuinely new, combined table (or adds new columns pulled in from the second table) - the two tables' data is physically brought together into one result before the model is even built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does creating a relationship combine the tables?&lt;/strong&gt; No. A relationship leaves both tables completely separate and intact inside the model. It only tells Power BI &lt;em&gt;how&lt;/em&gt; to look across from one to the other at query time - conceptually much closer to how &lt;code&gt;XLOOKUP&lt;/code&gt; worked in my Excel dashboard, pulling a value across on demand, without ever merging the two sheets into one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage of the workflow:&lt;/strong&gt;&lt;br&gt;
1.Merges happen in &lt;strong&gt;Power Query&lt;/strong&gt; (the "Get Data" / transformation stage) before the data lands in the model.&lt;br&gt;
2.Relationships are created in &lt;strong&gt;Model view&lt;/strong&gt;, after the tables already exist as separate entities inside the report.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When to choose a merge instead of a relationship:&lt;/strong&gt; when you need specific columns from Table B pulled directly into Table A as part of a single flattened result - for instance, if a single visual absolutely needs a column that DAX can't easily reach across a relationship, or you're deliberately building a single reporting table for a specific narrow purpose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How excessive merging affects the model:&lt;/strong&gt; overusing merges tends to recreate the flat-table problem from Section 1 - data gets duplicated across many wide, overlapping tables, storage and refresh times increase, and you lose the clean, redundancy-free structure a star schema is designed to give you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why keep fact and dimension tables separate:&lt;/strong&gt; separate tables connected by relationships keep the model small, avoid duplicating dimension data across every fact row, let Power BI's engine compress and query efficiently, and make it easy to reuse the same dimension (say, DimDate) across multiple fact tables without rebuilding it each time. Merging everything into one table trades all of that away for a false sense of simplicity.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Recommended Power BI Model
&lt;/h2&gt;

&lt;p&gt;For a typical business intelligence project, I would recommend a &lt;strong&gt;star schema&lt;/strong&gt;, with &lt;strong&gt;single-direction, one-to-many relationships&lt;/strong&gt; flowing from each dimension into a central fact table, reserving bidirectional filtering only for specific, well-justified cases.&lt;/p&gt;

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

&lt;p&gt;1.&lt;strong&gt;Query and report performance:&lt;/strong&gt; Power BI's VertiPaq engine is purpose-built to compress and query star schemas efficiently. A snowflake schema's extra join hops add measurable overhead at scale; a flat table's redundancy bloats storage and slows refresh.&lt;br&gt;
2.&lt;strong&gt;DAX simplicity:&lt;/strong&gt; with a clean star schema, most measures are simple aggregations (&lt;code&gt;SUM&lt;/code&gt;, &lt;code&gt;AVERAGE&lt;/code&gt;, &lt;code&gt;DISTINCTCOUNT&lt;/code&gt;) that automatically respect whatever filters are applied across any connected dimension, thanks to default filter propagation - no need for complex &lt;code&gt;USERELATIONSHIP()&lt;/code&gt; gymnastics or ambiguous-path troubleshooting.&lt;br&gt;
3.&lt;strong&gt;Model readability:&lt;/strong&gt; a star shape is genuinely easier for anyone (including a future version of the analyst who built it) to look at and immediately understand - every dimension is one hop from the fact table, full stop.&lt;br&gt;
4.&lt;strong&gt;Scalability:&lt;/strong&gt; adding a new dimension later (a new DimPromotion, say) is a clean, additive change - connect it directly to the fact table, no restructuring required.&lt;br&gt;
5.&lt;strong&gt;Data redundancy:&lt;/strong&gt; dramatically lower than a flat table, since descriptive attributes live once in each dimension rather than repeating on every transaction row.&lt;br&gt;
6.&lt;strong&gt;Maintainability:&lt;/strong&gt; updating a product's category means updating one row in DimProduct, not hunting through thousands of fact rows.&lt;/p&gt;

&lt;p&gt;I would only introduce snowflaking for a specific dimension where there's a clear, demonstrated reason - a genuinely large, deeply hierarchical dimension where normalizing meaningfully reduces redundancy - rather than snowflaking by default. And I would keep relationships single-direction unless a specific reporting requirement (like a genuine many-to-many scenario needing a bridge table) demands otherwise, since the performance and ambiguity costs of bidirectional filtering outweigh the convenience in most everyday reporting needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Note on Data Quality in the Worked Example
&lt;/h2&gt;

&lt;p&gt;Building this model surfaced two real data-quality issues worth naming rather than hiding, in the same spirit as the cleaning work documented in an earlier Excel project I completed on Jumia product data:&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;Missing Harvest Dates:&lt;/strong&gt; roughly 3% of records had a blank Harvest Date, which had to be filtered out of the Calendar table before it could be used as a relationship key - a dimension table's key column cannot contain blanks.&lt;br&gt;
2.&lt;strong&gt;A mismatched category:&lt;/strong&gt; the DimSeason dimension, built by extracting unique values from the fact table's Season column, ended up with only three values (Long Rains, Short Rains, Unknown), while the fact table itself also contained a fourth value, "Dry Season," not captured in that extraction. Left unresolved, any report slicing by Season would silently drop or misclassify those rows - a reminder that even a mechanically correct relationship can sit on top of an incomplete dimension, and that building a star schema doesn't eliminate the need to also check the data feeding it.&lt;/p&gt;

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

&lt;p&gt;The shift from an Excel-style flat table to a Power BI star schema mirrors a lesson from building the Jumia product dashboard: the shape you organize data into isn't cosmetic, it directly determines how easy, fast, and trustworthy every downstream calculation and chart will be. A star schema with clean, single-direction relationships is the closest thing Power BI has to a default best practice, and understanding &lt;em&gt;why&lt;/em&gt; it wins - not just that it does, is what separates rearranging tables from actually modelling data.&lt;/p&gt;

</description>
      <category>powerfuldevs</category>
      <category>analyst</category>
      <category>ai</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Building an Interactive Excel Dashboard for E-commerce Product Analysis: A Case Study of Jumia Products</title>
      <dc:creator>Nesta Munene</dc:creator>
      <pubDate>Sun, 06 Sep 2026 10:30:29 +0000</pubDate>
      <link>https://dev.to/nesta_munene_5f710317bb2e/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-case-study-of-jumia-540e</link>
      <guid>https://dev.to/nesta_munene_5f710317bb2e/building-an-interactive-excel-dashboard-for-e-commerce-product-analysis-a-case-study-of-jumia-540e</guid>
      <description>&lt;p&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;E-commerce platforms like Jumia generate a constant stream of data on pricing, discounts, and customer feedback, but that data is only useful once someone actually digs into it. For this project, I worked with a dataset of 111 products listed on Jumia to understand how price, discounting, and customer reviews relate to one another, and to turn that understanding into something Jumia's sellers could actually act on.&lt;/p&gt;

&lt;p&gt;This article walks through the full process of cleaning a messy real-world dataset, building out the analysis with Excel formulas and Pivot Tables, constructing an interactive dashboard, and the business insights that came out the other end including a couple of assumptions that didn't survive contact with the actual numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dataset Description&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The dataset included six core fields per product:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product&lt;/strong&gt; - product name&lt;br&gt;
&lt;strong&gt;Current Price&lt;/strong&gt; - selling price in KES&lt;br&gt;
&lt;strong&gt;Old Price&lt;/strong&gt; - price before discount&lt;br&gt;
&lt;strong&gt;Discount&lt;/strong&gt; - percentage discount applied&lt;br&gt;
&lt;strong&gt;Review&lt;/strong&gt; - number of customer reviews&lt;br&gt;
&lt;strong&gt;Ratings&lt;/strong&gt; - average customer rating out of 5&lt;/p&gt;

&lt;p&gt;Before any of this was usable, it needed cleaning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data Cleaning and Preparation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fddq09mubje2a42v2py46.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fddq09mubje2a42v2py46.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The original dataset&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two issues stood out immediately&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;The Review column was entirely negative, values like -2, -14, and -69, which makes no sense for a count of anything. This pointed to a sign error somewhere upstream in how the data was collected or exported, and was corrected to positive values.&lt;br&gt;
One row's Current Price was stored as text and range "1,620 - 1,980", a price range typed into a single cell instead of a number. This one bad cell was enough to silently break SUM, AVERAGE, and correlation calculations across the whole column unless it was fixed.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpin7htkpo162tsgobpav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpin7htkpo162tsgobpav.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also had to think carefully about a more subtle issue: roughly half the dataset that is 57 of 111 products, had no Review or Rating data at all. Rather than ignore this gap, I treated it as a finding in its own set. Any conclusion about "what makes a product well reviewed" in this analysis only applies to the half of the catalog that actually has review data. &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa5sa5cwhc475gz1pzz8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa5sa5cwhc475gz1pzz8m.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;em&gt;The empty fields&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enrichment: Calculated Columns&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With the base data clean, I added:&lt;/p&gt;

&lt;p&gt;Discount Amount = Old Price − Current Price&lt;br&gt;
Rating Category: Poor (below 3), Average (3–4), Excellent (4.5 and above)&lt;br&gt;
Discount Category: Low (below 20%), Medium (20–40%), Above/High (over 40%)&lt;br&gt;
Price Category: Low, Medium, High, based on where a product's price falls within the overall range&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsd09n3n3176o9isay0tr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsd09n3n3176o9isay0tr.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;em&gt;The Cleaned and Enriched Dataset&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Excel Techniques and Analysis&lt;/strong&gt;&lt;br&gt;
Descriptive statistics across the 111 products:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total products&lt;/strong&gt;              &lt;em&gt;&lt;strong&gt;111&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Average current price&lt;/strong&gt;       &lt;em&gt;&lt;strong&gt;KES 1,181&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Average discount&lt;/strong&gt;                &lt;em&gt;&lt;strong&gt;37%&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Average rating&lt;/strong&gt;              &lt;em&gt;&lt;strong&gt;3.88&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;Total reviews&lt;/strong&gt;               &lt;em&gt;&lt;strong&gt;721&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I did &lt;strong&gt;Correlation analysis&lt;/strong&gt;, using &lt;code&gt;=CORREL()&lt;/code&gt; to test three commonly assumed relationships:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Discount % vs. Review -0.14      No relationship&lt;/li&gt;
&lt;li&gt;Rating vs. Reviews   +0.07       No relationship&lt;/li&gt;
&lt;li&gt;Price vs. Rating +0.01       No relationship&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One thing I want to highlight about the Price vs. Rating result specifically, because it changed how I read the rest of the analysis. When I first built a Pivot Table comparing average price across Poor/Average/Excellent rating groups, the averages climbed 998, 1,369, 1,381 which looked like evidence that pricier products get rated higher. But the correlation was 0.01, essentially zero. Building a scatter plot settled it, ratings of 2.0 through 5.0 were scattered across the entire price range, with no visible upward drift. The Pivot averages were misleading because the Poor and Average rating groups only had 12 and 22 products respectively, which are small enough that a couple of outlier prices could swing the average without reflecting any real underlying pattern. It was a good reminder that a summary average can tell a different story than the full spread of the data, and it's worth checking both before drawing a conclusion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ranking and segmentation&lt;/strong&gt;, I used &lt;code&gt;SORT&lt;/code&gt;, &lt;code&gt;INDEX+SEQUENCE&lt;/code&gt;, and &lt;code&gt;XLOOKUP&lt;/code&gt;to build Top-10 lists (by Rating, Reviews, and Discount), and FILTER combining AND (*) and OR (+) logic, to isolate specific product segments.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Strong customer demand&lt;/strong&gt; (Reviews ≥ 20 AND Rating ≥ 4): 9 products, led by a 137-Piece Cake Decorating Tool Set (55 reviews, 4.6 rating).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High discount but low rating&lt;/strong&gt; (Discount ≥ 40% AND Rating &amp;lt; 3): 10 products, including a 5-PCS Stainless Steel Cooking Pot Set discounted 55% but rated only 2.1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High discount but low engagement&lt;/strong&gt; (Discount ≥ 40% AND Reviews ≤ 3): 9 products — heavily discounted, but barely bought or reviewed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Products needing better pricing or marketing strategies&lt;/strong&gt; (Reviews ≤ 3 OR Rating &amp;lt; 3): 23 products in total.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Category breakdowns via Pivot Tables and PivotCharts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rating Category:&lt;/strong&gt; 22 Average, 22 Excellent, 12 Poor, 55 Not Provided&lt;br&gt;
&lt;strong&gt;Discount Category:&lt;/strong&gt; 57% Above, 21% Medium, 19% Low Discount (approximate)&lt;br&gt;
&lt;strong&gt;Price Category:&lt;/strong&gt; 50% Low, 43% High, 7% Medium&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dashboard Creation Process&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final dashboard pulls all of this into one sheet, organized into four sections:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Overview/KPI cards - Total Products, Average Price, Average Discount %, Average Rating, Total Reviews, styled as five distinct summary cards.&lt;/li&gt;
&lt;li&gt;Product Performance - three bar charts for Top 10 by Rating, by Reviews, and by Discount.&lt;/li&gt;
&lt;li&gt;Trend Analysis - three scatter charts (no connecting lines, so the actual spread of the data is visible rather than hidden inside a single line or average), each labeled with its correlation value directly in the title.&lt;/li&gt;
&lt;li&gt;Product Categories - three pie charts (Rating, Discount, and Price Category), connected via slicers so that clicking a single category, instantly re-filters all three pie charts.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpkv7nkexbvvybops50gq.png" alt=" " width="800" height="500"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Key Insights and Business Recommendations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Are higher discounts leading to higher customer engagement?&lt;/strong&gt; No. The correlation is -0.14, and the scatter plot backs this up with no visible trend across the full 0–70% discount range.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do highly rated products have higher or lower prices?&lt;/strong&gt; Essentially neither. The correlation is 0.01. This was the most counter-intuitive finding of the project, especially since an initial Pivot Table look made it seem otherwise until I checked the raw scatter of the data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which products are performing best based on reviews and ratings?&lt;/strong&gt; The 9 "strong demand" products sheet, consistently high reviews paired with strong ratings, are the most validated products in the catalog and worth featuring or promoting.&lt;/p&gt;

&lt;p&gt;**Which products may need improved pricing strategies? **The 23 flagged products split into two genuinely different problems; some like a DIY File Folder rated 5 with only 1 review, simply aren't being seen, which is a marketing or visibility issue. Others like the discounted Cooking Pot Set above, have a real satisfaction problem that a bigger discount won't fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recommendations for Jumia sellers:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Don't treat discount depth as an engagement lever&lt;/strong&gt; - the data shows no payoff from deeper discounts on their own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Close the data gap&lt;/strong&gt; - nearly half the catalog has no review or rating at all, which limits how much sellers and buyers alike can trust any single product's track record.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit the 9 "high discount, low engagement" products specifically&lt;/strong&gt; - Since the discount clearly isn't the barrier, so something else likely is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't lump visibility problems in with quality problems&lt;/strong&gt; - a 5-star product with one review needs marketing. A heavily discounted product with a 2-star rating needs a quality fix, not more discounting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Closing Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most useful part of this project wasn't the dashboard itself, it was the number of instinctive assumptions that "bigger discount = more reviews," and "pricier = better rated" that turned out not to hold up once actually tested. Building the habit of double-checking a Pivot Table average against a correlation and a scatter plot, rather than trusting the first number that looks convincing, was my biggest practical lesson from this project.&lt;/p&gt;

&lt;p&gt;The full workbook which has raw data, cleaned data, all analysis sheets, Pivot Tables, charts, and the final interactive dashboard, is available in my GitHub repository linked below.&lt;/p&gt;

&lt;p&gt;GitHub repo: [&lt;a href="https://github.com/mimi580/Jumia-Product-Performance-Dashboard-An-E-commerce-Data-Analysis-Project/blob/main/Excel%20Jumia%20Dataset.xlsx" rel="noopener noreferrer"&gt;https://github.com/mimi580/Jumia-Product-Performance-Dashboard-An-E-commerce-Data-Analysis-Project/blob/main/Excel%20Jumia%20Dataset.xlsx&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>data</category>
      <category>analytics</category>
      <category>commerce</category>
    </item>
    <item>
      <title>Getting Started with Excel for Data Analytics: From Basics to Data Cleaning</title>
      <dc:creator>Nesta Munene</dc:creator>
      <pubDate>Sun, 30 Aug 2026 07:33:55 +0000</pubDate>
      <link>https://dev.to/nesta_munene_5f710317bb2e/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-570g</link>
      <guid>https://dev.to/nesta_munene_5f710317bb2e/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-570g</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;I have just covered excel basic functions and cleaning data for correct interpretation and derivation of insights. Learning about Statistical and Aggregate functions and finally about Conditional formatting and calculations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Excel?
&lt;/h2&gt;

&lt;p&gt;Simply put, I describe excel as a grid of boxes called cells, arranged in rows which are numbered 1, 2, 3... and columns which are lettered A, B, C.... Each cell can hold a number, a word, a date, or a formula.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basics to Know
&lt;/h2&gt;

&lt;p&gt;Formulas start with an equals sign (=). If you type =5+5 into a cell, Excel shows you 10. If you type =A1+A2, it adds together the numbers sitting in cells A1 and A2. This is the whole foundation of everything else. Formulas let a cell calculate something instead of just displaying a fixed number typed in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Messy Data I Was Working With
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fllw6d38hcektl7o54jh1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fllw6d38hcektl7o54jh1.png" alt=" " width="799" height="448"&gt;&lt;/a&gt;&lt;br&gt;
Looking at this data, some of the issues present include but not limited to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spelling mistakes. "Markting" instead of "Marketing."&lt;/li&gt;
&lt;li&gt;Missing information.&lt;/li&gt;
&lt;li&gt;Inconsistent naming and cell formatting.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 1 of Data Cleaning: We figure out how bad the data set is.
&lt;/h2&gt;

&lt;p&gt;To do this, we will use two formulas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;=COUNTA()- this will tell us how many cells in the selected range have some value typed in them.&lt;/li&gt;
&lt;li&gt;=COUNTBLANK() - this formula will tell us how many blank cells there in a selected range.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcx9ewjd58jpv27bgki0y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcx9ewjd58jpv27bgki0y.png" alt=" " width="799" height="445"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Figg2ywdx2izeskh7pp5r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Figg2ywdx2izeskh7pp5r.png" alt=" " width="800" height="445"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Fix Inconsistent Spelling and Capitalization and Spaces
&lt;/h2&gt;

&lt;p&gt;For this, we will use two formulas.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;=TRIM() - This formula removes any invisible characters.&lt;/li&gt;
&lt;li&gt;=PROPER() - Tis formula fixes capitalization, so "human resources" becomes "Human Resources.&lt;/li&gt;
&lt;li&gt;=LOWER() - This formula sets all characters to lower case. It is very handy when generating emails.&lt;/li&gt;
&lt;li&gt;=LEN() -This formula will tell you how many characters are in a cell, including the invisible ones.&lt;/li&gt;
&lt;li&gt;Although the =Len() character count formula works best when used alongside other character counting formulas like, =LEFT(), =RIGHT(), =MID()&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: Removing Duplicates
&lt;/h2&gt;

&lt;p&gt;This is a strenuous activity if it were to be manually by scrolling one cell/column after the other.&lt;br&gt;
Looking at the dirty data, we can see that there are double entries.&lt;br&gt;
In excel we can remove duplicates easily by using =COUNTIF() formula.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Formatting Columns Correctly
&lt;/h2&gt;

&lt;p&gt;This can apply in cases where the column,ie the date or salary column is not correctly formatted, the values will be misconstrued and not accurately represent the data as they should.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aggregate Functions
&lt;/h2&gt;

&lt;p&gt;These add up or combine a whole range of numbers into one result.&lt;/p&gt;

&lt;p&gt;=SUM() =adds everything in a range.&lt;br&gt;
=AVERAGE() = finds the mean value.&lt;br&gt;
=MIN()= smallest value in a range.&lt;br&gt;
=MAX() = largest value in a range.&lt;br&gt;
=COUNT() =counts how many cells contain numbers.&lt;br&gt;
=COUNTA() = counts how many cells have anything typed in them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conditional Calculations
&lt;/h2&gt;

&lt;p&gt;These only calculate based on a set condition.&lt;br&gt;
=IF()= returns one result if a condition is true, another if false. &lt;br&gt;
=SUMIF() and =SUMIFS() = adds numbers only where a condition (or several conditions) is met.&lt;br&gt;
=COUNTIF() and =COUNTIFS() = counts entries that meet a condition. &lt;/p&gt;

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

&lt;p&gt;This is week one in excel, learning the basics and building a foundation. The functions are quite versatile in their use once you understand how to use them to clean, organize and extract insights from a raw set of data.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>xlsx</category>
      <category>datascience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>My First Github Project: From a Local Folder to Github Using Git and SSH</title>
      <dc:creator>Nesta Munene</dc:creator>
      <pubDate>Sat, 22 Aug 2026 20:34:06 +0000</pubDate>
      <link>https://dev.to/nesta_munene_5f710317bb2e/-my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-b1a</link>
      <guid>https://dev.to/nesta_munene_5f710317bb2e/-my-first-github-project-from-a-local-folder-to-github-using-git-and-ssh-b1a</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ydabq0m7muph0ukuo7t.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ydabq0m7muph0ukuo7t.webp" alt=" " width="176" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I am on week two of learning Data Science and Analytics and I have just been introduced to Git and Github. Basing by the name I could tell that they are somehow connected. I got started by learning about configuring git through bash and creating a github account. Then creating folders using Git Bash, moving backward while on bash terminal, renaming on bash terminal, deleting, staging to eventually pushing a folder from local folder to github using Git bash and also pushing a local folder to Github using VS Code studio.&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps Taken During Git Bash Set-up and Configuration to the eventual pushing of the folder to Github.
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Downloading and Installing Git&lt;/li&gt;
&lt;li&gt;Running &lt;code&gt;git --version&lt;/code&gt; to ensure it installed correctly&lt;/li&gt;
&lt;li&gt;Then the Git Bash configuration where you run &lt;code&gt;git config --global user.name "Your Name"&lt;/code&gt; to set your name and then &lt;code&gt;git config --global user.email "Your Email"&lt;/code&gt; to set your email. It is usually recommended to use the actual email that is linked to your Github account. &lt;/li&gt;
&lt;li&gt;Then run &lt;code&gt;git config --global user.name&lt;/code&gt; and &lt;code&gt;git config --global user.email&lt;/code&gt; to confirm that the values actually went through.&lt;/li&gt;
&lt;li&gt;Then run &lt;code&gt;git config --global --list&lt;/code&gt; to show what you have configure so far, also it will show the branch you are on.&lt;/li&gt;
&lt;li&gt;The sixth step is setting up the SSH key which will be used to access my github since I intend to connect with my Github using SSH instead of HTTPS. Setting the SSH is by using &lt;code&gt;ssh-keygen -t ed25519 -C "your email"&lt;/code&gt; this is one of the crucial codes to remember about Bash. Then press enter to save on the default folder, then set passphrase (It will be blank as you do this, don't panic) if an existing key exists, you will be asked to overwrite or not.&lt;/li&gt;
&lt;li&gt;After setting the passphrase, it will be saved in the default folder, type in &lt;code&gt;cat ~/.ssh/id_ed25519.pub&lt;/code&gt; to get the SSH key which we shall link to Github.&lt;/li&gt;
&lt;li&gt;Open up Github account, login/create a new one, navigate to profile icon, then settings, then click on SSH and GPG keys, then select &lt;em&gt;New SSH key&lt;/em&gt; and paste the key from Git Bash and our Git Bash and Github are now linked and we can push straight from Bash to Github repo.&lt;/li&gt;
&lt;li&gt;The project I was working on was on Hospital Health Data Analysis. I had the .xlsx file ready but in my downloads folder. I could not move it in the convectional manner through files explorer but through Git Bash.&lt;/li&gt;
&lt;li&gt;Back to Bash, I typed &lt;code&gt;pwd&lt;/code&gt; this is the command for printing the working directory so that you know from which folder you are working in.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Creating of the Project Folder and README.md File
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; To create the Projector folder in which I was to work from and eventually push to Github, I used &lt;code&gt;cd Onedrive&lt;/code&gt; to move to Onedrive, this way I could backup my work always, then &lt;code&gt;mkdir Project001&lt;/code&gt; to make directory, after I used &lt;code&gt;ls&lt;/code&gt; command to see what folders and files were in my folder.
&lt;code&gt;cd&lt;/code&gt; stands for change directory which you can loosely translate as moving into another folder from the current one. &lt;code&gt;mkdir&lt;/code&gt; is the bash command for creating a folder and &lt;code&gt;ls&lt;/code&gt; is the command for listing, which is used to get a list of the all the content in a folder.&lt;/li&gt;
&lt;li&gt;Once the project was created, I created another folder for data through &lt;code&gt;mkdir data&lt;/code&gt; while I was in the project folder, then I had to create a README.md file which had the notes and about of the project detailed what the project was about, the tools used, challenges faced etc. To create the README.md file I used &lt;code&gt;touch README.md&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Moving/Copying the .xlsx File from Download to the Project Folder
&lt;/h2&gt;

&lt;p&gt;Once the project folder was ready, I had to copy the file from downloads folder to the project folder I had just created using Bash. This, I achieved by using the bash command &lt;code&gt;cp ~/Downloads/name of the .lsx file ~/Onedrive/Project001/data/&lt;/code&gt; &lt;code&gt;cp&lt;/code&gt; means copy and &lt;code&gt;mv&lt;/code&gt; means move, you can use either cp or move.&lt;br&gt;
Then I used command ls to confirm all was in order in the Project and data folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Editing the README.md
&lt;/h2&gt;

&lt;p&gt;First off, the .md stands for markdown language. We have already created the README.md by using Bash command &lt;code&gt;touch README.md&lt;/code&gt;. To write on the README.md we use command &lt;code&gt;echo "all about your project" &amp;gt; README.md&lt;/code&gt; a couple of things to know here is that echo is the command to print/write, then the &amp;gt; points to where the writing is to be done. The use of one &lt;code&gt;&amp;gt;&lt;/code&gt; means overwrite what was already existing, so to add onto what is existing on the README.md we use double &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;&lt;br&gt;
Then to create a space so as to write the next paragraph, I used command &lt;code&gt;echo "" &amp;gt;&amp;gt; README.md&lt;/code&gt; this command creates a space or line jump.&lt;br&gt;
I used &lt;code&gt;cat README.md&lt;/code&gt; to show what was in the README.md file. To edit the README.md file comfortable and easily, I used the Bash command &lt;code&gt;nano README.md&lt;/code&gt; which opens a new tab to allow you to edit the README.md like you would a txt or MS word file. Also, when correcting a README.md file, I used &lt;code&gt;mv README.md REEDME.md&lt;/code&gt; this works to rename a file or folder, then command &lt;code&gt;cd ..&lt;/code&gt; works to go back one step from the current folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preparing the Folder for Pushing to Github.
&lt;/h2&gt;

&lt;p&gt;Now that we have our project folder all working and the files in place, we are ready to stage our folder for push to Github.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;pwd&lt;/code&gt;to ensure you are in the right folder.&lt;/li&gt;
&lt;li&gt;Then cd to the right folder.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;ls&lt;/code&gt; command to ensure all files and folders are in place.&lt;/li&gt;
&lt;li&gt;Next, we initialize git in the project folder by using bash command &lt;code&gt;git init&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then we stage everything in the project folder by using &lt;code&gt;git add .&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Next, we confirm if the staging worked by using command &lt;code&gt;git status&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Here we commit the message by using git command &lt;code&gt;git commit -m "the message"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;We confirm which Git branch we are in by running &lt;code&gt;git branch&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Here we link our Github with the Bash by using command &lt;code&gt;git remote add origin 'the ssh link copied from github from the repository created&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Then command &lt;code&gt;git remote -v&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Here we now push our project folder. This is done using command &lt;code&gt;git push -u origin main&lt;/code&gt;
Once this is done and all was done correctly, the folder will be pushed to Github, if any error is faced, ensure the project folder had data in it and that you configured git bash and linked to Github Correctly.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;This is week two of Data Science and Analytics, I have a basic and solid understanding of Git Bash, I intend to push more on practice so that I can have this in my fingertips. I am excited of my journey, this is the beginning and I can't wait to delve deep all the way in the world of data.&lt;/p&gt;

&lt;p&gt;Next, I will be talking about pushing local folder to Github using VS Code which is faster and somehow easier, but we do not do it easy, do we?&lt;br&gt;
&lt;a href="https://www.luxdevhq.ai/" rel="noopener noreferrer"&gt;Learn more&lt;/a&gt;&lt;/p&gt;

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