<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ data visualization - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ data visualization - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 20 May 2026 15:59:15 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/data-visualization/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Data Visualization Tools for Svelte Developers
 ]]>
                </title>
                <description>
                    <![CDATA[ Svelte is a front-end framework for building fast and interactive web applications. Unlike many other well-known frameworks, it doesn’t use a virtual DOM. Instead, it turns your code into efficient Ja ]]>
                </description>
                <link>https://www.freecodecamp.org/news/data-visualization-tools-for-svelte-developers/</link>
                <guid isPermaLink="false">69dd2445217f5dfcbd1e423d</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daria Filozop ]]>
                </dc:creator>
                <pubDate>Mon, 13 Apr 2026 17:13:41 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/cd0a2c05-0604-46d2-a9c0-b914a187d492.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Svelte is a front-end framework for building fast and interactive web applications.</p>
<p>Unlike many other well-known frameworks, it doesn’t use a virtual DOM. Instead, it turns your code into efficient JavaScript during the build step, which makes apps smaller and faster. It also makes things reactive in a simple way, so it’s easier to manage data and keep your code clean.</p>
<p>Recently, the buzz around Svelte caught my attention. I wanted to understand what all the hype was about.</p>
<p>After polling <a href="https://www.reddit.com/r/webdevelopment/comments/1lpq27w/any_thoughts_about_svelte/?share_id=uMO0hMk04m4PJz8yk6lgf&amp;utm_content=2&amp;utm_medium=ios_app&amp;utm_name=ioscss&amp;utm_source=share&amp;utm_term=1">the Reddit community</a> for their opinions, their strong recommendations persuaded me to dive in and try it myself.</p>
<p>So, I did some more research to learn more about its distinctive features, and now I want to share this info with you here.</p>
<h2 id="heading-what-well-cover">What We’ll Cover:</h2>
<ul>
<li><p><a href="#heading-1-why-svelte-stands-out">1. Why Svelte Stands Out</a></p>
</li>
<li><p><a href="#heading-2-charts">2. Charts</a></p>
<ul>
<li><p><a href="#heading-layer-cake">Layer Cake</a></p>
</li>
<li><p><a href="#heading-fusioncharts">FusionCharts</a></p>
</li>
<li><p><a href="#heading-highcharts">Highcharts</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-3-pivot-tables">3. Pivot Tables</a></p>
<ul>
<li><a href="#heading-flexmonster">Flexmonster</a></li>
</ul>
</li>
<li><p><a href="#heading-4-grids">4. Grids</a></p>
<ul>
<li><a href="#heading-svar">SVAR</a></li>
</ul>
</li>
<li><p><a href="#heading-5-wrapping-up">5. Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-why-svelte-stands-out"><strong>Why Svelte Stands Out</strong></h2>
<p>One of Svelte's key features is that it has no virtual DOM and compiles your code during the build process. This makes your apps built with Svelte much faster compared to those built with other frameworks.</p>
<p>Svelte also makes apps reactive in a simple way by declaring variables. The code stays clean and easy to read, with scoped styles that don’t mix into other parts of the app.</p>
<p>It also has built-in animations and transitions, plus an easy store system for sharing state between components.</p>
<p>Beyond all this, Svelte focuses on accessibility, supports TypeScript, and delivers excellent performance thanks to its compile-time approach.</p>
<p>I think this <a href="https://github.com/sveltejs/svelte/discussions/10085">quote from Svelte creator Rich Harris</a> perfectly sums up his reason for creating this framework:</p>
<blockquote>
<p><em>“We're not trying to be the most popular framework; we're trying to be the best framework. Sometimes that means making choices that we believe in but that go against the grain of web development trends.”</em></p>
</blockquote>
<p>It seems like many developers admire this approach. According to the <a href="https://survey.stackoverflow.co/2025/technology#admired-and-desired">2025 StackOverflow Developer Survey</a>, Svelte is admired by 62.4% of respondents and desired by 11.1%. This suggests that it's catching up to more established frameworks like React, Angular, and Vue.</p>
<p>I've also noticed the continuous growth of the Svelte community. This expanding network provides strong support, with a variety of tools and libraries, and active channels on <a href="https://www.reddit.com/r/sveltejs/">Reddit</a> and <a href="https://discord.com/invite/svelte">Discord</a> where you can get advice from experienced developers.</p>
<p>My recent work on personal data visualization projects has shown me how powerful and enjoyable Svelte can be. But in my experience, there aren't yet many tools for working with Svelte. So to help my fellow developers, I’ve decided to share my experiences and recommend my 5 favorite data visualization tools that smoothly integrate with Svelte and work perfectly with it.</p>
<p>For convenience, I’ve divided them into three categories: Charts, Pivot Tables, and Grids. So, if you want to find something specific, you can go to the appropriate section.</p>
<h2 id="heading-charts"><strong>Charts</strong></h2>
<p>You use charts when you need to explain data clearly and visually, such as showing trends over time, comparing groups, or quickly highlighting key differences.</p>
<p>Here are some charting tools that integreat well with Svelte:</p>
<h3 id="heading-1-layer-cake"><strong>1.</strong> <a href="https://layercake.graphics/"><strong>Layer Cake</strong></a></h3>
<p>Layer Cake is an open-source graphics framework for Svelte that allows you to create a wide variety of charts, from columns to a multilayer map. On Reddit, the creator of LayerCake <a href="https://www.reddit.com/r/sveltejs/comments/194dfrg/comment/khhal06/">shares some insights</a> about his project:</p>
<blockquote>
<p><em>“It’s designed to give you the basic elements you need to make a responsive chart (D3 scales, SVG, canvas, etc) and lets you customize the rest in user-land.”</em></p>
</blockquote>
<p>The nice thing is that the creator actively responds to feedback, which helps make the product better.</p>
<p>LayerCake suggests using five types of components:</p>
<ul>
<li><p><a href="https://layercake.graphics/components#axis">Axis</a></p>
</li>
<li><p><a href="https://layercake.graphics/components#chart">Chart</a></p>
</li>
<li><p><a href="https://layercake.graphics/components#map">Map</a></p>
</li>
<li><p><a href="https://layercake.graphics/components#interaction">Interaction</a></p>
</li>
<li><p><a href="https://layercake.graphics/components#annotation">Annotation</a></p>
</li>
</ul>
<p>Also, <a href="https://github.com/mhkeller/layercake">with over 1.5k stars on GitHub</a>, the project is actively maintained and can be easily installed via npm.</p>
<p>Layer Cake is a good option when you need to build something unique rather than use pre-built chart templates.</p>
<p>License: MIT</p>
<h3 id="heading-2-fusioncharts"><strong>2.</strong> <a href="https://www.fusioncharts.com/svelte-charts?framework=svelte"><strong>FusionCharts</strong></a></h3>
<p>FusionCharts is a JavaScript charting library that suggests over 100 interactive charts and around 2,000 data-driven maps. It offers a special Svelte component called <a href="https://github.com/fusioncharts/svelte-fusioncharts">svelte-fusioncharts</a> that makes adding charts to apps simple.</p>
<p>FusionCharts is a commercial tool, but there's a trial version that you can use to try it out. You can also use it for free for non-commercial purposes (there will be a watermark).</p>
<p><a href="https://www.g2.com/products/fusioncharts/reviews">Based on user reviews on G2</a>, devs like FusionCharts for its extensive variety of chart types, its ability to handle large datasets quickly, and its easy implementation with strong customization options.</p>
<p>But they also report a decline in product support over the last few years, noting that fixing bugs can take a long time.</p>
<p>I really liked using their new <a href="https://www.fusioncharts.com/askfusiondev-ai">FusionDev AI</a> feature. It was super convenient to quickly get answers from the documentation and even some guidance on creating or customizing charts.</p>
<p>They work pretty well for business dashboards and enterprise apps that need a wide variety of ready-made charts and a quick setup (especially useful when working with large datasets).</p>
<p>License: Commercial</p>
<h3 id="heading-3-highcharts"><strong>3.</strong> <a href="https://www.highcharts.com/integrations/svelte/"><strong>Highcharts</strong></a></h3>
<p>Like FusionCharts, Highcharts is a commercial charting library that provides various chart types. <a href="https://www.g2.com/products/highcharts/reviews">Users highlight</a> its ease of use and effortless setup using simple code. It also has many customization options available.</p>
<p>While it may be pricier than some alternatives, many businesses find its advantages worthwhile: after all, 80 of the world's 100 largest companies use Highcharts. It's also a great option for non-commercial projects, which can use its free version.</p>
<p>Their wrapper <a href="https://github.com/highcharts/highcharts-svelte">@highcharts/svelte</a> lets you quickly integrate Highcharts into Svelte apps. It works with all their chart types and provides full customization.</p>
<p>Also, if you want an active community, Highcharts is a great option. They recently they created a <a href="https://discord.com/invite/xHxxcyyy6K">Discord server</a>, where you can share your projects or get inspiration for new ones.</p>
<p>Highcharts is a great choice for analytical platforms and financial dashboards. So if you need reliable, interactive charts with minimal effort, it's a perfect match.</p>
<p>License: Commercial</p>
<h2 id="heading-pivot-tables"><strong>Pivot Tables</strong></h2>
<p>You use pivot tables to quickly group and summarize big datasets. It lets you group data by categories, calculate totals or averages, and reorganize your information dynamically.</p>
<h3 id="heading-flexmonster"><a href="https://www.flexmonster.com/doc/integration-with-svelte/"><strong>Flexmonster</strong></a></h3>
<p>Flexmonster is a JavaScript pivot table library that allows you to quickly analyze and visualize data.</p>
<p>It's a commercial product, but it also has a full-featured trial version, plus they have a free entry license for dev purposes.</p>
<p><a href="https://www.g2.com/products/flexmonster-pivot-table-charts-component/reviews">From the reviews on G2</a> and <a href="https://www.capterra.com/p/138272/Flexmonster-Pivot-Table/">Capterra</a>, user feedback highlights a consistent trade-off: while the price is often cited as a con, the consensus is that its value justifies the cost. Users praise its speed, smooth integration with web apps, similarity to Excel, and ability to manage vast datasets without problems. People also cite the ability to create clear reports and exports.</p>
<p>As an enterprise solution, Flexmonster offers a wide range of options to customize reports entirely according to a project's specific needs. Also, the product is continuously updated, and customer support is one of its core strengths. Users consistently note that support is responsive, clear, and helpful, which ensures smooth adoption and reliable problem-solving.</p>
<p>Flexmonster now provides a wrapper for Svelte, which makes it easy to integrate pivot tables into Svelte apps without extra setup. They also provide a <a href="https://github.com/flexmonster/pivot-svelte">GitHub sample</a> that demonstrates many useful features. For example, it shows how to configure a pivot table, handle user interactions through events, work with Flexmonster's API, and much more. Altogether, it gives a clear picture of how to build a fully interactive reporting dashboard in a Svelte app.</p>
<p>By the way, <a href="https://youtu.be/rLJ5cyOVwl4?feature=shared">their video about integrating Flexmonster with Svelte</a> was the one I used, and it was very helpful.</p>
<p>Flexmonster also smoothly integrates with Highcharts and FusionCharts. You can find <a href="https://www.flexmonster.com/doc/available-tutorials-charts/">tutorials about these on their official webpage</a>.</p>
<p>Flexmonster is a great fit for a wide range of data-heavy applications. It’s a powerful engine for data visualization and analysis, and thanks to its flexibility and customization options, it can be easily integrated into almost any application, such as financial reporting, sales analysis, and audit systems.</p>
<p>License: Commercial</p>
<h2 id="heading-grids"><strong>Grids</strong></h2>
<p>A grid presents data in a structured table format, focusing on viewing, managing, and interacting with individual records.</p>
<h3 id="heading-svar"><a href="https://svar.dev/svelte/datagrid/"><strong>SVAR</strong></a></h3>
<p>SVAR is lightweight and compatible with Svelte's datagrid component, which helps you work quickly with big datasets.</p>
<p>It’s a relatively new tool, released in 2025, so there are fewer user reviews, but it seems to be growing in popularity. And for now, you can try it yourself because it’s completely free! It also covers all the key data viz use cases, like sorting, filtering, grouping, and editing data.</p>
<p>User support is one of SVAR’s strengths. The creators and community are active, and the <a href="https://forum.svar.dev/">SVAR Forum</a> offers reliable help whenever you need it.</p>
<p>So, it's a good option for apps that need to display and edit structured data, such as admin panels.</p>
<p>License: MIT</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>This was a small list of tools I recommend for data visualization while using Svelte. There are many more tools out there, but these stand out as stable, helpful, and easy to integrate. I hope that after reading this article, you’ve found the one that suits you the most.</p>
<p>Personally, these caught my attention because they're all pretty intuitive and provide powerful results. If you know other great tools, feel free to share your favorites with me!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Comprehensive Guide to Financial Storytelling using Data Visualization ]]>
                </title>
                <description>
                    <![CDATA[ In any analysis project, raw tables of numbers often don’t tell the full story. Visualisations simplify complexity by transforming data into shapes that our brains can quickly understand, emphasising  ]]>
                </description>
                <link>https://www.freecodecamp.org/news/financial-storytelling-using-data-visualization/</link>
                <guid isPermaLink="false">69b1ced06c896b0519c207be</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ finance ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Nikhil Adithyan ]]>
                </dc:creator>
                <pubDate>Wed, 11 Mar 2026 20:21:36 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/64ab3674-959f-44b5-8be2-4ca00a798621.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In any analysis project, raw tables of numbers often don’t tell the full story. Visualisations simplify complexity by transforming data into shapes that our brains can quickly understand, emphasising trends, outliers, and regime shifts that might be overlooked in raw data.</p>
<p>This is especially vital in finance and trading, where clear visuals can uncover risks, opportunities, and patterns, directly affecting decisions on position sizing, timing, and confidence.</p>
<p>Today, we'll use FMP APIs to interpret earnings data: extracting announcements, surprises, and price reactions across almost 1,000 stocks to identify actionable patterns in post‑earnings movements.</p>
<p>Here’s exactly what we’ll build:</p>
<ul>
<li><p><strong>Sector heatmap</strong>: Maps strongest 3/10-day post-earnings reactions by sector/market-cap buckets.</p>
</li>
<li><p><strong>EPS scatter</strong>: Tests if earnings beats drive returns (sector-colored, with regression).</p>
</li>
<li><p><strong>Return violins</strong>: Shows 3-day post-earnings volatility/skew by sector and market-cap.</p>
</li>
<li><p><strong>Mega-tech time series</strong>: Tracks AAPL/MSFT/NVDA post-earnings patterns over time.</p>
</li>
<li><p><strong>Monthly seasonality</strong>: Reveals calendar edges in post-earnings returns/surprises.</p>
</li>
<li><p><strong>Regime cross-section</strong>: Tests sector robustness across bull/bear/sideways markets.</p>
</li>
</ul>
<h3 id="heading-what-well-cover">What we'll cover:</h3>
<ol>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a href="#heading-data-extraction">Data Extraction</a></p>
</li>
<li><p><a href="#heading-storytelling-with-charts-and-visuals">Storytelling with Charts and Visuals</a></p>
<ul>
<li><p><a href="#heading-sector-heatmap">Sector Heatmap</a></p>
</li>
<li><p><a href="#heading-megacap-tech-time-series">Mega‑Cap Tech Time Series</a></p>
</li>
<li><p><a href="#heading-eps-surprise-scatter-plot">EPS Surprise Scatter Plot</a></p>
</li>
<li><p><a href="#heading-return-distribution-violins">Return Distribution Violins</a></p>
</li>
<li><p><a href="#heading-monthly-seasonality">Monthly Seasonality</a></p>
</li>
<li><p><a href="#heading-regime-crosssection">Regime Cross-Section</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-what-did-we-get-out-of-all-this-storyline">What Did We Get Out of All This Storyline?</a></p>
</li>
<li><p><a href="#heading-final-thoughts">Final Thoughts</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>To follow along, you should be comfortable with Python and basic data manipulation in pandas.</p>
<p>This is a code-first guide. I’ll focus on the workflow and the story the charts reveal, and I won’t explain every line of Python. You should be comfortable reading pandas code, loops, and basic plotting logic so you can follow along without needing a step-by-step breakdown of each block.</p>
<p>You’ll need:</p>
<ul>
<li><p>Python 3.10+</p>
</li>
<li><p>A Financial Modeling Prep (FMP) API key</p>
</li>
<li><p>pandas, numpy, matplotlib, seaborn, scipy installed</p>
</li>
<li><p>Enough local compute and patience to run API loops across a large stock universe</p>
</li>
</ul>
<h2 id="heading-data-extraction">Data Extraction</h2>
<p>In the first part of this article, we need to collect all the data required for our visualisation exercise. Using FMP’s Stock Screener API, we will retrieve NASDAQ stocks. The first API call will return 1,000 stocks.</p>
<pre><code class="language-python">import requests
import pandas as pd
import numpy as np
import json
from datetime import datetime, timedelta
import seaborn as sns
import matplotlib.pyplot as plt
from scipy import stats

token = 'YOUR FMP TOKEN'

url = f'https://financialmodelingprep.com/stable/company-screener'
querystring = {"apikey":token,"country":"US", "exchange": "NASDAQ", "isActiveTrading": True, "isEtf": False, "isFund": False}
resp = requests.get(url, querystring).json()

df_universe = pd.DataFrame(resp)
df_universe = df_universe[df_universe['exchangeShortName'] == 'NASDAQ']
df_universe
</code></pre>
<p>This will give us 1,000 stocks! Next, we'll bin the market capitalisation to gain a better understanding of the results later on, and we will keep only four columns that are necessary: the symbol, name, market cap, and sector.</p>
<pre><code class="language-python">bins = [0,
        250_000_000,    # 250M
        2_000_000_000,  # 2B
        10_000_000_000, # 10B
        200_000_000_000,# 200B
        float("inf")]

labels = ["Micro", "Small", "Mid", "Large", "Mega"]

df_universe["marketCap"] = pd.cut(df_universe["marketCap"], bins=bins, labels=labels, right=False)
df_universe = df_universe[['symbol', 'companyName', 'marketCap', 'sector']]
df_universe
</code></pre>
<img src="https://cdn-images-1.medium.com/max/1000/0*rAiF7Q5TqSNlRG4h.png" alt="0*rAiF7Q5TqSNlRG4h" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>Now it is time to retrieve the earnings using FMP’s Earnings Report API. We'll loop through each symbol and collect all the earnings the endpoint provides to us.</p>
<pre><code class="language-python">symbols = df_universe['symbol'].to_list()

all_dfs = []

for symbol in symbols:
    url = f"https://financialmodelingprep.com/stable/earnings?symbol={symbol}"
    params = {"apikey": token}
    resp = requests.get(url, params=params)

    if resp.status_code != 200:
        print(f"Error for {symbol}: {resp.status_code} - {resp.text}")
        continue

    data = resp.json()
    if not data:
        print(f"No data for {symbol}")
        continue

    df_symbol = pd.DataFrame(data)
    df_symbol["symbol"] = symbol
    all_dfs.append(df_symbol)

# Single DataFrame with all earnings
df_earnings = pd.concat(all_dfs, ignore_index=True)
df_earnings = df_earnings.dropna(subset=['epsActual', 'epsEstimated', 'revenueActual','revenueEstimated'])
df_earnings
</code></pre>
<p>Now we'll calculate the surprise, both for earnings and revenue in percentage terms, so we can later compare apples with apples! We'll keep everything from 2010 onwards.</p>
<pre><code class="language-python">df_earnings["eps_surprise"] = ((df_earnings["epsActual"] - df_earnings["epsEstimated"]) /
                               abs(df_earnings["epsEstimated"]) * 100).round(2)

df_earnings["revenue_surprise"] = ((df_earnings["revenueActual"] - df_earnings["revenueEstimated"]) /
                                   abs(df_earnings["revenueEstimated"]) * 100).round(2)

df_earnings = df_earnings[['symbol', 'date', 'eps_surprise', 'revenue_surprise']]

df_earnings["date"] = pd.to_datetime(df_earnings["date"])
df_earnings = df_earnings[df_earnings["date"] &gt; "2009-12-31"]
</code></pre>
<p>Lastly, as a final step in gathering the data needed for visualization, using FMP’s Historical Index Full Chart API, we'll loop through the stocks in our dataframe, retrieve the historical daily prices, and calculate the return of the stock 3 and 10 trading days before and after the earnings announcement.</p>
<pre><code class="language-python">unique_symbols = df_earnings["symbol"].unique()

price_results = []

print(f"Processing {len(unique_symbols)} symbols...")

for symbol in unique_symbols:
    # Fetch full historical prices
    url = f"https://financialmodelingprep.com/stable/historical-price-eod/full"
    params = {"apikey":token, "symbol":symbol, "from":'2009-10-01'}
    resp = requests.get(url, params=params)

    if resp.status_code != 200:
        print(f"Error for {symbol}: {resp.status_code}")
        continue

    data = resp.json()

    hist_df = pd.DataFrame(data)
    hist_df["date"] = pd.to_datetime(hist_df["date"])
    hist_df = hist_df.sort_values("date").reset_index(drop=True)

    # Get matching earnings rows
    earnings_symbol = df_earnings[df_earnings["symbol"] == symbol].copy()

    for _, row in earnings_symbol.iterrows():
        earn_date = pd.to_datetime(row["date"]).date()

        # === 3-DAY WINDOWS ===
        pre3_mask = (hist_df["date"].dt.date &lt; earn_date) &amp; \
                    (hist_df["date"].dt.date &gt;= earn_date - timedelta(days=10))
        pre3 = hist_df[pre3_mask].tail(3)

        post3_mask = (hist_df["date"].dt.date &gt; earn_date) &amp; \
                     (hist_df["date"].dt.date &lt;= earn_date + timedelta(days=10))
        post3 = hist_df[post3_mask].head(3)

        pre3_start = pre3["close"].iloc[0] if len(pre3) &gt;= 3 else None
        pre3_end = pre3["close"].iloc[-1] if len(pre3) &gt;= 1 else None
        post3_end = post3["close"].iloc[-1] if len(post3) &gt;= 3 else None

        pct_pre_3d = ((pre3_end - pre3_start) / pre3_start * 100) if pre3_start and pre3_end else None
        pct_post_3d = ((post3_end - pre3_end) / pre3_end * 100) if pre3_end and post3_end else None

        # === 10-DAY WINDOWS ===
        pre10_mask = (hist_df["date"].dt.date &lt; earn_date) &amp; \
                     (hist_df["date"].dt.date &gt;= earn_date - timedelta(days=20))
        pre10 = hist_df[pre10_mask].tail(10)

        post10_mask = (hist_df["date"].dt.date &gt; earn_date) &amp; \
                      (hist_df["date"].dt.date &lt;= earn_date + timedelta(days=20))
        post10 = hist_df[post10_mask].head(10)

        pre10_start = pre10["close"].iloc[0] if len(pre10) &gt;= 10 else None
        pre10_end = pre10["close"].iloc[-1] if len(pre10) &gt;= 1 else None
        post10_end = post10["close"].iloc[-1] if len(post10) &gt;= 10 else None

        pct_pre_10d = ((pre10_end - pre10_start) / pre10_start * 100) if pre10_start and pre10_end else None
        pct_post_10d = ((post10_end - pre10_end) / pre10_end * 100) if pre10_end and post10_end else None

        price_results.append({
            "symbol": symbol,
            "earn_date": earn_date,
            "month": earn_date.month,
            "pct_pre_3d": round(pct_pre_3d, 2) if pct_pre_3d else None,
            "pct_post_3d": round(pct_post_3d, 2) if pct_post_3d else None,
            "pct_pre_10d": round(pct_pre_10d, 2) if pct_pre_10d else None,
            "pct_post_10d": round(pct_post_10d, 2) if pct_post_10d else None,
            "eps_surprise": row["eps_surprise"],
            "revenue_surprise": row["revenue_surprise"]
        })



df_earnings = pd.DataFrame(price_results)
df_earnings.dropna(inplace=True)
df_earnings = df_universe.merge(df_earnings, on="symbol")
df_earnings
</code></pre>
<p>As you can see, at the end of the code, we have also merged the initial dataset, so all the information, such as name, marketCap, and sector, is now in a single dataset.</p>
<h2 id="heading-storytelling-with-charts-and-visuals">Storytelling with Charts and Visuals</h2>
<h3 id="heading-sector-heatmap">Sector Heatmap</h3>
<p>First, we'll present the Sector Heatmap of average 3-day post-earnings returns segmented by sector and market-cap category. This basic visualisation highlights areas with the most significant reactions, enabling traders to swiftly identify high-alpha sectors and market caps for earnings strategies.</p>
<pre><code class="language-python"># Aggregate: average post-earnings returns and EPS surprise
agg = (
    df_earnings
    .dropna(subset=['pct_post_3d', 'pct_post_10d', 'eps_surprise', 'marketCap', 'sector'])
    .groupby(['sector', 'marketCap'])
    .agg(
        avg_post3d=('pct_post_3d', 'mean'),
        avg_post10d=('pct_post_10d', 'mean'),
        avg_eps_surprise=('eps_surprise', 'mean')
    )
    .reset_index()
)

# Heatmap: average 3-day post-earnings return
heatmap_3d = agg.pivot(index='sector', columns='marketCap', values='avg_post3d')

plt.figure(figsize=(12, 8))
sns.heatmap(
    heatmap_3d,
    annot=True,
    fmt='.2f',
    cmap='RdYlGn',
    center=0,
    linewidths=0.5,
    linecolor='grey'
)
plt.title('Average 3-Day Post-Earnings Return by Sector and Market-Cap Bucket')
plt.xlabel('Market-cap bucket')
plt.ylabel('Sector')
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()
</code></pre>
<img src="https://cdn-images-1.medium.com/max/1000/0*u0AOCzVCWJ4NQMIS.png" alt="Heatmap of average 3-day post-earnings returns by sector and market-cap bucket for NASDAQ stocks" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>Consumer Cyclical and Materials are performing really well, with small and mid caps seeing positive reactions over 1.1%. Real Estate is also doing great, jumping up to +4.0% in mid caps. Energy and Financials are holding steady, staying close to zero. Technology, on the other hand, is showing more muted gains, under 1.1%, indicating there might be limited immediate upside from the big tech earnings.</p>
<p>Building on the 3‑day heatmap, we'll now look at the Sector Heatmap for average <em>10‑day</em> post‑earnings returns by sector and market‑cap category. This extends the timeframe to capture momentum persistence, revealing which sectors maintain or reverse short‑term reactions.</p>
<pre><code class="language-python"># Heatmap: average 10-day post-earnings return
heatmap_10d = agg.pivot(index='sector', columns='marketCap', values='avg_post10d')

plt.figure(figsize=(12, 8))
sns.heatmap(
    heatmap_10d,
    annot=True,
    fmt='.2f',
    cmap='RdYlGn',
    center=0,
    linewidths=0.5,
    linecolor='grey'
)
plt.title('Average 10-Day Post-Earnings Return by Sector and Market-Cap Bucket')
plt.xlabel('Market-cap bucket')
plt.ylabel('Sector')
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()
</code></pre>
<img src="https://cdn-images-1.medium.com/max/1000/0*DB7p_HYR-6jWYaaP.png" alt="Heatmap of average 10-day post-earnings returns by sector and market-cap bucket for NASDAQ stocks" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>Consumer Cyclical stands out with peaks at 3.2% (mega caps), and Industrials and Health Care show consistent gains in mid and large caps around 1.1%. Real Estate has eased after its 3-day surge. Technology has seen a small boost in mega caps (+1.8%) but remains less active overall compared to cyclicals.</p>
<h3 id="heading-megacap-tech-time-series"><strong>Mega‑Cap Tech Time&nbsp;Series</strong></h3>
<p>Extending the heatmaps, we’ll now look at a Mega-Cap Tech time series. It tracks 10-day post-earnings returns over time for AAPL, MSFT, NVDA, and a few other mega-cap tech names.</p>
<p>A bubble chart works well here because it encodes more than one thing at once. The x-axis is the earnings date, the y-axis is the 10-day post-earnings return, the bubble size scales with the absolute EPS surprise magnitude, and the color shows whether the surprise was a beat or a miss. This makes it easy to spot outlier quarters and see whether big surprises consistently lead to bigger post-earnings moves.</p>
<pre><code class="language-python"># Define mega-cap tech tickers (top ones from data: AAPL, MSFT, NVDA, AMZN, GOOG/GOOGL, META)
tech_tickers = ['AAPL', 'MSFT', 'NVDA', 'AMZN', 'GOOG', 'GOOGL', 'META']

# Filter data for mega-cap tech
df_tech = (
    df_earnings[df_earnings['symbol'].isin(tech_tickers)]
    .dropna(subset=['earn_date', 'pct_post_10d', 'eps_surprise'])
    .sort_values('earn_date')
    .assign(
        earn_date=lambda x: pd.to_datetime(x['earn_date'])
    )
)

# Create time-series plot: pct_post_10d vs earn_date, sized/color by eps_surprise
plt.figure(figsize=(14, 8))

# Scatter plot
scatter = plt.scatter(
    df_tech['earn_date'],
    df_tech['pct_post_10d'],
    s=np.abs(df_tech['eps_surprise']) * 50 + 20,  # Size by abs(eps_surprise)
    c=df_tech['eps_surprise'],
    cmap='RdYlBu_r',
    alpha=0.7,
    edgecolors='black',
    linewidth=0.5
)

plt.colorbar(scatter, label='EPS Surprise (%)')
plt.xlabel('Earnings Date')
plt.ylabel('10-Day Post-Earnings Return (%)')
plt.title('Mega-Cap Tech: 10-Day Post-Earnings Returns vs Time\n(Point size/color by EPS Surprise)')
plt.grid(True, alpha=0.3)

# Add trend line
z = np.polyfit(pd.to_numeric(df_tech['earn_date']), df_tech['pct_post_10d'], 1)
p = np.poly1d(z)
plt.plot(df_tech['earn_date'], p(pd.to_numeric(df_tech['earn_date'])), "r--", alpha=0.8, linewidth=2, label=f'Trend: {z[0]:.3f}x + {z[1]:.1f}')

plt.legend()
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
</code></pre>
<img src="https://cdn-images-1.medium.com/max/1500/1*vFJ_bKUzT1WGiJaiF53tEg.png" alt="Bubble chart of 10-day post-earnings returns over time for AAPL, MSFT, NVDA, AMZN, GOOG, GOOGL, META. Bubble size reflects EPS surprise magnitude. Color reflects beat or miss" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>That large red bubble around 2018 is almost certainly <strong>AAPL’s Q4 2018 earnings miss</strong> (Jan 2019 announcement, but fiscal Q4 2018 data) and it stands out because:</p>
<ul>
<li><p><strong>Large size</strong> = massive EPS surprise magnitude (Apple cut guidance dramatically, ~10% miss)</p>
</li>
<li><p><strong>Red colour</strong> = negative surprise</p>
</li>
<li><p><strong>Low Y position</strong> = poor 10‑day return (~-10% range visible)</p>
</li>
</ul>
<p>This was Apple’s infamous “iPhone demand warning” that triggered the January 2019 market panic. Perfect example of how one outlier event can anchor the whole trend line downward in your visualisation.</p>
<h3 id="heading-eps-surprise-scatter-plot">EPS Surprise Scatter&nbsp;Plot</h3>
<p>After identifying major tech trends, let's now look at the <strong>EPS Surprise Scatter</strong> plots. This plot checks a simple hypothesis. Do earnings beats lead to positive returns, and do misses lead to negative returns? We plot EPS surprise on the x-axis and post-earnings returns on the y-axis, then add a regression line to show the average relationship.</p>
<pre><code class="language-python"># Prepare data: drop NaNs and convert earn_date if needed (not used here)
df_plot = (
    df_earnings
    .dropna(subset=['eps_surprise', 'pct_post_3d', 'pct_post_10d', 'sector'])
    .copy()
)

# 1. Scatter: EPS Surprise vs 3-Day Post-Return, colored by sector
plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
sns.scatterplot(
    data=df_plot,
    x='eps_surprise',
    y='pct_post_3d',
    hue='sector',
    alpha=0.6,
    s=40
)

# Regression line (overall)
slope, intercept, r_value, p_value, std_err = stats.linregress(df_plot['eps_surprise'], df_plot['pct_post_3d'])
line = slope * df_plot['eps_surprise'] + intercept
plt.plot(df_plot['eps_surprise'], line, 'red', linestyle='--', linewidth=2,
         label=f'y = {slope:.3f}x + {intercept:.2f}\nR²={r_value**2:.3f}')
plt.xlabel('EPS Surprise (%)')
plt.ylabel('3-Day Post-Earnings Return (%)')
plt.title('EPS Surprise vs 3-Day Post-Return by Sector')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(True, alpha=0.3)

# 2. Scatter: EPS Surprise vs 10-Day Post-Return, colored by sector
plt.subplot(1, 2, 2)
sns.scatterplot(
    data=df_plot,
    x='eps_surprise',
    y='pct_post_10d',
    hue='sector',
    alpha=0.6,
    s=40
)

# Regression line (overall)
slope10, intercept10, r_value10, p_value10, std_err10 = stats.linregress(df_plot['eps_surprise'], df_plot['pct_post_10d'])
line10 = slope10 * df_plot['eps_surprise'] + intercept10
plt.plot(df_plot['eps_surprise'], line10, 'red', linestyle='--', linewidth=2,
         label=f'y = {slope10:.3f}x + {intercept10:.2f}\nR²={r_value10**2:.3f}')
plt.xlabel('EPS Surprise (%)')
plt.ylabel('10-Day Post-Earnings Return (%)')
plt.title('EPS Surprise vs 10-Day Post-Return by Sector')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# Optional: Summary table of correlations by sector
corr_3d = df_plot.groupby('sector')[['eps_surprise', 'pct_post_3d']].corr().unstack().xs('pct_post_3d', level=1, axis=1)['eps_surprise']
corr_10d = df_plot.groupby('sector')[['eps_surprise', 'pct_post_10d']].corr().unstack().xs('pct_post_10d', level=1, axis=1)['eps_surprise']

corr_df = pd.DataFrame({
    'Corr_EPS_3Day': corr_3d.round(3),
    'Corr_EPS_10Day': corr_10d.round(3)
}).sort_values('Corr_EPS_10Day', ascending=False)
</code></pre>
<img src="https://cdn-images-1.medium.com/max/1500/1*rEAHbGRiyJs-NT9VPRudDQ.png" alt="Scatter plot of EPS surprise versus post-earnings returns with sector colors and overall regression line" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>The red dashed trend line illustrates the <em>typical</em> relationship: for every 1% EPS beat, stocks tend to gain about 0.05–0.1% over 3 to 10 days. The gentle slope suggests that while surprises can give a little boost, <strong>they don’t guarantee large moves</strong>.</p>
<p>You’ll notice that Consumer Cyclical dots mainly cluster in the upper right (beats leading to gains), and Real Estate shows a steeper increase. The wide spread around the line indicates that other factors often influence stock movements beyond surprises.</p>
<h3 id="heading-return-distribution-violins">Return Distribution Violins</h3>
<p>Heatmaps show averages, but averages can hide risk. Violin plots show the full distribution of returns, including how wide the outcomes are and whether the tails are heavy. Here we plot 3-day post-earnings return distributions by sector and by market-cap bucket.</p>
<pre><code class="language-python"># Prepare data
df_plot = (
    df_earnings
    .dropna(subset=['pct_post_3d', 'sector', 'marketCap'])
    .copy()
)

