<?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: Njuguna Gichia</title>
    <description>The latest articles on DEV Community by Njuguna Gichia (@9ichia).</description>
    <link>https://dev.to/9ichia</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%2F4070940%2Fb1cb3d2c-ac47-4a09-813b-f0c007f3a777.png</url>
      <title>DEV Community: Njuguna Gichia</title>
      <link>https://dev.to/9ichia</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/9ichia"/>
    <language>en</language>
    <item>
      <title>Data Modelling, Relationships &amp; Joins in Power BI</title>
      <dc:creator>Njuguna Gichia</dc:creator>
      <pubDate>Sun, 13 Sep 2026 12:55:12 +0000</pubDate>
      <link>https://dev.to/9ichia/data-modelling-relationships-joins-in-power-bi-17a9</link>
      <guid>https://dev.to/9ichia/data-modelling-relationships-joins-in-power-bi-17a9</guid>
      <description>&lt;p&gt;Data modelling is the process of analyzing and defining different data types, as well as the relationships between those bits of data. In Power BI, data modelling is the process of organizing multiple tables and defining the relationships between them so that power BI can analyze and visualize business data. &lt;/p&gt;

&lt;p&gt;A good data model improves report performance, makes DAX calculations easier, supports accurate business insights, simplifies maintenance and provides better scalability as the amount of data and reporting requirements grow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Modelling Approaches.
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1.Flat Table.
&lt;/h4&gt;

&lt;p&gt;A flat table / flat data model organizes data into a single table where each row represents a record and each column represents an attribute. Flat tables approach consolidates all the necessary data into a single denormalized table before it gets to the BI tool which sometimes means one table with all the columns (Facts and Attributes) already joined and ready for use. &lt;/p&gt;

&lt;p&gt;Advantages&lt;br&gt;
    - It isn't tied to a specific tool since all transformations happen at a database level and so moving across tools becomes easier.&lt;br&gt;
    - It minimized the risk of discrepancies between reports and KPI's by ensuring a single source of data&lt;br&gt;
    - It makes it easier to track changes, roll back updates and maintain data integrity by allowing for version control&lt;br&gt;
    - It makes querying easier without needing to understand complex relationships between tables.&lt;/p&gt;

&lt;p&gt;Disadvantages.&lt;br&gt;
    - Can become large and occasionally slower to query when dealing with massive datasets or frequent refresh cycles.&lt;br&gt;
    - May struggle in high volume environments, when powering multiple dashboards or when using databases that aren't optimized for analytical workloads.&lt;br&gt;
    - Risk of increasing storage costs and complicating updates due to data duplication.&lt;br&gt;
    - Very costly to optimize especially because they become inefficient as datasets grow.&lt;/p&gt;

&lt;p&gt;Situations where appropriate.&lt;br&gt;
    -When your dataset has only a few thousand rows, making performance slowdowns unnoticeable. &lt;br&gt;
    - When individual users or small teams manage data in simple tools like Excel or CSV files.&lt;br&gt;
    - When you need to test an idea rapidly without spending time building complex table relationships.&lt;br&gt;
    - When denormalized data speeds up read operations in specific reporting layers or data pipelines by avoiding table joins. &lt;br&gt;
    - When you must easily share raw data across different apps, platforms, or serverless functions without a database engine.&lt;/p&gt;

&lt;p&gt;Implications for Power BI performance and model complexity.&lt;br&gt;
    - Using a flat table data model in Power BI severely undermines performance and increases model complexity because it conflicts directly with the tool's underlying VertiPaq columnar storage engine. By forcing data into one massive, denormalized table, you suffer from inefficient column compression and a high memory footprint due to repeated text values, which triggers sluggish slicers and slow DAX scan times as Power BI is forced to query millions of rows rather than tiny dimension tables. Furthermore, while a single table eliminates relationships, it introduces development complexity through cluttered field lists, rigid models that cannot scale to new business processes, and high-risk DAX bugs like Auto-Exist, which can silently cause incorrect report totals when multiple columns are filtered together.&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%2Fc9f6szqotl1evjayevu6.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%2Fc9f6szqotl1evjayevu6.png" width="762" height="380"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Star Schema
&lt;/h4&gt;

&lt;p&gt;The star schema features a central fact table that contains measurable quantitative data surrounded by dimension tables that contain descriptive attributes related to the fact data. The structure looks like a star, with a single dense table sitting at the center, and connected to surrounding lookup tables using simple relationships.&lt;/p&gt;

&lt;p&gt;This schema contains two distinct table types.&lt;br&gt;
    - Fact Tables.&lt;br&gt;
    These are at the center of the model. They record actual observations, metrics or transactional events (e.g., &lt;code&gt;Fact_Sales&lt;/code&gt;) and consist of continuous numerical values and a collection of Foreign Keys which act as pointers linking back to the surrounding descriptive tables.&lt;br&gt;
    - Dimension Tables.&lt;br&gt;
    These are tables surrounding the fact table that contain descriptive context or attributes related to the events recorded in the fact table (e.g., &lt;code&gt;Dim_Product&lt;/code&gt;, &lt;code&gt;Dim_Date&lt;/code&gt;, &lt;code&gt;Dim_Customer&lt;/code&gt;). Each Dimension table contains a unique Primary Key that anchors a one to many relationship flowing directly into the fact table. They also contain highly denormalized, flattened, repeated attributes to avoid deep branching relationships.&lt;/p&gt;

&lt;p&gt;Advantages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Yield rapid query responses because analytical databases scan short, wide tables to filter rows in long narrow tables.&lt;/li&gt;
&lt;li&gt;The layout is easy for business analysts, report developers and end users to understand and navigate.&lt;/li&gt;
&lt;li&gt;Aggregations run quickly because calculations are grouped by highly indexed dimensional attributes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disadvantages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Because the dimensional tables are denormalized and repeat text fields, they increase the physical storage size of those dimensions.&lt;/li&gt;
&lt;li&gt;This schema does not naturally handle complex hierarchy variations natively without forcing them into flat structures.&lt;/li&gt;
&lt;li&gt;Because a single star schema focuses around one core process, combining multiple distinct processes requires creating independent fact tables that share dimensions. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; Situations where appropriate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When stakeholders use tools like Tableau or PowerBI to build their own reports without needing to write complex SQL queries.&lt;/li&gt;
&lt;li&gt;When tracking performance metrics across consistent structural or Temporal intervals is required such as daily sales or machinery sensor output.&lt;/li&gt;
&lt;li&gt;When the data warehouses or data lakes process millions or billions of rows of historical data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; Implications for Power BI performance and model complexity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adopting a &lt;strong&gt;star-schema architecture&lt;/strong&gt; is the single most effective way to maximize Power BI performance and streamline model complexity because it aligns perfectly with the underlying &lt;strong&gt;VertiPaq in-memory columnar storage engine&lt;/strong&gt;. By separating transactional metrics into a central fact table and descriptive attributes into dedicated, highly compressed dimension tables, Power BI achieves &lt;strong&gt;superior data compression, smaller file sizes, and accelerated DAX query scans&lt;/strong&gt;. When users interact with report elements, visual rendering is nearly instant because slicers only need to query small, indexed dimension tables to dynamically pass filters down a clean &lt;strong&gt;one-to-many relationship path&lt;/strong&gt; to the fact table. From a usability standpoint, this structural layout reduces model complexity by eliminating confusing relationship loops and replacing multi-table snowflake structures with an &lt;strong&gt;intuitive field list&lt;/strong&gt;. Consequently, DAX formulas become remarkably simple, clean, and elegant, freeing report developers from writing defensive code to handle mismatched data granularities or fighting calculation defects like the &lt;strong&gt;Auto-Exist bug&lt;/strong&gt;, resulting in highly accurate calculations and faster report development.&lt;/li&gt;
&lt;/ul&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%2Fkp21gqa4woff2v503jxs.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%2Fkp21gqa4woff2v503jxs.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Snowflake Schema
&lt;/h4&gt;

&lt;p&gt;This is a multi-dimensional data model where centralized, quantitative fact tables connect to dimension tables that are broken down into further lookup tables. The complex branching relationships extend outward from the center, resembling a snowflake.&lt;/p&gt;

