1. Lighthouse

Level 4 · Count orders by channel

The request

From Andrew Ramos, Marketing Manager

“I've got the channel for this morning's orders as a plain list. How many came through web, app and marketplace?”

Your goal

Set result to a dictionary that maps each channel in channels to the number of times it appears, for example {'web': 6, ...}. Every channel in the list must appear as a key.

  • Store a dict in resultnot done yet

Your code

Python

Loading the editor…

    ResultPress Run to see yours

    Mote checks your result

    Press Run. Each row that matches the goal becomes a firefly in your lantern.

    The lesson

    The most common question in analysis

    “How many of each?” is the question you’ll answer most often as an analyst: orders per channel, customers per state, returns per reason. In plain Python, a dictionary is the natural tool, because each category becomes a key and its count becomes the value.

    Counting with get

    The trick is handling the first time you see a category, when its key doesn’t exist yet. .get with a default of 0 solves it in one line:

    counts = {}
    for channel in channels:
        counts[channel] = counts.get(channel, 0) + 1

    Walk through the first few passes:

    1. "web": not in counts, so get returns 0, and counts["web"] becomes 1.
    2. "app": not there either, so counts["app"] becomes 1.
    3. "web": already 1, so it becomes 2.

    At the end, every distinct channel is a key and the values add up to len(channels). That last fact is a quick sanity check you should get in the habit of running:

    sum(counts.values()) == len(channels)   # True

    The longer version with an if does the same thing and is worth recognising when you read other people’s code:

    if channel in counts:
        counts[channel] += 1
    else:
        counts[channel] = 1

    The shortcut: Counter

    Python’s standard library has a dictionary built for exactly this:

    from collections import Counter
    
    Counter(channels)
    # Counter({'web': 6, 'app': 4, 'marketplace': 2})
    Counter(channels).most_common(1)   # [('web', 6)]

    A Counter behaves like a dictionary, and it compares equal to a normal dictionary with the same counts. In real work you’ll use Counter or, more likely, pandas’ value_counts(), which you’ll meet in chapter 4. Writing the loop once yourself is still worth it: it’s the same logic those tools use, and interviewers like to ask for it without imports.

    Counting with conditions

    Because it’s a normal loop, you can add rules. Count only channels that aren’t empty, or normalise messy text first:

    for channel in raw_channels:
        key = channel.strip().lower()
        if key:
            counts[key] = counts.get(key, 0) + 1

    if key: skips empty text: an empty string "" counts as false in a condition, so blank channels are left out. Without the .strip().lower(), "Web", "web " and "web" would be counted as three different channels, a classic data-quality bug you’ll fix properly in the cleaning chapter.

    Common mistakes

    • Writing counts[channel] += 1 without a default. It fails with KeyError on the first new channel.
    • Creating counts = {} inside the loop, which wipes it on every pass.
    • Counting with a list and .count() for each value, like channels.count("web"). It works for three channels, but you have to know the categories in advance and it rescans the list every time.

    If you know SQL

    This loop is the plain-Python version of SELECT channel, COUNT(*) FROM orders GROUP BY channel.