# 1. Violin plot: 3-day post-returns by sector
plt.figure(figsize=(15, 6))

plt.subplot(1, 2, 1)
sns.violinplot(
    data=df_plot,
    x='sector',
    y='pct_post_3d',
    inner='quartile',
    palette='Set2'
)
plt.title('Distribution of 3-Day Post-Earnings Returns by Sector (Violin)')
plt.xlabel('Sector')
plt.ylabel('3-Day Post-Earnings Return (%)')
plt.xticks(rotation=45, ha='right')
plt.grid(True, alpha=0.3)

# 2. Violin plot: 3-day post-returns by market-cap group
plt.subplot(1, 2, 2)
sns.violinplot(
    data=df_plot,
    x='marketCap',
    y='pct_post_3d',
    inner='quartile',
    palette='Set3'
)
plt.title('Distribution of 3-Day Post-Earnings Returns by Market-Cap (Violin)')
plt.xlabel('Market-cap bucket')
plt.ylabel('3-Day Post-Earnings Return (%)')
plt.xticks(rotation=45, ha='right')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()


plt.show()

# Summary statistics table
summary = df_plot.groupby(['sector', 'marketCap'])['pct_post_3d'].agg(['mean', 'median', 'std', 'count']).round(2)
print("Summary Statistics: Mean/Median/Std/Count of 3-Day Returns by Sector &amp; Market-Cap")
print(summary)
</code></pre>
<img src="https://cdn-images-1.medium.com/max/1500/1*JLOvSp-2jwD5_ZNqeqdBEw.png" alt="Violin plots showing distribution of 3-day post-earnings returns by sector and by market-cap bucket" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>All violins concentrate near zero with modest variations (±5%), indicating that post-earnings reactions are <em>generally noisy and lack a clear direction.</em> Markets efficiently incorporate expectations, resulting in little predictable advantage. Consumer Cyclical and Materials sectors display slightly more frequent upside surprises, while small caps exhibit the greatest variability, reflecting higher risk and occasional gains. Not every visualization reveals alpha; this one honestly illustrates the difficulty involved.</p>
<h3 id="heading-monthly-seasonality">Monthly Seasonality</h3>
<p>After observing narrow return distributions near zero, let's now look at Monthly Seasonality in four panels: average 3/10‑day post‑returns, EPS surprises, and event counts by month. This reveals calendar effects,  systematic seasonal biases ,  that can influence timing of entries despite noisy individual responses.</p>
<pre><code class="language-python"># 1. Ensure earn_date is datetime
df_month = (
    df_earnings
    .dropna(subset=['earn_date', 'pct_post_3d', 'pct_post_10d', 'eps_surprise'])
    .copy()
)

df_month['earn_date'] = pd.to_datetime(df_month['earn_date'])

# 2. Derive month number and name
df_month['month_num'] = df_month['earn_date'].dt.month
df_month['month_name'] = df_month['earn_date'].dt.strftime('%b')

# 3. Aggregate averages by month
monthly_agg = (
    df_month
    .groupby('month_num')
    .agg(
        pct_post_3d_mean=('pct_post_3d', 'mean'),
        pct_post_10d_mean=('pct_post_10d', 'mean'),
        eps_surprise_mean=('eps_surprise', 'mean'),
        n_obs=('earn_date', 'count')
    )
    .reset_index()
    .sort_values('month_num')
)

# Keep a stable month order and names
month_order = monthly_agg['month_num'].tolist()
month_labels = df_month.drop_duplicates('month_num').set_index('month_num')['month_name'].reindex(month_order)

monthly_agg['month_name'] = month_labels.values

# 4. Plot bar charts
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle('Monthly Seasonality of Post-Earnings Returns and EPS Surprise', fontsize=16)

# Avg 3-day return
axes[0, 0].bar(monthly_agg['month_name'], monthly_agg['pct_post_3d_mean'], color='skyblue')
axes[0, 0].set_title('Avg 3-Day Post-Earnings Return by Month')
axes[0, 0].set_ylabel('Return (%)')
axes[0, 0].grid(alpha=0.3)

# Avg 10-day return
axes[0, 1].bar(monthly_agg['month_name'], monthly_agg['pct_post_10d_mean'], color='lightgreen')
axes[0, 1].set_title('Avg 10-Day Post-Earnings Return by Month')
axes[0, 1].set_ylabel('Return (%)')
axes[0, 1].grid(alpha=0.3)

# Avg EPS surprise
axes[1, 0].bar(monthly_agg['month_name'], monthly_agg['eps_surprise_mean'], color='salmon')
axes[1, 0].set_title('Avg EPS Surprise by Month')
axes[1, 0].set_ylabel('EPS Surprise')
axes[1, 0].grid(alpha=0.3)

# Number of observations
axes[1, 1].bar(monthly_agg['month_name'], monthly_agg['n_obs'], color='gold')
axes[1, 1].set_title('Number of Earnings Events by Month')
axes[1, 1].set_ylabel('Count')
axes[1, 1].grid(alpha=0.3)

for ax in axes.ravel():
    ax.set_xlabel('Month')
    ax.tick_params(axis='x', rotation=0)

plt.tight_layout()
plt.show()
</code></pre>
<img src="https://cdn-images-1.medium.com/max/1500/1*HjdZDaUhudYQZPNvOqy-_Q.png" alt="Four-panel bar charts showing monthly averages of 3-day returns, 10-day returns, EPS surprise, and event counts" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>Jan/Oct tend to have the best 3‑day returns, about 0.8%, while May/Jul usually see weaker results. The 10‑day trends show a similar but gentler pattern, with February and August reaching peaks. EPS surprises are slightly negative in January and May, possibly due to tough comparisons, and there are fewer events in July, August, and December because of holidays. While there’s a hint of seasonality, its impact is quite small, around 0.5%.</p>
<h3 id="heading-regime-cross-section">Regime Cross-Section</h3>
<p>Finally, after subtle monthly patterns, we'll look at the Regime Cross‑Section: sector 10‑day post‑earnings returns by market regime (heatmap at the top, bars below). This stress‑tests earlier findings  ( do patterns persist across bull, bear, and COVID eras), revealing rotation opportunities and regime dependence.</p>
<pre><code class="language-python"># Prepare data with year extraction
df_regimes = (
    df_earnings
    .dropna(subset=['earn_date', 'pct_post_10d', 'sector'])
    .copy()
)

df_regimes['earn_date'] = pd.to_datetime(df_regimes['earn_date'])
df_regimes['year'] = df_regimes['earn_date'].dt.year

# Define market regimes (adjust years based on your data/market history)
# Example: Bull (2023-2025), Bear/Transition (2022), COVID (2020-2021), etc.
def assign_regime(year):
    if year &gt;= 2023:
        return 'Bull (2023+)'
    elif year == 2022:
        return 'Bear (2022)'
    elif 2020 &lt;= year &lt;= 2021:
        return 'COVID Recovery'
    elif 2018 &lt;= year &lt;= 2019:
        return 'Pre-COVID'
    else:
        return 'Earlier'

df_regimes['market_regime'] = df_regimes['year'].apply(assign_regime)

# 1. Aggregate: average 10-day returns by sector and regime/year
agg_data = (
    df_regimes
    .groupby(['sector', 'market_regime'])['pct_post_10d']
    .agg(['mean', 'count'])
    .reset_index()
    .query('count &gt;= 5')  # Filter low-sample regimes
)

# 2. Visualization: Heatmap first (quick overview)
plt.figure(figsize=(12, 8))

plt.subplot(2, 1, 1)
pivot_heatmap = agg_data.pivot(index='sector', columns='market_regime', values='mean')
sns.heatmap(pivot_heatmap, annot=True, fmt='.2f', cmap='RdYlGn', center=0, linewidths=0.5)
plt.title('Average 10-Day Post-Earnings Returns: Sector x Market Regime Heatmap')

# 3. Bar charts: By regime (stacked by sector)
plt.subplot(2, 1, 2)
regime_order = agg_data.groupby('market_regime')['mean'].mean().sort_values(ascending=False).index
sns.barplot(data=agg_data, x='market_regime', y='mean', hue='sector',
            palette='Set2', order=regime_order)
plt.title('Average 10-Day Returns by Market Regime (Colored by Sector)')
plt.ylabel('10-Day Post-Return (%)')
plt.xlabel('Market Regime')
plt.xticks(rotation=45, ha='right')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(axis='y', alpha=0.3)

plt.tight_layout()
plt.show()

# 5. Summary tables
print("Average Returns by Sector x Market Regime (min 5 obs):")
print(agg_data.pivot(index='sector', columns='market_regime', values='mean').round(2))

# 6. Ranking: Best/worst performing sectors by regime
print("\nTop/Bottom Sectors by Regime:")
for regime in regime_order:
    regime_data = agg_data[agg_data['market_regime'] == regime].sort_values('mean', ascending=False)
    print(f"\n{regime}:")
    print(regime_data[['sector', 'mean', 'count']].round(2).head(3))
</code></pre>
<img src="https://cdn-images-1.medium.com/max/1000/0*Pn2sH97R2DCpRl7u.png" alt="Heatmap and bar chart showing average 10-day post-earnings returns by sector across market regimes" style="display:block;margin:0 auto" width="600" height="400" loading="lazy">

<p>Consumer Cyclical does well during Bull (2023+) and COVID Recovery (<del>1.5–2%), but it’s less favorable in Bear 2022. Utilities turned negative before COVID. The bottom bars show the COVID era led overall gains (</del>1%), with Basic Materials and Industrials being the strongest. The recent Bull remains positive but less so. Sector leadership shifts depending on the market regime , there are no consistent winners.</p>
<h2 id="heading-what-did-we-get-out-of-all-this-storyline">What Did We Get Out of All This Storyline?</h2>
<p>Guiding you through six interconnected visualizations, we’ve turned 15 years of earnings data into a clear and engaging story.</p>
<p>Each chart responds to a specific question, yet together, they paint a bigger picture: earnings surprises influence markets, but not in the same way everywhere. Some sectors, periods, and regimes often provide consistent advantages, while others don’t.</p>
<p>Here’s what the data shows us:</p>
<ul>
<li><p><strong>No definitive alpha here, but specific opportunities are present</strong>: Markets are mostly efficient,  returns hover near zero with weak surprise correlations ,  yet Consumer Cyclicals and Materials consistently show upside potential across different timeframes and market sizes. Timing your sector choice is important.</p>
</li>
<li><p><strong>Timing windows alter the story</strong>: 3-day reactions benefit Real Estate mid-caps (+4%), while 10-day reactions shift leadership to Consumer Cyclical mega-caps (+3.2%). Don’t assume all earnings reactions occur at the same pace.</p>
</li>
<li><p><strong>Mega-tech hype isn’t eternal</strong>: The bubble chart shows AAPL/MSFT/NVDA delivered strong returns from 2020–2022, but the falling trend since then indicates waning market enthusiasm. Don’t chase yesterday’s overhyped stocks.</p>
</li>
<li><p><strong>Calendar patterns reward patience</strong>: January and October deliver slightly stronger post-earnings returns (~0.8%), while July and August tend to have lower liquidity. Combine seasonal timing with sector choices for additional gains.</p>
</li>
<li><p><strong>Market regimes change winners</strong>: Cyclicals underperformed during COVID recovery and the bull run (2023+), while Industrials peaked during the recovery. There are no universal “best performers,” only the best performers <em>for now</em>. Adjust to the regime.</p>
</li>
<li><p><strong>The actionable setup</strong>: Small to mid-cap cyclical longs in January during bull markets combine all these signals for maximum conviction ,  where sector timing, seasonality, and regime alignment converge.</p>
</li>
</ul>
<h2 id="heading-final-thoughts">Final Thoughts</h2>
<p>This exercise shows why visualization is important in finance: raw tables of returns and surprises wouldn’t reveal these patterns.</p>
<ul>
<li><p>Heatmaps instantly highlighted sector winners.</p>
</li>
<li><p>Scatter plots demonstrated the weak surprise‑return connection. Bubble charts narrated the mega‑tech story over time.</p>
</li>
<li><p>Violins unveiled the harsh truth  that markets are noisy. Cross‑sectional regime analysis reminded us that yesterday’s approach doesn’t ensure tomorrow’s returns.</p>
</li>
</ul>
<p>The effort to interpret this data pays off: you shift from passive observation to active pattern recognition. You see not just what occurred, but where and when it happened. In trading and analysis, understanding the shape of complexity often surpasses having a perfect formula.</p>
<p>Visual storytelling turns data into intuition . And intuition, based on evidence, outperforms guesswork every time.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create Boxplots and Model Data in R Using ggplot2 ]]>
                </title>
                <description>
                    <![CDATA[ In this tutorial, you’ll walk through a complete data analysis project using the HR Analytics dataset by Saad Haroon on Kaggle. You’ll start by loading and cleaning the data, then explore it visually using boxplots with ggplot2. Finally, you’ll learn... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-boxplots-and-model-data-in-r/</link>
                <guid isPermaLink="false">69693680d6f0e208b327d21c</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tiffany Mojo Omondi ]]>
                </dc:creator>
                <pubDate>Thu, 15 Jan 2026 18:48:32 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1768418231372/f36e1cca-eed9-4620-bd7c-19788d8beafe.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this tutorial, you’ll walk through a complete data analysis project using the HR Analytics dataset by Saad Haroon on Kaggle. You’ll start by loading and cleaning the data, then explore it visually using boxplots with ggplot2. Finally, you’ll learn about statistical modelling using linear regression and logistic regression in R.</p>
<p>By the end of this article, you should understand how to create boxplots in R, why they matter, and how they fit into a real-world analytics workflow.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-your-r-environment">How to Set Up Your R Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-load-and-inspect-the-data">How to Load and Inspect the Data</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-clean-and-prepare-the-data">How to Clean and Prepare the Data</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-boxplots">How to Use Boxplots</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-boxplots-with-ggplot2">How to Create Boxplots with ggplot2</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-perform-exploratory-data-analysis">How to Perform Exploratory Data Analysis</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-linear-regression-models">How to Build Linear Regression Models</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-logistic-regression-models">How to Build Logistic Regression Models</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-visualization-comes-before-modeling">Why Visualization Comes Before Modeling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites"><strong>Prerequisites</strong></h2>
<p>Before you begin, you should be comfortable with the following:</p>
<ul>
<li><p>Basic R syntax (variables, functions, data frames).</p>
</li>
<li><p>Installing and loading R packages.</p>
</li>
<li><p>Understanding what rows and columns represent in a dataset.</p>
</li>
<li><p>Very basic statistics (mean, median, distributions).</p>
</li>
</ul>
<h2 id="heading-how-to-set-up-your-r-environment">How to Set Up Your R Environment</h2>
<p>Start by installing and loading the packages you will need.</p>
<pre><code class="lang-r">install.packages(c(<span class="hljs-string">"tidyverse"</span>, <span class="hljs-string">"ggplot2"</span>))
<span class="hljs-keyword">library</span>(tidyverse)
<span class="hljs-keyword">library</span>(ggplot2)
</code></pre>
<p><code>tidyverse</code> provides tools for data manipulation and visualization. <code>ggplot2</code> is the visualization engine you will use for boxplots. Loading the libraries makes their functions available for use</p>
<h2 id="heading-how-to-load-and-inspect-the-data">How to Load and Inspect the Data</h2>
<p>First, download the <a target="_blank" href="https://www.kaggle.com/datasets/saadharoon27/hr-analytics-dataset">HR Analytics dataset by Saad Haroon from Kaggle</a>.</p>
<p>Assuming the downloaded dataset is saved as "C:/Users/johndoe/Downloads/archive (2)/HR_Analytics.csv", load the path file into R.  </p>
<p>You can view a sample of the the dataset by running the <code>head</code> function. To view the structure of the dataset, you can run the <code>str</code> function.</p>
<pre><code class="lang-r">hr &lt;- read.csv(<span class="hljs-string">"C:/Users/johndoe/Downloads/archive (2)/HR_Analytics.csv"</span>)
head(hr)
str(hr)
</code></pre>
<p>The <code>read.csv</code> function imports the dataset into R. The <code>head</code> function shows the first six rows so you can preview the data. The <code>str</code> function reveals data types, helping you spot categorical versus numeric variables early.</p>
<p>Remember that understanding your data structure early prevents errors later when plotting or modeling. Once you run the <code>head</code> function, you should see the following in your console:</p>
<p>From the <code>head</code> function, you can see:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768489839861/f304305e-b889-4e25-8315-ff24c5201681.png" alt="first-six-rows-of-a-hr-dataset-shown-in-the-r-console" class="image--center mx-auto" width="1753" height="347" loading="lazy"></p>
<h3 id="heading-structure">Structure</h3>
<ul>
<li><p>Each row represents <strong>one employee</strong>.</p>
</li>
<li><p>Each column represents a <strong>feature/variable</strong> about the employee.</p>
</li>
</ul>
<h3 id="heading-key-columns-amp-meaning">Key Columns &amp; Meaning</h3>
<ul>
<li><p><code>EmpID</code> → Employee identifier</p>
</li>
<li><p><code>Age</code> → Age in years</p>
</li>
<li><p><code>AgeGroup</code> → Age category (for example, <code>18-25</code>)</p>
</li>
<li><p><code>Attrition</code> → Whether the employee left or not (<code>Yes/No</code>)</p>
</li>
<li><p><code>BusinessTravel</code> → Travel frequency (<code>Travel_Rarely</code>, <code>Travel_Frequently</code>, <code>Non-Travel</code>)</p>
</li>
<li><p><code>Department</code> → Employee department</p>
</li>
<li><p><code>DistanceFromHome</code> → Distance from home to office (km)</p>
</li>
<li><p><code>Education</code> / <code>EducationField</code> → Level and field of education</p>
</li>
<li><p><code>EmployeeCount</code> → Usually 1 per employee (redundant)</p>
</li>
<li><p><code>Gender</code> → Male / Female</p>
</li>
<li><p><code>JobRole</code> / <code>JobSatisfaction</code> → Job title and satisfaction level</p>
</li>
<li><p><code>MonthlyIncome</code> / <code>SalarySlab</code> → Salary amount and category</p>
</li>
<li><p><code>YearsAtCompany</code> / <code>YearsInCurrentRole</code> → Experience metrics</p>
</li>
<li><p><code>OverTime</code> → Works overtime (<code>Yes/No</code>)</p>
</li>
<li><p>Other features: <code>PerformanceRating</code>, <code>TrainingTimesLastYear</code>, <code>WorkLifeBalance</code>, <code>StockOptionLevel</code>, and so on.</p>
</li>
</ul>
<h3 id="heading-data-types"><strong>Data Types</strong></h3>
<ul>
<li><p><strong>Numeric</strong> → <code>Age</code>, <code>DistanceFromHome</code>, <code>MonthlyIncome</code>, <code>YearsAtCompany</code></p>
</li>
<li><p><strong>Categorical / Character</strong> → <code>Attrition</code>, <code>Gender</code>, <code>Department</code>, <code>JobRole</code></p>
</li>
</ul>
<h3 id="heading-observations"><strong>Observations</strong></h3>
<ul>
<li><p>The dataset is tabular, like a spreadsheet.</p>
</li>
<li><p>There are multiple categorical columns</p>
</li>
<li><p>There are multiple numeric columns</p>
</li>
<li><p>Some columns seem redundant or constant; doesn’t provide useful information because of the same values (for example, <code>EmployeeCount</code>)</p>
</li>
</ul>
<p>From the <code>str</code> function, you can gather that:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768488901453/80d8cae9-d569-4749-8028-0a6e9cc128c4.png" alt="r-output-showing-structure-of-hr-dataset" class="image--center mx-auto" width="1046" height="612" loading="lazy"></p>
<p>The dataset contains 1,480 observations and 38 variables. Each row represents one employee, and each column represents a feature about that employee.</p>
<p>Each column has a name, data type, and example values. For instance, <code>Age</code> and <code>DistanceFromHome</code> are numeric (<code>int</code>), with values like 28 or 12. <code>EmpID</code> and <code>Department</code> are character strings (<code>chr</code>), with examples like Research &amp; Development or Sales. Other features include <code>JobRole</code> (Analyst, Manager) and <code>Attrition</code> (Yes/No).</p>
<p>The dataset contains mixed data types. Some columns are numeric, such as <code>MonthlyIncome</code> or <code>YearsAtCompany</code>. Some are character or categorical, like <code>Gender</code> (Male/Female) and <code>BusinessTravel</code> (Travel_Rarely, Travel_Frequently). A few columns are redundant or constant. For example, <code>EmployeeCount</code> has the same value of 1 for all rows and does not provide useful information.</p>
<h2 id="heading-how-to-clean-and-prepare-the-data">How to Clean and Prepare the Data</h2>
<p>Before visualization, you must clean your data. In order to find out what you need to clean you can investigate the data.</p>
<p>Run the <code>summary</code> function to view the statistics of the dataset. You also need to run the <code>is.na</code> function to identify missing values to be removed.</p>
<pre><code class="lang-r">summary(hr)
colSums(is.na(hr))
</code></pre>
<p>The <code>summary</code> function gives quick statistics and flags suspicious values. The <code>is.na</code> function checks for missing data. Boxplots are sensitive to extreme values, so knowing what you are working with is critical.  </p>
<p>After running the <code>summary</code> function, the following will appear in your console:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768490404469/ef3bd30d-c3c9-4cf0-9c91-80a0e56f52f5.png" alt="r-summary-output-of-hr-dataset-showing-statistical-distributions" class="image--center mx-auto" width="1778" height="495" loading="lazy"></p>
<p>This shows the basic statistics of each column. After running the <code>is.na</code> function, the following will also appear in your console:  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1768490678134/00a12c24-224e-4c8f-80ee-bc7bbd4d8ca6.png" alt="r-output-showing-missing-value-counts-per-column-in-hr-dataset" class="image--center mx-auto" width="1832" height="198" loading="lazy"></p>
<p>From this output, you can see that only <code>YearsWithCurrManager</code> has <code>57</code>, meaning that <strong>57 employees</strong> don’t have a value for this column.</p>
<p>You can drop this whole column along with the other redundant columns we saw earlier on. You can do this with the code below.</p>
<pre><code class="lang-r">hr &lt;- hr %&gt;% select(-c(EmployeeCount, Over18, StandardHours, YearsWithCurrManager))
</code></pre>
<p>To verify if the columns are gone, use this code:</p>
<pre><code class="lang-r">colnames(hr)
</code></pre>
<p>Now we need to convert important categorical variables to factors. Doing this tells R that the column has <strong>two categories</strong> (‘Yes’ and ‘No’), not continuous text.</p>
<pre><code class="lang-r">hr$Attrition &lt;- as.factor(hr$Attrition)
hr$JobRole &lt;- as.factor(hr$JobRole)
hr$Department &lt;- as.factor(hr$Department)
</code></pre>
<p>This also ensures ggplot2 treats them correctly when grouping.</p>
<h2 id="heading-how-to-use-boxplots">How to Use Boxplots</h2>
<p>A boxplot displays key features of a dataset. The median is shown by the line in the middle of the box. The interquartile range is represented by the box itself while the whiskers show the spread of the data. Outliers appear as individual points.</p>
<p>Boxplots are mostly useful when you want to compare distributions across groups, such as income by job role or age by attrition status.</p>
<p>Let’s start with a simple boxplot of monthly income.</p>
<pre><code class="lang-r">ggplot(hr, aes(y = MonthlyIncome)) +
  geom_boxplot(fill = <span class="hljs-string">"blue"</span>) +
  labs(
    title = <span class="hljs-string">"Distribution of Monthly Income"</span>,
    y = <span class="hljs-string">"Monthly Income"</span>)
</code></pre>
<p>The <code>aes</code> function tells ggplot what variable to plot. <code>geom_boxplot</code> draws the boxplot. The <code>labs</code> function labels parts of the plot drawn, that is the <code>x</code> axis, <code>y</code> axis, and the title.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766410411798/200b1c22-3b73-49f0-ba30-9b83d28f3055.png" alt="A-vertical-boxplot-showing-the-distribution-of-employee-monthly-income." class="image--center mx-auto" width="473" height="523" loading="lazy"></p>
<h2 id="heading-how-to-create-boxplots-with-ggplot2">How to Create Boxplots with ggplot2</h2>
<p>Now lets compare <code>income</code> across <code>job roles</code>.</p>
<pre><code class="lang-r">ggplot(hr, aes(x = JobRole, y = MonthlyIncome)) +
  geom_boxplot(fill = <span class="hljs-string">"lightblue"</span>) +
  theme(axis.text.x = element_text(angle = <span class="hljs-number">45</span>, hjust = <span class="hljs-number">1</span>)) +
  labs(
    title = <span class="hljs-string">"Monthly Income by Job Role"</span>,
    x = <span class="hljs-string">"Job Role"</span>,
    y = <span class="hljs-string">"Monthly Income"</span>)
</code></pre>
<p>The x aesthetic lists all the job roles. The labels are rotated to improve readability. This visualization quickly reveals income differences across roles.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766508710023/c12ca136-38bf-492e-af90-24d7021b54a4.png" alt="Multiple-boxplots-comparing-monthly-income-distributions-across-different-job-roles." class="image--center mx-auto" width="852" height="522" loading="lazy"></p>
<h2 id="heading-how-to-perform-exploratory-data-analysis-eda">How to Perform Exploratory Data Analysis (EDA)</h2>
<p>Exploratory data analysis involves using visual methods to ask questions and gain a deeper understanding of the data.</p>
<p>We can use the example of <code>Years at company</code> by <code>department</code>.</p>
<pre><code class="lang-r">ggplot(hr, aes(x = Department, y = YearsAtCompany)) +
  geom_boxplot(fill = <span class="hljs-string">"darkblue"</span>) +
  labs(
    title = <span class="hljs-string">"Years at Company by Department"</span>,
    y = <span class="hljs-string">"Years at Company"</span>)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766512679598/5e5da8cd-8fe7-4fae-bbe9-362af901b330.png" alt="Boxplots-showing-employee-tenure-across-departments." class="image--center mx-auto" width="842" height="518" loading="lazy"></p>
<h2 id="heading-how-to-build-linear-regression-models">How to Build Linear Regression Models</h2>
<p>To understand how to build linear regression models, you have to model <code>MonthlyIncome</code> using <code>YearsAtCompany</code> with the command below.</p>
<p>The first one creates the model while the second displays it.</p>
<pre><code class="lang-r">hr_lm&lt;- lm(MonthlyIncome ~ YearsAtCompany, data = hr)
summary(hr_lm)
</code></pre>
<p>Linear regression estimates how income changes with tenure. This works when the variables are numeric.</p>
<p>After running the code, your console should show you this output:</p>
<pre><code class="lang-r">Call:
lm(formula = MonthlyIncome ~ YearsAtCompany, data = hr)

Residuals:
   Min     1Q Median     3Q    Max 
 -<span class="hljs-number">9506</span>  -<span class="hljs-number">2488</span>  -<span class="hljs-number">1186</span>   <span class="hljs-number">1403</span>  <span class="hljs-number">15483</span> 

Coefficients:
               Estimate Std. Error t value Pr(&gt;|t|)    
(Intercept)     <span class="hljs-number">3734.47</span>     <span class="hljs-number">159.41</span>   <span class="hljs-number">23.43</span>   &lt;<span class="hljs-number">2e-16</span> ***
YearsAtCompany   <span class="hljs-number">395.25</span>      <span class="hljs-number">17.14</span>   <span class="hljs-number">23.07</span>   &lt;<span class="hljs-number">2e-16</span> ***
---
Signif. codes:  <span class="hljs-number">0</span> ‘***’ <span class="hljs-number">0.001</span> ‘**’ <span class="hljs-number">0.01</span> ‘*’ <span class="hljs-number">0.05</span> ‘.’ <span class="hljs-number">0.1</span> ‘ ’ <span class="hljs-number">1</span>

Residual standard error: <span class="hljs-number">4032</span> on <span class="hljs-number">1478</span> degrees of freedom
Multiple R-squared:  <span class="hljs-number">0.2647</span>,    Adjusted R-squared:  <span class="hljs-number">0.2642</span> 
<span class="hljs-literal">F</span>-statistic:   <span class="hljs-number">532</span> on <span class="hljs-number">1</span> and <span class="hljs-number">1478</span> DF,  p-value: &lt; <span class="hljs-number">2.2e-16</span>
</code></pre>
<p>Let’s interpret this model.</p>
<p>If an employee has 0 years at the company, their base monthly income is $3734.47. This comes from the intercept.</p>
<p>For each year an employee spends at the company, their monthly income is predicted to increase by $395.25.</p>
<p>Both coefficients have p-values &lt; <code>2e-16</code>. This means they are highly significant. It strongly shows that the years an employee spends at a company affects their income.</p>
<p>The model’s R-squared is <code>0.2647</code>. This means about 26% of the variation in monthly income is explained by the years an employee spends at the company. This is low, so other factors like role, department, or education likely affect income too.</p>
<p>The model’s F-statistic is <code>532</code>, with a p-value &lt; <code>2.2e-16</code>. This means the model is statistically significant overall.</p>
<p>In general, the longer an employee stays at a company, the more they earn, roughly $395 extra per year. But years at the company alone explain only about a quarter of their income. You need to consider other variables for better predictions.</p>
<h2 id="heading-how-to-build-logistic-regression-models">How to Build Logistic Regression Models</h2>
<p>You can now learn how to predict attrition. The first command generates the model while the second displays it.</p>
<pre><code class="lang-r">hr_glm&lt;- glm(
  Attrition ~ MonthlyIncome + YearsAtCompany,
  data = hr,
  family = binomial)


summary(hr_glm)
</code></pre>
<p>Your console should show this as an output when you run both commands.</p>
<pre><code class="lang-r">Call:
glm(formula = Attrition ~ MonthlyIncome + YearsAtCompany, family = binomial, 
    data = hr)

Coefficients:
                 Estimate Std. Error z value Pr(&gt;|z|)    
(Intercept)    -<span class="hljs-number">8.094e-01</span>  <span class="hljs-number">1.375e-01</span>  -<span class="hljs-number">5.886</span> <span class="hljs-number">3.96e-09</span> ***
MonthlyIncome  -<span class="hljs-number">9.449e-05</span>  <span class="hljs-number">2.302e-05</span>  -<span class="hljs-number">4.104</span> <span class="hljs-number">4.05e-05</span> ***
YearsAtCompany -<span class="hljs-number">5.047e-02</span>  <span class="hljs-number">1.792e-02</span>  -<span class="hljs-number">2.817</span>  <span class="hljs-number">0.00485</span> ** 
---
Signif. codes:  <span class="hljs-number">0</span> ‘***’ <span class="hljs-number">0.001</span> ‘**’ <span class="hljs-number">0.01</span> ‘*’ <span class="hljs-number">0.05</span> ‘.’ <span class="hljs-number">0.1</span> ‘ ’ <span class="hljs-number">1</span>

(Dispersion parameter <span class="hljs-keyword">for</span> binomial family taken to be <span class="hljs-number">1</span>)

    Null deviance: <span class="hljs-number">1305.4</span>  on <span class="hljs-number">1479</span>  degrees of freedom
Residual deviance: <span class="hljs-number">1252.5</span>  on <span class="hljs-number">1477</span>  degrees of freedom
AIC: <span class="hljs-number">1258.5</span>

Number of Fisher Scoring iterations: <span class="hljs-number">5</span>
</code></pre>
<p>Logistic regression is used for binary outcomes, that is, yes or no. It estimates probability.</p>
<p>Let’s interpret this logistic regression model. The model predicts whether an employee is likely to leave the company (Attrition) based on their <code>Monthly Income</code> and <code>Years at Company.</code></p>
<p>The intercept is <code>-0.809</code>. This is the baseline log-odds of leaving when their income and years at the company are zero.</p>
<p>The employees’ <code>Monthly Income</code> has a coefficient of <code>-0.0000945</code>. This means that as their income increases, their chance of leaving decreases slightly. An increase in income makes them less likely to quit.</p>
<p>The employees’ <code>Years at Company</code> have a coefficient of <code>-0.0505</code>. This shows that the longer they stay, the less likely they are to leave. Each additional year reduces their attrition probability.</p>
<p>All coefficients are statistically significant. <code>Monthly Income</code> and <code>Years at Company</code> both strongly affect their likelihood to stay.</p>
<p>The model’s residual deviance is <code>1252.5</code>, lower than the null deviance of <code>1305.4</code>. This means the model explains some of the variation in attrition.</p>
<p>The key takeaway is that if an employee earns more and stays longer at the company, they are less likely to leave. These factors matter, but other elements also influence attrition.</p>
<h2 id="heading-why-visualization-comes-before-modeling">Why Visualization Comes Before Modeling</h2>
<p>Boxplots help you to:</p>
<ul>
<li><p><strong>Detect outliers:</strong> Boxplots highlight extreme values that interfere with model results.</p>
</li>
<li><p><strong>Compare groups:</strong> Boxplots allow quick comparison of distributions across different categories.</p>
</li>
<li><p><strong>Form hypotheses:</strong> Visual patterns assist in identifying relationships worth testing in a model.</p>
</li>
<li><p><strong>Validate modeling assumptions:</strong> Boxplots help check distribution shape and variance before modeling.</p>
</li>
</ul>
<p>Modeling without visualization often leads to misinterpretation or false confidence.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned how to load and clean data, understand boxplots and their importance. You also learned how to use ggplot2 to compare distributions, perform exploratory data analysis (EDA), build linear and logistic regression models, and link visualization insights to modeling results.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create Scatterplots and Model Data in R Using ggplot2 ]]>
                </title>
                <description>
                    <![CDATA[ You can use R as a powerful tool for data analysis, data visualization, and statistical modelling. In this guide, you’ll learn how to load real-world data into R, visualize patterns using ggplot2, build simple linear and logistic regression models, a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-scatterplots-and-model-data-in-r/</link>
                <guid isPermaLink="false">695ba922d307c8d32fc522ea</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ R Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tiffany Mojo Omondi ]]>
                </dc:creator>
                <pubDate>Mon, 05 Jan 2026 12:05:54 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767614352690/8b993426-f193-4ff3-b5ec-dd6dda11028e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You can use R as a powerful tool for data analysis, data visualization, and statistical modelling. In this guide, you’ll learn how to load real-world data into R, visualize patterns using ggplot2, build simple linear and logistic regression models, and interpret the models. By the end, you should know how to use R for your own projects.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-your-r-environment">How to Set Up Your R Environment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-data-types-in-r">How to Use Data Types in R</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-use-data-structures-in-r">How to Use Data Structures in R</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-import-data-in-r">How to Import Data in R</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-visualize-data-with-ggplot2">How to Visualize Data with ggplot2</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-statistical-models-in-r">How to Build Statistical Models in R</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we get started, you should have the following:</p>