&lt;p&gt;Built using three distinct structural layers. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Central Fact Tables.&lt;/strong&gt;
Contains transaction-level keys, numbers and facts - (e.g., &lt;code&gt;Fact_Sales&lt;/code&gt; containing metrics like &lt;code&gt;Quantity&lt;/code&gt; and &lt;code&gt;Revenue&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primary Dimension Tables.&lt;/strong&gt;
These are tables that map directly to the fact table via a foreign key. They store a secondary foreign key pointing further down the line (e.g., &lt;code&gt;Dim_Product&lt;/code&gt; contains a key for categories rather than the category text name).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sub-Dimension Tables.&lt;/strong&gt;
These are normalized lookup tables connecting strictly to primary dimensions tables rather than the core fact table (e.g., a standalone &lt;code&gt;Dim_Category&lt;/code&gt; table or a separate &lt;code&gt;Dim_Geography&lt;/code&gt; table containing city/country data).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Advantages.&lt;br&gt;
    - because of data normalization rules, text labels are never repeated across rows which minimizes storage in relational databases.&lt;br&gt;
    - Changing a group name or an attribute hierarchy only requires updating a singe record in a sub-dimension table instead of bulk-row modifications.&lt;br&gt;
    - Eliminates the risk of typing or recording anomalies since attributes are isolated in single, authoritative lookup sources.&lt;/p&gt;

&lt;p&gt;Disadvantages.&lt;br&gt;
    - Query engines must evaluate complex multi-table joins to trace a filter from a sub-dimension down to a transactional fact table.&lt;br&gt;
    - The visual layout is much more crowded and difficult to parse at a glance compared to a clean star structure.&lt;br&gt;
    - Keeping track of sequential, multi-layered keys increases development friction when writing ETL or data pipeline logic.&lt;/p&gt;

&lt;p&gt; Situations where appropriate.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environments where reducing physical storage footprints and ensuring total database normalization are the absolute priorities.&lt;/li&gt;
&lt;li&gt;When a single branch of dimensions (like a complex, multi-tiered geography master list) is shared globally across multiple entirely different business lines or separate fact tables.&lt;/li&gt;
&lt;li&gt;Systems where data is strictly read directly via a traditional SQL engine optimized to parse multi-table relational joins natively.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; Implications for Power BI performance and model complexity.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;In &lt;strong&gt;Power BI&lt;/strong&gt;, a snowflake schema should generally be avoided or flattened into a Star Schema during the ingestion phase due to several architectural friction points:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A snowflake schema significantly degrades Power BI performance and adds immense development overhead because it introduces &lt;strong&gt;multi-hop relationship chains&lt;/strong&gt; that force the &lt;strong&gt;VertiPaq columnar engine&lt;/strong&gt; to calculate complex cross-table joins during runtime. While it saves minimal physical disk storage, this design undermines Power BI’s native column compression algorithms, resulting in &lt;strong&gt;sluggish slicer response times&lt;/strong&gt; as filters must cascade through multiple intermediate lookup tables before arriving at the core fact table. From a usability standpoint, the model complexity spikes dramatically, loading the user interface with a &lt;strong&gt;cluttered, multi-table field list&lt;/strong&gt; that confuses report creators. This intricate web of relationships forces developers to write highly complex, defensive &lt;strong&gt;DAX measures&lt;/strong&gt; to accurately manage filter context across varying table granularities, drastically increasing the likelihood of development bottlenecks, unoptimized query paths, and frustrating calculation bugs.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2F4gp9vdrntxdikdtbg81w.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%2F4gp9vdrntxdikdtbg81w.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Fact Tables &amp;amp; Dimension Tables.
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Fact Tables.
&lt;/h4&gt;

&lt;p&gt;Fact tables are quantifiable events of businesses that are recorded at a certain degree of detail. It exclusively records &lt;strong&gt;measurable, quantitative business events&lt;/strong&gt; at the exact moment they occur. The information stored inside consists entirely of numeric data points known as &lt;strong&gt;measures&lt;/strong&gt; and structural foreign keys (FK) used to identify when, where, and how the event happened.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measures (Fact Tables)&lt;/strong&gt; are numeric values meant to be aggregated using mathematical operations such as &lt;code&gt;SUM&lt;/code&gt;, &lt;code&gt;AVERAGE&lt;/code&gt;, &lt;code&gt;MIN&lt;/code&gt;, or &lt;code&gt;MAX&lt;/code&gt;. Examples include physical units sold, gross profit margins, account balances, or sensor temperature readings.&lt;/p&gt;
&lt;h4&gt;
  
  
  Dimension Tables.
&lt;/h4&gt;

&lt;p&gt;Facts are given a descriptive context by dimension tables. They specify the way users slice, filter, group, and drill into measures. They contain the textual, categorical, or qualitative information that answers the "who, what, where, and when" of a transaction. Dimension rows are relatively stable and slow-moving compared to the rapidly expanding rows of a fact table.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Descriptive Attributes (Dimension Tables)&lt;/strong&gt; are textual descriptors, IDs, or dates used to &lt;strong&gt;filter, group, slice, and slice-and-dice&lt;/strong&gt; measures in a report. Examples include an employee’s job title, a product’s color, a customer's country, or a calendar month name.&lt;/p&gt;
&lt;h4&gt;
  
  
  Granularity.
&lt;/h4&gt;

&lt;p&gt;Grain defines exactly what one row represents in a fact table. All foreign keys and measures inside the fact table have to match this chosen grain to prevent double counting or data corruption during reporting.&lt;/p&gt;

&lt;p&gt;Fact Table Example.&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%2Ff5gwu9treqphbfcuudi5.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%2Ff5gwu9treqphbfcuudi5.png" width="799" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dimension Table Example.&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%2Fn67io0yv9yfyijceem4q.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%2Fn67io0yv9yfyijceem4q.png" width="799" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Table plain Text. &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%2Fof15zyz45cvpwi8mym6z.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%2Fof15zyz45cvpwi8mym6z.png" width="690" height="320"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Relationships in Power BI
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;relationship&lt;/strong&gt; in Power BI defines a logical link between two tables based on a shared column. In a relational data model, data is split into specialized tables to eliminate redundancy and improve performance (normalization). Relationships allow Power BI to filter and slice metrics in transaction tables using descriptive attributes from dimension tables without combining everything into a single massive, flat table.&lt;/p&gt;
&lt;h2&gt;
  
  
  Core Data Modeling Concepts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Primary Key (PK):&lt;/strong&gt; A column (or set of columns) in a dimension table where every value is completely unique. It serves as the master identifier for a single entity (e.g., &lt;code&gt;CustomerKey&lt;/code&gt; in &lt;code&gt;Dim_Customer&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Foreign Key (FK):&lt;/strong&gt; A column in a table that references a Primary Key in another table. It allows multiple records to map back to a single primary entity (e.g., &lt;code&gt;CustomerKey&lt;/code&gt; in &lt;code&gt;Fact_Sales&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unique Values:&lt;/strong&gt; Ensures that each key appears exactly once on the "One" side of a relationship. If duplicates exist where Power BI expects unique values, data integrity is lost, leading to calculation errors.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cardinality:&lt;/strong&gt; Refers to the numerical mapping between rows of two related tables (e.g., 1:*, 1:1, &lt;em&gt;:&lt;/em&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Referential Integrity:&lt;/strong&gt; The rule ensuring that every Foreign Key value in a fact table exists as a matching Primary Key in the corresponding dimension table. If a sale records &lt;code&gt;CustomerKey = 999&lt;/code&gt;, but key &lt;code&gt;999&lt;/code&gt; is missing from &lt;code&gt;Dim_Customer&lt;/code&gt;, referential integrity is broken, resulting in blank/unmatched categories in reports.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Active vs. Inactive Relationships:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Active Relationship:&lt;/strong&gt; The default link between two tables used to propagate filter context automatically across visuals. Only &lt;strong&gt;one&lt;/strong&gt; active relationship can exist between any two tables at a time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inactive Relationship:&lt;/strong&gt; A dormant connection created when multiple paths exist between two tables (e.g., &lt;code&gt;Dim_Date&lt;/code&gt; linked to both &lt;code&gt;OrderDate&lt;/code&gt; and &lt;code&gt;ShipDate&lt;/code&gt; in &lt;code&gt;Fact_Sales&lt;/code&gt;). It remains unused until explicitly activated in DAX measures using functions like &lt;code&gt;USERELATIONSHIP()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Example from Snowflake-Schema-Main
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Dim_Customer&lt;/code&gt; Table:&lt;/strong&gt; &lt;code&gt;CustomerKey&lt;/code&gt; is the &lt;strong&gt;Primary Key&lt;/strong&gt;. It contains strictly &lt;strong&gt;unique values&lt;/strong&gt; because each customer is registered only once in master records.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;Fact_Sales&lt;/code&gt; Table:&lt;/strong&gt; &lt;code&gt;CustomerKey&lt;/code&gt; acts as a &lt;strong&gt;Foreign Key&lt;/strong&gt;. A single customer can make multiple purchases over time, so their &lt;code&gt;CustomerKey&lt;/code&gt; appears &lt;strong&gt;multiple times&lt;/strong&gt; (many rows) across transactional records.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Relationship Cardinalities
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. One-to-Many (1:*)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; One row in the dimension table connects to zero, one, or multiple rows in the fact table. Filters automatically flow from the "One" side (dimension) to refine the "Many" side (fact).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; &lt;code&gt;Dim_Product&lt;/code&gt; (&lt;code&gt;1&lt;/code&gt;) connects to &lt;code&gt;Fact_Sales&lt;/code&gt; (&lt;code&gt;*&lt;/code&gt;) via &lt;code&gt;ProductKey&lt;/code&gt;. Filtering for "Laptops" filters all transaction records for laptops.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; This is the &lt;strong&gt;standard best practice&lt;/strong&gt; for dimensional data modeling (Star Schema / Snowflake Schema).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When NOT to Use:&lt;/strong&gt; Never use if both tables contain non-unique, repeating key values.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Dim_Product ] (1)  &amp;lt;---------&amp;gt;  (*) [ Fact_Sales ]
(ProductKey: PK)                      (ProductKey: FK)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F2zcbg45dxsttd7kg751j.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%2F2zcbg45dxsttd7kg751j.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. One-to-One (1:1)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; One row in Table A links directly to exactly one matching row in Table B.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; Linking a &lt;code&gt;Dim_Customer&lt;/code&gt; table to a separate &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt; table where sensitive user details are stored on a 1-to-1 basis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; Useful when splitting large tables for security purposes, performance optimization, or separating frequently accessed columns from rarely used ones.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When NOT to Use:&lt;/strong&gt; Avoid when unnecessary, as two 1:1 tables can almost always be merged into a single table, reducing model complexity.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Dim_Customer ] (1)  &amp;lt;---------&amp;gt;  (1) [ Dim_CustomerSecurity ]
(CustomerKey)                           (CustomerKey)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fsvzvfyao7l9beznlg8iw.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%2Fsvzvfyao7l9beznlg8iw.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  3. Many-to-Many (&lt;em&gt;:&lt;/em&gt;)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Neither table has unique values in the key column. Rows on both sides connect to multiple rows in the opposite table, requiring bi-directional filtering by default or bridge handling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; Linking a &lt;code&gt;Fact_Sales&lt;/code&gt; table directly to a &lt;code&gt;Fact_Targets&lt;/code&gt; table on &lt;code&gt;DateKey&lt;/code&gt; when both tables contain multiple rows for each date.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When to Use:&lt;/strong&gt; Use sparingly when modeling direct relationship scenarios where unique keys cannot be established.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When NOT to Use:&lt;/strong&gt; Avoid using as a quick fix for duplicate key issues. &lt;em&gt;: Relationships create complex DAX calculations, introduce ambiguity, and can produce unpredictable visual aggregations. Instead, build a intermediate bridge/dimension table with unique values to split it into two 1:&lt;/em&gt; relationships.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Fact_Sales ] (*)  &amp;lt;--- (Bridge / Intermediate) ---&amp;gt;  (*) [ Fact_Targets ]
(DateKey)                                                   (DateKey)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fq5u6poooa4x8eu0ldsvy.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%2Fq5u6poooa4x8eu0ldsvy.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Filter Direction.
&lt;/h3&gt;

&lt;p&gt;When you select a value in a report visual or slicer (such as choosing a specific year or product category), Power BI creates a &lt;strong&gt;filter context&lt;/strong&gt;. This filter context flows automatically across active relationships between tables to isolate the relevant transaction rows in your fact table.&lt;/p&gt;
&lt;h3&gt;
  
  
  How Filter Context Flows
&lt;/h3&gt;

&lt;p&gt;Filters flow along the relationship line between tables, moving from the table where the selection was made to the target table. The direction in which this filter context is allowed to travel depends on the &lt;strong&gt;Filter Direction&lt;/strong&gt; setting of the relationship.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ Dimension Table ]  ─── (Filter Direction Arrow) ───&amp;gt;  [ Fact Table ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. Single-Direction Filtering (Default &amp;amp; Standard)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Filters travel in &lt;strong&gt;one direction only&lt;/strong&gt;—from the "One" side (Dimension) to the "Many" side (Fact).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt; Selecting an entity in a dimension table filters the records in the fact table. However, filtering a fact table does &lt;strong&gt;not&lt;/strong&gt; filter or restrict the items shown in the dimension table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model View Indicator:&lt;/strong&gt; A single arrowhead pointing from the dimension table toward the fact table (&lt;code&gt;1 ──&amp;gt; *&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2F6w9bne02owk5j7xfn1oi.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%2F6w9bne02owk5j7xfn1oi.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Bidirectional / Both Filtering
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Filters travel in &lt;strong&gt;both directions&lt;/strong&gt; across the relationship.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt; Selecting a value in a dimension filters the fact table, and filtering the fact table simultaneously filters the connected dimension table (as well as any other downstream dimension tables).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model View Indicator:&lt;/strong&gt; A double arrowhead pointing toward both tables (&lt;code&gt;1 &amp;lt;──&amp;gt; *&lt;/code&gt; or &lt;code&gt;* &amp;lt;──&amp;gt; *&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fgdp37djj9wu4datsfree.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%2Fgdp37djj9wu4datsfree.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step Example: Filtering &lt;code&gt;Fact_Sales&lt;/code&gt; from &lt;code&gt;Dim_Product&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Using our dataset model (&lt;code&gt;Dim_Category&lt;/code&gt; ──&amp;gt; &lt;code&gt;Dim_Product&lt;/code&gt; ──&amp;gt; &lt;code&gt;Fact_Sales&lt;/code&gt;):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;User Action:&lt;/strong&gt; A user clicks on the &lt;strong&gt;"Electronics"&lt;/strong&gt; category in a report slicer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;First Propagation:&lt;/strong&gt; The filter context targets &lt;code&gt;Dim_Category&lt;/code&gt; where &lt;code&gt;CategoryName = "Electronics"&lt;/code&gt;. It passes down the &lt;code&gt;1 ──&amp;gt; *&lt;/code&gt; relationship on &lt;code&gt;CategoryKey&lt;/code&gt; to &lt;code&gt;Dim_Product&lt;/code&gt;, instantly filtering &lt;code&gt;Dim_Product&lt;/code&gt; to only include products belonging to Electronics (e.g., &lt;code&gt;ProductKey = 1&lt;/code&gt; for "Laptop Pro" and &lt;code&gt;ProductKey = 2&lt;/code&gt; for "Smartphone X").&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Second Propagation:&lt;/strong&gt; The filter context continues down the next &lt;code&gt;1 ──&amp;gt; *&lt;/code&gt; relationship on &lt;code&gt;ProductKey&lt;/code&gt; to &lt;code&gt;Fact_Sales&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Final Result:&lt;/strong&gt; Power BI filters &lt;code&gt;Fact_Sales&lt;/code&gt; to keep only rows where &lt;code&gt;ProductKey&lt;/code&gt; is &lt;code&gt;1&lt;/code&gt; or &lt;code&gt;2&lt;/code&gt;, dynamically recalculating metrics like &lt;code&gt;SUM(Revenue)&lt;/code&gt; or &lt;code&gt;SUM(Quantity)&lt;/code&gt; strictly for Electronics transactions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why Bidirectional Filtering Should Be Used Carefully
&lt;/h3&gt;

&lt;p&gt;While bidirectional filtering allows tables to filter each other, enabling it permanently in relationship properties introduces major data modeling risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ambiguous Filter Paths:&lt;/strong&gt; When multiple bidirectional relationships exist in a model, Power BI creates closed loops (circular paths). The engine cannot determine which path to take to apply a filter, leading to unpredictable measure results or DAX calculation errors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unnecessary Model Complexity &amp;amp; Slow Performance:&lt;/strong&gt; Bidirectional paths force Power BI's VertiPaq engine to evaluate dynamic cross-filtering on large tables at report runtime, increasing memory usage and slowing down report visuals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unexpected Slicer Masking:&lt;/strong&gt; Filtering a transaction table can unexpectedly mask or hide valid items in dimension drop-downs, confusing users who expect to see all available lookup options.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Keep physical relationship filter directions set to &lt;strong&gt;Single&lt;/strong&gt;. If bidirectional filtering is required for a specific business metric, activate it dynamically inside individual DAX measures using &lt;code&gt;CROSSFILTER()&lt;/code&gt; rather than changing the physical model properties.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Joins in Power Query.
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;join&lt;/strong&gt; is a relational operation that combines columns from two tables based on matching values in one or more common key columns.&lt;/p&gt;

&lt;p&gt;In Power Query, tables are combined using &lt;strong&gt;Merge Queries&lt;/strong&gt; (&lt;code&gt;Home&lt;/code&gt; $\rightarrow$ &lt;code&gt;Merge Queries&lt;/code&gt;). You select a primary table (Left Table), a secondary table (Right Table), and highlight the matching key columns in both preview panels. Power Query evaluates the matching key values and appends a nested &lt;code&gt;Table&lt;/code&gt; column containing the matched rows from the right table, which can then be expanded.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source Sample Tables from Our Model
&lt;/h3&gt;

&lt;p&gt;To illustrate each join type clearly, we use two sample tables from our dataset:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Left Table: &lt;code&gt;Dim_Customer&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contains records for &lt;code&gt;CustomerKey&lt;/code&gt; 1 through 5.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Right Table: &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contains records for &lt;code&gt;CustomerKey&lt;/code&gt; 1 through 4, plus an unassigned security record with &lt;code&gt;CustomerKey&lt;/code&gt; 99.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  1. Left Outer Join (All from First, Matching from Second)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Evaluates every row in the left table and retrieves matching rows from the right table. If no match exists in the right table, &lt;code&gt;null&lt;/code&gt; values are filled in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Records Retained:&lt;/strong&gt; All rows from the &lt;strong&gt;Left Table&lt;/strong&gt; + matched rows from the &lt;strong&gt;Right Table&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; Merging master customer details (&lt;code&gt;Dim_Customer&lt;/code&gt;) with optional security audit records (&lt;code&gt;Dim_CustomerSecurity&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  2. Right Outer Join (All from Second, Matching from First)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Evaluates every row in the right table and retrieves matching rows from the left table. Unmatched left attributes are filled with &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Records Retained:&lt;/strong&gt; All rows from the &lt;strong&gt;Right Table&lt;/strong&gt; + matched rows from the &lt;strong&gt;Left Table&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; Ensuring all compliance records in &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt; are evaluated against customer master records.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  3. Full Outer Join (All Rows from Both Tables)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Combines all records from both tables regardless of matches. Missing pairs on either side are filled with &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Records Retained:&lt;/strong&gt; &lt;strong&gt;All rows from both tables&lt;/strong&gt; (complete union of matched and unmatched keys).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; Reconciling two lists to see all active customers and all security profiles.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  4. Inner Join (Only Matching Rows)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Keeps only rows where the key value exists in &lt;strong&gt;both&lt;/strong&gt; the left and right tables. Unmatched records from both sides are dropped.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Records Retained:&lt;/strong&gt; &lt;strong&gt;Strictly matching pairs&lt;/strong&gt; present in both tables.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; Returning only customers who have completed security verification.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  5. Left Anti Join (Rows Only in First Table)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Filters the left table to isolate rows that have &lt;strong&gt;no matching key&lt;/strong&gt; in the right table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Records Retained:&lt;/strong&gt; &lt;strong&gt;Left-only unmatched rows&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; Identifying customers in &lt;code&gt;Dim_Customer&lt;/code&gt; who are missing a security profile in &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  6. Right Anti Join (Rows Only in Second Table)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How It Works:&lt;/strong&gt; Filters the right table to isolate rows that have &lt;strong&gt;no matching key&lt;/strong&gt; in the left table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Records Retained:&lt;/strong&gt; &lt;strong&gt;Right-only unmatched rows&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Practical Example:&lt;/strong&gt; Finding orphan security profiles in &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt; that are not assigned to any customer in &lt;code&gt;Dim_Customer&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Power Query Joins vs Power BI Relationships
&lt;/h3&gt;

&lt;p&gt;Merging tables in Power Query and establishing model relationships in Power BI serve fundamentally different functions within your analytical data pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Structural Differences
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Physical Data Combination in Power Query Merge:&lt;/strong&gt; Yes, a Power Query Merge physically combines attributes into a single query structure during data transformation. When expanding columns from &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt; into &lt;code&gt;Dim_Customer&lt;/code&gt;, Power Query reshapes the underlying M-code query and loads a single combined table into memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separation via Model Relationships:&lt;/strong&gt; No, creating a relationship between tables does &lt;strong&gt;not&lt;/strong&gt; combine them physically. Both tables remain distinct physical storage objects in the VertiPaq engine. The relationship acts as a logical bridge allowing filter context to pass dynamically between them at visual rendering time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Workflow Stage Execution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Power Query Merge:&lt;/strong&gt; Occurs at the &lt;strong&gt;ETL (Extract, Transform, Load) stage&lt;/strong&gt; before data is compressed and loaded into the tabular data model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Relationships:&lt;/strong&gt; Defined in the &lt;strong&gt;Model View stage&lt;/strong&gt; after data has been loaded into the VertiPaq engine, governing DAX calculation context and reporting visuals.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Core Comparison Matrix
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature / Aspect&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Power Query Merge Queries&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Power BI Model Relationships&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Denormalize, consolidate, or clean datasets&lt;/td&gt;
&lt;td&gt;Build Star/Snowflake schemas for dynamic analytics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage Impact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Permanently increases table width (more columns/rows)&lt;/td&gt;
&lt;td&gt;Keeps tables lean and distinct in VertiPaq memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution Engine&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Power Query Formula Engine (M)&lt;/td&gt;
&lt;td&gt;VertiPaq Analytics Engine (DAX)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dynamic Interactivity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Static (fixed during data refresh)&lt;/td&gt;
&lt;td&gt;Dynamic (responds instantly to slicers and visual filters)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  When to Choose a Merge vs. a Relationship
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. When to Use a Merge (Power Query)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consolidating 1-to-1 Extensions:&lt;/strong&gt; Merging extended attribute lookup tables (e.g., merging &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt; into &lt;code&gt;Dim_Customer&lt;/code&gt; to avoid holding unnecessary table entities in your model).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flattening Snowflake Dimensions:&lt;/strong&gt; Collapsing multi-level dimension hierarchies (e.g., merging &lt;code&gt;Dim_Category&lt;/code&gt; directly into &lt;code&gt;Dim_Product&lt;/code&gt; to create a clean, single-level Product dimension table).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-filtering Fact Rows:&lt;/strong&gt; Joining reference keys to eliminate unwanted rows before loading data into the model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. When to Use a Relationship (Model View)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connecting Fact and Dimension Tables:&lt;/strong&gt; Linking &lt;code&gt;Fact_Sales&lt;/code&gt; to &lt;code&gt;Dim_Customer&lt;/code&gt; or &lt;code&gt;Dim_Product&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Preserving Multi-Fact Models:&lt;/strong&gt; Connecting shared dimensions (e.g., &lt;code&gt;Dim_Category&lt;/code&gt; or &lt;code&gt;Dim_Date&lt;/code&gt;) to multiple fact tables like &lt;code&gt;Fact_Sales&lt;/code&gt; and &lt;code&gt;Fact_Targets&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Impact of Excessive Merging on Data Model Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Severe Storage Bloat:&lt;/strong&gt; Merging dimension attributes directly into large fact tables (e.g., merging &lt;code&gt;Dim_Customer&lt;/code&gt; attributes into 1,000,000 rows of &lt;code&gt;Fact_Sales&lt;/code&gt;) forces repetitive string text (such as customer names and email addresses) into every fact row. This ruins VertiPaq run-length encoding (RLE) dictionary compression and balloons your file size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Granularity Errors and Measure Corruption:&lt;/strong&gt; Merging a table with a higher row count (1-to-Many) into a fact table duplicates transaction metrics, causing measures like &lt;code&gt;SUM(SalesAmount)&lt;/code&gt; or &lt;code&gt;COUNTROWS()&lt;/code&gt; to return inaccurate, double-counted figures.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Keeping Fact and Dimension Tables Separate is Preferable
&lt;/h3&gt;

&lt;p&gt;Keeping fact tables (containing numerical events/metrics) separated from dimension tables (containing descriptive attributes) inside a &lt;strong&gt;Star Schema&lt;/strong&gt; provides critical modeling advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimal Compression:&lt;/strong&gt; High-cardinality text fields are stored once in lightweight dimension lookup tables. Fact tables retain only narrow integer keys (&lt;code&gt;CustomerKey&lt;/code&gt;, &lt;code&gt;ProductKey&lt;/code&gt;), allowing the VertiPaq engine to compress millions of rows efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexible Analytics Across Shared Dimensions:&lt;/strong&gt; A single standalone dimension table (e.g., &lt;code&gt;Dim_Category&lt;/code&gt;) can simultaneously filter multiple fact tables (&lt;code&gt;Fact_Sales&lt;/code&gt; and &lt;code&gt;Fact_Targets&lt;/code&gt;), enabling side-by-side performance tracking against target KPIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean, Readable DAX:&lt;/strong&gt; Keeping entities separate simplifies DAX measures, avoiding complex filtering logic required when working with oversized single-flat-table models.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Recommended Power BI Model
&lt;/h3&gt;

&lt;p&gt;Merging tables in Power Query and establishing model relationships in Power BI serve fundamentally different functions within your analytical data pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture Overview: Merge vs. Relationship
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Key Structural Differences
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Physical Data Combination in Power Query Merge:&lt;/strong&gt; Yes, a Power Query Merge physically combines attributes into a single query structure during data transformation. When expanding columns from &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt; into &lt;code&gt;Dim_Customer&lt;/code&gt;, Power Query reshapes the underlying M-code query and loads a single combined table into memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Separation via Model Relationships:&lt;/strong&gt; No, creating a relationship between tables does &lt;strong&gt;not&lt;/strong&gt; combine them physically. Both tables remain distinct physical storage objects in the VertiPaq engine. The relationship acts as a logical bridge allowing filter context to pass dynamically between them at visual rendering time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Workflow Stage Execution:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Power Query Merge:&lt;/strong&gt; Occurs at the &lt;strong&gt;ETL (Extract, Transform, Load) stage&lt;/strong&gt; before data is compressed and loaded into the tabular data model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model Relationships:&lt;/strong&gt; Defined in the &lt;strong&gt;Model View stage&lt;/strong&gt; after data has been loaded into the VertiPaq engine, governing DAX calculation context and reporting visuals.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Core Comparison Matrix
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature / Aspect&lt;/th&gt;
&lt;th&gt;Power Query Merge Queries&lt;/th&gt;
&lt;th&gt;Power BI Model Relationships&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Denormalize, consolidate, or clean datasets&lt;/td&gt;
&lt;td&gt;Build Star/Snowflake schemas for dynamic analytics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage Impact&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Permanently increases table width (more columns/rows)&lt;/td&gt;
&lt;td&gt;Keeps tables lean and distinct in VertiPaq memory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Execution Engine&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Power Query Formula Engine (M)&lt;/td&gt;
&lt;td&gt;VertiPaq Analytics Engine (DAX)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dynamic Interactivity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Static (fixed during data refresh)&lt;/td&gt;
&lt;td&gt;Dynamic (responds instantly to slicers and visual filters)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  When to Choose a Merge vs. a Relationship
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. When to Use a Merge (Power Query)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consolidating 1-to-1 Extensions:&lt;/strong&gt; Merging extended attribute lookup tables (e.g., merging &lt;code&gt;Dim_CustomerSecurity&lt;/code&gt; into &lt;code&gt;Dim_Customer&lt;/code&gt; to avoid holding unnecessary table entities in your model).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flattening Snowflake Dimensions:&lt;/strong&gt; Collapsing multi-level dimension hierarchies (e.g., merging &lt;code&gt;Dim_Category&lt;/code&gt; directly into &lt;code&gt;Dim_Product&lt;/code&gt; to create a clean, single-level Product dimension table).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pre-filtering Fact Rows:&lt;/strong&gt; Joining reference keys to eliminate unwanted rows before loading data into the model.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. When to Use a Relationship (Model View)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connecting Fact and Dimension Tables:&lt;/strong&gt; Linking &lt;code&gt;Fact_Sales&lt;/code&gt; to &lt;code&gt;Dim_Customer&lt;/code&gt; or &lt;code&gt;Dim_Product&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Preserving Multi-Fact Models:&lt;/strong&gt; Connecting shared dimensions (e.g., &lt;code&gt;Dim_Category&lt;/code&gt; or &lt;code&gt;Dim_Date&lt;/code&gt;) to multiple fact tables like &lt;code&gt;Fact_Sales&lt;/code&gt; and &lt;code&gt;Fact_Targets&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Impact of Excessive Merging on Data Model Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Severe Storage Bloat:&lt;/strong&gt; Merging dimension attributes directly into large fact tables (e.g., merging &lt;code&gt;Dim_Customer&lt;/code&gt; attributes into 1,000,000 rows of &lt;code&gt;Fact_Sales&lt;/code&gt;) forces repetitive string text (such as customer names and email addresses) into every fact row. This ruins VertiPaq run-length encoding (RLE) dictionary compression and balloons your file size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Granularity Errors and Measure Corruption:&lt;/strong&gt; Merging a table with a higher row count (1-to-Many) into a fact table duplicates transaction metrics, causing measures like &lt;code&gt;SUM(SalesAmount)&lt;/code&gt; or &lt;code&gt;COUNTROWS()&lt;/code&gt; to return inaccurate, double-counted figures.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Why Keeping Fact and Dimension Tables Separate is Preferable
&lt;/h3&gt;

&lt;p&gt;Keeping fact tables (containing numerical events/metrics) separated from dimension tables (containing descriptive attributes) inside a &lt;strong&gt;Star Schema&lt;/strong&gt; provides critical modeling advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Optimal Compression:&lt;/strong&gt; High-cardinality text fields are stored once in lightweight dimension lookup tables. Fact tables retain only narrow integer keys (&lt;code&gt;CustomerKey&lt;/code&gt;, &lt;code&gt;ProductKey&lt;/code&gt;), allowing the VertiPaq engine to compress millions of rows efficiently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexible Analytics Across Shared Dimensions:&lt;/strong&gt; A single standalone dimension table (e.g., &lt;code&gt;Dim_Category&lt;/code&gt;) can simultaneously filter multiple fact tables (&lt;code&gt;Fact_Sales&lt;/code&gt; and &lt;code&gt;Fact_Targets&lt;/code&gt;), enabling side-by-side performance tracking against target KPIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean, Readable DAX:&lt;/strong&gt; Keeping entities separate simplifies DAX measures, avoiding complex filtering logic required when working with oversized single-flat-table models.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>analytics</category>
      <category>data</category>
      <category>database</category>
    </item>
    <item>
      <title>Getting Started with Excel for Data Analytics: From Basics to Data Cleaning.</title>
      <dc:creator>Njuguna Gichia</dc:creator>
      <pubDate>Wed, 02 Sep 2026 20:26:38 +0000</pubDate>
      <link>https://dev.to/9ichia/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-438k</link>
      <guid>https://dev.to/9ichia/getting-started-with-excel-for-data-analytics-from-basics-to-data-cleaning-438k</guid>
      <description>&lt;p&gt;Microsoft Excel is a spreadsheet software that allows users to organize, analyze, calculate and visualize data. Despite the rise of Python, R and SQL, Excel has remained a foundational data analysis tool across industries because of it's low learning curve, powerful features like pivot tables, formulas, functions and quick charts and because no coding experience is needed to navigate or see results.&lt;/p&gt;

&lt;p&gt;In this article, we will explore navigating the grid, essential formulas, data filtering and cleaning messy data using Excel's built-in features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding The Excel Interface
&lt;/h2&gt;

&lt;p&gt;The excel interface consists of these core elements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Ribbon &amp;amp; Tabs&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The toolbar across the top that contains the primary commands organized into tabs (&lt;strong&gt;Home, Insert, Draw, Page Layout&lt;/strong&gt; etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The Quick Access Toolbar

&lt;ul&gt;
&lt;li&gt;The icons on the top left corner to Save, Undo and Redo.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Formula Bar&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;The area above the grid where the content or the formula of the selected cell appears.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name Box&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Displays the address of the selected Cell (e.g. &lt;code&gt;B3&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Grid&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;This is the visual network of intersecting horizontal lines and vertical lines that creates the workspace. The Grid is made up of 

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rows&lt;/strong&gt; - Horizontal lines of cells labelled vertically with numbers (e.g. Row 1)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Columns&lt;/strong&gt; - Vertical line of cells labelled horizontally with letters (e.g. Column A)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cells&lt;/strong&gt; - A single box where a row and a column intersect (e.g. &lt;code&gt;B4&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Range&lt;/strong&gt; - A group of selected cells (e.g., &lt;code&gt;A1:C3&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Worksheet Tabs&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;The tabs at the bottom that show the name of the spreadsheet and also allow you to navigate between the sheets in a workbook.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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%2F0ox3e5o699t9gpca6q0n.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%2F0ox3e5o699t9gpca6q0n.png" alt="Alt text" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Essential Navigation &amp;amp; Keyboard Shortcuts
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Keyboard Navigation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Arrow keys&lt;/code&gt; – Move one cell at a time&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Arrow key&lt;/code&gt; – Jump to the end of the data region&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Tab&lt;/code&gt; – Move one cell right&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Enter&lt;/code&gt; – Move one cell down&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + S&lt;/code&gt; – Save the file&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Mouse Navigation:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Click to select a single cell&lt;/li&gt;
&lt;li&gt;Click &amp;amp; Drag to select multiple cells&lt;/li&gt;
&lt;li&gt;Scroll to move vertically or horizontally across the sheet&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Efficiency Combinations (Keyboard &amp;amp; Mouse):
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Right Arrow&lt;/code&gt; to jump to the end of row&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Down Arrow&lt;/code&gt; to jump to the bottom&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl + Shift + Arrow Keys&lt;/code&gt; to select ranges efficiently&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Data Environment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Data Types.
&lt;/h3&gt;

&lt;p&gt;Excel supports 4 primary data types. i.e.,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text&lt;/strong&gt; - Any non-numeric or character based information e.g. names, addresses, descriptions).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Numbers&lt;/strong&gt; - Any values that can participate in mathematical calculations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dates and Time&lt;/strong&gt; - Values used to track time-based events and calculations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boolean&lt;/strong&gt; - Logical values, either (&lt;code&gt;TRUE&lt;/code&gt; or &lt;code&gt;FALSE&lt;/code&gt;) usually generated from logical formulas.&lt;/li&gt;
&lt;/ul&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%2F87gq0b3ssa5x51f8jkyu.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%2F87gq0b3ssa5x51f8jkyu.png" alt="Alt text" width="590" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Entering Data
&lt;/h3&gt;

&lt;p&gt;We can enter data anywhere in the grid by: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clicking on a cell&lt;/li&gt;
&lt;li&gt;Typing in our value (e.g. &lt;code&gt;Hello&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Enter&lt;/code&gt; to move down or &lt;code&gt;Tab&lt;/code&gt; to move right&lt;/li&gt;
&lt;li&gt;Double click on the cell or selecting it and pressing &lt;code&gt;F2&lt;/code&gt; to edit existing content.
### Formatting Basics.
Formatting changes how the data looks without changing the values stored in the cells, making the data visually clear and more professional.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Text Formatting.
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Selecting the Cell&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Home &amp;gt; **Font Group&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Clicking &lt;strong&gt;Bold&lt;/strong&gt; (&lt;code&gt;Ctrl+B&lt;/code&gt;), &lt;strong&gt;&lt;em&gt;Italic&lt;/em&gt;&lt;/strong&gt; (&lt;code&gt;Ctrl + I&lt;/code&gt;), Underline (&lt;code&gt;Ctrl + U&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Change Font, Font Size, and Font Colour.&lt;/li&gt;
&lt;/ul&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%2Ft37hjaia1h8pt43ywn3m.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%2Ft37hjaia1h8pt43ywn3m.png" alt="Alt text" width="800" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Number Formatting
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Select cells with numeric data. &lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Home &amp;gt; Number section&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose the appropriate format:

&lt;ul&gt;
&lt;li&gt;Number (with decimals)&lt;/li&gt;
&lt;li&gt;Currency (KES, $, etc.)&lt;/li&gt;
&lt;li&gt;Percentage&lt;/li&gt;
&lt;li&gt;Date formats&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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%2F7wvk93d0ebbxihxlyzqw.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%2F7wvk93d0ebbxihxlyzqw.png" alt="Alt text" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alternatively, we can access the Format Cells Dialogue by (&lt;code&gt;Ctrl+1&lt;/code&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%2Flibhyyckkc24dep7yip9.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%2Flibhyyckkc24dep7yip9.png" alt="Alt text" width="542" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Cleaning and Sorting.
&lt;/h3&gt;

&lt;p&gt;Data Cleaning is the process of formatting, or removing incorrect, duplicate or incomplete data within a dataset. Sometimes, especially when working with large datasets, data can get misplaced, mistyped or mislabeled. Cleaning ensures that the dataset is accurate and consistent. &lt;/p&gt;

&lt;p&gt;Data cleaning prevents making decisions based on flawed data, catches and fixes errors early and provides clean inputs for formulas and charts.&lt;/p&gt;

&lt;p&gt;For Practice, I used a spreadsheet containing HR data, applying a combination of built-in excel tools and formulas to clean it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Best Practice:&lt;/strong&gt; Always preserve your original raw data. Make all required cleaning changes on a duplicate worksheet or separate file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  How to Duplicate Your Data
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click anywhere in the spreadsheet and press &lt;strong&gt;Ctrl + A&lt;/strong&gt; to select all cells.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Press &lt;strong&gt;Ctrl + C&lt;/strong&gt; to copy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the &lt;strong&gt;+&lt;/strong&gt; button at the bottom of the window to create a new sheet.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click cell &lt;strong&gt;A1&lt;/strong&gt; in the new sheet and press &lt;strong&gt;Ctrl + V&lt;/strong&gt; to paste.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Double-click the sheet tab and rename it to &lt;code&gt;Cleaned_HR_Data&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This gives us a canvas to work in.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Data Cleaning Workflow
&lt;/h2&gt;

&lt;p&gt;We did the cleaning in distinct stages.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Analyzing the Data&lt;/strong&gt;:
&lt;/h3&gt;

&lt;p&gt;Here we checked the data for visible errors and inconsistencies. In this dataset, we found mixed data types in numeric fields (text mixed with numbers), missing/blank values, duplicate entries, currency formatting errors, typos and misspellings etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Removing duplicates:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The second step was to delete identical rows or entries that were recorded more than once. I achieved this by:&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Selecting the entire spreadsheet using &lt;code&gt;Ctrl+A&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;navigating to the Data Tab and Clicking Remove Duplicates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Confirming the target columns and clicking OK&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2Fu7j3aqcy1px5xfyba04l.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%2Fu7j3aqcy1px5xfyba04l.png" alt="Alt text" width="800" height="450"&gt;&lt;/a&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%2F7ar9dl1dbavrtlqprop4.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%2F7ar9dl1dbavrtlqprop4.png" alt="Alt text" width="799" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Fixing structural errors&lt;/strong&gt;:
&lt;/h4&gt;

&lt;p&gt;This step involved correcting typos, standardizing inconsistent capitalization (e.g., changing "Nairobi", "nairobi", and "NAIROBI" into one uniform format), merging mislabeled categories and trimming extra spaces in the text columns. Certain categories like employer ID also had inconsistent formatting. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standardizing Codes:&lt;/strong&gt; &lt;br&gt;
Employer ID inconsistent formatting was remedied by selecting the column, then applying an auto filter using &lt;code&gt;Shift+Ctrl+L&lt;/code&gt; and checking the Drop down to see the range of values I had. Then I selected the Column, and &lt;code&gt;Ctrl+H&lt;/code&gt; to &lt;strong&gt;find and replace&lt;/strong&gt; and replaced all &lt;code&gt;EMP-&lt;/code&gt; with a Blank to fix the formatting.&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%2Fop5e65rhmkas6gmbt3d2.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%2Fop5e65rhmkas6gmbt3d2.png" alt="Alt text" width="268" height="466"&gt;&lt;/a&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%2Fozs4j9tqivmxkobybol0.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%2Fozs4j9tqivmxkobybol0.png" alt="Alt text" width="534" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trimming Spaces and fixing Capitalization:&lt;/strong&gt; 
&lt;strong&gt;TRIM()&lt;/strong&gt;&amp;nbsp;removes extra spaces between words. 
Name Entries were fixed by using &lt;code&gt;=PROPER(TRIM(TEXT))&lt;/code&gt; on the first and last name columns for both text length and proper case and then replacing the names in both columns using Paste (Values)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Handling missing values:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Deciding whether to filter out empty cells, fill them with zeroes, or input an average value. &lt;br&gt;
Empty/missing values in the remaining text and numerical Columns were replaced by &lt;code&gt;unknown&lt;/code&gt; converting them into unknown values using the &lt;code&gt;Ctrl+H&lt;/code&gt; find and replace feature. &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%2Fe9i8r73m0j8ixf1eyxag.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%2Fe9i8r73m0j8ixf1eyxag.png" alt="Alt text" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Standardizing formats:&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Ensuring all dates followed a consistent format (e.g., &lt;code&gt;YYYY-MM-DD&lt;/code&gt;) and numbers are converted from plain text into actual numeric formats.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Salary &amp;amp; Bonuses:&lt;/strong&gt; Highlighted the numeric columns and pressed &lt;strong&gt;Ctrl + 1&lt;/strong&gt; to set the format to &lt;strong&gt;Currency (Ksh)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&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%2Fye1utosqh4qwuga72cqx.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%2Fye1utosqh4qwuga72cqx.png" alt="Alt text" width="542" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dates:&lt;/strong&gt; Selected the date column and set the formatting to &lt;code&gt;DD/MM/YYYY&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&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%2Fshtwfj3k0lkipxqgo0nj.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%2Fshtwfj3k0lkipxqgo0nj.png" alt="Alt text" width="542" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To verify that we had successfully cleaned and validated our data, we applied auto filters &lt;code&gt;Ctrl + Shift + L&lt;/code&gt; to the entire Spreadsheet and sorted each column to confirm that our categories were uniform, and our numbers were formatted correctly and whether we had any lingering errors. We then had a 'clean' dataset that was ready for analysis. &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>datascience</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding the Git Workflow: Working Directory, Staging, Commit and Push.</title>
      <dc:creator>Njuguna Gichia</dc:creator>
      <pubDate>Sat, 22 Aug 2026 20:20:07 +0000</pubDate>
      <link>https://dev.to/9ichia/understanding-the-git-workflow-working-directory-staging-commit-and-push-226i</link>
      <guid>https://dev.to/9ichia/understanding-the-git-workflow-working-directory-staging-commit-and-push-226i</guid>
      <description>&lt;p&gt;Two weeks ago, I joined a Data Science bootcamp and part of the learning outcomes for this week was independently navigating the Git Workflow to successfully upload a test project as part of the data portfolio to a GitHub repository. &lt;/p&gt;

&lt;p&gt;Git is a version control system that runs locally on a personal computer and allows us to keep track of changes made to our projects. Git creates saved checkpoints knowns as commits that act as snapshots of the state of the projects. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; is an online service where we can store Git repositories. While Git is installed and works locally on our personal computers, GitHub stores our repositories online and allows us to share and collaborate on projects &lt;/p&gt;

&lt;p&gt;My project was a custom energy consumption segmentation analysis using k means. Other than local python, this project required additional installation of &lt;code&gt;pandas&lt;/code&gt;, &lt;code&gt;numpy&lt;/code&gt; for data processing and manipulation, &lt;code&gt;scikit-learn&lt;/code&gt; for preprocessing, and &lt;code&gt;matplotlib&lt;/code&gt; and &lt;code&gt;seaborn&lt;/code&gt; for the data visualization. &lt;/p&gt;

&lt;p&gt;The Git workflow happened in 4 distinct stages.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Working Directory.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The working directory is the folder containing my project files where the terminal or Git is currently working from. These include: &lt;br&gt;
    - &lt;strong&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/strong&gt; file which is a description of the entire project written in raw markdown. It contains information about the project such as:&lt;br&gt;
        - What the project is about&lt;br&gt;
        - What dataset was used&lt;br&gt;
        - The tools used &lt;br&gt;
        - The analysis was performed&lt;br&gt;
        - Contents of each folder&lt;br&gt;
        - Important findings&lt;br&gt;
        - How another person can understand the project&lt;br&gt;
    - &lt;strong&gt;&lt;code&gt;Data&lt;/code&gt;&lt;/strong&gt; Folder which contains an excel spreadsheet named &lt;code&gt;energy_consumption_data.csv&lt;/code&gt; that contained the consumer data.&lt;br&gt;
    - &lt;strong&gt;&lt;code&gt;Scripts&lt;/code&gt;&lt;/strong&gt; Folder which contains a K means python script named &lt;code&gt;segmentation.py&lt;/code&gt;. Python script files typically end with the &lt;code&gt;.py&lt;/code&gt; extension.&lt;/p&gt;

&lt;p&gt;To create a working directory using Git Bash, I opened Gitbash on Desktop by clicking on the windows icon on the taskbar, typing in &lt;code&gt;bash&lt;/code&gt; and clicking on Gitbash to open a new window. Once the window was open, I ran &lt;strong&gt;&lt;code&gt;cd Desktop&lt;/code&gt;&lt;/strong&gt;, to navigate to my Desktop where I created a new Folder Titled &lt;code&gt;energy_consumption_analysis&lt;/code&gt; by running the command &lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir energy_customer_data_analysis&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;cd&lt;/code&gt; means change directory and it allows you to navigate in and out of directories. &lt;code&gt;cd&lt;/code&gt; allows you to enter a folder while &lt;strong&gt;&lt;code&gt;cd ..&lt;/code&gt;&lt;/strong&gt; allows you to move backward by exiting a directory or a folder into the parent directory. Inside &lt;code&gt;energy_customer_data_analysis&lt;/code&gt;, I created two folders &lt;code&gt;Data&lt;/code&gt; and &lt;code&gt;Scripts&lt;/code&gt; simultaneously by running the &lt;strong&gt;&lt;code&gt;mkdir&lt;/code&gt;&lt;/strong&gt; command which allows you to create 2 folder simultaneously by listing two folder names separated by a space: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;mkdir Data Scripts&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;command created two folders named &lt;code&gt;Data&lt;/code&gt; and &lt;code&gt;Scripts&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I also created the &lt;code&gt;README.md&lt;/code&gt; file by running &lt;strong&gt;&lt;code&gt;touch README.md&lt;/code&gt;&lt;/strong&gt; in bash.&lt;/p&gt;

&lt;p&gt;to make sure that I had created all the files and folders, I ran the &lt;strong&gt;&lt;code&gt;ls&lt;/code&gt;&lt;/strong&gt; command in bash which allowed me to see all the files and folders created in the working directory.&lt;/p&gt;

&lt;p&gt;I copied the CSV file from my downloads into the &lt;code&gt;Data&lt;/code&gt; folder then used bash to navigate into the &lt;code&gt;Scripts&lt;/code&gt; folder by running &lt;strong&gt;&lt;code&gt;cd Scripts&lt;/code&gt;&lt;/strong&gt; since I was still inside my project folder. once inside the Scripts folder, I ran &lt;strong&gt;&lt;code&gt;touch segmentation.py&lt;/code&gt;&lt;/strong&gt; to create the python script file and then ran &lt;strong&gt;&lt;code&gt;code .&lt;/code&gt;&lt;/strong&gt; in bash to then open &lt;code&gt;segmentation.py&lt;/code&gt; in VS Code.  &lt;/p&gt;

&lt;p&gt;After writing the python code in VS Code, I went back to bash and ran &lt;code&gt;cd ..&lt;/code&gt; to exit the scripts folder and ran &lt;code&gt;nano README.md&lt;/code&gt; to open the README file in Bash's text editor &lt;code&gt;nano&lt;/code&gt; where i wrote the description for the project in Markdown. Once this was complete, &lt;code&gt;Ctrl + O&lt;/code&gt;, then &lt;code&gt;Enter&lt;/code&gt; to save then &lt;code&gt;Ctrl + X&lt;/code&gt; to go back to bash. To see what's inside the README file, use &lt;code&gt;cat README.md&lt;/code&gt; in bash to display text inside the &lt;code&gt;README.md&lt;/code&gt; file and &lt;code&gt;ls&lt;/code&gt; to inspect the project folder. Once satisfied with everything, we then move on to the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Staging Area.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The staging area is the preparation area for the next commit. Here, we Initialize Git, check changes and stage files. Before running any git commands, we check our location by running &lt;strong&gt;&lt;code&gt;pwd&lt;/code&gt;&lt;/strong&gt; . &lt;code&gt;Pwd&lt;/code&gt; means print working directory and allows us to see the exact location we are working from. &lt;/p&gt;

&lt;h3&gt;
  
  
  Initialize git
&lt;/h3&gt;

&lt;p&gt;Once we ascertain that we are in the correct project folder, we can initialize git by running the command &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git init&lt;/code&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;which instructs Git to begin managing the project. When run successfully, we should see : `Initialized empty Git repository in (the working directory path)&lt;/p&gt;

&lt;p&gt;We also run &lt;strong&gt;&lt;code&gt;ls -la&lt;/code&gt;&lt;/strong&gt; which allows us to see a &lt;code&gt;.git&lt;/code&gt; folder which acts as Git's internal memory for the project. &lt;/p&gt;

&lt;h3&gt;
  
  
  Check Project Status
&lt;/h3&gt;

&lt;p&gt;We check project status by running &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git status&lt;/code&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;This allows git to show us exactly what is happening in our project and because this is a completely new project and repository that git has not started tracking, our project status is untracked.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project Staging
&lt;/h3&gt;

&lt;p&gt;We can add individual files in our directory by running &lt;code&gt;git add &amp;lt;filename&amp;gt;&lt;/code&gt; to select the individual file or we can run &lt;strong&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;/strong&gt; to add everything in the current directory. This moves the selected files from the working directory into the staging area. &lt;/p&gt;

&lt;p&gt;We can check the status of our project by running &lt;code&gt;git status&lt;/code&gt; and if the staging is successful, our selected files and folders should be listed in green. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Commit.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We create the first commit by running &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git commit -m "Add Energy Consumption Segmentation Analysis Project"&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git commit&lt;/code&gt; creates a saved Git checkpoint while &lt;code&gt;-m&lt;/code&gt; means the message we want to attach to the commit which in this case is &lt;code&gt;"Add Energy Consumption Segmentation Analysis Project"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The message explains what was saved. A good commit message creates an understandable history of the project. &lt;/p&gt;

&lt;h3&gt;
  
  
  Commit History
&lt;/h3&gt;

&lt;p&gt;We can view the commit history by running &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git log&lt;/code&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;which shows us the commit history or by running:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git log --oneline&lt;/code&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;for a much shorter commit history. &lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the Github Repository.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;We can create a new repository in GitHub through our browser.&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Github.com&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;Sign in.&lt;/li&gt;
&lt;li&gt;Once Signed in Click the &lt;code&gt;+&lt;/code&gt; button.&lt;/li&gt;
&lt;li&gt;Select: &lt;strong&gt;New repository&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter &lt;strong&gt;Repository Name(e.g.,&lt;a href="https://github.com/njugunagichia/Energy-Consumer-Data-Segmentation-Analysis" rel="noopener noreferrer"&gt; &lt;code&gt;energy_consumer_data_segmentation_analysis&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;You can also Add an optional description such as:(&lt;code&gt;energy_consumer_data_analysis_using_Python&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Choose between a &lt;strong&gt;Public&lt;/strong&gt; or &lt;strong&gt;Private&lt;/strong&gt; Repository (keep in mind that a public repository can generally be viewed by anyone and should not be used for sensitive or confidential data. In our case, the data is synthetic and non-specific so a public repository is fine.) &lt;/li&gt;
&lt;li&gt;Leave options such as: &lt;strong&gt;Add README&lt;/strong&gt;, &lt;strong&gt;Add .gitignore&lt;/strong&gt;, and &lt;strong&gt;Add license unchecked.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Create New Repository.&lt;/strong&gt; &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After creating the repository, navigate to the connection options, Select &lt;strong&gt;SSH&lt;/strong&gt; if you have it already configured.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Push.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Pushing means sending committed changes on our projects to GitHub.&lt;/p&gt;

&lt;p&gt;After copying the SSH string, return to Git Bash. To check whether we are still in the project, run &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pwd&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If still in the folder, run: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git remote add origin git@github.com:USERNAME/project-name.git&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;USERNAME&lt;/code&gt;&lt;/strong&gt;: is your GitHub Username&lt;br&gt;
&lt;strong&gt;&lt;code&gt;Project-name.git&lt;/code&gt;&lt;/strong&gt;: is the name of the repository you've just created.&lt;/p&gt;

&lt;p&gt;type &lt;strong&gt;&lt;code&gt;git remote add origin&lt;/code&gt;&lt;/strong&gt; and then press &lt;code&gt;Shift + Insert&lt;/code&gt; on your keyboard to paste the SSH string  you've just copied from GitHub to complete the command and then run it. &lt;/p&gt;

&lt;h3&gt;
  
  
  Checking the Remote.
&lt;/h3&gt;

&lt;p&gt;A remote is a connection between our local repository and another repository which is in our case, the one on GitHub. &lt;/p&gt;

&lt;p&gt;We check the remote by running: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git remote -v&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;origin git@github.com:USERNAME/project-name.git (fetch)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;means that Git can retrieve information from the remote repository&lt;/p&gt;

&lt;p&gt;&lt;code&gt;origin git@github.com:USERNAME/project-name.git (push)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;means that git can send commits to the remote Repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pushing the Code
&lt;/h3&gt;

&lt;p&gt;Pushing means sending the committed changes in my project to the Remote Git Repository.&lt;/p&gt;

&lt;p&gt;we do this by running: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;git push -u origin main&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
Bash will prompt you to enter the configured passphrase. if you have one, type it in and then &lt;strong&gt;Enter&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Verifying the Push
&lt;/h3&gt;

&lt;p&gt;Return to the repository page on your browser and refresh it. &lt;br&gt;
GitHub should render the contents in your &lt;code&gt;README.md&lt;/code&gt; file visually.&lt;br&gt;
You should also be in a position to see your files and the contents in those files (i.e the CSV file in the &lt;code&gt;Data&lt;/code&gt; folder and the &lt;code&gt;.py&lt;/code&gt; file in the &lt;code&gt;Scripts&lt;/code&gt; folder).&lt;/p&gt;

&lt;p&gt;If we can see this, then our project has successfully been pushed to GitHub.&lt;/p&gt;

</description>
      <category>git</category>
      <category>github</category>
      <category>python</category>
      <category>datascience</category>
    </item>
  </channel>
</rss>