<ul>
<li><p>R installed (version 4.0 or higher).</p>
</li>
<li><p>RStudio installed (recommended for beginners).</p>
</li>
<li><p>Basic familiarity with programming concepts such as variables and functions.</p>
</li>
<li><p>A basic understanding of statistics (mean, correlation, regression).</p>
</li>
</ul>
<h2 id="heading-how-to-set-up-your-r-environment">How to Set Up Your R Environment</h2>
<p>Before you start working with data, load the required libraries:</p>
<pre><code class="lang-plaintext">library(tidyverse)   # Data manipulation + ggplot2
library(readxl)      # Importing Excel files
</code></pre>
<p>These load the required libraries into the R. <code>tidyverse</code> is a collection of packages used for data manipulation and visualization, including <code>ggplot2</code>. <code>readxl</code> allows you to import Excel files directly into R without converting them to CSV format first.</p>
<h2 id="heading-how-to-use-data-types-in-r">How to Use Data Types in R</h2>
<p>Knowing data types helps you avoid errors and choose the right analysis methods.</p>
<h3 id="heading-common-data-types">Common Data Types</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Data type</td><td>Example</td><td>Use case</td></tr>
</thead>
<tbody>
<tr>
<td>Numeric</td><td><code>x &lt;- 5.7</code></td><td>Measurements, prices</td></tr>
<tr>
<td>Integer</td><td><code>y &lt;- 10L</code></td><td>Counts</td></tr>
<tr>
<td>Character</td><td><code>"House prices"</code></td><td>Text labels</td></tr>
<tr>
<td>Logical</td><td><code>TRUE</code></td><td>Conditions</td></tr>
<tr>
<td>Complex</td><td><code>2 + 3i</code></td><td>Advanced math</td></tr>
</tbody>
</table>
</div><h3 id="heading-numeric-data-types-in-r">Numeric Data Types in R</h3>
<pre><code class="lang-r">price &lt;- <span class="hljs-number">199.99</span>
tax &lt;- <span class="hljs-number">16.5</span>
total_cost &lt;- price + tax
total_cost
</code></pre>
<p>Numeric data is used for continuous values such as measurements, prices, or averages. As you can see, these are numeric values that can be used in a calculation. Numeric data types allow arithmetic operations such as addition, subtraction, multiplication, and division.</p>
<h3 id="heading-integer-data-types-in-r">Integer Data Types in R</h3>
<pre><code class="lang-r">students &lt;- <span class="hljs-number">30L</span>
classes &lt;- <span class="hljs-number">4L</span>
total_students &lt;- students * classes
total_students
</code></pre>
<p>Integers are whole numbers and are commonly used for counting. The <code>L</code> tells R that the values are integers. Integers are useful when working with counts, indexes, or discrete values.</p>
<h3 id="heading-character-data-types-in-r">Character Data Types in R</h3>
<pre><code class="lang-r">course_name &lt;- <span class="hljs-string">"Data Science"</span>
university &lt;- <span class="hljs-string">"Harvard University"</span>
paste(course_name, <span class="hljs-string">"at"</span>, university)
</code></pre>
<p>Character data is used to store text such as names, labels, or categories. The example above shows how character data can be combined using the <code>paste()</code> function. This data type cannot be used in mathematical operations.</p>
<h3 id="heading-logical-data-types-in-r">Logical Data Types in R</h3>
<pre><code class="lang-r">score &lt;- <span class="hljs-number">75</span>
passed &lt;- score &gt;= <span class="hljs-number">50</span>
passed
</code></pre>
<p>Logical data represents Boolean values: <code>TRUE</code> or <code>FALSE</code>. These are commonly used in conditions and filtering. Here, R evaluates a condition and returns <code>TRUE</code> because the score meets the requirement. Logical values are essential in decision-making and control flow.</p>
<h3 id="heading-complex-data-types-in-r">Complex Data Types in R</h3>
<p>Complex numbers contain both real and imaginary parts and are mostly used in advanced mathematical computations.</p>
<pre><code class="lang-r">z &lt;- <span class="hljs-number">2</span> + <span class="hljs-number">3i</span>
Mod(z)
</code></pre>
<p>This example calculates the magnitude of a complex number. Complex data types are rarely used in basic data analysis but are available in R.</p>
<h2 id="heading-how-to-use-data-structures-in-r">How to Use Data Structures in R</h2>
<p>R stores data in different structures depending on your goals. This is important because choosing the right structure makes operations easier. Its functions behave differently depending on the structure. Moreover, structures help R understand whether your data are numbers, categories, or text.</p>
<h3 id="heading-common-data-structures-in-r">Common Data Structures in R</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Structure</td><td>Best for</td></tr>
</thead>
<tbody>
<tr>
<td>Vector</td><td>Single column of data</td></tr>
<tr>
<td>Matrix</td><td>Numeric tables</td></tr>
<tr>
<td>Data Frame</td><td>Spreadsheet-like data</td></tr>
<tr>
<td>List</td><td>Mixed objects</td></tr>
</tbody>
</table>
</div><pre><code class="lang-r">vec &lt;- c(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>)
mat &lt;- matrix(<span class="hljs-number">1</span>:<span class="hljs-number">9</span>, nrow = <span class="hljs-number">3</span>)
df &lt;- data.frame(Name = c(<span class="hljs-string">"Car"</span>, <span class="hljs-string">"Bike"</span>), Number = c(<span class="hljs-number">110</span>, <span class="hljs-number">95</span>))
lst &lt;- list(numbers = vec, matrix = mat, info = df)

str(lst) <span class="hljs-comment">##shows the structure of the list</span>
</code></pre>
<p>Lets understand the code above:</p>
<ul>
<li><p><code>vec</code> is a vector that stores a single type of data.</p>
</li>
<li><p><code>mat</code> is a matrix that organizes numeric values into rows and columns.</p>
</li>
<li><p><code>df</code> is a data frame that works like a spreadsheet, allowing different data types in each column.</p>
</li>
<li><p><code>lst</code> is a list that stores multiple objects of different types.</p>
</li>
<li><p>The <code>str()</code> function shows how these objects are nested within the list.</p>
</li>
</ul>
<h2 id="heading-how-to-import-data-in-r"><strong>How to Import Data in R</strong></h2>
<p>Now you can start working with your real data. You can import files into R by copying the path of the CSV or Excel file and pasting it into the command.</p>
<p><strong>For Windows:</strong> Replace single backward slashes / with either double backward slashes \ or single forward slashes \. For example:</p>
<pre><code class="lang-r">
Windows
```r
data &lt;- read.csv("C:\\Users\\file\\Documents\\data.csv") or 
data &lt;- read.csv("C:/Users/file/Documents/data.csv")
</code></pre>
<p><strong>For macOS/Linux:</strong> Single forward slashes work fine:</p>
<pre><code class="lang-r">macOS/Linux
data &lt;- read.csv(<span class="hljs-string">"/Users/file/Documents/data.csv"</span>)
</code></pre>
<h3 id="heading-how-to-read-a-csv-and-excel-file"><strong>How to Read a CSV and Excel File</strong></h3>
<pre><code class="lang-r"><span class="hljs-comment">#Import CSV file </span>
data &lt;- read.csv(<span class="hljs-string">"C:/Users/file/Documents/data.csv"</span>) or data &lt;- read.csv(<span class="hljs-string">"C:\\Users\\file\\Documents\\data.csv"</span>) <span class="hljs-comment">## for windows</span>

head(data.csv)
</code></pre>
<p>You can import a CSV file into R using a file path. On Windows systems, file paths can use either double forward slashes (<code>//</code>) or double backslashes (<code>\</code>). The imported data is stored as a data frame named data.</p>
<pre><code class="lang-r">data_excel &lt;- read_excel(<span class="hljs-string">"C:/Users/file/Documents/HR Data Set.xlsx"</span>)
head(data_excel)
</code></pre>
<p>You can import an Excel file into R using the code <code>read_excel()</code> function from the <code>readxl</code> package. The <code>head()</code> function is then used to preview the first few rows of the dataset.</p>
<p>Use the following commands to understand your data:</p>
<pre><code class="lang-r">str(data.csv)
summary(data.csv)

str(data_excel)
summary(data_excel)
</code></pre>
<p><code>str()</code> shows the structure of the dataset, including column names and data types. <code>summary()</code> provides descriptive statistics such as minimum, maximum, mean, and quartiles for each variable. Together, these functions help you understand the dataset before analysis.</p>
<h2 id="heading-how-to-visualize-data-with-ggplot2"><strong>How to Visualize Data with ggplot2</strong></h2>
<p>Visualization helps you spot patterns before you build models.</p>
<h3 id="heading-scatter-plot-example"><strong>Scatter Plot Example</strong></h3>
<p>We’ll use the built-in <code>mtcars</code> dataset in R. First, load the library to make it available for use:</p>
<pre><code class="lang-r">data(mtcars)
<span class="hljs-keyword">library</span>(ggplot2)

ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
  geom_point(size = <span class="hljs-number">3</span>,color=<span class="hljs-string">"blue"</span>) +geom_smooth(method=<span class="hljs-string">"lm"</span>,color=<span class="hljs-string">"red"</span>,se=<span class="hljs-literal">FALSE</span>)+
  labs(
    title = <span class="hljs-string">"Fuel Efficiency by Weight and Cylinders"</span>,
    x = <span class="hljs-string">"Weight (1000 lbs)"</span>,
    y = <span class="hljs-string">"Miles per Gallon"</span>
  ) +
  theme_minimal()
</code></pre>
<p>Let us break down the code to grasp it fully:</p>
<ul>
<li><p><code>data(mtcars)</code> loads the built-in <code>mtcars</code> dataset, which contains information about car specifications.</p>
</li>
<li><p><code>library(ggplot2)</code> enables data visualization.</p>
</li>
<li><p><code>aes()</code> was used to insert your dataset columns, which defines the <code>x</code> and <code>y</code> values.</p>
</li>
<li><p><code>aes()</code> was used to design the plot outside. For example, set point <code>size</code> and <code>color</code>.</p>
</li>
<li><p><code>geom_smooth()</code> wass used to add a trend line with. Here, we use <code>method="lm"</code> to fit a linear regression line. The <code>se=TRUE/FALSE</code> option controls the shading for confidence intervals. Use <code>TRUE</code> if you want the shading and <code>FALSE</code> if you don’t.</p>
</li>
<li><p><code>labs()</code> was used for label the plot and set the <code>title</code>, <code>x</code>-axis, and <code>y</code>-axis labels.</p>
</li>
<li><p>Finally, we set the plot theme using <code>theme_minimal()</code>.</p>
</li>
</ul>
<p>Running this code will produce a scatterplot showing fuel efficiency by weight and cylinders. The plot should look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765914755069/8921e803-7fa6-4705-802c-23ff8918bee5.png" alt="Scatterplot of mpg against vehicle weight with regression line" class="image--center mx-auto" width="912" height="527" loading="lazy"></p>
<h2 id="heading-how-to-build-statistical-models-in-r"><strong>How to Build Statistical Models in R</strong></h2>
<h3 id="heading-linear-regression"><strong>Linear Regression</strong></h3>
<p>You can use linear regression for continuous outcomes, basically to predict numerical values. For example, to predict a car’s miles per gallon (<code>mpg</code>) based on weight (<code>wt</code>) and horsepower (<code>hp</code>), you can use this formula:</p>
<pre><code class="lang-r">lm_model &lt;- lm(mpg ~ wt + hp, data = mtcars)
summary(lm_model)
</code></pre>
<p>But what does it mean?</p>
<ul>
<li><p><code>lm()</code> stands for linear model.</p>
</li>
<li><p>The response variable is <code>mpg</code>. This is the outcome you want to predict.</p>
</li>
<li><p>Predictor variables are <code>wt</code> and <code>hp</code>. These explain changes in the response.</p>
</li>
</ul>
<p>Once you run the model, it should look like this in your console:</p>
<pre><code class="lang-r">Call:
lm(formula = mpg ~ wt + hp, data = mtcars)

Residuals:
   Min     1Q Median     3Q    Max 
-<span class="hljs-number">3.941</span> -<span class="hljs-number">1.600</span> -<span class="hljs-number">0.182</span>  <span class="hljs-number">1.050</span>  <span class="hljs-number">5.854</span> 

Coefficients:
            Estimate Std. Error t value Pr(&gt;|t|)    
(Intercept) <span class="hljs-number">37.22727</span>    <span class="hljs-number">1.59879</span>  <span class="hljs-number">23.285</span>  &lt; <span class="hljs-number">2e-16</span> ***
wt          -<span class="hljs-number">3.87783</span>    <span class="hljs-number">0.63273</span>  -<span class="hljs-number">6.129</span> <span class="hljs-number">1.12e-06</span> ***
hp          -<span class="hljs-number">0.03177</span>    <span class="hljs-number">0.00903</span>  -<span class="hljs-number">3.519</span>  <span class="hljs-number">0.00145</span> ** 
---
Signif. codes:  <span class="hljs-number">0</span> ‘***’ <span class="hljs-number">0.001</span> ‘**’ <span class="hljs-number">0.01</span> ‘*’ <span class="hljs-number">0.05</span> ‘.’ <span class="hljs-number">0.1</span> ‘ ’ <span class="hljs-number">1</span>

Residual standard error: <span class="hljs-number">2.593</span> on <span class="hljs-number">29</span> degrees of freedom
Multiple R-squared:  <span class="hljs-number">0.8268</span>,    Adjusted R-squared:  <span class="hljs-number">0.8148</span> 
<span class="hljs-literal">F</span>-statistic: <span class="hljs-number">69.21</span> on <span class="hljs-number">2</span> and <span class="hljs-number">29</span> DF,  p-value: <span class="hljs-number">9.109e-12</span>
</code></pre>
<p>Here’s an interpretation of the linear regression model:</p>
<ul>
<li><p>You created a model on miles per gallon (<code>mpg</code>) based on weight (<code>wt</code>) and horsepower (<code>hp</code>).</p>
</li>
<li><p>The intercept <code>37.227</code> is the <code>mpg</code> when <code>wt=0</code> and <code>hp=0</code>. In other words, when all other variables are <code>0</code>, the base <code>mpg</code> is <code>37.227</code>. The intercept is always the baseline value of the outcome when all other variables in the model are zero.</p>
</li>
<li><p>With every additional unit of weight (1000lbs), the <code>mpg</code> decreases by <code>3.877</code>. This variable affects the <code>mpg</code> greatly as seen with the <code>p-value</code>. The <code>p-value</code> is &lt;0.001, hence strong and statistically significant.</p>
</li>
<li><p>With every additional unit of horsepower, the <code>mpg</code> decreases by <code>0.031</code>. This variable affects the <code>mpg</code>, as seen with the <code>p-value</code> being <code>0.00145</code>, which is <strong>less than 0.01</strong>, indicating that horsepower is a statistically significant predictor of <code>mpg</code>, although its effect is smaller compared to vehicle weight.</p>
</li>
</ul>
<h3 id="heading-does-the-model-fit-the-data-and-why">Does the Model Fit the Data, and Why?</h3>
<p>The R-squared value shows that 83% of the variation in <code>mpg</code> is explained by weight and horsepower.</p>
<p><strong>Summary of the interpretation</strong>: Cars that are heavier and with more horsepower have lower fuel efficiency. These two variables explain most of the variation in <code>mpg</code> in the dataset.</p>
<h3 id="heading-logistic-regression"><strong>Logistic Regression</strong></h3>
<p>You can use logistic regression for binary outcomes, like yes/no questions. For example, predicting whether a vehicle is automatic or manual based on weight and horsepower.</p>
<pre><code class="lang-r">glm_model &lt;- glm(am ~ wt + hp, data = mtcars, family = binomial)
summary(glm_model)
</code></pre>
<p>Lets understand the code</p>
<ul>
<li><p><code>glm()</code> stands for generalized linear model.</p>
</li>
<li><p>The <code>family=binomial</code> option tells R to run logistic regression.</p>
</li>
<li><p>The response variable <code>am</code> indicates transmission type: 0 = automatic, 1 = manual.</p>
</li>
<li><p>Predictor variables remain <code>wt</code> and <code>hp</code>.</p>
</li>
</ul>
<p>Once you run the model, it should look like this in your console:</p>
<pre><code class="lang-r">Call:
glm(formula = am ~ wt + hp, family = binomial, data = mtcars)

Coefficients:
            Estimate Std. Error z value Pr(&gt;|z|)   
(Intercept) <span class="hljs-number">18.86630</span>    <span class="hljs-number">7.44356</span>   <span class="hljs-number">2.535</span>  <span class="hljs-number">0.01126</span> * 
wt          -<span class="hljs-number">8.08348</span>    <span class="hljs-number">3.06868</span>  -<span class="hljs-number">2.634</span>  <span class="hljs-number">0.00843</span> **
hp           <span class="hljs-number">0.03626</span>    <span class="hljs-number">0.01773</span>   <span class="hljs-number">2.044</span>  <span class="hljs-number">0.04091</span> * 
---
Signif. codes:  <span class="hljs-number">0</span> ‘***’ <span class="hljs-number">0.001</span> ‘**’ <span class="hljs-number">0.01</span> ‘*’ <span class="hljs-number">0.05</span> ‘.’ <span class="hljs-number">0.1</span> ‘ ’ <span class="hljs-number">1</span>

(Dispersion parameter <span class="hljs-keyword">for</span> binomial family taken to be <span class="hljs-number">1</span>)

    Null deviance: <span class="hljs-number">43.230</span>  on <span class="hljs-number">31</span>  degrees of freedom
Residual deviance: <span class="hljs-number">10.059</span>  on <span class="hljs-number">29</span>  degrees of freedom
AIC: <span class="hljs-number">16.059</span>

Number of Fisher Scoring iterations: <span class="hljs-number">8</span>
</code></pre>
<p>Here’s an interpreting of the logistic regression model:</p>
<ul>
<li><p>The intercept <code>18.866</code> represents the log-odds of a car being manual when <code>wt=0</code> and <code>hp=0</code>. In other words, when all other variables are <code>0</code>, the baseline log-odds of the outcome is <code>18.866</code>. The intercept is always the baseline value of the outcome when all other variables in the model are zero.</p>
</li>
<li><p>With every additional unit of weight (1000 lbs), the log odds of the car being manual decrease by <code>8.083</code>. This variable strongly affects the probability of the car being manual, as seen with the <code>p-value</code> being <code>0.008</code>, which is statistically significant.</p>
</li>
<li><p>With every additional unit of horsepower, the log odds of the car being manual increase by <code>0.036</code>. This variable also affects the probability of being manual, as seen with the <code>p-value</code> being <code>0.041</code>, which is statistically significant.</p>
</li>
</ul>
<p><strong>Summary of the interpretation</strong>: Heavier cars are more likely to be automatic, while higher horsepower slightly increases the chance of being manual. Together, <code>wt</code> and <code>hp</code> explain a large portion of transmission type variation.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this tutorial, you learned how to use R for data analysis, visualization, and statistical modeling, and how to set up your R environment and work with basic data types and data structures.</p>
<p>This article also showed you how to import real-world datasets and explore them using summary statistics. This should help you understand your data before analysis.</p>
<p>Using ggplot2, we visualized the relationships and identified patterns. We built and interpreted a linear regression model to predict fuel efficiency and a logistic regression model to classify transmission type.</p>
<p>You also learned how to interpret coefficients, p-values, and goodness-of-fit measures.</p>
<p>With these skills, you can load datasets, visualize trends, and build simple predictive models in R. Keep practicing with new datasets and explore more advanced techniques to improve your data analysis skills.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Forecast Time Series Data with Python Darts ]]>
                </title>
                <description>
                    <![CDATA[ When analyzing time series data, your main objective is to consider the period during which the data is collected and how your variable of interest changes over time. There are various libraries for time series forecasting in Python, and Darts is one... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-forecast-time-series-data-with-python-darts/</link>
                <guid isPermaLink="false">68e40c4dd441014d7e52dc0d</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adejumo Ridwan Suleiman ]]>
                </dc:creator>
                <pubDate>Mon, 06 Oct 2025 18:37:01 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759775700643/6f7d18b3-2060-4708-b56e-3450acf58546.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When analyzing time series data, your main objective is to consider the period during which the data is collected and how your variable of interest changes over time.</p>
<p>There are various libraries for time series forecasting in Python, and <a target="_blank" href="https://unit8co.github.io/darts/">Darts</a> is one of them. Unlike other forecasting libraries, Darts is a high-level forecasting library with algorithms to handle various time series data, regardless of the kind of trend they portray.</p>
<p>This tutorial will walk you through how you can forecast time series data using Python Darts. This will help you make meaningful insights whenever you come across time series data such as stock prices, weather measurements, and so on.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-python-darts">What is Python Darts?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-set-up-dependencies">How to Set Up Dependencies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-dataset">Understanding the Dataset</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-prepare-the-data-for-darts">How to Prepare the Data for Darts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-a-forecasting-model">How to Build a Forecasting Model</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-classical-model">Classical Model</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-machine-learning-models">Machine Learning Models</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-forecast-with-deep-learning-models">How to Forecast with Deep Learning models</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-model-evaluation">Model Evaluation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-backtesting">BackTesting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-hyper-parameter-tuning">Hyper Parameter Tuning</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-use-cases">Real-World Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-best-practices">Best Practices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-what-is-python-darts">What is Python Darts?</h2>
<p>Python Darts is an open-source library for time series analysis and forecasting. It has various models ranging from statistical time series models like ARIMA, and SARIMA, to machine learning and deep learning models like Prophet, and LSTM.</p>
<p>It has various algorithms for handling missing imputations in time series data, and can handle time series problems ranging from univariate, multivariate to hierarchical time series.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before we proceed, you will need to have the following:</p>
<ul>
<li><p>Python 3.9+ installed.</p>
</li>
<li><p>Jupyter Notebook, Google Colab, or Positron to run your code.</p>
</li>
<li><p>Download the <a target="_blank" href="https://www.kaggle.com/datasets/kalilurrahman/netflix-stock-data-live-and-latest">Netflix stock data</a>.</p>
</li>
<li><p>Have the following libraries installed:</p>
<ul>
<li><p><code>darts</code> for time series analysis</p>
</li>
<li><p><code>pandas</code> for data wrangling</p>
</li>
<li><p><code>matplotlib</code> for data visualization.</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-how-to-set-up-dependencies">How to Set Up Dependencies</h2>
<p>Load the following libraries.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> darts
<span class="hljs-keyword">from</span> darts <span class="hljs-keyword">import</span> TimeSeries
<span class="hljs-keyword">from</span> darts.models <span class="hljs-keyword">import</span> ARIMA
<span class="hljs-keyword">from</span> darts.models <span class="hljs-keyword">import</span> RegressionModel
<span class="hljs-keyword">from</span> lightgbm <span class="hljs-keyword">import</span> LGBMRegressor
<span class="hljs-keyword">from</span> darts.models <span class="hljs-keyword">import</span> RNNModel
<span class="hljs-keyword">from</span> darts.metrics <span class="hljs-keyword">import</span> mape
<span class="hljs-keyword">import</span> itertools
</code></pre>
<h2 id="heading-understanding-the-dataset">Understanding the Dataset</h2>
<p>The Netflix stock data contains historical daily prices of Netflix stock from the year 2002 till date.</p>
<p>Load the data and have a preview of it.</p>
<pre><code class="lang-python">netflix = pd.read_csv(<span class="hljs-string">"/kaggle/input/netflix-stock-data-live-and-latest/Netflix_stock_history.csv"</span>)
netflix[<span class="hljs-string">'Date'</span>] = pd.to_datetime(netflix[<span class="hljs-string">'Date'</span>], utc=<span class="hljs-literal">True</span>).dt.tz_convert(<span class="hljs-literal">None</span>)
netflix.head()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757927775470/2d4b542c-3869-40c5-844c-a733b5cc4bea.png" alt="Image showing the first 5 rows of the Netflix stock data" class="image--center mx-auto" width="1059" height="484" loading="lazy"></p>
<p>To forecast a time series data, we need a <code>Date</code> column, which we already have, and then the variable of interest. We have several variables, but for this tutorial, we will focus on the <code>Close</code> variable of Netflix stocks.</p>
<p>Let’s visualize the data to see how Netflix closing price performed over the years.</p>
<pre><code class="lang-python">netflix.plot(x=<span class="hljs-string">'Date'</span>, y=<span class="hljs-string">'Close'</span>, figsize=(<span class="hljs-number">10</span>,<span class="hljs-number">5</span>))
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757928810807/75a1fa13-4f2e-4bdd-a539-5eaf2663843a.png" alt="Image showing a line chart of Netflix stock data from 2000 to date" class="image--center mx-auto" width="1036" height="517" loading="lazy"></p>
<p>From the chart above, you can see that Netflix stock showed exponential growth in recent years. This means that the data is non-stationary, implying that there are no consistent changes over time.</p>
<p>There are a lot of random fluctuations in the data, which might make it difficult to forecast. Such data usually requires advanced models to handle the various fluctuations or noise present in the data.</p>
<h2 id="heading-how-to-prepare-the-data-for-darts"><strong>How to Prepare the Data for Darts</strong></h2>
<p>Before preparing the data for Darts, you need to take note of few things.</p>
<p>First of all, if you look at our data preview earlier on, you would notice that it is recorded daily, we also need to fill in missing dates.</p>
<p>Copy and paste this code into your notebook.</p>
<pre><code class="lang-python">start = netflix[<span class="hljs-string">'Date'</span>].min()
end = netflix[<span class="hljs-string">'Date'</span>].max()

netflix = (
    netflix.set_index(<span class="hljs-string">'Date'</span>)
           .reindex(pd.date_range(start=start, end=end, freq=<span class="hljs-string">'D'</span>))
           .ffill()
           .reset_index()
           .rename(columns={<span class="hljs-string">'index'</span>: <span class="hljs-string">'Date'</span>})
)
netflix.head()
</code></pre>
<p>The code above ensures the <code>netflix</code> dataset has a continuous daily time series by filling in missing dates.</p>
<p>First, it finds the earliest <code>start</code> and latest <code>end</code> dates in the data, then creates a full daily date range between them.</p>
<p>By setting the <code>Date</code> column as the index and using <code>.reindex()</code> method, it inserts rows for any missing dates, which initially contain <code>NaN</code>.</p>
<p>The <code>.ffill()</code> method (forward fill) replaces these gaps by carrying forward the last known value, which is common for stock data when markets are closed, such as weekends.</p>
<p>Finally, the index is reset, and the column is renamed back to <code>Date</code>, producing a clean, continuous dataset ready for time series analysis.</p>
<p>Next, we need to convert the data to a Darts <code>Timeseries</code> object to make it usable by the Darts library.</p>
<pre><code class="lang-python"> = TimeSeries.from_dataframe(
    netflix,
    time_col=<span class="hljs-string">'Date'</span>,
    value_cols=<span class="hljs-string">'Close'</span>,
)
</code></pre>
<p>The code above converts the <code>netflix</code> DataFrame into a Darts <code>TimeSeries</code> object, which is optimized for time series modeling and forecasting.</p>
<p>It takes the <code>Date</code> column (<code>time_col='Date'</code>) as the timeline and the <code>Close</code> column (<code>value_cols='Close'</code>) as the target values to forecast.</p>
<p>The resulting <code>series</code> object is now structured for use with Darts’ advanced forecasting models like ARIMA, Prophet, RNNs, and other time series algorithms.</p>
<p>Just like you would with any other machine learning model, you need to split your data into a training set and a validation set.</p>
<pre><code class="lang-python">train, val = series.split_before(<span class="hljs-number">0.8</span>)
</code></pre>
<h2 id="heading-how-to-build-a-forecasting-model"><strong>How to Build a Forecasting Model</strong></h2>
<p>When building a forecasting model, you have the privilege of trying various models and picking the best-performing one.</p>
<p>The Darts library has various algorithms for time series analysis, from popular statistical algorithms like the Auto Regressive Integrated Moving Average (ARIMA) and Moving Average (MA) models, to machine learning and deep learning algorithms like Prophet and Long Short Term Memory (LSTM).</p>
<p>Note, I will only demonstrate how these algorithms work - it’s not necessary that we get accurate model metrics. But with further feature engineering, hyperparameter tuning, and cross-validation, you can get good results on your own.</p>
<h3 id="heading-classical-model">Classical Model</h3>
<p>The classical mode is the use of statistical time series models such as ARIMA. ARIMA is made up of the following components:</p>
<ul>
<li><p><strong>AR (AutoRegressive):</strong> Predict past values by looking at previous ones.</p>
</li>
<li><p><strong>I (Integrated):</strong> Remove trends by focusing on changes instead of raw values.</p>
</li>
<li><p><strong>MA (Moving Average):</strong> Learn from the errors of past predictions to improve accuracy.</p>
</li>
</ul>
<p>Run the code below in your notebook to fit an ARIMA model.</p>
<pre><code class="lang-python">arima_model = ARIMA()
arima_model.fit(train)
arima_forecast = arima_model.predict(len(val))
</code></pre>
<p>To visualize the forecast by the model, call the <code>.plot()</code> method on the <code>forecast</code> object.</p>
<pre><code class="lang-python">series.plot(label=<span class="hljs-string">'actual'</span>)
arima_forecast.plot(label=<span class="hljs-string">'forecast'</span>)
plt.legend()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758028284156/a40f2341-cfc6-4a9f-8297-e0511c2bb254.png" alt="Image showing the ARIMA model forecast of netflix stock " class="image--center mx-auto" width="820" height="646" loading="lazy"></p>
<p>You can improve the model by adding some additional parameters to the <code>ARIMA()</code> class. You can read more about that in the <a target="_blank" href="https://unit8co.github.io/darts/generated_api/darts.models.forecasting.arima.html">Darts documentation</a>.</p>
<h3 id="heading-machine-learning-models"><strong>Machine Learning Models</strong></h3>
<p>Classical models like ARIMA can’t handle non-linear data. Machine learning models fill this gap. We’ll use the LightGBM model as an example.</p>
<p>The LightGBM is a machine learning model that builds models sequentially based on decision trees. It adds new decision trees that correct the errors of previous trees.</p>
<p>Although it was not designed to handle time series, with some feature engineering such as lags, rolling statistics, and seasonal indicators, you can make it learn patterns from time series data.</p>
<p>Run this code on your notebook to fit a LightGBM model on the Netflix data.</p>
<pre><code class="lang-python">lgbm = LGBMRegressor()
lgbm_model = RegressionModel(lags=<span class="hljs-number">12</span>, model=lgbm)
lgbm_model.fit(train)
lgbm_forecast = lgbm_model.predict(len(val))
</code></pre>
<p>From the code above, the <code>lag</code> argument is set to <code>12</code>, which is the value of the Netflix stock price for 12 days before a selected day.</p>
<p>Let’s have a view of the forecast by running the following code.</p>
<pre><code class="lang-python">series.plot(label=<span class="hljs-string">'actual'</span>)
lgbm_forecast.plot(label=<span class="hljs-string">'forecast'</span>)
plt.legend()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758029933172/54f34a69-4f6b-4b44-85ab-d0b45931d701.png" alt="Image showing the LightGBM model forecast of netflix stock " class="image--center mx-auto" width="813" height="631" loading="lazy"></p>
<p>You can read more about tuning the LightGBM model from the <a target="_blank" href="https://unit8co.github.io/darts/generated_api/darts.models.forecasting.lgbm.html">Darts documentation</a> to improve the above model.</p>
<h3 id="heading-how-to-forecast-with-deep-learning-models"><strong>How to Forecast with Deep Learning models</strong></h3>
<p>You can go for deep learning models designed for time series, such as LSTM, a kind of Recurrent Neural Network (RNN) designed to capture long-term dependencies in sequential data.</p>
<p>Run the following code to build the LSTM model.</p>
<pre><code class="lang-python">lstm_model = RNNModel(model=<span class="hljs-string">'LSTM'</span>, input_chunk_length=<span class="hljs-number">12</span>, output_chunk_length=<span class="hljs-number">6</span>, n_epochs=<span class="hljs-number">100</span>)
lstm_model.fit(train)
lstm_forecast = rnn_model.predict(len(val))
</code></pre>
<p>Now let’s visualize the forecast and see what we have.</p>
<pre><code class="lang-python">series.plot(label=<span class="hljs-string">'actual'</span>)
lstm_forecast.plot(label=<span class="hljs-string">'forecast'</span>)
plt.legend()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758116174578/2ff80218-2254-452d-8d4c-2f85c61612de.png" alt="Image showing the LSTM model forecast of Netflix stock " class="image--center mx-auto" width="682" height="526" loading="lazy"></p>
<p>You can look up the <a target="_blank" href="https://unit8co.github.io/darts/generated_api/darts.models.forecasting.rnn_model.html">Darts documentation</a> to improve the model and check out other deep learning models also.</p>
<h2 id="heading-model-evaluation"><strong>Model Evaluation</strong></h2>
<p>Now that you have three models, you need to select the best one among them using the Mean Absolute Percentage Error (MAPE).</p>
<p>It expresses the average absolute error as a percentage of the actual values, and the closer your value is to 0, the better your model.</p>
<p>Run the following to print the MAPE of each respective model.</p>
<pre><code class="lang-python">arima_error = mape(val, arima_forecast)
print(<span class="hljs-string">"MAPE:"</span>, arima_error)
lgbm_error = mape(val, lgbm_forecast)
print(<span class="hljs-string">"MAPE:"</span>, lgbm_error)
lstm_error = mape(val, lstm_forecast)
print(<span class="hljs-string">"MAPE:"</span>, lstm_error)
</code></pre>
<pre><code class="lang-bash">&gt; MAPE: 38.33262525601514
&gt; MAPE: 39.00241495209449
&gt; MAPE: 38.82910057097827
</code></pre>
<p>The model with the lowest MAPE is the ARIMA model with approximately 38.33, which means it’s our best-performing model.</p>
<h2 id="heading-backtesting">BackTesting</h2>
<p>Darts has a feature called backtesting that allows you to evaluate your models based on historical data, using a rolling forecast.</p>
<p>Backtesting is like a time machine for forecasting. It simulates how your model would have performed in the past by repeatedly training it on historical data up to a certain point, making a prediction for the next step, then moving forward, and repeating the process.</p>
<p>This rolling evaluation simulates how the model would behave in real-world conditions, where future data is unknown, helping you measure its consistency and reliability over time, instead of just testing it once on a single validation set.</p>
<p>Since the ARIMA model is currently our best-performing model, run the code below to implement backtesting.</p>
<pre><code class="lang-python">
<span class="hljs-comment"># Perform backtesting on the training + validation series</span>
backtest_series = train.concatenate(val)

<span class="hljs-comment"># Backtest</span>
backtest_forecast = arima_model.historical_forecasts(
    series=backtest_series,
    start=<span class="hljs-number">0.8</span>,          <span class="hljs-comment"># fraction of the series to start forecasting from</span>
    forecast_horizon=len(val),
    stride=<span class="hljs-number">1</span>,           <span class="hljs-comment"># step size of rolling forecast</span>
    retrain=<span class="hljs-literal">True</span>,       <span class="hljs-comment"># retrain the model at each step</span>
    verbose=<span class="hljs-literal">True</span>
)

<span class="hljs-comment"># Compute metrics</span>
error = mape(backtest_series[-len(val):], backtest_forecast)
print(<span class="hljs-string">f"MAPE: <span class="hljs-subst">{error:<span class="hljs-number">.2</span>f}</span>%"</span>)
</code></pre>
<pre><code class="lang-bash">&gt; historical forecasts: 100%|██████████| 1/1 [00:02&lt;00:00,  2.69s/it]MAPE: 47.27%
</code></pre>
<p>In the code above,</p>
<ul>
<li><p>The <code>start</code> argument defines where to start backtesting, which in this case is the last 20% series of the data.</p>
</li>
<li><p>The <code>forecast_horizon</code> is how many steps ahead to forecast at each point.</p>
</li>
<li><p>The <code>stride</code> is how frequently to retrain/forecast.</p>
</li>
<li><p>The <code>retrain=True</code> refits the model at each step for realistic evaluation.</p>
</li>
</ul>
<p>You can see that the MAPE, after backtesting, is higher because backtesting is more realistic, and it is more difficult to achieve a lower MAPE.</p>
<p>On your own, you can try to replicate backtesting for the other models.</p>
<h2 id="heading-hyper-parameter-tuning">Hyper Parameter Tuning</h2>
<p>The ARIMA model has three hyperparameter:</p>
<ul>
<li><p><code>p</code> which is the AR order</p>
</li>
<li><p><code>d</code> which is the differencing order</p>
</li>
<li><p><code>q</code> which is the MA order</p>
</li>
</ul>
<p>You can use either grid or random search to tune your ARIMA model in Darts.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Define possible values</span>
p_values = range(<span class="hljs-number">0</span>, <span class="hljs-number">4</span>)
d_values = range(<span class="hljs-number">0</span>, <span class="hljs-number">3</span>)
q_values = range(<span class="hljs-number">0</span>, <span class="hljs-number">4</span>)

best_mape = float(<span class="hljs-string">'inf'</span>)
best_params = <span class="hljs-literal">None</span>

<span class="hljs-keyword">for</span> p, d, q <span class="hljs-keyword">in</span> itertools.product(p_values, d_values, q_values):
    <span class="hljs-keyword">try</span>:
        arima_model = ARIMA(p=p, d=d, q=q)
        arima_model.fit(train)
        arima_forecast = arima_model.predict(len(val))
        arima_error = mape(val, arima_forecast)
        <span class="hljs-keyword">if</span> arima_error &lt; best_mape:
            best_mape = arima_error
            best_params = (p, d, q)
    <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e:
        <span class="hljs-comment"># Some combinations may fail</span>
        <span class="hljs-keyword">continue</span>

print(<span class="hljs-string">f"Best ARIMA params: p=<span class="hljs-subst">{best_params[<span class="hljs-number">0</span>]}</span>, d=<span class="hljs-subst">{best_params[<span class="hljs-number">1</span>]}</span>, q=<span class="hljs-subst">{best_params[<span class="hljs-number">2</span>]}</span> with MAPE=<span class="hljs-subst">{best_mape:<span class="hljs-number">.2</span>f}</span>%"</span>)
</code></pre>
<pre><code class="lang-bash">&gt; Best ARIMA params: p=2, d=0, q=3 with MAPE=35.95%
</code></pre>
<p>In the above code, you define a range of possible values for the <code>p</code>, <code>d</code> , and <code>q</code> components, iterating over each combination of those values and choosing the model with the best MAPE among them.</p>
<p>Note that each model has its specific parameter you would have to tune, and you will need to check <a target="_blank" href="https://unit8co.github.io/darts/userguide/hyperparameter_optimization.html">the Darts documentation</a> for the hyperparameters of other models.</p>
<h2 id="heading-real-world-use-cases"><strong>Real-World Use Cases</strong></h2>
<p>Forecasting time series data has a lot of real-world applications, some of which are:</p>
<ul>
<li><p><strong>Stock price prediction:</strong> Like the dataset used in this tutorial, forecasting is used in finance for stock price prediction, allowing investors to manage risk.</p>
</li>
<li><p><strong>Demand forecasting for inventory:</strong> As a store owner, you can forecast product demands based on past sales of a product. This lets you know products that are in high demand.</p>
</li>
<li><p><strong>Energy consumption prediction:</strong> Governments, industries, and consumers can plan and manage energy production, distribution, and consumption efficiently, based on data from past usage. This helps to avoid blackouts and wastage, enabling them to prepare ahead.</p>
</li>
</ul>
<h2 id="heading-best-practices">Best Practices</h2>
<ul>
<li><p><strong>Always visualize residuals:</strong> Residuals are the difference between forecasted values and actual values. You must visualize them to detect outliers and unusual events.</p>
</li>
<li><p><strong>Perform proper backtesting:</strong> Backtesting lets you see a more realistic model, subjected to various changes that can occur in real life. When you backtest all your models, you end up getting a model that performs well when forecasting.</p>
</li>
<li><p><strong>Avoid data leakage:</strong> Do not train your models on validation sets to avoid bias, and always use cross-validation where necessary.</p>
</li>
<li><p><strong>Use domain knowledge for feature engineering:</strong> Ensure you understand the data you are working with. This comes in handy in feature engineering, when you want to come up with new features to help your forecasting model, especially in multivariate time series forecasting.</p>
</li>
</ul>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>This tutorial is more like an overview, especially if you are new to time series, but you can build a lot just from what you have learned.</p>
<p>You already have an idea of what time series and forecasting are, and how you can use the Darts Python library to achieve that.</p>
<p>You also learned of various models for forecasting time series data, and how you can apply techniques such as backtesting and hyperparameter tuning to achieve better results.</p>
<p>Another interesting thing with Darts is its ability to handle <a target="_blank" href="https://unit8co.github.io/darts/userguide/timeseries.html#hierarchical-time-series">hierarchical time series</a>. Here, data is structured at aggregated levels.</p>
<p>Darts is one of the most powerful time series libraries in Python and has a lot of models to handle various cases. You can proceed to explore models such as <a target="_blank" href="https://unit8co.github.io/darts/generated_api/darts.models.forecasting.transformer_model.html">Transformers</a> and also <a target="_blank" href="https://unit8co.github.io/darts/examples/01-multi-time-series-and-covariates.html">multi-series forecasting</a>, which are used for special use cases.</p>
<p>If you are interested in more data science and statistics articles, don’t forget to check out <a target="_blank" href="https://learndata.xyz/blog">my blog</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Get Started with Matplotlib – With Code Examples and Visualizations ]]>
                </title>
                <description>
                    <![CDATA[ One of the key steps in data analysis is data visualization, as it helps you notice certain features, tendencies, and relevant patterns that may not be obvious in raw data. Matplotlib is one of the most effective libraries for Python, and it allows t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/getting-started-with-matplotlib/</link>
                <guid isPermaLink="false">67046b93639bbc713991b8a3</guid>
                
                    <category>
                        <![CDATA[ Matplotlib ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oyedele Tioluwani ]]>
                </dc:creator>
                <pubDate>Mon, 07 Oct 2024 23:15:31 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1727947002230/9ab7fb41-65fe-4bf5-bb59-8f514a3e9396.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>One of the key steps in data analysis is data visualization, as it helps you notice certain features, tendencies, and relevant patterns that may not be obvious in raw data. Matplotlib is one of the most effective libraries for Python, and it allows the plotting of static, animated, and interactive graphics.</p>
<p>This guide explores Matplotlib's capabilities, focusing on solving specific data visualization problems and offering practical examples to apply to your projects.</p>
<p>Here’s what we are going to cover in this article:</p>
<ul>
<li><p><a class="post-section-overview" href="#heading-importance-of-data-visualization-in-data-analysis">Importance of Data Visualization in Data Analysis</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-brief-overview-of-matplotlib">Brief Overview of Matplotlib</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-getting-started-with-matplotlib">Getting Started with Matplotlib</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-installation-and-setup">Installation and Setup</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-your-first-plot">How to Create Your First Plot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-exploring-different-types-of-plots">Exploring Different Types of Plots</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-advanced-plot-customizations">Advanced Plot Customizations</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-work-with-multiple-plots">How to Work with Multiple Plots</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-enhance-plot-aesthetics">How to Enhance Plot Aesthetics</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-save-and-export-plots">How to Save and Export Plots</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-interactive-plotting-and-animation">Interactive Plotting and Animation</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-interactive-features-in-matplotlib">Interactive Features in Matplotlib</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-animations">How to Create Animations</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-optimize-plots-for-large-datasets">How to Optimize Plots for Large Datasets</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-efficient-plotting-techniques-for-large-datasets">Efficient Plotting Techniques for Large Datasets</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-statistical-data-visualization">Statistical Data Visualization</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-common-visualization-pitfalls-and-how-to-avoid-them">Common Visualization Pitfalls and How to Avoid Them</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-overplotting">Overplotting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-misleading-scales-and-axes">Misleading Scales and Axes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-color-misuse">Color Misuse</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-misleading-use-of-3d-plots">Misleading Use of 3D Plots</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-misleading-use-of-area-charts">Misleading Use of Area Charts</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-importance-of-data-visualization-in-data-analysis">Importance of Data Visualization in Data Analysis</h2>
<p>Assuming that you are dealing with the sales data of a big chain of stores. Raw data may contain hundreds or thousands of rows, with possible columns such as product categories, sales regions, and monthly revenues. These useful concepts and raw data analytical approaches present the data in a very complex manner which can be estranged for anyone to undertake.</p>
<p>However, by visualizing the data, you can have a broad view of what is likely to be occurring, such as, which product category is succeeding, or which region is lagging.</p>
<p>Data visualization is a process of getting data into more easily comprehensible and analyzable forms for decision-making. Matplotlib is particularly effective at addressing these challenges for data scientists and analysts, due to the vast number of plot types and possible alterations that are available.</p>
<h2 id="heading-brief-overview-of-matplotlib">Brief Overview of Matplotlib</h2>
<p>Matplotlib, which is now one of the most popular plotting software currently running in the Python environment, was started by John Hunter in the year 2003. With it, one can obtain various forms of static, dynamic, and even animated plots, making it an indispensable tool for any scientist, engineer, or data analyst.</p>
<p>Some common problems that Matplotlib can help solve include:</p>
<ul>
<li><p>Visualize large datasets to identify patterns and outliers.</p>
</li>
<li><p>Design exemplary complex graphics for the publication of academic articles.</p>
</li>
<li><p>Combining data gathered from different sources into interactive and informative illustrations.</p>
</li>
<li><p>Adapting trends in plots to make clear the information that is being portrayed.</p>
</li>
</ul>
<h2 id="heading-getting-started-with-matplotlib">Getting Started with Matplotlib</h2>
<h3 id="heading-installation-and-setup">Installation and Setup</h3>
<p>Before we dive into creating plots, let's get Matplotlib installed and set up. You can install Matplotlib using <code>pip</code> or <code>conda</code>:</p>
<pre><code class="lang-python">pip install matplotlib
</code></pre>
<p>Alternatively, if you're using Anaconda:</p>
<pre><code class="lang-python">conda install matplotlib
</code></pre>
<p>To verify the installation:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib
print(matplotlib.__version__)
</code></pre>
<h3 id="heading-how-to-create-your-first-plot">How to Create Your First Plot</h3>
<p>Let’s start by solving a common problem: let’s assume that you have a set of data that records daily temperature for a given month, and you want to study the variation of temperature.</p>
<p>Here’s how you can create a simple line plot to visualize this trend:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Simulating daily temperature data</span>
days = np.arange(<span class="hljs-number">1</span>,<span class="hljs-number">20</span>)
temperature = np.random.normal(loc=<span class="hljs-number">25</span>, scale=<span class="hljs-number">5</span>, size=len(days))

plt.plot(days, temperature, marker=<span class="hljs-string">'o'</span>)
plt.title(<span class="hljs-string">'Daily Temperatures in August'</span>)
plt.xlabel(<span class="hljs-string">'Day'</span>)
plt.ylabel(<span class="hljs-string">'Temperature (°C)'</span>)
plt.grid(<span class="hljs-literal">True</span>)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727733970801/479efd1e-0324-4c93-b12e-50942b78f183.png" alt="A simple  plot" width="600" height="400" loading="lazy"></p>
<ul>
<li><p>We used <code>np.arange</code> to construct a series of days.</p>
</li>
<li><p><code>np.random.normal</code> models temperature data with a mean (<code>loc</code>) equaling 20 degrees Celsius and a standard deviation (<code>scale</code>) equal to 5 degrees Celsius.</p>
</li>
<li><p><code>plt.plot</code> creates a line plot with markers for each day.</p>
</li>
<li><p>Titles and labels were added to make the plot informative.</p>
</li>
</ul>
<h3 id="heading-exploring-different-types-of-plots">Exploring Different Types of Plots</h3>
<p>Matplotlib supports various plot types, each suited to specific data visualization problems.</p>
<h4 id="heading-line-plots">Line Plots</h4>
<p>Line plots are ideal for visualizing trends over time or continuous data. For example, tracking the monthly sales of a product:</p>
<pre><code class="lang-python">months = np.arange(<span class="hljs-number">1</span>,<span class="hljs-number">13</span>)
sales = np.random.randint(<span class="hljs-number">2000</span>, <span class="hljs-number">4000</span>, size=len(months))
plt.plot(months, sales, color=<span class="hljs-string">'red'</span>, linestyle=<span class="hljs-string">'--'</span>, marker=<span class="hljs-string">'o'</span>)
plt.title(<span class="hljs-string">"Monthly Sales of Product "</span>)
plt.xlabel(<span class="hljs-string">"Month"</span>)
plt.ylabel(<span class="hljs-string">"Sales (Units)"</span>)
plt.grid(<span class="hljs-literal">True</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734299673/80917af9-81c1-4adc-aeef-63aac02d6b66.png" alt="Using line plots to track monthly sales" width="600" height="400" loading="lazy"></p>
<h4 id="heading-scatter-plots">Scatter Plots</h4>
<p>They are used for the construction of simple relations between two variables of data where the appearance of the points are compared. For instance, visualizing the relationship between advertisement spending and sales:</p>
<pre><code class="lang-python">ad_spend = np.random.randint(<span class="hljs-number">50</span>, <span class="hljs-number">1000</span>, size=<span class="hljs-number">50</span>)
sales = ad_spend * np.random.uniform(<span class="hljs-number">0.8</span>, <span class="hljs-number">1.2</span>, size=<span class="hljs-number">50</span>)

plt.scatter(ad_spend, sales, color=<span class="hljs-string">'blue'</span>)
plt.title(<span class="hljs-string">"Advertisement Spending vs. Sales"</span>)
plt.xlabel(<span class="hljs-string">"Ad Spend (USD)"</span>)
plt.ylabel(<span class="hljs-string">"Sales (Units)"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734341461/0ebd072d-3bd8-498c-9e6f-3917497ba5a9.png" alt="A scatter plot representation" width="600" height="400" loading="lazy"></p>
<h4 id="heading-bar-charts">Bar Charts</h4>
<p>Bar charts are effective for comparing categorical data. For example, visualizing the total revenue generated by several product groupings:</p>
<pre><code class="lang-python">groupings = [<span class="hljs-string">'Musical Instruments'</span>, <span class="hljs-string">'Furniture'</span>, <span class="hljs-string">'Clothing'</span>, <span class="hljs-string">'Food'</span>]
revenue = [<span class="hljs-number">50000</span>, <span class="hljs-number">30000</span>, <span class="hljs-number">20000</span>, <span class="hljs-number">40000</span>]

plt.bar(groupings, revenue, color=<span class="hljs-string">'green'</span>)
plt.title(<span class="hljs-string">"Revenue by Product Grouping"</span>)
plt.xlabel(<span class="hljs-string">"Group"</span>)
plt.ylabel(<span class="hljs-string">"Revenue (EURO)"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734374042/a81a751d-2b5f-4c8a-98e9-3170756c440e.png" alt="A bar chart visualization" width="600" height="400" loading="lazy"></p>
<h4 id="heading-histograms">Histograms</h4>
<p>They are used to view the distribution of numerical data based on frequency. For example, visualizing the distribution of customer ages in a survey:</p>
<pre><code class="lang-python">ages = np.random.randint(<span class="hljs-number">18</span>, <span class="hljs-number">65</span>, size=<span class="hljs-number">2000</span>)

plt.hist(ages, bins=<span class="hljs-number">10</span>, color=<span class="hljs-string">'purple'</span>, edgecolor=<span class="hljs-string">'black'</span>)
plt.title(<span class="hljs-string">"Age Distribution of Survey Participants"</span>)
plt.xlabel(<span class="hljs-string">"Age"</span>)
plt.ylabel(<span class="hljs-string">"Number of Participants"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734397041/19eeae57-97b9-4a29-9773-393627cb0d1c.png" alt="Histogram showing the distribution of customer ages" width="600" height="400" loading="lazy"></p>
<h4 id="heading-pie-charts">Pie Charts</h4>
<p>Pie charts are used to display the percentages of data in graphical format. For example, visualizing the market share of different companies:</p>
<pre><code class="lang-python">companies = [<span class="hljs-string">'Company W'</span>, <span class="hljs-string">'Company X'</span>, <span class="hljs-string">'Company Y'</span>, <span class="hljs-string">'Company Z'</span>]
market_share = [<span class="hljs-number">40</span>, <span class="hljs-number">30</span>, <span class="hljs-number">20</span>, <span class="hljs-number">10</span>]

plt.pie(market_share, labels=companies, autopct=<span class="hljs-string">'%1.1f%%'</span>, colors=[<span class="hljs-string">'blue'</span>, <span class="hljs-string">'orange'</span>, <span class="hljs-string">'green'</span>, <span class="hljs-string">'red'</span>])
plt.title(<span class="hljs-string">"Market Share by Company"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734413363/a626ebb2-f3bc-4fb9-98e1-57d2dfdead8e.png" alt="A pie chart representation" width="600" height="400" loading="lazy"></p>
<h2 id="heading-advanced-plot-customizations">Advanced Plot Customizations</h2>
<h3 id="heading-how-to-work-with-multiple-plots">How to Work with Multiple Plots</h3>
<p>In some situations, you’ll be required to compare multiple datasets in a single figure. For example, comparing sales trends across different regions. This can be achieved using subplots:</p>
<pre><code class="lang-python">regions = [<span class="hljs-string">'North'</span>, <span class="hljs-string">'South'</span>, <span class="hljs-string">'East'</span>, <span class="hljs-string">'West'</span>]
sales_data = np.random.randint(<span class="hljs-number">500</span>, <span class="hljs-number">5000</span>, size=(<span class="hljs-number">4</span>, <span class="hljs-number">12</span>))

fig, axs = plt.subplots(<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">8</span>))
fig.suptitle(<span class="hljs-string">'Monthly Sales by Region'</span>)

<span class="hljs-keyword">for</span> i, region <span class="hljs-keyword">in</span> enumerate(regions):
    ax = axs[i // <span class="hljs-number">2</span>, i % <span class="hljs-number">2</span>]
    ax.plot(months, sales_data[i], marker=<span class="hljs-string">'o'</span>)
    ax.set_title(region)
    ax.set_xlabel(<span class="hljs-string">"Month"</span>)
    ax.set_ylabel(<span class="hljs-string">"Sales (Units)"</span>)

plt.tight_layout()
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734447574/336f9425-183a-4035-8f14-6462d0e1c358.png" alt="multiple plot diagrams comparing sales trend" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-enhance-plot-aesthetics">How to Enhance Plot Aesthetics</h3>
<p>Among the typical options for common plotting is the possibility to control the appearance of a plot to make it informative and aesthetically pleasing.</p>
<p>Here’s an example:</p>
<pre><code class="lang-python">plt.plot(days, temperature, color=<span class="hljs-string">'orange'</span>, marker=<span class="hljs-string">'x'</span>, linestyle=<span class="hljs-string">'-'</span>)
plt.title(<span class="hljs-string">"Daily Temperatures in August"</span>, fontsize=<span class="hljs-number">16</span>)
plt.xlabel(<span class="hljs-string">"Day"</span>, fontsize=<span class="hljs-number">12</span>)
plt.ylabel(<span class="hljs-string">"Temperature (°C)"</span>, fontsize=<span class="hljs-number">12</span>)
plt.grid(<span class="hljs-literal">True</span>)
plt.legend([<span class="hljs-string">'Temperature'</span>], loc=<span class="hljs-string">'upper right'</span>)
plt.annotate(<span class="hljs-string">'Coldest Day'</span>, xy=(<span class="hljs-number">5</span>, <span class="hljs-number">10</span>), xytext=(<span class="hljs-number">7</span>, <span class="hljs-number">5</span>),
             arrowprops=dict(facecolor=<span class="hljs-string">'black'</span>, arrowstyle=<span class="hljs-string">'-&gt;'</span>))
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734492330/12638dc3-dd99-427f-ba1d-2ec59cadd03a.png" alt="Image showing an aesthetically pleasing plot" width="600" height="400" loading="lazy"></p>
<p>The code changes colors and markers, line styles, titles, and axis labels of the desired font size, grid on, adds legend and annotates the coldest day by an arrow. These improvements make the plot informative and neat and as a result, a professional and clear message would be delivered.</p>
<h3 id="heading-how-to-save-and-export-plots">How to Save and Export Plots</h3>
<p>Once you've created a plot, you might need to save it in a specific format for a report or presentation. Below is an example on how to save plots efficiently:</p>
<pre><code class="lang-python">plt.plot(days, temperature)
plt.title(<span class="hljs-string">"Daily Temperatures in August"</span>)
plt.xlabel(<span class="hljs-string">"Day"</span>)
plt.ylabel(<span class="hljs-string">"Temperature (°C)"</span>)

<span class="hljs-comment"># Saving the plot</span>
plt.savefig(<span class="hljs-string">"daily_temperatures_august.png"</span>, dpi=<span class="hljs-number">300</span>, bbox_inches=<span class="hljs-string">'tight'</span>)
plt.savefig(<span class="hljs-string">"daily_temperatures_august.pdf"</span>, format=<span class="hljs-string">'pdf'</span>, bbox_inches=<span class="hljs-string">'tight'</span>)
</code></pre>
<p>The <code>dpi</code> parameter controls the resolution of the saved plot, and <code>bbox_inches='tight'</code> ensure that the plot is saved without extra whitespace.</p>
<h2 id="heading-interactive-plotting-and-animation">Interactive Plotting and Animation</h2>
<h3 id="heading-interactive-features-in-matplotlib">Interactive Features in Matplotlib</h3>
<p>You can also make your plots interactive. For example, rather than viewing an entire plot, one might move closer to a region of interest, or when the plot has to be changed in some way because of the user input.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

x = np.linspace(<span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">100</span>)
y = np.cos(x)

fig, ax = plt.subplots()
ax.plot(x, y)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">on_click</span>(<span class="hljs-params">event</span>):</span>
    <span class="hljs-comment"># This function is called when the plot is clicked</span>
    print(<span class="hljs-string">f"The Coordinates were clicked at: (<span class="hljs-subst">{event.xdata}</span>, <span class="hljs-subst">{event.ydata}</span>)"</span>)

fig.canvas.mpl_connect(<span class="hljs-string">'button_press_event'</span>, on_click)
plt.show()
</code></pre>
<p>The code generates a cosine wave plot and sets a click event handler on it with the <code>on_click</code> name. Once you click anywhere on the plot, the handler prints the coordinates of the click on the Python console.</p>
<h3 id="heading-how-to-create-animations">How to Create Animations</h3>
<p>Animations can be handy in showing how things evolve. For instance, the increase of a stock price or the incubation period of a disease:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.animation <span class="hljs-keyword">as</span> animation

fig, ax = plt.subplots()
line, = ax.plot(x, y)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update</span>(<span class="hljs-params">frame</span>):</span>
    line.set_ydata(np.cos(x + frame / <span class="hljs-number">10</span>))
    <span class="hljs-keyword">return</span> line,

ani = animation.FuncAnimation(fig, update, frames=range(<span class="hljs-number">100</span>), blit=<span class="hljs-literal">True</span>)
plt.show()
</code></pre>
<p>The code forms an animated cosine wave, which over time seems to move horizontally and creates an impression of a wave moving from left or right. Such animations can also be useful if the data should be represented in terms of change with time.</p>
<h2 id="heading-how-to-optimize-plots-for-large-datasets">How to Optimize Plots for Large Datasets</h2>
<p>The size of the dataset being considered when dealing with big data is characterized by the amount of data, thus, the importance of performance needs to be expressed. It is often too slow and takes much memory to plot large quantities of data. Here are some tips you need to employ to make the most of your plots.</p>
<h3 id="heading-efficient-plotting-techniques-for-large-datasets">Efficient Plotting Techniques for Large Datasets</h3>
<h4 id="heading-downsampling">Downsampling</h4>
<p>In this process, you sample fewer points than what the original plot has.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate large dataset</span>
x_huge = np.linspace(<span class="hljs-number">0</span>, <span class="hljs-number">100</span>, <span class="hljs-number">10000</span>)
y_huge = np.sin(x_huge) + np.random.normal(<span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>, size=x_huge.shape)

<span class="hljs-comment"># Downsample the data</span>
x_downsampled = x_huge[::<span class="hljs-number">10</span>]
y_downsampled = y_huge[::<span class="hljs-number">10</span>]

plt.plot(x_downsampled, y_downsampled)
plt.title(<span class="hljs-string">"Downsampled Plot"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734654600/041f79ce-0519-4d6c-830f-099b0be2ac4f.png" alt="A downsampled plot image" width="600" height="400" loading="lazy"></p>
<p>With this, we reduce the number of points to plot the graph on and plot a point after an interval of 10 points. It reduces the load to be rendered but does so without distorting the general structure of the data.</p>
<h4 id="heading-data-aggregation">Data Aggregation</h4>
<p>Data Aggregation is a process where data gathered in numerical form is grouped into classes to arrive at tabulations of the observations under a given class.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate large dataset</span>
x_huge = np.linspace(<span class="hljs-number">0</span>, <span class="hljs-number">100</span>, <span class="hljs-number">10000</span>)
y_huge = np.sin(x_huge) + np.random.normal(<span class="hljs-number">0</span>, <span class="hljs-number">0.1</span>, size=x_huge.shape)

<span class="hljs-comment"># Aggregate the data into bins</span>
bins = np.linspace(<span class="hljs-number">0</span>, <span class="hljs-number">100</span>, <span class="hljs-number">100</span>)
y_aggregated = [np.mean(y_huge[(x_huge &gt;= bins[i]) &amp; (x_huge &lt; bins[i+<span class="hljs-number">1</span>])]) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(bins)<span class="hljs-number">-1</span>)]

plt.plot(bins[:<span class="hljs-number">-1</span>], y_aggregated)
plt.title(<span class="hljs-string">"Aggregated Plot"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Average Y"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734688145/696c2a72-64d8-4dd1-97ad-217979f91707.png" alt="An aggregated plot image" width="600" height="400" loading="lazy"></p>
<p>This process reduces the number of data points needed to represent the data distribution, making the plot easier to read and interpret while still capturing the overall trend of the original data.</p>
<h3 id="heading-statistical-data-visualization">Statistical Data Visualization</h3>
<p>Statistical plots are useful for summarizing and understanding large datasets, some of which include the following:</p>
<h4 id="heading-box-plots">Box Plots</h4>
<p>It displays the data distribution based on a five-number summary: minimum, first quartile, median, third quartile, and maximum.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate random data</span>
data = np.random.randn(<span class="hljs-number">1000</span>)
plt.boxplot(data)
plt.title(<span class="hljs-string">"Box Plot"</span>)
plt.ylabel(<span class="hljs-string">"Values"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734716151/ddfa3387-8aa7-47ba-af4b-31faef782c32.png" alt="A box plot representation" width="600" height="400" loading="lazy"></p>
<p>They are especially used in positional outlier detection and the comparison of the dispersion and symmetry of two variables.</p>
<h4 id="heading-violin-plot">Violin Plot</h4>
<p>It employs a box plot as well as a density plot to present more specific information regarding the value distribution of the given variables.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate random data</span>
data = np.random.randn(<span class="hljs-number">1000</span>)
plt.violinplot(data)
plt.title(<span class="hljs-string">"Violin Plot"</span>)
plt.ylabel(<span class="hljs-string">"Values"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734737336/4b2e08a7-68ab-4060-ab6b-c925eb4e38e4.png" alt="A violin plot representation" width="600" height="400" loading="lazy"></p>
<p>Violin plots can be used when there is a need to represent full distributions.</p>
<h2 id="heading-common-visualization-pitfalls-and-how-to-avoid-them">Common Visualization Pitfalls and How to Avoid Them</h2>
<h3 id="heading-overplotting">Overplotting</h3>
<p>A value is rendered over-plotted when many observations are superimposed in the same foreground, which makes the figures messy, and the points or patterns become obscure. This is particularly common in scatter plots or line plots with large datasets.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate large dataset</span>
x = np.random.rand(<span class="hljs-number">10000</span>)
y = np.random.rand(<span class="hljs-number">10000</span>)

<span class="hljs-comment"># Plot without transparency (over-plotting)</span>
plt.scatter(x, y)
plt.title(<span class="hljs-string">"Scatter Plot with Over-plotting"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.show()

<span class="hljs-comment"># Plot with transparency to reduce over-plotting</span>
plt.scatter(x, y, alpha=<span class="hljs-number">0.1</span>)  <span class="hljs-comment"># Set alpha for transparency</span>
plt.title(<span class="hljs-string">"Scatter Plot with Reduced Over-plotting"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734768136/4de79ed6-6f57-45d3-909b-e2b547a26232.png" alt="An image of over-plotting and reduced over-plotting" width="600" height="400" loading="lazy"></p>
<p>In the first plot, without transparency, the data points overlap significantly, making it hard to identify any patterns or density areas. In the second plot, transparency (<code>alpha=0.1</code>) is applied to the data points, allowing denser regions to become more apparent while reducing clutter. This technique makes it easier to interpret the plot's data distribution.</p>
<h3 id="heading-misleading-scales-and-axes">Misleading Scales and Axes</h3>
<p>It is possible to choose the scales and axes in such a way that it changes the overall perception of the plot. Misleading scales mess up the actual picture an analyst gets about the data and leads to making improper conclusions.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate data</span>
x = np.arange(<span class="hljs-number">10</span>)
y1 = np.random.randint(<span class="hljs-number">50</span>, <span class="hljs-number">100</span>, size=<span class="hljs-number">10</span>)
y2 = y1 + np.random.randint(<span class="hljs-number">-5</span>, <span class="hljs-number">5</span>, size=<span class="hljs-number">10</span>)

<span class="hljs-comment"># Plot with truncated y-axis</span>
plt.plot(x, y1, label=<span class="hljs-string">'Data 1'</span>)
plt.plot(x, y2, label=<span class="hljs-string">'Data 2'</span>)
plt.ylim(<span class="hljs-number">90</span>, <span class="hljs-number">100</span>)  <span class="hljs-comment"># Truncated y-axis</span>
plt.title(<span class="hljs-string">"Plot with Truncated Y-Axis"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.legend()
plt.show()

<span class="hljs-comment"># Plot with full y-axis</span>
plt.plot(x, y1, label=<span class="hljs-string">'Data 1'</span>)
plt.plot(x, y2, label=<span class="hljs-string">'Data 2'</span>)
plt.title(<span class="hljs-string">"Plot with Full Y-Axis"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.legend()
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727734992341/e257fe37-1b47-4ed4-82fd-5c2e9a458202.png" alt="Truncated Y-axis vs Full Y-axis" width="600" height="400" loading="lazy"></p>
<p>What can be gathered from the first plot is that the range of the y-axis is fixed. This brings out a graph that is quite misleading. The second plot uses the full y-axis, providing a more accurate representation of the data.</p>
<h3 id="heading-color-misuse">Color Misuse</h3>
<p>The somewhat weak link in data visualization is the way colors are chosen and, more often than not, used improperly. Issues are low contrasts, picking colors that a color-blind person cannot differentiate, and creating color importance where there is none.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate data</span>
x = np.linspace(<span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">100</span>)
y1 = np.sin(x)
y2 = np.cos(x)

<span class="hljs-comment"># Plot with non-colorblind-friendly palette</span>
plt.plot(x, y1, color=<span class="hljs-string">'red'</span>, label=<span class="hljs-string">'sin(x)'</span>)
plt.plot(x, y2, color=<span class="hljs-string">'green'</span>, label=<span class="hljs-string">'cos(x)'</span>)
plt.title(<span class="hljs-string">"Plot with Non-Colorblind-Friendly Colors"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.legend()
plt.show()

<span class="hljs-comment"># Plot with colorblind-friendly palette</span>
plt.plot(x, y1, color=<span class="hljs-string">'#0072B2'</span>, label=<span class="hljs-string">'sin(x)'</span>)  <span class="hljs-comment"># Blue</span>
plt.plot(x, y2, color=<span class="hljs-string">'#D55E00'</span>, label=<span class="hljs-string">'cos(x)'</span>)  <span class="hljs-comment"># Orange</span>
plt.title(<span class="hljs-string">"Plot with Colorblind-Friendly Colors"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.legend()
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727735130128/9dc47d8a-9d2a-4982-9185-29e76014f9c5.png" alt="image highlighting color importance" width="600" height="400" loading="lazy"></p>
<p>The first plot employs red and green which are notoriously difficult for users with red-green color blindness. The second plot uses a colorblind web-friendly palette to ensure that everyone can understand the plot without being confused by the colors.</p>
<h3 id="heading-misleading-use-of-3d-plots">Misleading Use of 3D Plots</h3>
<p>3D plots can be visually appealing but often add unnecessary complexities and can be misleading if not used appropriately. They are most effective when the third dimension genuinely adds value to the visualization, such as when displaying multivariate data. However, 3D plots make it a bit difficult to have a comparison of the values in the plots.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> mpl_toolkits.mplot3d <span class="hljs-keyword">import</span> Axes3D
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate data</span>
x = np.linspace(<span class="hljs-number">-5</span>, <span class="hljs-number">5</span>, <span class="hljs-number">100</span>)
y = np.linspace(<span class="hljs-number">-5</span>, <span class="hljs-number">5</span>, <span class="hljs-number">100</span>)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**<span class="hljs-number">2</span> + Y**<span class="hljs-number">2</span>))

<span class="hljs-comment"># 3D plot</span>
fig = plt.figure()
ax = fig.add_subplot(<span class="hljs-number">111</span>, projection=<span class="hljs-string">'3d'</span>)
ax.plot_surface(X, Y, Z, cmap=<span class="hljs-string">'viridis'</span>)
plt.title(<span class="hljs-string">"3D Plot"</span>)
plt.show()

<span class="hljs-comment"># 2D contour plot</span>
plt.contourf(X, Y, Z, cmap=<span class="hljs-string">'viridis'</span>)
plt.colorbar(label=<span class="hljs-string">'Z value'</span>)
plt.title(<span class="hljs-string">"2D Contour Plot"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727735152366/965da133-cfb7-4db4-bbbc-c98d7271bd82.png" alt="3D plot vs 2D contour plot" width="600" height="400" loading="lazy"></p>
<p>The 3D plot helps to plot the data in three dimensions, but it is not easy to understand the exact height difference of the regions because of the perspective. The 2D contour plot, however, uses varying colors to reflect the dimension data (Z values), making it easier and more accurate to compare areas in the graph. More often than not, the 2D plots used are better representations and easier to understand compared to the 3D ones.</p>
<h3 id="heading-misleading-use-of-area-charts">Misleading Use of Area Charts</h3>
<p>Area charts can effectively show trends over time or the distribution of a whole into parts. However, they may be confusing if some of the areas intersect or if the accumulation scheme of the chart is not clear.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate data</span>
x = np.arange(<span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">1</span>)
y1 = np.array([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>])
y2 = np.array([<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">5</span>, <span class="hljs-number">4</span>, <span class="hljs-number">6</span>, <span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">6</span>, <span class="hljs-number">8</span>])

<span class="hljs-comment"># Stacked area chart (potentially misleading)</span>
plt.fill_between(x, y1, color=<span class="hljs-string">'skyblue'</span>, alpha=<span class="hljs-number">0.5</span>)
plt.fill_between(x, y2, color=<span class="hljs-string">'orange'</span>, alpha=<span class="hljs-number">0.5</span>)
plt.title(<span class="hljs-string">"Misleading Stacked Area Chart"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.show()

<span class="hljs-comment"># Improved area chart with non-overlapping areas</span>
plt.fill_between(x, y1, color=<span class="hljs-string">'skyblue'</span>, alpha=<span class="hljs-number">0.5</span>)
plt.fill_between(x, y1 + y2, y1, color=<span class="hljs-string">'orange'</span>, alpha=<span class="hljs-number">0.5</span>)
plt.title(<span class="hljs-string">"Improved Stacked Area Chart"</span>)
plt.xlabel(<span class="hljs-string">"X"</span>)
plt.ylabel(<span class="hljs-string">"Y"</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1727735170489/d5e4bea1-713f-4e75-9cd7-b8e3a15f6331.png" alt="A representation of use of area charts" width="600" height="400" loading="lazy"></p>
<p>In the first area chart, the areas overlap, which can create confusion about the contribution of each category to the whole. The second plot improves clarity by stacking the areas on top of each other without overlap, clearly showing the cumulative nature of the data.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>With Matplotlib, one has many features to solve particular visualization problems in the data analysis field. You can use it for line plots, complex data handling, large data processing, creating animated plots, and so on.</p>
<p>In this guide, we have explored the important aspects of Matplotlib and tried to bring them closer to solving real problems that you may face in your day-to-day programming work.</p>
<p>We also included detailed examples to support these applications. In whatever capacity you engage with the data, whether as a data scientist, engineer, or analyst, Matplotlib enables you to tell your data’s narrative in the best way possible.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Analyze and Visualize Large Datasets with Microsoft Excel Using Pivot Tables and Charts ]]>
                </title>
                <description>
                    <![CDATA[ By Samuel A. Olubiyo Microsoft Excel is a very powerful tool that you can use to analyze and visualize data.  In this tutorial, you will learn how to build a simple Excel Dashboard that visualizes important data from a large dataset.  The dataset we'... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/analyze-and-visualize-large-datasets-with-excel-pivot-tables-charts/</link>
                <guid isPermaLink="false">66d4601347a8245f78752a81</guid>
                
                    <category>
                        <![CDATA[ data analysis ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ excel ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 05 Jan 2024 17:40:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/all-charts-with-conditional-formatting-1.PNG" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Samuel A. Olubiyo</p>
<p>Microsoft Excel is a very powerful tool that you can use to analyze and visualize data. </p>
<p>In this tutorial, you will learn how to build a simple Excel Dashboard that visualizes important data from a large dataset. </p>
<p>The dataset we'll be working with is the transaction records of a super store for a period of four years. Our goal is to gain important insights from the dataset and visualize those insights graphically with Microsoft Excel.</p>
<p>This tutorial is tailored for those who are already familiar with Excel. In it, you will learn:</p>
<ul>
<li>How to format dates in Excel using the TEXT function.</li>
<li>How to sort the entire data set.</li>
<li>How to create multiple Pivot Tables on the same worksheet</li>
<li>How to create charts based on the Pivot Table.</li>
<li>How to create slicers to filter data, and finally,</li>
<li>How to use conditional formatting.</li>
</ul>
<p>In order to make the most of this tutorial, I have provided a data set for you to use. You can <a target="_blank" href="https://github.com/Lordsamdev/superstoredata/blob/main/Super%20Store%20Dataset.xlsx">download it here</a>.</p>
<p>If you're new to data analysis and visualization with Excel, the freeCodeCamp website contains a lot of tutorials for beginners. <a target="_blank" href="https://www.freecodecamp.org/news/tag/excel/">Here is a link to some articles on Excel from beginner to advanced</a> if you need to brush up on your skills.</p>
<h2 id="heading-our-dataset">Our Dataset</h2>
<p>After downloading the Excel file and opening it, you will notice one thing instantly: The data is huge! It is a data set containing the transactions of a superstore for a period of four years (from 2014 to 2017). </p>
<p>This Excel file is made up of 9995 rows and 21 columns. We can’t gain any useful insights from this data set just by staring at it, which is why we need to analyze and visualize it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Data-Overview.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of the dataset</em></p>
<p>The easiest way to do this is by using Pivot Tables. A Pivot Table is one of Microsoft Excel's powerful tools you can use to calculate, analyze and summarize data. It helps you see comparisons, trends, and patterns in your data and you will learn how to use it in this tutorial.</p>
<p>Before we continue, let's take a look at the data set again: column C contains the order dates for each product sold. The order date column is important in this tutorial, because we need to sort the entire dataset based on the dates each customer ordered a product.</p>
<h2 id="heading-how-to-format-dates-in-excel-using-the-text-function">How to Format Dates in Excel Using the TEXT Function.</h2>
<p>In our dataset, the dates are arranged haphazardly and the date formatting makes it hard to tell exactly when each customer ordered a product. To fix this, we'll use the TEXT function to convert the dates to text.</p>
<p>Before you do this, insert a new column beside column C. This will be your new column D and where the newly formatted dates will reside. You can give it a new name – in my own case, I named it “Formatted Dates.”</p>
<p>After that is done, insert the formula in the screenshot below and press enter:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/formatting-a-date.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Formula to convert dates into text</em></p>
<p>Or just copy and paste the formula below:</p>
<p>=TEXT(C2, "d mmmm yyyy")</p>
<p>Of course, the formula only works for the first cell in the column. To repeat it across the entire column, just double-tap the little node at the right end of the cell when it's highlighted (as you can see in the below screenshot):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/flash-fill-node.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Tap on the node to fill the remaining cells in the column automatically</em></p>
<p>Now, you should have dates in a more readable format across column D.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/formatted-date-column.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>The dates in a more readable format</em></p>
<p>For the purpose of this analysis, we need to extract the years from the dates we have just formatted. To do this, create a new column beside column D, this will be your new column E. Name the column as you like, but in my case, I named it “Year”.</p>
<p>Now use the formula in the screenshot below and press enter:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/getting-the-year.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Formula to get the year from the date</em></p>
<p>Or simply copy and paste the formula below:</p>
<p>=RIGHT(D2,4)</p>
<p>This will extract the year at the end of the date. Double-tap the node at the end of the cell to repeat it across the entire column. You should get a similar result as shown in the screenshot below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/The-year.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot showing the extracted year</em></p>
<h2 id="heading-how-to-sort-the-entire-dataset">How to Sort the Entire Dataset</h2>
<p>The next step in this tutorial is to sort the entire data set based on the newly extracted Year column.</p>
<p>Highlight the entire Year column and go to the sort tab, as you can see in the screenshot below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/The-sort-tab.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Sorting the dataset</em></p>
<p>Leave all options at default and press OK.</p>
<p>Now the entire data set should be sorted.</p>
<h2 id="heading-how-to-create-multiple-pivot-tables-on-the-same-worksheet">How to Create Multiple Pivot Tables on the Same Worksheet</h2>
<p>The next step in this tutorial is to create the pivot tables we'll use to make sense of this data.</p>
<p>Go to the insert tab and click on Pivot Table. A dialogue box should pop up asking you for the range of the data you want the pivot table to be created from – which by default is the entire data set.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/pivot-table-creation.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a Pivot Table</em></p>
<p>You will also have options to use the existing worksheet to create the pivot table or a new worksheet. Select the <em>new worksheet</em> option and press OK.</p>
<p>You should have a result like you can see in the screenshot below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/pivot-table-worksheet.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>The Pivot Table Worksheet</em></p>
<p>From here things start to get interesting.</p>
<p>For this exercise, I am only interested in three things: </p>
<ul>
<li>The category of products with the highest sales for each of the four years (2014 to 2017)</li>
<li>Which sub-category has the highest sales </li>
<li>Which region drives the most sales to this super store.</li>
</ul>
<p>I also want to visualize this information using graphs and charts. Thankfully, Excel has the tools we need to achieve all these.</p>
<p>In case you don’t know how to create a Pivot Table, here is a comprehensive <a target="_blank" href="https://www.freecodecamp.org/news/how-to-create-a-pivot-table-in-excel/">freeCodeCamp article</a> teaching you how to do that.</p>
<p>So we need to create three Pivot Tables, one for the sales by category, one for the sales by sub-category, and one for the sales by region.</p>
<p>To create the first table, simply select sales and category from the PivotTable Fields at the right hand side of your screen.</p>
<p>After creating the first Pivot Table, to add another table on the same worksheet, simply go to the insert tab and click on Pivot Table, then go to the original worksheet with the dataset and highlight everything, click OK.</p>
<p>Repeat the step to create the last table for the sales by region.</p>
<p>You should have three tables as shown in the screenshot below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/All-pivot-tables-1.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot showing all three Pivot Tables</em></p>
<h2 id="heading-how-to-create-charts-based-on-the-pivot-table">How to Create Charts Based on the Pivot Table</h2>
<p>The next step is to create the charts to visualize what is represented in the Pivot Tables. This is quite straightforward – just highlight each table and click the insert tab to insert the chart of your choice.</p>
<p>I used a pie chart for the sales by category table, and column charts for the other two tables on the worksheet. But you can use whatever chart(s) you want.</p>
<p>If you follow my steps exactly, you should have a result similar to the screenshot below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/All-charts-and-tables.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot showing all the charts</em></p>
<h2 id="heading-how-to-create-slicers-to-filter-data">How to Create Slicers to Filter Data</h2>
<p>The next step is to use slicers to filter each table by the year so that we can see what the total sales for each category, sub-category, and region are by year.</p>
<p>To do this, highlight each table and click on the analyze tab, then click on the slicer button as shown in this screenshot:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/insert-slicer.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a slicer</em></p>
<p>You'll see a list of options. Look for Year, and click it.</p>
<p>Now you should have a slicer for the years 2014 to 2017. Clicking on the corresponding button for each year will filter the table and show the sales for the year. Here is what it should look like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/All-charts-with-slicers.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot showing all the slicers</em></p>
<h2 id="heading-how-to-use-conditional-formatting">How to Use Conditional Formatting</h2>
<p>Finally, you can use conditional formatting to indicate the highest and lowest values on each table. You can play around with this as you like.</p>
<p>To use conditional formatting, click on the conditional formatting tab, and use this screenshot as a guide:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/conditional-formatting.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>Using conditional formatting</em></p>
<p>Highlight the values you would like to use conditional formatting for. I used the color scales option to indicate the highest and lowest values by different colors, then I used the data bars option for the sales by sub-category table.</p>
<p>If you did exactly what I did, you should have something close to the screenshot below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/all-charts-with-conditional-formatting.PNG" alt="Image" width="600" height="400" loading="lazy">
<em>The completed dashboard</em></p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>This little project we have built together can be expanded to get more insights into the data set, this can prove very useful when making business decisions. </p>
<p>This dashboard we have built has revealed that the best selling category is electronics and the best selling sub-category is phones. I also learned that the most sales came from the western region just by glancing at this dashboard.</p>
<p>I hope this tutorial has been helpful. Here is <a target="_blank" href="https://github.com/Lordsamdev/superstoredata/blob/main/Super%20Store%20Tutorial.xlsx">the link</a> to the completed version of this project – you can compare it with what you have built and see how well you did.</p>
<p>If you have any questions, you can reach out to me on <a target="_blank" href="https://twitter.com/thelordsamdev">X</a> and <a target="_blank" href="https://www.linkedin.com/in/lordsamdev/">LinkedIn</a>. Thanks for reading.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Build a Visualization for Leetcode's Two Sum Problem – HTML, CSS, & JavaScript Project ]]>
                </title>
                <description>
                    <![CDATA[ With the current state of the job market, there are a lot of people grinding out LeetCode as a way to prepare for technical interviews.  But sometimes it would be nice if there were a visualization showing the algorithms behind these problems.  In th... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-visualization-for-leetcode-two-sum-problem/</link>
                <guid isPermaLink="false">66b8d935d482a18d3e028263</guid>
                
                    <category>
                        <![CDATA[ coding interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ leetcode ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Jessica Wilkins ]]>
                </dc:creator>
                <pubDate>Tue, 21 Nov 2023 21:08:22 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/11/nubelson-fernandes--Xqckh_XVU4-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>With the current state of the job market, there are a lot of people grinding out <a target="_blank" href="https://leetcode.com/">LeetCode</a> as a way to prepare for technical interviews. </p>
<p>But sometimes it would be nice if there were a visualization showing the algorithms behind these problems. </p>
<p>In this tutorial, we will build out a <a target="_blank" href="https://codepen.io/Jessica-Wilkins-the-decoder/full/eYxVyKN">visualization</a> showing a couple of approaches to a popular LeetCode problem called <a target="_blank" href="https://leetcode.com/problems/two-sum/">Two Sum</a>. We will use vanilla HTML, CSS, and JavaScript to build this project out. </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></li>
<li><a class="post-section-overview" href="#heading-project-setup">Project Setup</a></li>
<li><a class="post-section-overview" href="#heading-how-to-solve-leetcodes-two-sum-problem">How to Solve LeetCode's Two Sum Problem</a><ul>
<li><a class="post-section-overview" href="#heading-description">Description</a></li>
<li><a class="post-section-overview" href="#heading-brute-force-approach">Brute Force Approach</a></li>
<li><a class="post-section-overview" href="#heading-brute-force-javascript-solution-and-time-complexity">Brute Force JavaScript Solution and Time Complexity</a></li>
<li><a class="post-section-overview" href="#heading-map-approach-and-solution">Map Approach and Solution</a></li>
<li><a class="post-section-overview" href="#heading-time-complexity-for-the-map-solution">Time Complexity for the Map Solution</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-overview-for-the-two-sum-visualization">Overview  for the Two Sum Visualization</a></li>
<li><a class="post-section-overview" href="#heading-adding-the-brute-force-visualization">Adding the Brute Force Visualization</a><ul>
<li><a class="post-section-overview" href="#heading-creating-the-const-and-let-variables">Creating the const and let Variables</a></li>
<li><a class="post-section-overview" href="#heading-creating-the-getclassname-function">Creating the getClassName Function</a></li>
<li><a class="post-section-overview" href="#heading-creating-the-bruteforceapproach-function">Creating the bruteForceApproach Function</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-disable-the-bruteforcesolutionbtn-when-the-animation-is-in-progress">How to Disable the bruteForceSolutionBtn When the Animation is in Progress</a></li>
<li><a class="post-section-overview" href="#heading-adding-the-map-solution-visualization">Adding the Map Solution Visualization</a><ul>
<li><a class="post-section-overview" href="#heading-creating-the-const-variables">Creating the const Variables</a></li>
<li><a class="post-section-overview" href="#heading-creating-the-optimalapproach-async-function">Creating the optimalApproach Async Function</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-reset-the-table-output-for-the-map-solution">How to Reset the Table Output for the Map Solution</a></li>
<li><a class="post-section-overview" href="#heading-final-solution-code-and-live-example">Final Solution Code and Live Example</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>This tutorial assumes that you have basic knowledge of HTML, CSS and JavaScript. If you haven't gone through a beginner course in any of those languages, then I would suggest starting with these resources:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/learn/2022/responsive-web-design/">freeCodeCamp's Responsive Web Design Certification</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/">freeCodeCamp's JavaScript Algorithms and Data Structures Certification</a></li>
</ul>
<p>This tutorial also assumes that you have some basic knowledge of how to work with a code editor or IDE. If not, then I would suggest looking into these resources:</p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=WPqXP_kLzpo">Visual Studio Code Crash Course</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-codepen/">How to Use CodePen</a> </li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-replit/">How to Use Replit</a></li>
</ul>
<h2 id="heading-project-setup">Project Setup</h2>
<p>You are free to build out this project in either your local code editor of choice, or through an online IDE or editor like <a target="_blank" href="https://codepen.io/">CodePen</a>, <a target="_blank" href="https://codesandbox.io/">CodeSandbox</a>, or <a target="_blank" href="https://replit.com/">Replit</a>. </p>
<p>This project will consist of three files: <code>index.html</code>, <code>index.js</code>, and <code>styles.css</code>. Since this project is going to mainly focus on JavaScript, I have supplied all of the HTML and CSS in <a target="_blank" href="https://github.com/jdwilkin4/leetcode-two-sum-starter-code">this GitHub repo here</a>. </p>
<p>You are free to <a target="_blank" href="https://www.freecodecamp.org/news/how-to-fork-a-github-repository/">fork</a> and <a target="_blank" href="https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository">clone</a> the repository, or you can copy the code found in the HTML and CSS files and add it to your project.</p>
<p>Once you get your project environment setup, then you should start the local server and see this result on the screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-19-at-4.18.24-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visualization styles for Leetcode's Two Sum problem</em></p>
<h2 id="heading-how-to-solve-leetcodes-two-sum-problem">How to Solve LeetCode's Two Sum problem</h2>
<p>Before we can build out the visualization for this problem, we need to first understand and solve the problem.</p>
<h3 id="heading-description">Description</h3>
<p>For this problem, you will be given a list of numbers in any order and a target number. The goal is to find the pair of numbers that adds up to the target and return an array of indices for that pair of numbers.</p>
<p>In this example, we have the following list and target number:</p>
<pre><code class="lang-js">[<span class="hljs-number">2</span>,<span class="hljs-number">7</span>,<span class="hljs-number">11</span>,<span class="hljs-number">15</span>]
<span class="hljs-attr">target</span>: <span class="hljs-number">9</span>
</code></pre>
<p>The numbers 2 and 7 equal 9 so we would return <code>[0,1]</code> because that represents the indices for where the pair of numbers can be found in the array. </p>
<p>For this problem, you can assume there will be at least two numbers or more in the array and there will only be <strong>one</strong> possible solution. </p>
<p>So for example you can not have this input here which produces no solution because there are no two numbers in that list that add up to the target.</p>
<pre><code class="lang-js">[<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>]
<span class="hljs-attr">target</span>: <span class="hljs-number">55</span>
</code></pre>
<p>You will also not get an input with multiple solutions. The following input has two answers of <code>[0,1]</code> and <code>[1,2]</code> which goes against the rules of this problem. </p>
<pre><code class="lang-js">[<span class="hljs-number">3</span>,<span class="hljs-number">3</span>,<span class="hljs-number">3</span>]
<span class="hljs-attr">target</span>: <span class="hljs-number">6</span>
</code></pre>
<h3 id="heading-brute-force-approach">Brute Force Approach</h3>
<p>The more intuitive approach would be to start at the beginning of the list of numbers and compare each possible pair of numbers until we find the pair that adds up to the target. </p>
<p>Let's take a look at this example here:</p>
<pre><code class="lang-js">[<span class="hljs-number">11</span>, <span class="hljs-number">15</span>, <span class="hljs-number">2</span>, <span class="hljs-number">7</span>]
<span class="hljs-attr">target</span>:<span class="hljs-number">9</span>
</code></pre>
<p>We can start with the first number in the list (11) and check each possible pair and see if it adds up to the target number (9).</p>
<pre><code><span class="hljs-number">11</span> + <span class="hljs-number">15</span> = <span class="hljs-number">9</span>? NO
<span class="hljs-number">11</span> + <span class="hljs-number">2</span> = <span class="hljs-number">9</span>? NO
<span class="hljs-number">11</span> + <span class="hljs-number">7</span> = <span class="hljs-number">9</span>? NO
</code></pre><p>Since none of those pairs equal the target (9), then we move to the second number in the list (15) and check all possible pairs. There is no need to check 11+15 because we already checked that earlier.</p>
<pre><code><span class="hljs-number">15</span> + <span class="hljs-number">2</span> = <span class="hljs-number">9</span>? NO
<span class="hljs-number">15</span> + <span class="hljs-number">7</span> = <span class="hljs-number">9</span>? NO
</code></pre><p>Since none of those pairs equal the target (9), then we move to the third number in the list (2) and check all possible pairs.</p>
<pre><code><span class="hljs-number">2</span> + <span class="hljs-number">7</span> = <span class="hljs-number">9</span>? YES!!!
</code></pre><p>Now, we have found the pair that adds up to the target we would return <code>[2,3]</code> because that represents the indices for where the pair of numbers can be found in the array. </p>
<h3 id="heading-brute-force-javascript-solution-and-time-complexity">Brute Force JavaScript Solution and Time Complexity</h3>
<p>This solution uses a nested <code>for</code> loop which would be an O(n²) time complexity. The outer loop is used to get the current number in the list and the inner loop is used to check if the sum of the current number and other numbers in the list add up to the target.</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{number}</span> <span class="hljs-variable">target</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number[]}</span></span>
 */</span>

<span class="hljs-keyword">var</span> twoSum = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">nums, target</span>) </span>{
  <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">2</span>) <span class="hljs-keyword">return</span> [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>];

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; nums.length; i++) {
    <span class="hljs-keyword">const</span> currentNum = nums[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; nums.length; j++) {
      <span class="hljs-keyword">if</span> (currentNum + nums[j] === target) <span class="hljs-keyword">return</span> [i, j];
    }
  }
};
</code></pre>
<p><strong>Note:</strong> I have added an additional check in my solution to check if the input array has only two numbers. In that case, we immediately return <code>[0,1]</code> because those are the only possible indices for that test case. </p>
<pre><code class="lang-js"> <span class="hljs-keyword">if</span> (nums.length === <span class="hljs-number">2</span>) <span class="hljs-keyword">return</span> [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>];
</code></pre>
<p>So far, our input arrays have been very small. But if we had an input array of 100, 500, or 1000+ numbers, then it could take a while to find the pair that adds up to the target. </p>
<p>In the next section, we are going to take a look at a solution that utilizes JavaScript's <code>Map</code> object and runs in linear time O(n).</p>
<h3 id="heading-map-approach-and-solution">Map Approach and Solution</h3>
<p>In the brute force approach, we started at the beginning of the array and compared all possible pairs of numbers until we found the pair that added up to the target. But in this approach we can use JavaScript's <code>Map</code> object and one <code>for</code> loop to find that pair.</p>
<p>JavaScript's <code>Map</code> object is a collection of key-value pairs that allows for quick lookups and has built in methods like <code>set()</code>, <code>get()</code> and <code>has()</code>.</p>
<p>Let's work with the same example from earlier:</p>
<pre><code class="lang-js">[<span class="hljs-number">11</span>, <span class="hljs-number">15</span>, <span class="hljs-number">2</span>, <span class="hljs-number">7</span>]
<span class="hljs-attr">target</span>:<span class="hljs-number">9</span>
</code></pre>
<p>We can start looping through the array and look at the current number in the list which would be <code>nums[i]</code>. We also want to create a new <code>map</code> object which will be empty to start.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

<span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i=<span class="hljs-number">0</span>; i&lt;nums.length; i++){

}
</code></pre>
<p>Inside our loop, we need to calculate the difference which will be the target minus the current number.</p>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i=<span class="hljs-number">0</span>; i&lt;nums.length; i++){
        <span class="hljs-keyword">const</span> difference = target - nums[i]
    }
</code></pre>
<p>Since we know there can only be two numbers that add up to the target, we can check if the difference is in the <code>map</code>. If so, we have found the pair and can return the indices. Otherwise, we can add that current number to the <code>map</code> along with its index.</p>
<pre><code class="lang-js">    <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">let</span> i=<span class="hljs-number">0</span>; i &lt; nums.length; i++) {
        <span class="hljs-keyword">const</span> difference = target - nums[i]

        <span class="hljs-keyword">if</span>(map.has(difference)) {
            <span class="hljs-keyword">return</span> [map.get(difference), i]
        } <span class="hljs-keyword">else</span> {
            map.set(nums[i], i)
        }
    }
</code></pre>
<p>In the following code, the <code>has()</code> method is used to check if the following <code>key</code> is in the <code>map</code> object. This method will return a boolean of true or false. </p>
<pre><code class="lang-js">map.has(difference)
</code></pre>
<p>The <code>get()</code> method is used to return that element from the <code>map</code>. </p>
<pre><code class="lang-js"> <span class="hljs-keyword">if</span>(map.has(difference)) {
   <span class="hljs-keyword">return</span> [map.get(difference), i]
 }
</code></pre>
<p>The <code>set()</code> method will add or update an entry in the <code>map</code> with a key and value.</p>
<pre><code class="lang-js"><span class="hljs-keyword">else</span> {
  map.set(nums[i], i)
}
</code></pre>
<p>Here is the complete code for this approach:</p>
<pre><code class="lang-js"><span class="hljs-comment">/**
 * <span class="hljs-doctag">@param <span class="hljs-type">{number[]}</span> <span class="hljs-variable">nums</span></span>
 * <span class="hljs-doctag">@param <span class="hljs-type">{number}</span> <span class="hljs-variable">target</span></span>
 * <span class="hljs-doctag">@return <span class="hljs-type">{number[]}</span></span>
 */</span>
<span class="hljs-keyword">var</span> twoSum = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">nums, target</span>) </span>{
    <span class="hljs-keyword">if</span>(nums.length === <span class="hljs-number">2</span>) <span class="hljs-keyword">return</span> [<span class="hljs-number">0</span>,<span class="hljs-number">1</span>]

    <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; nums.length; i++) {
        <span class="hljs-keyword">const</span> difference = target - nums[i]

        <span class="hljs-keyword">if</span> (map.has(difference)) {
            <span class="hljs-keyword">return</span> [map.get(difference), i]
        } <span class="hljs-keyword">else</span> {
            map.set(nums[i], i)
        }
    }

};
</code></pre>
<h3 id="heading-time-complexity-for-the-map-solution">Time Complexity for the Map Solution</h3>
<p>This solution would be a linear time complexity O(n). Since we are only using one loop instead of two, we have improved on the time complexity and no longer running in quadratic time O(n²) like we were earlier.</p>
<p>In the next few sections, we are going to start to build out the visualizations for each of these approaches. </p>
<h2 id="heading-overview-for-the-two-sum-visualization">Overview for the Two Sum Visualization</h2>
<p>The goal of this project is to create visualizations for both the map and brute force solutions. </p>
<p>For the brute force solution, we will show what is it like to walk through each pair of numbers until we find the pair that adds up to the target.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-20-at-8.43.08-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Brute Force approach visualization</em></p>
<p>For the map solution, we will show the map being built out and checking for the pair that adds up to the target. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-20-at-8.51.40-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Map solution visualization</em></p>
<h2 id="heading-adding-the-brute-force-visualization">Adding the Brute Force Visualization</h2>
<h3 id="heading-creating-the-const-and-let-variables">Creating the <code>const</code> and <code>let</code> Variables</h3>
<p>We first need to create <code>const</code> variables and assign them the result of accessing the HTML elements responsible for displaying the brute force solution button and output.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceSolutionBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"brute-force-visual-btn"</span>);
<span class="hljs-keyword">const</span> bruteForceNumbersOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .numbers-array"</span>
);
<span class="hljs-keyword">const</span> bruteForceTextOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .result-text"</span>
);
</code></pre>
<p>The next step is to create <code>const</code> variables for the test case array and target that will be used for both visualizations. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testCaseArray = [<span class="hljs-number">11</span>, <span class="hljs-number">15</span>, <span class="hljs-number">2</span>, <span class="hljs-number">7</span>];
<span class="hljs-keyword">const</span> target = <span class="hljs-number">9</span>;
</code></pre>
<p>Then, we need to create the <code>let</code> variables that will represent the current number we are looking at in the outer loop and the compliment number we are looking at in the inner loop. </p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> currentNum;
<span class="hljs-keyword">let</span> currentCompliment;
</code></pre>
<h3 id="heading-creating-the-getclassname-function">Creating the <code>getClassName</code> Function</h3>
<p>In our visualization we want to show the user the current pair of numbers we are checking by applying different colored borders around them. The current number will have a green border around it and the current compliment number will have a blue border around it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-20-at-10.02.46-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In order to dynamically update these styles over time, we need to create a function that will be responsible for adding the appropriate classes to the current number and it compliment. </p>
<p>First, start by creating a new <code>getClassName</code> function that takes in a <code>num</code> parameter.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getClassName = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {

};
</code></pre>
<p>Inside that function, create a <code>switch</code> statement that has the <code>num</code> for the expression we are checking for. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getClassName = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (num) {

  }
};
</code></pre>
<p>The first <code>case</code> should check for <code>currentNum</code> and return a string for the <code>current-num</code> class.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getClassName = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (num) {
    <span class="hljs-keyword">case</span> currentNum:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='current-num'"</span>;
  }
};
</code></pre>
<p>The second <code>case</code> should check for the <code>currentCompliment</code> and return a string for the <code>compliment-num</code> class. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getClassName = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (num) {
    <span class="hljs-keyword">case</span> currentNum:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='current-num'"</span>;
    <span class="hljs-keyword">case</span> currentCompliment:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='compliment-num'"</span>;
  }
};
</code></pre>
<p>For the <code>default</code> case, it should return an empty string because we are not going to apply any classes for that element. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> getClassName = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (num) {
    <span class="hljs-keyword">case</span> currentNum:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='current-num'"</span>;
    <span class="hljs-keyword">case</span> currentCompliment:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='compliment-num'"</span>;
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
  }
};
</code></pre>
<h3 id="heading-creating-the-bruteforceapproach-function">Creating the <code>bruteForceApproach</code> Function</h3>
<p>This function will be responsible for executing the brute force solution and displaying the visualization on the page. </p>
<p>We first need to create the <code>bruteForceApproach</code> function which will be an <code>async</code> function. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {

};
</code></pre>
<p>Then, we need to add the outer loop for our test case array.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {

  }
};
</code></pre>
<p>Inside the <code>for</code> loop, update the <code>currentNum</code> to assign it the value of the current number we are looking at in the test case array.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
  }
};
</code></pre>
<p>Next, create the inner <code>for</code> loop.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {

    }
  }
};
</code></pre>
<p>Inside the inner <code>for</code> loop, update the <code>currentCompliment</code> number and assign it the value of <code>testCaseArray[j]</code>. This is meant to represent each number to the right of the current number. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {
      currentCompliment = testCaseArray[j];
    }
  }
};
</code></pre>
<p>Next, we need to add a <code>setTimeout</code> which will delay the visual changes made to the markup by one second. This is what is going to help create the animated effect of showing the different pairs of numbers. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {
      currentCompliment = testCaseArray[j];
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));
    }
  }
};
</code></pre>
<p>Then we need to update the HTML for the output. Start by assigning the test case array to <code>bruteForceNumbersOutput.innerHTML</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {
      currentCompliment = testCaseArray[j];
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));

      bruteForceNumbersOutput.innerHTML = testCaseArray;
    }
  }
};
</code></pre>
<p>Then, we want to use the <code>map</code> method on the array, to create a new array of <code>span</code> elements which represents each number in the array along with the styles. We also need to chain the <code>join</code> method on that to remove the commas that the <code>map</code> method adds when the new array is created.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {
      currentCompliment = testCaseArray[j];
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));

      bruteForceNumbersOutput.innerHTML = testCaseArray
        .map(
          <span class="hljs-function">(<span class="hljs-params">num, index</span>) =&gt;</span>
            <span class="hljs-string">`
            &lt;span <span class="hljs-subst">${getClassName(num)}</span>&gt;
            <span class="hljs-subst">${testCaseArray[index]}</span>
            &lt;/span&gt;
          `</span>
        )
        .join(<span class="hljs-string">""</span>);
    }
  }
};
</code></pre>
<p>If we don't find a pair that adds up to the target, then we want to display a message to the user. Update the text content for the <code>bruteForceTextOutput</code> and assign it the following message:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {
      currentCompliment = testCaseArray[j];
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));

      bruteForceNumbersOutput.innerHTML = testCaseArray
        .map(
          <span class="hljs-function">(<span class="hljs-params">num, index</span>) =&gt;</span>
            <span class="hljs-string">`
            &lt;span <span class="hljs-subst">${getClassName(num)}</span>&gt;
            <span class="hljs-subst">${testCaseArray[index]}</span>
            &lt;/span&gt;
          `</span>
        )
        .join(<span class="hljs-string">""</span>);

      bruteForceTextOutput.textContent = <span class="hljs-string">`Does the sum of <span class="hljs-subst">${currentNum}</span> + <span class="hljs-subst">${currentCompliment}</span> equal <span class="hljs-subst">${target}</span>? NO!`</span>;
    }
  }
};
</code></pre>
<p>The last piece is to add a condition that checks if we found the pair of numbers that adds up to the target. If so, then we can display that final indices array and <code>return</code> from the function. </p>
<pre><code class="lang-js">  <span class="hljs-keyword">if</span> (currentNum + currentCompliment === target) {
      bruteForceTextOutput.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${i}</span>, <span class="hljs-subst">${j}</span>]`</span>;
      <span class="hljs-keyword">return</span>;
  }
</code></pre>
<p>To test out the brute force visualization, we will need to add an event listener to the <code>bruteForceSolutionBtn</code>. The event listener should listen for a <code>"click"</code> event and should reference the <code>bruteForceApproach</code> function.</p>
<pre><code class="lang-js">bruteForceSolutionBtn.addEventListener(<span class="hljs-string">"click"</span>, bruteForceApproach);
</code></pre>
<p>This should be your complete code so far:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceSolutionBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"brute-force-visual-btn"</span>);
<span class="hljs-keyword">const</span> bruteForceNumbersOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .numbers-array"</span>
);
<span class="hljs-keyword">const</span> bruteForceTextOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .result-text"</span>
);
<span class="hljs-keyword">const</span> testCaseArray = [<span class="hljs-number">11</span>, <span class="hljs-number">15</span>, <span class="hljs-number">2</span>, <span class="hljs-number">7</span>];
<span class="hljs-keyword">const</span> target = <span class="hljs-number">9</span>;
<span class="hljs-keyword">let</span> currentNum;
<span class="hljs-keyword">let</span> currentCompliment;

<span class="hljs-keyword">const</span> getClassName = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (num) {
    <span class="hljs-keyword">case</span> currentNum:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='current-num'"</span>;
    <span class="hljs-keyword">case</span> currentCompliment:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='compliment-num'"</span>;
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
  }
};

<span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {
      currentCompliment = testCaseArray[j];
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));

      bruteForceNumbersOutput.innerHTML = testCaseArray
        .map(
          <span class="hljs-function">(<span class="hljs-params">num, index</span>) =&gt;</span>
            <span class="hljs-string">`
            &lt;span <span class="hljs-subst">${getClassName(num)}</span>&gt;
            <span class="hljs-subst">${testCaseArray[index]}</span>
            &lt;/span&gt;
          `</span>
        )
        .join(<span class="hljs-string">""</span>);

      bruteForceTextOutput.textContent = <span class="hljs-string">`Does the sum of <span class="hljs-subst">${currentNum}</span> + <span class="hljs-subst">${currentCompliment}</span> equal <span class="hljs-subst">${target}</span>? NO!`</span>;

      <span class="hljs-keyword">if</span> (currentNum + currentCompliment === target) {
        bruteForceTextOutput.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${i}</span>, <span class="hljs-subst">${j}</span>]`</span>;
        <span class="hljs-keyword">return</span>;
      }
    }
  }
};

bruteForceSolutionBtn.addEventListener(<span class="hljs-string">"click"</span>, bruteForceApproach);
</code></pre>
<p>Try out your visualization by clicking on the "Show Visualization" button for the Brute force approach. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-20-at-10.42.51-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Result of clicking the "show visualization" button for brute force approach</em></p>
<h2 id="heading-how-to-disable-the-bruteforcesolutionbtn-when-the-animation-is-in-progress">How to Disable the <code>bruteForceSolutionBtn</code> When the Animation is in Progress</h2>
<p>If you try to click on the <code>bruteForceSolutionBtn</code> multiple times in a row, you will see glitches in the animation. To fix that, we should disable the button when the animation is running and then re-enable it when the animation is complete. </p>
<p>Inside the <code>bruteForceApproach</code> function, set the disabled attribute for the <code>bruteForceSolutionBtn</code>. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  bruteForceSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
</code></pre>
<p>Inside the <code>if</code> statement, remove the disabled attribute for the <code>bruteForceSolutionBtn</code>.</p>
<pre><code class="lang-js">   <span class="hljs-keyword">if</span> (currentNum + currentCompliment === target) {
        bruteForceTextOutput.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${i}</span>, <span class="hljs-subst">${j}</span>]`</span>;
        bruteForceSolutionBtn.removeAttribute(<span class="hljs-string">"disabled"</span>);
        <span class="hljs-keyword">return</span>;
   }
</code></pre>
<p>Here is the complete code with the fix:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceSolutionBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"brute-force-visual-btn"</span>);
<span class="hljs-keyword">const</span> bruteForceNumbersOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .numbers-array"</span>
);
<span class="hljs-keyword">const</span> bruteForceTextOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .result-text"</span>
);
<span class="hljs-keyword">const</span> testCaseArray = [<span class="hljs-number">11</span>, <span class="hljs-number">15</span>, <span class="hljs-number">2</span>, <span class="hljs-number">7</span>];
<span class="hljs-keyword">const</span> target = <span class="hljs-number">9</span>;
<span class="hljs-keyword">let</span> currentNum;
<span class="hljs-keyword">let</span> currentCompliment;

<span class="hljs-keyword">const</span> getClassName = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (num) {
    <span class="hljs-keyword">case</span> currentNum:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='current-num'"</span>;
    <span class="hljs-keyword">case</span> currentCompliment:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='compliment-num'"</span>;
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
  }
};

<span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  bruteForceSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {
      currentCompliment = testCaseArray[j];
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));

      bruteForceNumbersOutput.innerHTML = testCaseArray
        .map(
          <span class="hljs-function">(<span class="hljs-params">num, index</span>) =&gt;</span>
            <span class="hljs-string">`
            &lt;span <span class="hljs-subst">${getClassName(num)}</span>&gt;
            <span class="hljs-subst">${testCaseArray[index]}</span>
            &lt;/span&gt;
          `</span>
        )
        .join(<span class="hljs-string">""</span>);

      bruteForceTextOutput.textContent = <span class="hljs-string">`Does the sum of <span class="hljs-subst">${currentNum}</span> + <span class="hljs-subst">${currentCompliment}</span> equal <span class="hljs-subst">${target}</span>? NO!`</span>;

      <span class="hljs-keyword">if</span> (currentNum + currentCompliment === target) {
        bruteForceTextOutput.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${i}</span>, <span class="hljs-subst">${j}</span>]`</span>;
        bruteForceSolutionBtn.removeAttribute(<span class="hljs-string">"disabled"</span>);
        <span class="hljs-keyword">return</span>;
      }
    }
  }
};

bruteForceSolutionBtn.addEventListener(<span class="hljs-string">"click"</span>, bruteForceApproach);
</code></pre>
<p>Try out the visualization again, and now you should see that the button is disabled when the animation is running.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-20-at-10.56.36-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image showing how button is disabled when animation is showing</em></p>
<h2 id="heading-adding-the-map-solution-visualization">Adding the Map Solution Visualization</h2>
<h3 id="heading-creating-the-const-variables">Creating the <code>const</code> Variables</h3>
<p>We are going to create some new <code>const</code> variables which represent the optimal solution button element, output, and table elements for the animation.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalSolutionBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"optimal-visual-btn"</span>);
<span class="hljs-keyword">const</span> currentValueOutput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"current-value-output"</span>);
<span class="hljs-keyword">const</span> finalOptimalSolutionResult = <span class="hljs-built_in">document</span>.getElementById(
  <span class="hljs-string">"final-optimal-result"</span>
);
<span class="hljs-keyword">const</span> table = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"table-output"</span>);
<span class="hljs-keyword">const</span> tableBodyOutput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"map-table-body"</span>);
</code></pre>
<p>Here is the complete list of variable declarations for both visualizations:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceSolutionBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"brute-force-visual-btn"</span>);
<span class="hljs-keyword">const</span> bruteForceNumbersOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .numbers-array"</span>
);
<span class="hljs-keyword">const</span> bruteForceTextOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .result-text"</span>
);
<span class="hljs-keyword">const</span> optimalSolutionBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"optimal-visual-btn"</span>);
<span class="hljs-keyword">const</span> currentValueOutput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"current-value-output"</span>);
<span class="hljs-keyword">const</span> finalOptimalSolutionResult = <span class="hljs-built_in">document</span>.getElementById(
  <span class="hljs-string">"final-optimal-result"</span>
);
<span class="hljs-keyword">const</span> table = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"table-output"</span>);
<span class="hljs-keyword">const</span> tableBodyOutput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"map-table-body"</span>);

<span class="hljs-keyword">const</span> testCaseArray = [<span class="hljs-number">11</span>, <span class="hljs-number">15</span>, <span class="hljs-number">2</span>, <span class="hljs-number">7</span>];
<span class="hljs-keyword">const</span> target = <span class="hljs-number">9</span>;
<span class="hljs-keyword">let</span> currentNum;
<span class="hljs-keyword">let</span> currentCompliment;
</code></pre>
<h3 id="heading-creating-the-optimalapproach-async-function">Creating the <code>optimalApproach</code> Async Function</h3>
<p>The first step is to create the new <code>optimalApproach</code> function which will be an <code>async</code> function. You can add this below your <code>bruteForceApproach</code> function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {

};
</code></pre>
<p>Just like the <code>bruteForceApproach</code> function, we want to disable the button when the animation starts to prevent users from clicking it multiple times and breaking the animation.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
};
</code></pre>
<p>When the page first loads, the table is hidden by default. We want to show the table element when the animation starts.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
};
</code></pre>
<p>Each time we run this animation, we want to display messages to the user on if we have found the correct pair or not. At the beginning of the animation, we want to clear the previous output. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
  currentValueOutput.innerHTML = <span class="hljs-string">""</span>;
};
</code></pre>
<p>Then, we need to create an empty <code>map</code> object which will eventually be updated over time in the <code>for</code> loop.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
  currentValueOutput.innerHTML = <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();
};
</code></pre>
<p>Next, we need to create a <code>for</code> loop which will be responsible for looping through each number in the array and updating the animation overtime. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
  currentValueOutput.innerHTML = <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {

  }
};
</code></pre>
<p>Inside the loop, we need to add the expression for calculating the difference.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
  currentValueOutput.innerHTML = <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    <span class="hljs-keyword">const</span> difference = target - testCaseArray[i];
  }
};
</code></pre>
<p>Then, we need to add a <code>setTimeout</code> which will delay the changes by 2 seconds in the HTML markup and help with the animation effect.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
  currentValueOutput.innerHTML = <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    <span class="hljs-keyword">const</span> difference = target - testCaseArray[i];

    <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">2000</span>));
  }
};
</code></pre>
<p>We then need to add an <code>if</code> statement to check if the map has the difference value.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
  currentValueOutput.innerHTML = <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    <span class="hljs-keyword">const</span> difference = target - testCaseArray[i];

    <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">2000</span>));

    <span class="hljs-keyword">if</span> (map.has(difference)) {

    }
  }
};
</code></pre>
<p>Inside the <code>if</code> statement, we need to update the text content to show the final indices array result on the screen. We will use the <code>get</code> method to get the index value from the <code>map</code>. </p>
<pre><code class="lang-js"> <span class="hljs-keyword">if</span> (map.has(difference)) {
      finalOptimalSolutionResult.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${map.get(
        difference
      )}</span>, <span class="hljs-subst">${i}</span>]`</span>;
 }
</code></pre>
<p>We also need to update the output for displaying a message that shows we have found the pair of numbers that adds up to the target. </p>
<pre><code class="lang-js">  <span class="hljs-keyword">if</span> (map.has(difference)) {
      finalOptimalSolutionResult.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${map.get(
        difference
      )}</span>, <span class="hljs-subst">${i}</span>]`</span>;
      currentValueOutput.innerHTML = <span class="hljs-string">`
      &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
      &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? YES, we found that pair of numbers that add up to the target.&lt;/p&gt;
    `</span>;
  }
</code></pre>
<p>We also need to remove the disabled attribute from the <code>optimalSolutionBtn</code> and return from the function. </p>
<pre><code class="lang-js">  <span class="hljs-keyword">if</span> (map.has(difference)) {
      finalOptimalSolutionResult.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${map.get(
        difference
      )}</span>, <span class="hljs-subst">${i}</span>]`</span>;
      currentValueOutput.innerHTML = <span class="hljs-string">`
      &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
      &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? YES, we found that pair of numbers that add up to the target.&lt;/p&gt;
    `</span>;
      optimalSolutionBtn.removeAttribute(<span class="hljs-string">"disabled"</span>);
      <span class="hljs-keyword">return</span>;
  }
</code></pre>
<p>If the pair has not been found, then we need to add an <code>else</code> clause.</p>
<pre><code class="lang-js">  <span class="hljs-keyword">if</span> (map.has(difference)) {
      finalOptimalSolutionResult.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${map.get(
        difference
      )}</span>, <span class="hljs-subst">${i}</span>]`</span>;
      currentValueOutput.innerHTML = <span class="hljs-string">`
      &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
      &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? YES, we found that pair of numbers that add up to the target.&lt;/p&gt;
    `</span>;
      optimalSolutionBtn.removeAttribute(<span class="hljs-string">"disabled"</span>);
      <span class="hljs-keyword">return</span>;
  } <span class="hljs-keyword">else</span> {

  }
</code></pre>
<p>Inside the <code>else</code> clause, we need to update the message to show that we have not found the pair and that the current number <code>testCaseArray[i]</code> is going to be added to the <code>map</code> along with its index value.</p>
<pre><code class="lang-js"><span class="hljs-keyword">else</span> {
      currentValueOutput.innerHTML = <span class="hljs-string">`
        &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
        &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? No.&lt;/p&gt;
        &lt;p&gt;Add the current number <span class="hljs-subst">${testCaseArray[i]}</span> to our map.&lt;/p&gt;
      `</span>;
}
</code></pre>
<p>We then need to update the table output with the current number and its index value.</p>
<pre><code class="lang-js"><span class="hljs-keyword">else</span> {
      currentValueOutput.innerHTML = <span class="hljs-string">`
        &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
        &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? No.&lt;/p&gt;
        &lt;p&gt;Add the current number <span class="hljs-subst">${testCaseArray[i]}</span> to our map.&lt;/p&gt;
      `</span>;
      tableBodyOutput.innerHTML += <span class="hljs-string">`
      &lt;tr&gt;
        &lt;td&gt;<span class="hljs-subst">${testCaseArray[i]}</span>&lt;/td&gt;
        &lt;td&gt;<span class="hljs-subst">${i}</span>&lt;/td&gt;
      &lt;/tr&gt;
    `</span>;
}
</code></pre>
<p>Lastly, use the <code>set</code> method to set the current number and index value in the <code>map</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">else</span> {
      currentValueOutput.innerHTML = <span class="hljs-string">`
        &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
        &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? No.&lt;/p&gt;
        &lt;p&gt;Add the current number <span class="hljs-subst">${testCaseArray[i]}</span> to our map.&lt;/p&gt;
      `</span>;
      tableBodyOutput.innerHTML += <span class="hljs-string">`
      &lt;tr&gt;
        &lt;td&gt;<span class="hljs-subst">${testCaseArray[i]}</span>&lt;/td&gt;
        &lt;td&gt;<span class="hljs-subst">${i}</span>&lt;/td&gt;
      &lt;/tr&gt;
    `</span>;
      map.set(testCaseArray[i], i);
}
</code></pre>
<p>Here is the complete code for your <code>optimalApproach</code> function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
  currentValueOutput.innerHTML = <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    <span class="hljs-keyword">const</span> difference = target - testCaseArray[i];

    <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">2000</span>));

    <span class="hljs-keyword">if</span> (map.has(difference)) {
      finalOptimalSolutionResult.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${map.get(
        difference
      )}</span>, <span class="hljs-subst">${i}</span>]`</span>;
      currentValueOutput.innerHTML = <span class="hljs-string">`
      &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
      &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? YES, we found that pair of numbers that add up to the target.&lt;/p&gt;
    `</span>;
      optimalSolutionBtn.removeAttribute(<span class="hljs-string">"disabled"</span>);
      <span class="hljs-keyword">return</span>;
    } <span class="hljs-keyword">else</span> {
      currentValueOutput.innerHTML = <span class="hljs-string">`
        &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
        &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? No.&lt;/p&gt;
        &lt;p&gt;Add the current number <span class="hljs-subst">${testCaseArray[i]}</span> to our map.&lt;/p&gt;
      `</span>;
      tableBodyOutput.innerHTML += <span class="hljs-string">`
      &lt;tr&gt;
        &lt;td&gt;<span class="hljs-subst">${testCaseArray[i]}</span>&lt;/td&gt;
        &lt;td&gt;<span class="hljs-subst">${i}</span>&lt;/td&gt;
      &lt;/tr&gt;
    `</span>;
      map.set(testCaseArray[i], i);
    }
  }
};
</code></pre>
<p>To test out this visualization, add an event listener to the <code>optimalSolutionBtn</code> and pass in the <code>"click"</code> event and <code>optimalApproach</code> function reference. </p>
<pre><code class="lang-js">optimalSolutionBtn.addEventListener(<span class="hljs-string">"click"</span>, optimalApproach);
</code></pre>
<p>When you click on the "Show Visualization" button for the map solution, you should see the animation, as shown below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-20-at-12.05.05-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visualization for map solution</em></p>
<h2 id="heading-how-to-reset-the-table-output-for-the-map-solution">How to Reset the Table Output for the Map Solution</h2>
<p>If you try to run the animation multiple times, then you will see that the table shows the results from the previous run.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/Screenshot-2023-11-20-at-12.09.35-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Table showing results from the previous run</em></p>
<p>To fix this, we can reset the table before each run of the animation. Start by creating a <code>resetTable</code> function above your <code>optimalApproach</code> function.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> resetTable = <span class="hljs-function">() =&gt;</span> {

};

<span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
    .........
</code></pre>
<p>Inside that function, clear out the table and final text results. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> resetTable = <span class="hljs-function">() =&gt;</span> {
  tableBodyOutput.innerHTML = <span class="hljs-string">""</span>;
  finalOptimalSolutionResult.textContent = <span class="hljs-string">""</span>;
};
</code></pre>
<p>Call the <code>resetTable</code> function inside your <code>optimalApproach</code> function in order to see the results of resetting the table.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  resetTable();
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
    ...........
</code></pre>
<p>Test out your animation again, and now you should see that the table results reset before each new animation run. </p>
<h2 id="heading-final-solution-code-and-live-example">Final Solution Code and Live Example</h2>
<p>Here is the complete JavaScript solution code for both visualizations:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> bruteForceSolutionBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"brute-force-visual-btn"</span>);
<span class="hljs-keyword">const</span> bruteForceNumbersOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .numbers-array"</span>
);
<span class="hljs-keyword">const</span> bruteForceTextOutput = <span class="hljs-built_in">document</span>.querySelector(
  <span class="hljs-string">"#brute-force-output &gt; .result-text"</span>
);
<span class="hljs-keyword">const</span> optimalSolutionBtn = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"optimal-visual-btn"</span>);
<span class="hljs-keyword">const</span> currentValueOutput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"current-value-output"</span>);
<span class="hljs-keyword">const</span> finalOptimalSolutionResult = <span class="hljs-built_in">document</span>.getElementById(
  <span class="hljs-string">"final-optimal-result"</span>
);
<span class="hljs-keyword">const</span> table = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"table-output"</span>);
<span class="hljs-keyword">const</span> tableBodyOutput = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"map-table-body"</span>);

<span class="hljs-keyword">const</span> testCaseArray = [<span class="hljs-number">11</span>, <span class="hljs-number">15</span>, <span class="hljs-number">2</span>, <span class="hljs-number">7</span>];
<span class="hljs-keyword">const</span> target = <span class="hljs-number">9</span>;
<span class="hljs-keyword">let</span> currentNum;
<span class="hljs-keyword">let</span> currentCompliment;

<span class="hljs-keyword">const</span> getClassName = <span class="hljs-function">(<span class="hljs-params">num</span>) =&gt;</span> {
  <span class="hljs-keyword">switch</span> (num) {
    <span class="hljs-keyword">case</span> currentNum:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='current-num'"</span>;
    <span class="hljs-keyword">case</span> currentCompliment:
      <span class="hljs-keyword">return</span> <span class="hljs-string">"class='compliment-num'"</span>;
    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">return</span> <span class="hljs-string">""</span>;
  }
};

<span class="hljs-keyword">const</span> bruteForceApproach = <span class="hljs-keyword">async</span> () =&gt; {
  bruteForceSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    currentNum = testCaseArray[i];
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> j = i + <span class="hljs-number">1</span>; j &lt; testCaseArray.length; ++j) {
      currentCompliment = testCaseArray[j];
      <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">1000</span>));

      bruteForceNumbersOutput.innerHTML = testCaseArray
        .map(
          <span class="hljs-function">(<span class="hljs-params">num, index</span>) =&gt;</span>
            <span class="hljs-string">`
              &lt;span <span class="hljs-subst">${getClassName(num)}</span>&gt;
              <span class="hljs-subst">${testCaseArray[index]}</span>
              &lt;/span&gt;
            `</span>
        )
        .join(<span class="hljs-string">""</span>);

      bruteForceTextOutput.textContent = <span class="hljs-string">`Does the sum of <span class="hljs-subst">${currentNum}</span> + <span class="hljs-subst">${currentCompliment}</span> equal <span class="hljs-subst">${target}</span>? NO!`</span>;

      <span class="hljs-keyword">if</span> (currentNum + currentCompliment === target) {
        bruteForceTextOutput.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${i}</span>, <span class="hljs-subst">${j}</span>]`</span>;
        bruteForceSolutionBtn.removeAttribute(<span class="hljs-string">"disabled"</span>);
        <span class="hljs-keyword">return</span>;
      }
    }
  }
};

<span class="hljs-keyword">const</span> resetTable = <span class="hljs-function">() =&gt;</span> {
  tableBodyOutput.innerHTML = <span class="hljs-string">""</span>;
  finalOptimalSolutionResult.textContent = <span class="hljs-string">""</span>;
};

<span class="hljs-keyword">const</span> optimalApproach = <span class="hljs-keyword">async</span> () =&gt; {
  resetTable();
  optimalSolutionBtn.setAttribute(<span class="hljs-string">"disabled"</span>, <span class="hljs-string">""</span>);
  table.style.display = <span class="hljs-string">"block"</span>;
  currentValueOutput.innerHTML = <span class="hljs-string">""</span>;
  <span class="hljs-keyword">const</span> map = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Map</span>();

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; testCaseArray.length; ++i) {
    <span class="hljs-keyword">const</span> difference = target - testCaseArray[i];

    <span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, <span class="hljs-number">2000</span>));

    <span class="hljs-keyword">if</span> (map.has(difference)) {
      finalOptimalSolutionResult.textContent = <span class="hljs-string">`Final indices: [<span class="hljs-subst">${map.get(
        difference
      )}</span>, <span class="hljs-subst">${i}</span>]`</span>;
      currentValueOutput.innerHTML = <span class="hljs-string">`
      &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
      &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? YES, we found that pair of numbers that add up to the target.&lt;/p&gt;
    `</span>;
      optimalSolutionBtn.removeAttribute(<span class="hljs-string">"disabled"</span>);
      <span class="hljs-keyword">return</span>;
    } <span class="hljs-keyword">else</span> {
      currentValueOutput.innerHTML = <span class="hljs-string">`
        &lt;p&gt;Difference(<span class="hljs-subst">${difference}</span>) = target(<span class="hljs-subst">${target}</span>) - current number(<span class="hljs-subst">${testCaseArray[i]}</span>)&lt;/p&gt;
        &lt;p&gt;Is the difference(<span class="hljs-subst">${difference}</span>) in our map? No.&lt;/p&gt;
        &lt;p&gt;Add the current number <span class="hljs-subst">${testCaseArray[i]}</span> to our map.&lt;/p&gt;
      `</span>;
      tableBodyOutput.innerHTML += <span class="hljs-string">`
        &lt;tr&gt;
          &lt;td&gt;<span class="hljs-subst">${testCaseArray[i]}</span>&lt;/td&gt;
          &lt;td&gt;<span class="hljs-subst">${i}</span>&lt;/td&gt;
        &lt;/tr&gt;
      `</span>;
      map.set(testCaseArray[i], i);
    }
  }
};

bruteForceSolutionBtn.addEventListener(<span class="hljs-string">"click"</span>, bruteForceApproach);
optimalSolutionBtn.addEventListener(<span class="hljs-string">"click"</span>, optimalApproach);
</code></pre>
<p>Here is a <a target="_blank" href="https://codepen.io/Jessica-Wilkins-the-decoder/full/eYxVyKN">link</a> again to the final live result on CodePen.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>I hope you enjoyed that project and learned a little bit more about how the Two Sum problem works. </p>
<p>I encourage you to play around with the project and maybe add some new features on your own like testing out different numbers or asking for user inputs for the numbers array and targets. 👍🏾</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Podcast: Data Visualization with Dr. Curran Kelleher ]]>
                </title>
                <description>
                    <![CDATA[ Today I'm joined by Dr. Curran Kelleher. He's a data visualization expert and has taught a number of in-depth data visualization courses on freeCodeCamp's YouTube channel. We talk about what it's like to get a Ph.D. under one of the pioneers of data ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/podcast-data-visualization-curran-kelleher/</link>
                <guid isPermaLink="false">66b8d50aeb5c4db85a0b3401</guid>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ phd ]]>
                    </category>
                
                    <category>
                        <![CDATA[ podcast ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Quincy Larson ]]>
                </dc:creator>
                <pubDate>Fri, 17 Nov 2023 21:09:40 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/11/quincy_and_curran_jpeg-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Today I'm joined by Dr. Curran Kelleher. He's a data visualization expert and has taught a number of in-depth data visualization courses on freeCodeCamp's YouTube channel.</p>
<p>We talk about what it's like to get a Ph.D. under one of the pioneers of data visualization.</p>
<p>We also talk about how he uses his visualization skills in industry, his many years living in India, and his love of teaching.</p>
<p>I think you're going to walk away with a deeper understanding of data, the human brain, and how we process information. You'll also learn some practical career tips.</p>
<p>I hope these weekly freeCodeCamp podcasts are firing you up about learning more about technology.</p>
<p>Be sure to follow The freeCodeCamp podcast in your favorite podcast app. And share this podcast with a friend. Let's inspire more folks to learn to code and build careers for themselves in tech.</p>
<p>You can listen to the podcast in Apple Podcasts, Spotify, or your favorite podcast app. You can also listen to the podcast below, right in your browser:</p>
<div class="embed-wrapper"><iframe src="https://play.libsyn.com/embed/episode/id/28694578/height/192/theme/modern/size/large/thumbnail/yes/custom-color/34345c/time-start/00:00:00/playlist-height/200/direction/backward/download/yes" height="192" width="100%" style="border:none" title="Embedded content" loading="lazy"></iframe></div>

<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/quincy_and_curran_jpeg.png" alt="Image" width="600" height="400" loading="lazy">
<em>Me with Dr. Curran Kelleher at South Park Commons in NYC</em></p>
<p>Some relevant links from our discussion:</p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/data-visualizatoin-with-d3/">Curran's 20-hour Data Visualization with D3 course on freeCodeCamp</a></p>
<p><a target="_blank" href="https://www.esri.com/en-us/esri-press/browse/semiology-of-graphics-diagrams-networks-maps">"Semiology of Graphics: Diagrams, Networks, Maps" book</a> that Curran mentions</p>
<p><a target="_blank" href="https://github.com/curran/portfolio">Curran's portfolio of work</a></p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=NGYGl_xxfXA">Bret Victor's talk "Inventing on Principle"</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create Diagrams as Code with Mermaid, GitHub, and Visual Studio Code ]]>
                </title>
                <description>
                    <![CDATA[ Diagrams are an important part of technical documentation. In this article we will explore how we can use code to generate diagrams and leverage them in Markdown. Here is an example of how a code generated diagram looks like: Diagram generated by co... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/diagrams-as-code-with-mermaid-github-and-vs-code/</link>
                <guid isPermaLink="false">66adea301ad24d82983fd24b</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ documentation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zaira Hira ]]>
                </dc:creator>
                <pubDate>Wed, 06 Sep 2023 20:51:45 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/mermaid-code-as-a-diagram.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Diagrams are an important part of technical documentation. In this article we will explore how we can use code to generate diagrams and leverage them in Markdown.</p>
<p>Here is an example of how a code generated diagram looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/Untitled-design--1-.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Diagram generated by code</em></p>
<p>No tools, no dragging, aligning and snapping shapes to places. Just code. Interesting right?</p>
<h2 id="heading-pre-requisites">Pre-requisites</h2>
<p>To follow along with this tutorial, you should have the following:</p>
<ul>
<li><p>A basic understanding of Markdown. Have a look at <a target="_blank" href="https://www.freecodecamp.org/news/markdown-cheat-sheet/">this guide</a> if you aren't familiar with Markdown.</p>
</li>
<li><p>Visual Studio Code with a Markdown previewing extension (covered in detail in coming sections).</p>
</li>
<li><p>GitHub, to understand how you can render diagrams there.</p>
</li>
</ul>
<h2 id="heading-advantages-of-generating-diagrams-as-code">Advantages of Generating Diagrams as Code</h2>
<p>There are several advantages of generating diagrams as code rather than using traditional methods to manually 'create' diagrams. Let's see some of them:</p>
<ul>
<li><p><strong>Dynamic</strong>: Code-generated diagrams are dynamic which means that you can easily update them by updating the code.</p>
</li>
<li><p><strong>Editable</strong>: With code-generated images, you are not relying on complex image generating tools. You can simply edit the code in a text editor and get an updated image.</p>
</li>
<li><p><strong>Efficient</strong>: Code-generated images are fast to load compared to static images. Also you don't need to host them separately as an image in your website.</p>
</li>
<li><p><strong>Quick to create</strong>: You can use a template and quickly come up with diagrams just using code. You don't need to invest the time and effort in learning image creation tools, that are usually overwhelming to start with.</p>
</li>
</ul>
<h2 id="heading-how-to-render-and-view-mermaid-code">How to Render and View Mermaid Code</h2>
<p>There are several ways you can create and view Mermaid diagrams.</p>
<h3 id="heading-vscode">VSCode</h3>
<p>First, install a Markdown previewer that has the support for Mermaid. Here is an example of such an extension: <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid">Markdown Preview Mermaid Support</a>.</p>
<p>Create an empty Markdown file using the extension <code>.md</code>. Write your code in this file and open the preview on the right pane:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/08/image-226.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Code and preview in VSCode</em></p>
<h3 id="heading-stackedit">StackEdit</h3>
<p><a target="_blank" href="https://stackedit.io/">StackEdit</a> is an online, browser-based Markdown previewer. It provides an editor window and a preview on the right side.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732173257560/a5cf3d3d-7db4-4176-a1b8-fc59597d5966.png" alt="a5cf3d3d-7db4-4176-a1b8-fc59597d5966" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><em>Code and preview in StackEdit</em></p>
<h3 id="heading-github">GitHub</h3>
<p>You can add Mermaid diagrams to create compelling README files in GitHub. Simply edit the <code>README.md</code> or any other Markdown file in GitHub to render Mermaid diagrams.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-40.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>Edit code in GitHub</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-41.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><em>View and render Mermaid diagram in GitHub</em></p>
<h2 id="heading-how-to-generate-diagrams-as-code-with-mermaid">How to Generate Diagrams as Code with Mermaid</h2>
<p>Mermaid is a JavaScript-based tool that transforms Markdown-style text into dynamic diagrams, allowing you to create and modify them effortlessly.</p>
<p>Mermaid makes it easy to generate diagrams and visuals using simple text and code.</p>
<p>It follows a simple syntax:</p>
<pre><code class="lang-bash">```mermaid
    your code goes here
    .
    .
    .

```
</code></pre>
<p>With Mermaid, you can generate the following diagram types:</p>
<ul>
<li><p>Flowchart</p>
</li>
<li><p>Sequence Diagram</p>
</li>
<li><p>Class Diagram</p>
</li>
<li><p>Gantt</p>
</li>
<li><p>Pie Chart</p>
</li>
</ul>
<p>Let's explore them one by one.</p>
<h3 id="heading-how-to-create-a-flowchart">How to Create a Flowchart</h3>
<p>A flowchart is a picture that shows the steps of a process using symbols, helping to explain the process in a clear and organized way. A flow chart is composed of nodes that are connected by arrows.</p>
<p>You can render flowcharts in mermaid using this example:</p>
<pre><code class="lang-bash">```mermaid
flowchart TD;
    A[Start] --&gt; B[Process 1];
    B --&gt; C[Process 2];
    C --&gt; D[End];
```
</code></pre>
<p><strong>Result:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732173454651/613d31f6-102b-4a62-a24a-0360e5c32ca5.png" alt="613d31f6-102b-4a62-a24a-0360e5c32ca5" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><em>Flowcharts in mermaid</em></p>
<p><strong>Syntax breakdown:</strong></p>
<ul>
<li><p><code>flowchart</code>: This keyword tells that we are creating a flowchart.</p>
</li>
<li><p><code>TD</code>: this is the orientation of the flowchart and stands for Top to Down. The other FlowChart orientations are:<br>  – <code>TB</code> - Top to bottom,same as TD.<br>  – <code>BT</code> - Bottom to top<br>  – <code>RL</code> - Right to left<br>  – <code>LR</code> - Left to right</p>
</li>
<li><p><code>--&gt;</code>: The direction of the arrow connecting the nodes.</p>
</li>
</ul>
<h3 id="heading-how-to-create-a-sequence-diagram"><strong>How to Create a Sequence Diagram</strong></h3>
<p>A sequence diagram is an illustrative representation of interactions between processes, demonstrating their operational flow and the sequence of execution.</p>
<p>You can render sequence diagrams in mermaid using this syntax:</p>
<pre><code class="lang-bash">```mermaid
sequenceDiagram
    participant Client
    participant Server
    Client-&gt;&gt;Server: Register user
    activate Server
    Server--&gt;&gt;Client: User already exists.
    deactivate Server

```
</code></pre>
<p><strong>Result:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732173517259/9abf9118-8eb5-4203-ac16-c188d40a3e1f.png" alt="9abf9118-8eb5-4203-ac16-c188d40a3e1f" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><em>Sequence diagram in mermaid</em></p>
<p><strong>Syntax breakdown:</strong></p>
<ul>
<li><p><code>sequenceDiagram</code>: This keyword specifies that we are making a sequence diagram.</p>
</li>
<li><p><code>participant</code>: These are the participants or the actors in a sequence diagram.</p>
</li>
<li><p><code>activate/ deactivate</code>: It is possible to activate and deactivate an actor. Activation shows as a small rectangle between interactions.</p>
</li>
<li><p><code>--&gt;&gt;</code>: Connecting lines (dashed).</p>
</li>
<li><p><code>-&gt;</code>: Connecting lines (solid).</p>
</li>
</ul>
<h3 id="heading-how-to-create-a-class-diagram"><strong>How to Create a Class Diagram</strong></h3>
<p>Class diagrams are used to visualize the structure and relationships of classes, interfaces, and their interactions in object-oriented programming (OOP). You can render class diagrams in Mermaid using this syntax:</p>
<pre><code class="lang-bash">```mermaid
classDiagram
    class Animal {
        +name: string
        +age: int
        +makeSound(): void
    }

    class Dog {
        +breed: string
        +bark(): void
    }

    class Cat {
        +color: string
        +meow(): void
    }

    Animal &lt;|-- Dog
    Animal &lt;|-- Cat

```
</code></pre>
<p><strong>Result:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732173586580/980dadee-760a-4593-9a73-fbddb6ea7d41.png" alt="980dadee-760a-4593-9a73-fbddb6ea7d41" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><em>Class diagram in mermaid</em></p>
<p><strong>Syntax breakdown:</strong></p>
<ul>
<li><p>Defining classes: An individual class is defined with the <code>class</code> keyword followed by the class name.</p>
</li>
<li><p>Adding class properties: Class properties are added with a <code>+</code> sign. In the example above, <code>+breed</code> is a property.</p>
</li>
<li><p>Adding methods: Methods are recognized by mermaid using <code>()</code>, the round braces. Note that all the properties and methods are grouped under the same class using curly braces.</p>
</li>
<li><p>Defining return types: Return types are defined after the method name/ class name. <code>string</code> and <code>void</code> are the return types in the above code.</p>
</li>
<li><p>Defining relation ships: In OOP, relationships are the specific types of logical connections found on class and object diagrams. The following relationship types are supported in mermaid:</p>
</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Type</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td>&lt;</td><td>--</td><td>Inheritance</td></tr>
<tr>
<td>*--</td><td>Composition</td></tr>
<tr>
<td>o--</td><td>Aggregation</td></tr>
<tr>
<td>--&gt;</td><td>Association</td></tr>
<tr>
<td>--</td><td>Link (Solid)</td></tr>
<tr>
<td>..&gt;</td><td>Dependency</td></tr>
<tr>
<td>..</td><td>&gt;</td><td>Realization</td></tr>
<tr>
<td>..</td><td>Link (Dashed)</td></tr>
</tbody>
</table>
</div><p>Here is a quick implementation of inheritance:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732173642098/8cac704a-455a-4317-93cc-885c4d28b066.png" alt="8cac704a-455a-4317-93cc-885c4d28b066" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><em>Inheritance</em></p>
<h3 id="heading-how-to-create-a-gantt-chart"><strong>How to Create a Gantt Chart</strong></h3>
<p>A Gantt chart serves as a visual representation in the form of a bar chart. It effectively showcases a project's timeline, revealing the duration required for individual project components to reach completion.</p>
<p>You can render Gantt charts in Mermaid using this example:</p>
<pre><code class="lang-bash">```mermaid
gantt
    title Project Schedule
    dateFormat YYYY-MM-DD
    axisFormat %m/%d

    section Planning
    Define Project : 2023-01-01, 7d
    Research : 2023-01-08, 14d
    Define Requirements : 2023-01-22, 7d

    section Development
    Design : 2023-01-29, 21d
    Implementation : 2023-02-19, 28d

    section Testing
    Unit Testing : 2023-03-19, 14d
    Integration Testing : 2023-04-02, 14d

    section Deployment
    Deploy : 2023-04-16, 7d
    User Training : 2023-04-23, 14d

    section Maintenance
    Ongoing Support : 2023-05-07, 30d

```
</code></pre>
<p><strong>Result:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732173699584/2755cdf2-a95e-40fa-a4ea-18eddd8d2919.png" alt="2755cdf2-a95e-40fa-a4ea-18eddd8d2919" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><em>Gantt charts in mermaid</em></p>
<p><strong>Syntax breakdown:</strong></p>
<ul>
<li><p><code>gantt</code> specifies that you want to render a Gantt chart in mermaid.</p>
</li>
<li><p><code>title</code>represents the project title.</p>
</li>
<li><p><code>dateFormat YYYY-MM-DD</code> is the input date format for the chart.</p>
</li>
<li><p><code>axisFormat %m/%d</code> represents the shown date format, the output date, in the x-axis.</p>
</li>
<li><p><code>section</code> is used to separate different parts of the project.</p>
</li>
</ul>
<p>The x axis represents time and the y records the different tasks and the order in which they are to be completed.</p>
<h3 id="heading-how-to-create-a-pie-chart"><strong>How to Create a Pie Chart</strong></h3>
<p>A pie chart, also known as a circle chart, is a round visual representation used for displaying statistical data. It is divided into segments or slices to visually convey the numerical proportions of different categories or values.</p>
<p>Here is an example to create a pie chart in mermaid:</p>
<pre><code class="lang-bash">```mermaid
pie
    title Distribution of Expenses
    <span class="hljs-string">"Food"</span> : 60
    <span class="hljs-string">"Rent"</span> : 15
    <span class="hljs-string">"Entertainment"</span> : 10
    <span class="hljs-string">"Savings"</span> : 15

```
</code></pre>
<p><strong>Result:</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1732173761958/0664d574-0cc0-49d3-8744-68d1dbdd4d15.png" alt="0664d574-0cc0-49d3-8744-68d1dbdd4d15" class="image--center mx-auto" width="600" height="400" loading="lazy"></p>
<p><em>Pie charts in mermaid</em></p>
<p><strong>Syntax breakdown:</strong></p>
<p>In this example:</p>
<ul>
<li><p><code>pie</code> indicates that we are creating a pie chart.</p>
</li>
<li><p><code>title</code> sets the title for the pie chart.</p>
</li>
<li><p>The items in double quotes represent the categories (e.g., "Food," "Rent," "Entertainment," "Savings").</p>
</li>
<li><p>The numbers after the colons represent the proportions or percentages for each category. In this case, "Food" occupies 60% of the chart, "Rent" 15%, "Entertainment" 10%, and "Savings" 15%.</p>
</li>
</ul>
<h2 id="heading-wrapping-up"><strong>Wrapping up</strong></h2>
<p>In this article, we just scratched the surface of rendering diagrams in Mermaid. The diagrams are highly customizable and allow you to create very complex diagrams as well.</p>
<p>Mermaid supports even more types of diagrams that are not mentioned in this tutorial. To learn more about Mermaid, check out their <a target="_blank" href="https://web.archive.org/web/20240526110100/http://mermaid.js.org/">official documentation</a>.</p>
<p>I hope you found this article helpful. I would love to connect with you on any of these <a target="_blank" href="https://web.archive.org/web/20240526110100/https://zaira_.bio.link/">platforms</a>.</p>
<p>See you in the next tutorial, happy coding 😁</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Why Data Visualization is Important for UX Design ]]>
                </title>
                <description>
                    <![CDATA[ These days, we find ourselves consuming vast amounts of information, at an unprecedented rate. From online transactions, to social media interactions, to scientific research, the complexity of data grows exponentially. This reveals a challenge — how ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/why-data-visualization-is-important-for-ux-design/</link>
                <guid isPermaLink="false">66d03a45ab216b411575949d</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ User Interface ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ux design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Faith Olohijere ]]>
                </dc:creator>
                <pubDate>Thu, 01 Jun 2023 15:39:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/luke-chesser-JKUTrJ4vK00-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>These days, we find ourselves consuming vast amounts of information, at an unprecedented rate. From online transactions, to social media interactions, to scientific research, the complexity of data grows exponentially. This reveals a challenge — how to transform this raw data to actionable insight. </p>
<p>This is where data visualization comes in. Data visualization is a very important concept we should all consider when designing for our users.</p>
<p>In this article, you'll learn what data visualization is, how it relates to UX Design, and challenges faced when designing for data visualization.</p>
<h2 id="heading-what-is-data-visualization">What is Data Visualization?</h2>
<p>Data Visualization can be defined as being able to view data in designs. This could be done using charts, maps, tables, and so on. Data visualization simply enables users to see and understand data, without stressing their head or eyes. </p>
<p>By leveraging the power of visual perception, data visualization empowers individuals and organizations to gain deeper insights, and make informed decisions.</p>
<h2 id="heading-how-does-data-visualization-relate-to-ux-design">How Does Data Visualization Relate to UX Design?</h2>
<p>You might be wondering if and how data visualization relates to UX design. After all, isn't data all about numbers?</p>
<p>They do relate! You see, data visualization isn't just about numbers. It's about representing these numbers in a way that makes sense to the user, and also helps them make decisions. </p>
<p>As UX designers, our primary goal is to solve a problem for our users. When we design for data visualization, we're reducing the strain of going through bulky amounts of data for our users, and generally making their lives easier.</p>
<h2 id="heading-why-is-data-visualization-important">Why is Data Visualization important?</h2>
<p>Data Visualization is important for so many reasons, some of which are:</p>
<ul>
<li>Enhancement of understanding: Just putting out data might confuse a particular user or customer. Using visuals to interpret the data makes it easier and more fun for the users.</li>
<li>Communication of insight: Data visualization helps communicate insights on a digital platform. Users will be able to understand the data, data sources and how it's being analyzed.</li>
<li>Better user experience: Overall, data visualization helps in making sure your user has a better experience while interacting with your platform. You're generally trying to make their lives easier and reduce information overload.</li>
<li>Informed decision-making: Helping the user understand the data better, will keep them informed, and help them make better decisions which can boost their businesses.</li>
</ul>
<h2 id="heading-challenges-of-designing-for-data-visualization">Challenges of Designing for Data Visualization</h2>
<p>Data visualization is so easy to get wrong. Because of the delicate nature of data and how broad it can appear, designers might face some challenges when trying to help users visualize data. Some of these challenges include:</p>
<ul>
<li>Bulky/complex data: The bulky nature of the data might make it difficult to represent the data using visuals. Also, simplifying the data without losing information can be very tricky.</li>
<li>Cluttered interface: Somewhat related to the previous point, the overwhelming nature of the data can make the design look cluttered. Because you're designing with a lot of data, you might end up having a messy interface, while trying to put it all on a screen. You have to find a way to make sure your user interfaces don't look cluttered with an overload of information.</li>
<li>Usage of color: Despite the fact that we want the interface to look visually appealing, we have to consider the fact that colors can distract users from the overall intention, which is to communicate data to the users. Therefore, we should figure out a way to strike the balance, especially when differentiating color categories and highlighting important information.</li>
<li>Background of the target audience: You should also consider the background and understanding of your target audience. Some users might not have technical knowledge so, it would be best not to use jargon while designing for them.</li>
</ul>
<h2 id="heading-how-to-design-efficiently-for-data-visualization">How to Design Efficiently for Data Visualization</h2>
<p>To effectively design for data visualization and correctly interpret data for your users, you should consider these tips:</p>
<h3 id="heading-define-the-purpose">Define the purpose</h3>
<p>First of all, you'll want to define your purpose for the design. This is a common step in most designs. You need to understand the purpose of the visualization – is it to convey trends, monitor business growth, and so on. </p>
<p>Also, consider the domain, requirements, and possible constraints. This will help you determine the best visualization type to use.  </p>
<p>For example, say you're designing a data visualization for a social media tracking platform. The purpose here is to track the growth of the social media account, note what posts are most engaged with, and basically providing actionable insights to help the user make decisions that would further boost the account.</p>
<h3 id="heading-know-your-audience">Know your audience</h3>
<p>Another tip for designing effectively is to know your audience. You have to understand what your audience needs before figuring out how to help them. </p>
<p>You can conduct some research on the kind of people that would use the data visualization tool for the domain you're working on.</p>
<p>Using the same example as the first tip, your audience would generally be social media managers, brand ambassadors, or others who work primarily in the social media space. Do note that the audience may vary in terms of age, expertise, and personal preferences. </p>
<h3 id="heading-choose-the-visualization-type">Choose the visualization type</h3>
<p>Here, you choose the best visualization type for conveying your information. You can decide to use bar charts, tables, graphs, and so on, to represent your data.</p>
<p>Continuing with our example, you'd want to select visualizations that effectively represent progress over time, such as bar charts, progress charts, and so on. You might also want to analyze key data such as active followers. Would you use a bar chart or a line chart to do so? This is what choosing the visualization type entails.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/15319232948826_guardianmasterclass-dataviz-1292.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Examples of some data visualization charts. Image from [OpenClassrooms](https://www.google.com/url?sa=i&amp;url=https%3A%2F%2Fopenclassrooms.com%2Fen%2Fcourses%2F4555961-apply-metrics-to-design-decisions%2F5403056-decide-on-an-approach-to-present-information&amp;psig=AOvVaw11EJaN3uJ8zzLGJ7VRciQd&amp;ust=1685717146266000&amp;source=images&amp;cd=vfe&amp;ved=0CBEQjRxqFwoTCKjA</em>--nov8CFQAAAAAdAAAAABAR)_</p>
<h3 id="heading-have-an-intuitive-and-simple-layout">Have an intuitive and simple layout</h3>
<p>Here, you'd have to think of the kind of layout you want to use for your design. You would want to go for a simple layout that would help your users easily understand the visuals.</p>
<p>For the social media data visualization, you might want to: </p>
<ul>
<li>Incorporate a clear hierarchy of elements using size, colors, and placement.</li>
<li>Use familiar patterns like icons or symbols, to represent different social media metrics.</li>
<li>Embrace a minimalist approach by displaying essential information only. </li>
<li>Design a clear navigation system so users would always understand their current location on the application. </li>
</ul>
<p>Having an intuitive layout can help reduce information overload on your users. When elements are arranged logically, and the visualization is simple and free of clutter, your users are sure to have a great experience.</p>
<h3 id="heading-use-accessible-colors">Use accessible colors</h3>
<p>Next, choose colors that are easy on the eyes. Aside from the background and primary colors, you might use color coding to differentiate between different metrics/elements. </p>
<p>For example, you may decide to get the gender demography of the audience for the social media account. To represent this data, you could use a circle graph (doughnut), and choose different colors to represent the genders.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/Circle-Chart.png" alt="Image" width="600" height="400" loading="lazy">
<em>An example of a circle graph with each element differentiated by colors.</em></p>
<p>Please note that accessibility isn't only for people with disabilities. Make sure to use colors that don't distract the user from important elements and information. You can use <a target="_blank" href="https://www.freecodecamp.org/news/the-60-30-10-rule-in-design/">the 60-30-10 rule</a> to choose a color palette that improves understanding and aids interpretation.</p>
<h3 id="heading-a-data-visualization-dashboard">A Data Visualization Dashboard</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/Desktop---6--3-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of a dashboard for a Data Visualization Tool</em></p>
<p>The image above shows a dashboard for a social media data visualization tool. The dashboard contains performance metrics, analytics of likes, followers and comments on the account. The dashboard also contains the demographics of the audience, engagement rates and posts activity. </p>
<p>All these are important data analytics information which are useful to the owner of the account.</p>
<p>You can see how charts and bar graphs are used to interpret the data. Imagine having one big list which has the demographics of each user, each like and comment posted, everyone who engaged with each posts, and so on. It would be a bit overwhelming and hard to sift through to find insights.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The average person consumes about 40-75 gigabytes of data per day. Now, that's quite a lot. Imagine having to take in this huge amount of data through cluttered and disorganized interfaces. This would make it difficult to understand and interpret the data.</p>
<p>As designers, it's our job to ease the experiences of users while interacting with our products. We have to focus and align our design choices with the purpose and audience, as well as continuously evaluate our visualizations to ensure they effectively convey insights and appropriately inform the viewers. Remember, this gets better with practice.</p>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create an Interactive Heatmap Using JavaScript ]]>
                </title>
                <description>
                    <![CDATA[ By Shachee Swadia Data visualization is a powerful tool that helps us make sense of complex data. With it, we can spot patterns and trends that might take much more time to become obvious just by looking at raw numbers.  One particularly useful chart... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/interactive-heatmap-in-javascript/</link>
                <guid isPermaLink="false">66d460f633b83c4378a51841</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Heat map ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 16 May 2023 23:26:39 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/05/heatmapchartjs.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Shachee Swadia</p>
<p>Data visualization is a powerful tool that helps us make sense of complex data. With it, we can spot patterns and trends that might take much more time to become obvious just by looking at raw numbers. </p>
<p>One particularly useful chart type is the <strong>heatmap</strong>, and I’m excited to teach you how to create one with JavaScript in this tutorial.</p>
<h2 id="heading-what-is-a-heatmap">What is a Heatmap?</h2>
<p>A heatmap is a two-dimensional representation of the magnitude of a phenomenon through colors. It provides a <a target="_blank" href="https://datavizcatalogue.com/methods/heatmap.html">quick visual summary</a> of high and low values in the data. </p>
<p>For instance, did you know that an average of 108 people died per day in road accidents in the U.S. in 2021? Using a heatmap chart, we can analyze the days and times of fatal accidents. This will be the visualization we will be building during the tutorial.</p>
<p>So, grab your cup of coffee and let's dive into this step-by-step guide. By the end, you'll have the skills to easily create your own interactive JavaScript heatmaps.</p>
<h1 id="heading-the-heatmap-chart-well-build">The Heatmap Chart We'll Build</h1>
<p>Here is how the final JS-based heatmap chart will look:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/heatmapchart-006.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Ready to dive in? Let's go!</p>
<h1 id="heading-how-to-make-a-javascript-heatmap"><strong>How to Make a JavaScript Heatmap</strong></h1>
<p>Great, let's start creating a simple yet beautiful heatmap chart using JavaScript. With just four easy-to-follow steps, you'll have a stunning interactive heatmap in no time. </p>
<p>Don't worry about any complicated coding or overwhelming technicalities. We'll keep things straightforward and easy to understand.</p>
<h2 id="heading-1-create-an-html-page">1. Create an HTML Page</h2>
<p>First things first, we need to create a web page that'll hold our super-cool heatmap. We start by making a basic HTML page, complete with a <code>div</code> element to hold our chart. Let’s also specify the style of the <code>div</code> to make it stretch over the whole page. Don't worry, it’s easy-peasy:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Heatmap in JavaScript<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>&gt;</span><span class="css">      
      <span class="hljs-selector-tag">html</span>, <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-id">#container</span> { 
        <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>; <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>; 
      } 
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h2 id="heading-2-include-the-required-javascript-files">2. Include the Required JavaScript Files</h2>
<p>Okay, let's be real: building a JS heatmap from scratch would be a real pain in the you-know-what. Instead, we're gonna take the easier route and use a JavaScript charting library. </p>
<p>There are a <a target="_blank" href="https://en.wikipedia.org/wiki/Comparison_of_JavaScript_charting_libraries">ton of various JS charting libraries</a> out there. For this project, we're gonna go with the <a target="_blank" href="https://www.anychart.com/">AnyChart JS library</a>, which supports heatmap charts and is free for personal and other non-profit purposes. </p>
<p>To make things work, we need to add a couple of scripts to our web page's <code>&lt;head&gt;</code> section. Specifically, we need to include the base and heatmap modules. Sounds easy, right?</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Heatmap in JavaScript<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.anychart.com/releases/8.11.0/js/anychart-core.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.anychart.com/releases/8.11.0/js/anychart-heatmap.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>&gt;</span><span class="css">      
      <span class="hljs-selector-tag">html</span>, <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-id">#container</span> { 
        <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>; <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>; 
      } 
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-comment">// All the code for the JS heatmap will come here</span>
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h2 id="heading-3-add-the-data">3. Add the Data</h2>
<p>Each chart is complete with the data, right? We’re gonna grab our data from the <a target="_blank" href="https://injuryfacts.nsc.org/motor-vehicle/overview/crashes-by-time-of-day-and-day-of-week/">NSC website</a> and add it to our HTML file in the proper format.</p>
<p>For our heatmap, each data point needs to include an <code>x</code> value (day), a <code>y</code> value (hour), and a <code>heat</code> value (number of accidents). We'll wrap this data in a function that we'll call when we create the JS chart.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getData</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> [
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">705</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">713</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">657</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">957</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1137</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">956</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">482</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">641</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">631</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">905</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1137</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">986</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">465</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">616</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">627</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">914</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1159</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1066</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">584</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">718</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">660</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">966</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1161</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1186</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">715</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">747</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">738</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1056</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1426</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1631</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1383</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">641</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">635</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1034</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1400</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1593</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1486</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">695</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">564</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">932</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1292</span>
    },
    {
      <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
      <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
      <span class="hljs-attr">heat</span>: <span class="hljs-number">1211</span>
    }
  ];
}
</code></pre>
<h2 id="heading-4-write-the-necessary-js-code-for-the-chart">4. Write the Necessary JS Code for the Chart</h2>
<p>Here's the fun part: it's time to write the JavaScript code that'll make our heatmap chart look amazing.</p>
<p>We'll enclose everything in a function to ensure the code only executes when the page is ready. We'll create the graph using the <code>heatmap()</code> function and add the data we created in the previous step.</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> chart = anychart.heatMap(getData());
</code></pre>
<p>Then, we'll give the chart a descriptive title:</p>
<pre><code class="lang-js">chart.title(<span class="hljs-string">"Fatal Car Crashes in U.S. in 2021 by Time of Day and Day of Week”);</span>
</code></pre>
<p>Finally, we'll set the container reference and draw the chart. Voilà!</p>
<pre><code class="lang-js">сhart.container(<span class="hljs-string">'container’);
chart.draw();</span>
</code></pre>
<p>And there you have it. With just a little bit of HTML and JavaScript, you can create a totally rad interactive heatmap. You can see the entire code of this JS-based heatmap below and check it out live <a target="_blank" href="https://playground.anychart.com/DEyz9Bjb">here</a>. After that, we'll learn how to customize our heatmap in all kinds of fun ways.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/heatmapchart-001.png" alt="Image" width="600" height="400" loading="lazy"></p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Heatmap in JavaScript<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.anychart.com/releases/8.11.0/js/anychart-core.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.anychart.com/releases/8.11.0/js/anychart-heatmap.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>&gt;</span><span class="css">      
      <span class="hljs-selector-tag">html</span>, <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-id">#container</span> { 
        <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>; <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>; 
      } 
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      anychart.onDocumentReady(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-comment">// create a heatmap</span>
        <span class="hljs-keyword">let</span> chart = anychart.heatMap(getData());
        <span class="hljs-comment">// name the heatmap</span>
        chart.title(<span class="hljs-string">"Fatal Car Crashes in U.S. in 2021 by Time of Day and Day of Week"</span>);
        <span class="hljs-comment">// set the container for the heatmap</span>
        chart.container(<span class="hljs-string">"container"</span>);
        <span class="hljs-comment">// draw the heatmap</span>
        chart.draw();
      });
      <span class="hljs-comment">// add the data</span>
      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getData</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> [
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">705</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">713</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">657</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">957</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1137</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">956</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">482</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">641</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">631</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">905</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1137</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">986</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">465</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">616</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">627</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">914</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1159</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1066</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">584</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">718</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">660</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">966</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1161</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1186</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">715</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">747</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">738</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1056</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1426</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1631</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1383</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">641</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">635</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1034</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1400</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1593</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1486</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">695</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">564</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">932</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1292</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1211</span>
          }
        ];
      }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>This heatmap is both visually appealing and informative. Upon examining the chart, it becomes clear that there are certain times when the number of accidents is significantly higher. It is unsurprising to see that these peak times are during weekends and the darker hours of the day.</p>
<p>But there's a lot more we can do with our heatmap...</p>
<h1 id="heading-how-to-customize-a-js-heatmap"><strong>How to Customize a JS Heatmap</strong></h1>
<p>As we saw, having the basic chart ready was really simple and fast. But there is so much more we can do to enhance the heatmap. It's not so difficult, either. </p>
<h2 id="heading-how-to-change-the-color-palette">How to Change the Color Palette</h2>
<p>We can use a diverging colour palette to make our JavaScript heatmap more effective in highlighting the data. This type of color scheme helps to emphasize the difference between high and low values, with less being good and more being alarming. </p>
<p>We can define four colors and value ranges using an ordinal color scale and then set the chart colors to use that color scale. This way, we can create a heatmap that quickly draws the viewer's attention to the most significant data points.</p>
<p>Here's the code to do that:</p>
<pre><code><span class="hljs-keyword">let</span> colorScale = anychart.scales.ordinalColor();
colorScale.ranges([
  { <span class="hljs-attr">less</span>: <span class="hljs-number">500</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#B0D8A4"</span> },
  { <span class="hljs-attr">from</span>: <span class="hljs-number">500</span>, <span class="hljs-attr">to</span>: <span class="hljs-number">900</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#FEE191"</span> },
  { <span class="hljs-attr">from</span>: <span class="hljs-number">900</span>, <span class="hljs-attr">to</span>: <span class="hljs-number">1300</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#FD8060"</span> },
  { <span class="hljs-attr">greater</span>: <span class="hljs-number">1300</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#CC333F"</span> }
]);
chart.colorScale(colorScale);
</code></pre><p>And here's the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/heatmapchart-002.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-modify-the-hover-styling">How to Modify the Hover Styling</h2>
<p>When we change the color palette of our heatmap, we also need to modify the hover colors to match the base colors. This is simple to achieve with the <code>color.darken</code> function. </p>
<p>We can set the chart settings and hover chart settings to ensure that the hover colors match the base colors. This allows us to create a visually consistent and easy-to-read heatmap, making it more effective in communicating the underlying data.</p>
<pre><code>chart
  .hovered()
  .fill(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> anychart.color.darken(<span class="hljs-built_in">this</span>.sourceColor, <span class="hljs-number">0.25</span>);
  });
</code></pre><p><img src="https://www.freecodecamp.org/news/content/images/2023/05/heatmapchart-003.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-change-the-labels">How to Change the Labels</h2>
<p>By default, the labels on our heatmap show the actual numbers. But we can customize the labels to provide greater flexibility and make the chart easier to read. </p>
<p>We can enable HTML for the labels to allow for greater formatting options. Then, we can configure the labels to display as 'low' to 'extreme' based on the value of the tile. We can also make the 'high' and 'extreme' values appear in bold to make them stand out.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// enable html for the labels</span>
chart.labels().useHtml(<span class="hljs-literal">true</span>);

<span class="hljs-comment">// configure the labels</span>
chart.labels().format(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> heat = <span class="hljs-built_in">this</span>.heat;
  <span class="hljs-keyword">if</span> (heat &lt; <span class="hljs-number">500</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">"Low"</span>;
  <span class="hljs-keyword">if</span> (heat &lt; <span class="hljs-number">1000</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">"Medium"</span>;
  <span class="hljs-keyword">if</span> (heat &lt; <span class="hljs-number">1500</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">"&lt;span style='font-weight:bold'&gt;High&lt;/span&gt;"</span>;
  <span class="hljs-keyword">if</span> (heat &gt;= <span class="hljs-number">1500</span>) <span class="hljs-keyword">return</span> <span class="hljs-string">"&lt;span style='font-weight:bold'&gt;Extreme&lt;/span&gt;"</span>;
});
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/heatmapchart-004.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the final version, I decided to ultimately remove the labels since the colors are quite indicative of the values.</p>
<h2 id="heading-how-to-format-the-title-and-tooltip">How to Format the Title and Tooltip</h2>
<p>Now it's time to make our JS heatmap visualization even more exciting with some formatting tweaks. </p>
<p>First, we'll enable HTML for the tooltip, so we can customize it with some eye-catching formatting. We'll display the number of accidents in the heading and the day as well as the timing in the body of the tooltip. This will add more context and help the user to better understand the data.</p>
<pre><code class="lang-javascript">chart.tooltip().title().useHtml(<span class="hljs-literal">true</span>);
chart
  .tooltip()
  .useHtml(<span class="hljs-literal">true</span>)
  .titleFormat(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> <span class="hljs-string">"Accidents - "</span> + <span class="hljs-built_in">this</span>.heat;
  })
  .format(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> (
      <span class="hljs-string">'&lt;span style="color: #CECECE"&gt;Day: &lt;/span&gt;'</span> +
      <span class="hljs-built_in">this</span>.x +
      <span class="hljs-string">"&lt;br/&gt;"</span> +
      <span class="hljs-string">'&lt;span style="color: #CECECE"&gt;Time: &lt;/span&gt;'</span> +
      <span class="hljs-built_in">this</span>.y
    );
  });
</code></pre>
<p>Let’s also add a bit of padding under the main title to make it more spaced out and visually appealing:</p>
<pre><code class="lang-javascript">chart
  .title()
  .enabled(<span class="hljs-literal">true</span>)
  .text(<span class="hljs-string">"Fatal Car Crashes in U.S. in 2021 by Time of Day and Day of Week"</span>)
  .padding([<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">20</span>, <span class="hljs-number">0</span>]);
</code></pre>
<p>Here's what those modifcations look like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/heatmapchart-005.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-modify-the-axes">How to Modify the Axes</h2>
<p>For better readability, we can add padding between the axes labels and the chart tiles and remove the axes lines since the tiles form a boundary by themselves.</p>
<pre><code class="lang-javascript">chart.xAxis().stroke(<span class="hljs-literal">null</span>);
chart.yAxis().stroke(<span class="hljs-literal">null</span>);
chart.yAxis().labels().padding([<span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]);
chart.xAxis().labels().padding([<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">0</span>]);
</code></pre>
<p>And there you have it! With just a few aesthetic changes, we've transformed a simple heatmap into a stunning visualization that really drives home a powerful message. You can check it out below with the full source code, and you can take a closer look at the interactive version of the heatmap and play with the code live <a target="_blank" href="https://playground.anychart.com/UDF2ym4E">here</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/05/heatmapchart-006-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Heatmap in JavaScript<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.anychart.com/releases/8.11.0/js/anychart-core.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.anychart.com/releases/8.11.0/js/anychart-heatmap.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> 
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text/css"</span>&gt;</span><span class="css">      
      <span class="hljs-selector-tag">html</span>, <span class="hljs-selector-tag">body</span>, <span class="hljs-selector-id">#container</span> { 
        <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>; <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>; <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>; 
      } 
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>  
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"container"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      anychart.onDocumentReady(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        <span class="hljs-comment">// create a heatmap</span>
        <span class="hljs-keyword">var</span> chart = anychart.heatMap(getData());
        <span class="hljs-comment">// set a custom color scale</span>
        <span class="hljs-keyword">var</span> colorScale = anychart.scales.ordinalColor();
        colorScale.ranges([
          { <span class="hljs-attr">less</span>: <span class="hljs-number">500</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#B0D8A4"</span> },
          { <span class="hljs-attr">from</span>: <span class="hljs-number">500</span>, <span class="hljs-attr">to</span>: <span class="hljs-number">900</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#FEE191"</span> },
          { <span class="hljs-attr">from</span>: <span class="hljs-number">900</span>, <span class="hljs-attr">to</span>: <span class="hljs-number">1300</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#FD8060"</span> },
          { <span class="hljs-attr">greater</span>: <span class="hljs-number">1300</span>, <span class="hljs-attr">color</span>: <span class="hljs-string">"#CC333F"</span> }
        ]);
        chart.colorScale(colorScale);
        <span class="hljs-comment">// style the coloring in the hovered state</span>
        chart
          .hovered()
          .fill(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">return</span> anychart.color.darken(<span class="hljs-built_in">this</span>.sourceColor, <span class="hljs-number">0.25</span>);
          });
        <span class="hljs-comment">// hide the labels</span>
        chart.labels(<span class="hljs-literal">false</span>);
        <span class="hljs-comment">// customize the axes</span>
        chart.xAxis().stroke(<span class="hljs-literal">null</span>);
        chart.yAxis().stroke(<span class="hljs-literal">null</span>);
        chart.yAxis().labels().padding([<span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>]);
        chart.xAxis().labels().padding([<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">0</span>]);
        <span class="hljs-comment">// set the tooltip</span>
        chart.tooltip().title().useHtml(<span class="hljs-literal">true</span>);
        chart
          .tooltip()
          .useHtml(<span class="hljs-literal">true</span>)
          .titleFormat(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">return</span> <span class="hljs-string">"Accidents - "</span> + <span class="hljs-built_in">this</span>.heat;
          })
          .format(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
            <span class="hljs-keyword">return</span> (
              <span class="hljs-string">'&lt;span style="color: #CECECE"&gt;Day: &lt;/span&gt;'</span> +
              <span class="hljs-built_in">this</span>.x +
              <span class="hljs-string">"&lt;br/&gt;"</span> +
              <span class="hljs-string">'&lt;span style="color: #CECECE"&gt;Time: &lt;/span&gt;'</span> +
              <span class="hljs-built_in">this</span>.y
            );
          });
        <span class="hljs-comment">// name the heatmap</span>
        chart
          .title()
          .enabled(<span class="hljs-literal">true</span>)
          .text(<span class="hljs-string">"Fatal Car Crashes in U.S. in 2021 by Time of Day and Day of Week"</span>)
          .padding([<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">20</span>, <span class="hljs-number">0</span>]);
        <span class="hljs-comment">// set the container for the heatmap</span>
        chart.container(<span class="hljs-string">"container"</span>);
        <span class="hljs-comment">// draw the heatmap</span>
        chart.draw();
      });
      <span class="hljs-comment">// add the data</span>
      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getData</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-keyword">return</span> [
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">705</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">713</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">657</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">957</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1137</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Monday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">956</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">482</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">641</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">631</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">905</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1137</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Tuesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">986</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">465</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">616</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">627</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">914</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1159</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Wednesday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1066</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">584</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">718</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">660</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">966</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1161</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Thursday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1186</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">715</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">747</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">738</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1056</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1426</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Friday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1631</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1383</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">641</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">635</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1034</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1400</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Saturday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1593</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Midnight–3:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1486</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">695</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 a.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">564</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"Noon–3:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">932</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"4:00–7:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1292</span>
          },
          {
            <span class="hljs-attr">x</span>: <span class="hljs-string">"Sunday"</span>,
            <span class="hljs-attr">y</span>: <span class="hljs-string">"8:00–11:59 p.m."</span>,
            <span class="hljs-attr">heat</span>: <span class="hljs-number">1211</span>
          }
        ];
      }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In conclusion, data visualization is an incredibly powerful tool that can help us uncover important insights from our data. And with JavaScript, creating beautiful and impactful charts, such as a heatmap, can be a breeze. </p>
<p>So don't be afraid to experiment with different chart types, styles, and libraries to create your own hard-hitting visualizations. And above all, remember to stay safe out there on the roads!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Data Visualization with Matplotlib – a Step by Step Guide ]]>
                </title>
                <description>
                    <![CDATA[ SEE is a beautiful Apple TV series that depicts a dystopia where humans have lost their sight. Hundreds of years later, it was considered a myth that people could ever see.  Jason Momoa is one of the leads and plays Baba Voss, an elite warrior. Jason... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/introduction-to-data-vizualization-using-matplotlib/</link>
                <guid isPermaLink="false">66c71f7455df43f1418b5b21</guid>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Matplotlib ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mene-Ejegi Ogbemi ]]>
                </dc:creator>
                <pubDate>Mon, 24 Apr 2023 18:32:32 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/04/data-visualization-1.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://tv.apple.com/us/show/see/umc.cmc.3s4mgg2y7h95fks9gnc4pw13m">SEE</a> is a beautiful Apple TV series that depicts a dystopia where humans have lost their sight. Hundreds of years later, it was considered a myth that people could ever see. </p>
<p>Jason Momoa is one of the leads and plays Baba Voss, an elite warrior. Jason's wife gives birth to sighted twins, and years after, during battle, Baba Voss sometimes needs the aid of the sighted children. They helped him understand the terrain better, even with his battlefield mastery. We could say his children helped him visualize things.</p>
<p>In ancient times, before digital devices, data visualization was also a myth. Earlier humans understood the need for visualization, so they had resources like maps, hieroglyphs, rock art, and so on. Eyewitnesses typically draw their paths and other relevant information on stones, wood, or scrolls. </p>
<p>Like Baba Voss's kids, these resources make it easier for humans to have a visual perspective on things or environments. </p>
<p>So what does visualization actually mean in this context? We can define visualization as "any technique for creating images, diagrams, or animations to communicate a message." (<a target="_blank" href="https://en.wikipedia.org/wiki/Visualization_(graphics)">source</a>)</p>
<p>In this article, we'll explore what data visualization is and how you can use the data visualization tool Matplotlib to explore and analyze data. You'll learn how to use it to create charts that help business owners and stakeholders get more insight about data and make informed decisions.</p>
<h2 id="heading-what-is-data-visualization">What is Data Visualization?</h2>
<p>Data visualization refers to the integration of data and visual elements like images, charts, diagrams, and so on to communicate messages to different stakeholders. </p>
<p>These stakeholders can be users, team members, managers, or top executive members of an organization. </p>
<p>Data in this context refers to different input gathered from the organization database or gotten from external sources, like public databases or private organizations, that have given access through their APIs.</p>
<p>We'll work with an employee layoff dataset which contains details of employees that have been laid off in different industries from 2020 to 2022. The columns in the dataset include the names of companies, locations, industries, total laid off, percentage laid off, date, countries, and other relevant columns. </p>
<p>Below is a snapshot of the data frame:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/08/layoff-table.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-what-is-matplotlib">What is Matplotlib?</h2>
<p>Matplotlib is a popular Python library for displaying data and creating static, animated, and interactive plots. This program lets you draw appealing and informative graphics like line plots, scatter plots, histograms, and bar charts. </p>
<p>Matplotlib is highly customizable and flexible, which makes it a preferred choice for data analysts and scientists working in fields such as finance, science, engineering, and social sciences. </p>
<p>In this article, I'll show you how to create a bar chart, a pie chart, and a line plot to explain how you can do data visualization using Matplotlib.</p>
<p>The first thing you need is to import the Matplotlib and other relevant libraries like Pandas, Numpy and their sub modules.</p>
<pre><code class="lang-python"><span class="hljs-comment">#Imports packages</span>
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.dates <span class="hljs-keyword">as</span> mdates
<span class="hljs-keyword">from</span> matplotlib.ticker <span class="hljs-keyword">import</span> MaxNLocator
</code></pre>
<p>In the code above, we import the Pandas package, which analyzes and manipulates our data. We imported Matplotlib and we'll use the Pyplot module for data visualization. </p>
<p>We'll use the Numpy package imported in the third line for numerical computations. We'll also work with the date module for date manipulations when plotting our chart. The last module is the ticker module, which sets ticks on plot axes. With these modules, you can analyze, manipulate, compute, and visualize your data.</p>
<h2 id="heading-how-to-create-a-bar-chart">How to Create a Bar Chart</h2>
<p>Bar charts help you with categorical values. That is, if you want to compare different entities on quantity, a bar chart is an excellent way to visualize it. In the layoff dataset, we'll compare different companies that laid off employees according to the number of staff laid off.</p>
<pre><code class="lang-python">plt.figure(figsize= (<span class="hljs-number">8</span>, <span class="hljs-number">6</span>))
industry_val = df_layoffs.groupby(<span class="hljs-string">'company'</span>)[<span class="hljs-string">'total_laid_off'</span>].sum().sort_values(ascending = <span class="hljs-literal">False</span>).head(<span class="hljs-number">10</span>)
industry_val.plot(label=<span class="hljs-string">""</span>, kind=<span class="hljs-string">'bar'</span>)
plt.show()
</code></pre>
<p>The code above is one way to create a bar chart. It shows the top 10 companies with the highest number of layoffs. </p>
<p>We first set the size of the graph to 8 inches by 6 inches. Then, we group our data in the dataframe by the sum total of employees laid off by each company. We then sort in descending order and select the top 10 with the highest layoffs. Finally, we create our bar chart using the selected data. The last line (<code>plt.show()</code>) displays the graph which is shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/layoff-bar-chart.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>From the chart above, you will notice that Meta and Amazon had the highest number of laid off staff while Twitter had the fewest layoffs.</p>
<h3 id="heading-how-to-create-a-pie-chart">How to Create a Pie Chart</h3>
<p>A pie chart represents a whole sector, with each portion allocated according to its size to a sub-sector. The industry column will be a perfect fit for using pie chart. We'll see which industry had most and fewest layoffs.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Group the data by industry and sum the total laid off employees</span>
industry_val = df_layoffs.groupby(<span class="hljs-string">'industry'</span>)[<span class="hljs-string">'total_laid_off'</span>].sum().sort_values(ascending=<span class="hljs-literal">False</span>).head()

<span class="hljs-comment"># create the pie chart and display the labels and values inside the pie</span>
plt.figure(figsize=(<span class="hljs-number">8</span>, <span class="hljs-number">6</span>))
plt.pie(industry_val, labels=industry_val.index, autopct=<span class="hljs-string">'%1.1f%%'</span>)
plt.title(<span class="hljs-string">'Laid Off Employees by Industry'</span>)
plt.show()
</code></pre>
<p>First, the code groups the data by industry and sums up the total number of laid-off employees for each industry. It then sorts the industries in descending order based on the total number of laid-off employees and selects the top values using the <code>head()</code> function.</p>
<p>Next, we create a pie chart to visualize the data. The size of each slice in the pie represents the proportion of laid-off employees in that industry. The pie chart labels show the names of the industries. The percentage values inside the slices show the proportion of laid-off employees in that industry. The chart is titled "Laid Off Employees by Industry."</p>
<p>Finally, the pie chart is displayed using the <code>plt.show()</code> function. Like we did in the bar chart, the <code>plt.figure(figsize=(8, 6))</code> function sets the chart size to be 8 inches wide and 6 inches tall.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/layoff-industry.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The chart above shows the proportion of layoffs across different industries. The transportation sector and consumer sector are the industry mostly affected followed by retail, finance and food industry.</p>
<h3 id="heading-how-to-create-a-line-chart">How to Create a Line chart</h3>
<p>Line charts show changes over time for an entity. With our dataset, a line chart could be used to show the trend of layoffs over the past year or two.  This depends on what you are trying to communicate, but we'll work with a one year analysis.</p>
<pre><code class="lang-python"><span class="hljs-comment"># convert date column to datetime object</span>
df_layoffs[<span class="hljs-string">'date'</span>] = pd.to_datetime(df_layoffs[<span class="hljs-string">'date'</span>])

<span class="hljs-comment"># select data for one-year duration starting from January 1st, 2022</span>
start_date = pd.Timestamp(<span class="hljs-string">'2022-01-01'</span>)
end_date = start_date + pd.DateOffset(years=<span class="hljs-number">1</span>)
df_one_year = df_layoffs.loc[(df_layoffs[<span class="hljs-string">'date'</span>] &gt;= start_date) &amp; (df_layoffs[<span class="hljs-string">'date'</span>] &lt; end_date)]

<span class="hljs-comment"># plot the selected data</span>
df_date = df_one_year.groupby(<span class="hljs-string">'date'</span>)[<span class="hljs-string">'total_laid_off'</span>].sum()
plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">4</span>))
plt.plot(df_date.index, df_date.values)
plt.xlabel(<span class="hljs-string">'Date'</span>)
plt.ylabel(<span class="hljs-string">'Total Laid Off'</span>)
plt.title(<span class="hljs-string">'Laid Off Trend for 2022'</span>)
plt.xticks(rotation=<span class="hljs-number">45</span>)
<span class="hljs-comment"># set the format of the x-axis labels to show Month-Year</span>
date_fmt = mdates.DateFormatter(<span class="hljs-string">'%b-%Y'</span>)
plt.gca().xaxis.set_major_formatter(date_fmt)

<span class="hljs-comment"># Use MaxNLocator to reduce the number of xticks</span>
locator = MaxNLocator(nbins=<span class="hljs-number">10</span>)
plt.gca().xaxis.set_major_locator(locator)

plt.show()
</code></pre>
<p>In comparison to the bar charts and pie charts, this code is much more challenging. But here is an explanation:</p>
<p>The first line of the code converts the 'date' column of the DataFrame (df_layoffs) into a DateTime object so that the dates can be handled easily.</p>
<pre><code class="lang-python"><span class="hljs-comment"># convert date column to datetime object</span>
df_layoffs[<span class="hljs-string">'date'</span>] = pd.to_datetime(df_layoffs[<span class="hljs-string">'date'</span>])
</code></pre>
<p>Next, we select the data for a one-year duration starting on January 1st, 2022. The start date is defined as a Timestamp object, and the end date is set as one year from the start date using the pd.DateOffset function. The loc function is then used to filter the DataFrame rows, selecting only those that fall within this one-year duration. Remember we are working with a year's data.</p>
<pre><code class="lang-python"><span class="hljs-comment"># select data for one-year duration starting from January 1st, 2022</span>
start_date = pd.Timestamp(<span class="hljs-string">'2022-01-01'</span>)
end_date = start_date + pd.DateOffset(years=<span class="hljs-number">1</span>)
df_one_year = df_layoffs.loc[(df_layoffs[<span class="hljs-string">'date'</span>] &gt;= start_date) &amp; (df_layoffs[<span class="hljs-string">'date'</span>] &lt; end_date)]
</code></pre>
<p>After that, we group the selected data by date and calculate the total number of layoffs on each date using the groupby and sum functions. This is stored in a new DataFrame called <code>df_date</code>.</p>
<pre><code class="lang-python"><span class="hljs-comment"># plot the selected data</span>
df_date = df_one_year.groupby(<span class="hljs-string">'date'</span>)[<span class="hljs-string">'total_laid_off'</span>].sum()
</code></pre>
<p>Then, we create a plot of the laid off trend for 2022 using the matplotlib library. The plot size is set to (10, 4) using the figure function.</p>
<pre><code class="lang-python">plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">4</span>))
</code></pre>
<p>The x-axis represents the date, and the y-axis represents the total number of layoffs. The xlabel function labels the x-axis as 'Date,' and the ylabel function labels the y-axis as 'Total Laid Off.'</p>
<pre><code class="lang-python">plt.plot(df_date.index, df_date.values)
plt.xlabel(<span class="hljs-string">'Date'</span>)
plt.ylabel(<span class="hljs-string">'Total Laid Off'</span>)
</code></pre>
<p>The plot title is set to 'Laid Off Trend for 2022' using the title function.</p>
<pre><code class="lang-python">plt.title(<span class="hljs-string">'Laid Off Trend for 2022'</span>)
</code></pre>
<p>The x-axis labels are rotated by 45 degrees using the xticks function to avoid overcrowding.</p>
<pre><code class="lang-python">plt.xticks(rotation=<span class="hljs-number">45</span>)
</code></pre>
<p>The format of the x-axis labels is set to show the Month-Year format using the DateFormatter function.</p>
<pre><code class="lang-python"><span class="hljs-comment"># set the format of the x-axis labels to show Month-Year</span>
date_fmt = mdates.DateFormatter(<span class="hljs-string">'%b-%Y'</span>)
plt.gca().xaxis.set_major_formatter(date_fmt)
</code></pre>
<p>Finally, the number of xticks on the plot is reduced using the MaxNLocator function, which reduces the number of xticks to 10.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Use MaxNLocator to reduce the number of xticks</span>
locator = MaxNLocator(nbins=<span class="hljs-number">10</span>)
plt.gca().xaxis.set_major_locator(locator)
</code></pre>
<p>The plot is then displayed using the show function.</p>
<pre><code class="lang-python">plt.show()
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/layoff-line-chart.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The chart above shows layoff trends and patterns for 2022.</p>
<p>You can also analyze how well an entity performed over different periods of time. The second chart shows an analysis of employee layoffs in 2020 versus 2022.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> matplotlib.dates <span class="hljs-keyword">as</span> mdates
<span class="hljs-keyword">from</span> matplotlib.ticker <span class="hljs-keyword">import</span> MaxNLocator

<span class="hljs-comment"># convert date column to datetime object</span>
df_layoffs[<span class="hljs-string">'date'</span>] = pd.to_datetime(df_layoffs[<span class="hljs-string">'date'</span>])

<span class="hljs-comment"># filter data to only include 2020 and 2022</span>
df_filtered = df_layoffs[(df_layoffs[<span class="hljs-string">'date'</span>].dt.year == <span class="hljs-number">2020</span>) | (df_layoffs[<span class="hljs-string">'date'</span>].dt.year == <span class="hljs-number">2022</span>)]

<span class="hljs-comment"># group data by year and calculate total layoffs</span>
df_filtered[<span class="hljs-string">'year'</span>] = df_filtered[<span class="hljs-string">'date'</span>].dt.year
df_yearly = df_filtered.groupby([<span class="hljs-string">'year'</span>, <span class="hljs-string">'date'</span>])[<span class="hljs-string">'total_laid_off'</span>].sum().reset_index()

<span class="hljs-comment"># create subplots and plot the data for each year in separate charts</span>
fig, axs = plt.subplots(ncols=<span class="hljs-number">2</span>, figsize=(<span class="hljs-number">14</span>, <span class="hljs-number">8</span>))
<span class="hljs-keyword">for</span> i, year <span class="hljs-keyword">in</span> enumerate(df_yearly[<span class="hljs-string">'year'</span>].unique()):
    df_year = df_yearly.loc[df_yearly[<span class="hljs-string">'year'</span>] == year]
    axs[i].plot(df_year[<span class="hljs-string">'date'</span>], df_year[<span class="hljs-string">'total_laid_off'</span>])
    axs[i].set_xlabel(<span class="hljs-string">'Date'</span>)
    axs[i].set_ylabel(<span class="hljs-string">'Total Laid Off'</span>)
    axs[i].set_title(<span class="hljs-string">f'Laid Off Trend for <span class="hljs-subst">{year}</span>'</span>)
    axs[i].xaxis.set_major_formatter(mdates.DateFormatter(<span class="hljs-string">'%b-%Y'</span>))
    axs[i].tick_params(axis=<span class="hljs-string">'x'</span>, rotation=<span class="hljs-number">45</span>)
    locator = MaxNLocator(nbins=<span class="hljs-number">10</span>)
    axs[i].xaxis.set_major_locator(locator)

<span class="hljs-comment"># set y-axis limit to 0-14000 for each subplot</span>
<span class="hljs-keyword">for</span> ax <span class="hljs-keyword">in</span> axs:
    ax.set_ylim([<span class="hljs-number">0</span>, <span class="hljs-number">14000</span>])

plt.show()
</code></pre>
<p>Let's review the different components of the code above.</p>
<p>The 'date' column in the DataFrame is converted to a datetime object.</p>
<pre><code class="lang-python"><span class="hljs-comment"># convert date column to datetime object</span>
df_layoffs[<span class="hljs-string">'date'</span>] = pd.to_datetime(df_layoffs[<span class="hljs-string">'date'</span>])
</code></pre>
<p>Next, the code filters the data to only include layoffs from the years 2020 and 2022. It then groups the filtered data by year and date and calculates the total number of layoffs for each date.</p>
<pre><code class="lang-python"><span class="hljs-comment"># filter data to only include 2020 and 2022</span>
df_filtered = df_layoffs[(df_layoffs[<span class="hljs-string">'date'</span>].dt.year == <span class="hljs-number">2020</span>) | (df_layoffs[<span class="hljs-string">'date'</span>].dt.year == <span class="hljs-number">2022</span>)]

<span class="hljs-comment"># group data by year and calculate total layoffs</span>
df_filtered[<span class="hljs-string">'year'</span>] = df_filtered[<span class="hljs-string">'date'</span>].dt.year
df_yearly = df_filtered.groupby([<span class="hljs-string">'year'</span>, <span class="hljs-string">'date'</span>])[<span class="hljs-string">'total_laid_off'</span>].sum().reset_index()
</code></pre>
<p>We then create two subplots and plot the total number of layoffs for each year in separate charts. We set the x-axis labels to the date format of 'MMM-YYYY' (for example, Jan-2022) and rotate them by 45 degrees. We also set the y-axis label to 'Total Laid Off' and the chart title to 'Laid Off Trend for {year}' (for example, Laid Off Trend for 2020). Finally, we show the charts using the <code>plt.show()</code> command.</p>
<pre><code class="lang-python"><span class="hljs-comment"># create subplots and plot the data for each year in separate charts</span>
fig, axs = plt.subplots(ncols=<span class="hljs-number">2</span>, figsize=(<span class="hljs-number">14</span>, <span class="hljs-number">8</span>))
<span class="hljs-keyword">for</span> i, year <span class="hljs-keyword">in</span> enumerate(df_yearly[<span class="hljs-string">'year'</span>].unique()):
    df_year = df_yearly.loc[df_yearly[<span class="hljs-string">'year'</span>] == year]
    axs[i].plot(df_year[<span class="hljs-string">'date'</span>], df_year[<span class="hljs-string">'total_laid_off'</span>])
    axs[i].set_xlabel(<span class="hljs-string">'Date'</span>)
    axs[i].set_ylabel(<span class="hljs-string">'Total Laid Off'</span>)
    axs[i].set_title(<span class="hljs-string">f'Laid Off Trend for <span class="hljs-subst">{year}</span>'</span>)
    axs[i].xaxis.set_major_formatter(mdates.DateFormatter(<span class="hljs-string">'%b-%Y'</span>))
    axs[i].tick_params(axis=<span class="hljs-string">'x'</span>, rotation=<span class="hljs-number">45</span>)
    locator = MaxNLocator(nbins=<span class="hljs-number">10</span>)
    axs[i].xaxis.set_major_locator(locator)

plt.show()
</code></pre>
<p>Overall, the code is used to filter, group, and visualize data related to company layoffs specifically focusing on trends for 2020 and 2022. You can see the result in the chart below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/04/line-chart-comparison-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>We started by discussing what visualization is and how data visualization is significant in transforming raw numbers into insight and business sense. </p>
<p>Then we used the popular Python library Matplotlib, which is a tool for data visualization, to create bar charts, pie charts, and line charts. There are also other use cases not covered in this article, like histograms, scatter plots, box plots, and so on. </p>
<p>By using these visualizations, we can make sense of our data and take actions that wouldn't be possible by looking at raw numbers. Data visualization can help us achieve better outcomes in other areas such as finance, science, engineering, etc. For further study, you can check the official matplotlib documentation <a target="_blank" href="https://matplotlib.org/stable/index.html">here</a>.</p>
<p>Thank you for reading! Please follow me on <a target="_blank" href="https://www.linkedin.com/in/ogbemi-ejegi/">LinkedIn</a> where I also post more data related content.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Chart.js Tutorial – How to Make Marimekko Charts in Angular ]]>
                </title>
                <description>
                    <![CDATA[ By Swatej Patil Data visualization is an essential part of data analysis. And charts are one of the most effective ways to present data in a clear and concise manner.  Marimekko charts are an excellent choice for displaying complex data sets in a com... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/chart-js-tutorial-how-to-make-marimekko-charts-in-angular/</link>
                <guid isPermaLink="false">66d46149706b9fb1c166b9ab</guid>
                
                    <category>
                        <![CDATA[ Angular ]]>
                    </category>
                
                    <category>
                        <![CDATA[ chartjs ]]>
                    </category>
                
                    <category>
                        <![CDATA[ charts ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 21 Mar 2023 17:51:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/austin-distel-DfjJMVhwH_8-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Swatej Patil</p>
<p>Data visualization is an essential part of data analysis. And charts are one of the most effective ways to present data in a clear and concise manner. </p>
<p>Marimekko charts are an excellent choice for displaying complex data sets in a compact and visually appealing format. </p>
<p>A Marimekko chart, also known as a mosaic chart or mekko chart, is a combination of a stacked bar chart and a 100% stacked bar chart. The width of each bar represents the total value of the corresponding category, and the height of each bar represents the relative contribution of each sub-category to that total. </p>
<p>In this tutorial, we will explore how to create a Marimekko chart using Chart.js, a powerful charting library. We'll delve into the details of how to structure the data for Marimekko charts, as well as how to customize the chart's appearance and behavior using Chart.js options and APIs.</p>
<h1 id="heading-getting-started"><strong>Getting Started</strong></h1>
<p>I am assuming that you already have familiarity with creating simple line and bar charts using Chart.js in an Angular application. In this guide, there are certain concepts that will be easier to comprehend if you have prior knowledge.</p>
<p>Don't worry if you don't – I've got you covered. You can follow my <a target="_blank" href="https://www.freecodecamp.org/news/how-to-make-bar-and-line-charts-using-chartjs-in-angular/">Chart.js Tutorial – How to Make Bar and Line Charts in Angular</a> to get started.</p>
<h2 id="heading-how-to-structure-data-for-marimekko-charts">How to Structure Data for Marimekko Charts</h2>
<p>Let's discuss the data structure required for Marimekko charts before creating the chart. </p>
<p>Marimekko charts need an array of objects, with each object representing a category. Each object must have a label and a sub-array of objects, where each sub-object represents a sub-category. </p>
<p>Each sub-object must have a label and a value. The value represents the proportion of the sub-category in relation to the total of its category.</p>
<p>Here's an example of how to structure data for a Marimekko chart:</p>
<pre><code class="lang-jsx">data: [
  {
    <span class="hljs-attr">label</span>: <span class="hljs-string">'Category 1'</span>,
    <span class="hljs-attr">subcategories</span>: [
      { <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 1'</span>, <span class="hljs-attr">value</span>: <span class="hljs-number">10</span> },
      { <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 2'</span>, <span class="hljs-attr">value</span>: <span class="hljs-number">20</span> },
      { <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 3'</span>, <span class="hljs-attr">value</span>: <span class="hljs-number">30</span> }
    ]
  },
  {
    <span class="hljs-attr">label</span>: <span class="hljs-string">'Category 2'</span>,
    <span class="hljs-attr">subcategories</span>: [
      { <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 1'</span>, <span class="hljs-attr">value</span>: <span class="hljs-number">40</span> },
      { <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 2'</span>, <span class="hljs-attr">value</span>: <span class="hljs-number">50</span> },
      { <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 3'</span>, <span class="hljs-attr">value</span>: <span class="hljs-number">60</span> }
    ]
  }
]
</code></pre>
<p>In this example, we have two categories: Category 1 and Category 2, with three subcategories each. The values for the subcategories represent the proportion of the subcategory in relation to the total of its category. For example, in Category 1, Subcategory 1 represents 10 out of 60, or 16.7% of the total.</p>
<h2 id="heading-how-to-create-a-marimekko-chart-with-chartjs">How to Create a Marimekko Chart with Chart.js</h2>
<p>Now that we have our data structured correctly, let's move on to creating our Marimekko chart using Chart.js. </p>
<p>First, we need to create a canvas element in our HTML code to hold the chart:</p>
<pre><code class="lang-jsx">&lt;canvas id=<span class="hljs-string">"marimekkoChart"</span>&gt;&lt;/canvas&gt;
</code></pre>
<p>Next, we'll need to install Chart.js and import it into our Angular component:</p>
<pre><code class="lang-jsx">npm install chart.js
</code></pre>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> Chart <span class="hljs-keyword">from</span> <span class="hljs-string">'chart.js/auto'</span>;
</code></pre>
<p>In our component class, we can then create a new Chart object and pass in our data and options:</p>
<pre><code class="lang-jsx">ngAfterViewInit() {
  <span class="hljs-keyword">const</span> canvas = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'marimekkoChart'</span>) <span class="hljs-keyword">as</span> HTMLCanvasElement;
  <span class="hljs-keyword">const</span> ctx = canvas.getContext(<span class="hljs-string">'2d'</span>) <span class="hljs-keyword">as</span> CanvasRenderingContext2D;

  <span class="hljs-keyword">const</span> data = {
    <span class="hljs-attr">labels</span>: [<span class="hljs-string">'Category 1'</span>, <span class="hljs-string">'Category 2'</span>],
    <span class="hljs-attr">datasets</span>: [
      {
        <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 1'</span>,
        <span class="hljs-attr">data</span>: [<span class="hljs-number">10</span>, <span class="hljs-number">40</span>],
        <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'rgba(255, 99, 132, 0.7)'</span>,
        <span class="hljs-attr">borderWidth</span>: <span class="hljs-number">1</span>
      },
      {
        <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 2'</span>,
        <span class="hljs-attr">data</span>: [<span class="hljs-number">20</span>, <span class="hljs-number">50</span>],
        <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'rgba(54, 162, 235, 0.7)'</span>,
        <span class="hljs-attr">borderWidth</span>: <span class="hljs-number">1</span>
      },
      {
        <span class="hljs-attr">label</span>: <span class="hljs-string">'Subcategory 3'</span>,
        <span class="hljs-attr">data</span>: [<span class="hljs-number">30</span>, <span class="hljs-number">60</span>],
        <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'rgba(255, 206, 86, 0.7)'</span>,
        <span class="hljs-attr">borderWidth</span>: <span class="hljs-number">1</span>
      }
    ]
  };

  <span class="hljs-keyword">const</span> options = {
    <span class="hljs-attr">indexAxis</span>: <span class="hljs-string">'y'</span>,
    <span class="hljs-attr">plugins</span>: {
      <span class="hljs-attr">legend</span>: {
        <span class="hljs-attr">position</span>: <span class="hljs-string">'bottom'</span>
      }
    }
  };

  <span class="hljs-keyword">const</span> marimekkoChart = <span class="hljs-keyword">new</span> Chart(ctx, {
    <span class="hljs-attr">type</span>: <span class="hljs-string">'bar'</span>,
    <span class="hljs-attr">data</span>: data,
  });
}
</code></pre>
<p>In this example, we're creating a Marimekko chart with three subcategories for two categories. We've set the type of chart to 'bar', and we're passing in our data and options. The 'indexAxis' option is set to 'y' to make the chart horizontal, and the 'legend' option is set to position the legend at the bottom of the chart.</p>
<p>Congratulations! If you have followed along carefully then you shouldn’t run into any errors and your output may look like the following:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Mekkochart.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And that's it! With this code, we can create a Marimekko chart in Chart.js in Angular. </p>
<p>You can further customize your chart using various Chart.js options and APIs, such as adjusting the colors, labels, and tooltip behaviors, to make it even more informative and engaging.</p>
<h1 id="heading-conclusion">C<strong>onclusion</strong></h1>
<p>Chart.js is a very useful and powerful library. In this quick tutorial, we've covered how to create a Marimekko chart in Chart.js in Angular. If you want to include any type of chart in your Angular application, then it is very easy to make them with Chart.js.</p>
<p>The full code for this Angular application is hosted on my <a target="_blank" href="https://github.com/SwatejPatil/Chart.js-Tutorial-How-to-Make-a-Marimekko-Chart-in-Angular">GitHub Repo</a>.</p>
<p>I hope you found this tutorial helpful and informative. If you have any questions or feedback, feel free to to contact me on <a target="_blank" href="http://www.linkedin.com/in/swatejpatil/">LinkedIn</a>!</p>
<h3 id="heading-related-articles-ive-written-about-chartjs"><strong>Related Articles I've Written about Chart.js:</strong></h3>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/chart-js-zooom-plugin/">How to Make Bar and Line Charts using Chart.js in Angular</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-make-pie-and-doughnut-charts-using-chartjs-in-angular/">Chart.js Tutorial – How to Make Pie and Doughnut Charts in Angular</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/chart-js-zooom-plugin/">How to Add the Chart.js Zoom Plugin to an Angular App</a></li>
</ul>
<p>Photo by <a target="_blank" href="https://unsplash.com/@austindistel?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Austin Distel</a> on <a target="_blank" href="https://unsplash.com/photos/DfjJMVhwH_8?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Data Visualization in Google Sheets for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ Spreadsheets are the OG resource for visualizing data with charts and graphs...unless you count chalkboards, I suppose.  Spreadsheets are built to churn through tons of data. And by using a few simple built-in tools, you can glean valuable insights f... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/data-visualization-in-google-sheets/</link>
                <guid isPermaLink="false">66b8ddd7753e1e313e83948d</guid>
                
                    <category>
                        <![CDATA[ beginners guide ]]>
                    </category>
                
                    <category>
                        <![CDATA[ data visualization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ google sheets ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Eamonn Cottrell ]]>
                </dc:creator>
                <pubDate>Thu, 16 Mar 2023 20:55:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/FCC-Data-Visualization-in-Google-Sheets---Bar-and-Pie-Charts.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Spreadsheets are the OG resource for visualizing data with charts and graphs...unless you count chalkboards, I suppose. </p>
<p>Spreadsheets are built to churn through tons of data. And by using a few simple built-in tools, you can glean valuable insights from large chunks of data.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/og.gif" alt="Image" width="600" height="400" loading="lazy">
<em>gif of "OG" graphic</em></p>
<p>When dealing with small sets of data, you can often find answers and insights at a glance. But when your spreadsheets begin to reach into the hundreds and thousands of rows, charts can help condense all those numbers down to useable pieces of information...especially if you're presenting to people who aren't good with numbers!</p>
<h2 id="heading-video-overview">Video Overview</h2>
<p>Speaking of visuals:</p>
<ul>
<li><a target="_blank" href="https://docs.google.com/spreadsheets/d/1kJ5vDDtb8B7SDQDBK-WxgK-Tc2Dk9KlF29qxjjxz65Y/edit#gid=370701475">Here's a link</a> to the demo spreadsheet with all our data and charts.</li>
<li>And here's the video walkthrough of everything covered below:</li>
</ul>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/QYc1gUWnhS4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-how-to-get-the-data">How to Get the Data</h2>
<p>Kaggle is a wonderful resource to find interesting data sets. We're using this video game sales dataset. To import it into a Google Sheet, all that we need to do is create a new Google Sheet by typing <code>sheets.new</code> in the address bar of our browser.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-140.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of web address bar</em></p>
<p>Then, select <code>File, Import</code> from the menu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-141.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of file menu in google sheets</em></p>
<p>You can now upload the .csv file you downloaded from Kaggle.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-142.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of importing options in google sheets</em></p>
<p>This will give you several import options. If you're following along and using a completely blank, new spreadsheet, simply select <code>Replace spreadsheet</code> and it will pull everything in automatically. </p>
<p>If the data is cleaned well, and Kaggle datasets typically are, you can leave the separator to <code>Detect automatically</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-143.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of import file options</em></p>
<p>This will give us a lovely 16,000+ row spreadsheet full of video game data. 😁</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-145.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of spreadsheet dataset</em></p>
<h2 id="heading-how-to-insert-charts">How to Insert Charts</h2>
<p>From here, we need to select <code>Insert - Chart</code> from the toolbar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-146.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of insert chart in google sheets</em></p>
<p>We'll be confronted with a blank chart in the middle of the screen and a Chart editor in the right sidebar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-147.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of chart editor</em></p>
<p>Now let's make sure we're referencing the correct data range. Google Sheets is pretty smart, and if you click the little graph icon to the right of the data range form, it will suggest some ranges to use. In our case, the range we need is suggested: <code>A1:K16600</code>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/selectrange.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We're going to find the <em>sales by genre</em>, so next let's select <code>Genre</code> for our x-axis:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-148.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of chart options</em></p>
<p>Sometimes Google Sheets will be not-so-smart. If there are a ton of series listed and a funky graph, you can simply remove all the series and manually add what you need:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-149.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of chart series</em></p>
<p>Now click the <code>Aggregate</code> button to group all the sales data for each genre, and select <code>NA-Sales</code> as the Series to display the sales in millions of dollars on the y-axis.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-150.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of chart series options</em></p>
<p>And voilà! We've got a standard issue column bar chart. But we can do better. At the top right of our chart editor, we can <code>Customize</code> the chart further by changing the appearance, font, gridlines and titles.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-151.png" alt="Image" width="600" height="400" loading="lazy">
<em>chart editor screenshot</em></p>
<h2 id="heading-how-to-customize-the-chart">How to Customize the Chart</h2>
<p>From the customization tab, we have a lot of options. We can style our chart by changing the background color and font. We can make it 3D, and we can choose whether or not to maximize the chart in the chart window.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-152.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chart style screenshot</em></p>
<p>We can then add chart titles, subtitles and axis titles and also modify the color and fonts.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-153.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chart titles screenshot</em></p>
<p>Then, we can individually edit each <code>Series</code>. In our example we're only using one series, but if there were more, you could modify each of their styles independently.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-154.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of series customization options</em></p>
<p>If you have a legend, you can modify those options in the next dropdown window:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-155.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Then there are customization options for both the horizontal and vertical axes. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-156.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of axes options</em></p>
<p>And the last block of customization options is for gridlines and tick marks. These can be toggled on and off, and we can change the color and frequency of the grid and tick lines.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-157.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Once we're done, we now have a more stylized chart:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-158.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of column chart in Google Sheets</em></p>
<p>If we'd like to move this chart around, we can drag it throughout the current spreadsheet. Or, we can put it on its own dedicated sheet by clicking the three dots in the top right and selecting <code>Move to own sheet</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-159.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-how-to-publish-the-chart">How to Publish the Chart</h2>
<p>Here's an added bonus: you can actually publish the chart (or the whole worksheet) to the web. Select the <code>Publish Chart</code> option from the dropdown on the chart shown above, or select <code>File, Share, Publish to web</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-16-at-10.46.55-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>screenshot of publish to web options</em></p>
<p>From here, you'll get to select what you wish to publish and how you want it displayed. For this example, we'll select the <code>Sales by Platform</code> chart to be shared as an interactive chart.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-16-at-10.49.29-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of publishing options in google sheets</em></p>
<p>This will generate a shareable link to the chart. It may take a few seconds to load, but once it does, you'll have a nice chart to easily share that is interactive. When you hover over the slices, it will display the percent of sales of the pie slice.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/Screenshot-2023-03-16-at-10.52.14-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of a published chart</em></p>
<p><a target="_blank" href="https://docs.google.com/spreadsheets/d/e/2PACX-1vRZ-uidgV1M_YVX6qvEi5RSGddmUvRRl3a7ehHfGx9VX3JI7dP-NVX2teVlwBbhmg7ChXsp37Ss0zDt/pubchart?oid=1851187878&amp;format=interactive">Here's the link to the chart that we just made.</a> </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Thanks for reading! I hope that you learned something in this beginners tutorial on data visualization in Google Sheets. </p>
<p>You can really do a whole lot using the basic built-in charts available in Google Sheets as well as Microsoft Excel. Charts remain an extremely helpful way to interpret large data sets.</p>
<p>Please check out my <a target="_blank" href="https://www.youtube.com/@eamonncottrell?sub_confirmation=1">YouTube channel here</a> &amp; <a target="_blank" href="https://www.linkedin.com/in/eamonncottrell/">LinkedIn page here</a>.</p>
<p>Have a great one!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
