Computer Programming 1 (Python) • Core Data Structures

Dictionaries for Frequency Counting — I can use dictionaries to count frequencies and build simple histograms at my level.

Learn how Python dictionaries let you tally items and visualize data with simple text-based histograms.

A Python coding terminal with a program flow and laptop.
Inside this lesson 10 sections 5 questions 8 figures

SECTION 1

Historical Context & Motivation

Counting things is one of the oldest computational tasks humans have ever performed. Long before computers existed, merchants scratched tally marks into clay tablets to track inventory, and census workers recorded population counts on paper ledgers. The core idea — pairing a category with a count — is exactly what a Python dictionary does when you use it for frequency counting.

In the history of programming, the concept of mapping keys to values evolved from simple lookup tables into one of the most versatile data structures in modern languages. Python's dictionary (the dict type) traces its roots through decades of computer science research on hash tables and associative arrays. Understanding this timeline helps you appreciate why dictionaries are so central to Python programming today.

1953 • Hash Tables Invented

IBM researcher Hans Peter Luhn developed hash tables, the underlying data structure that makes dictionaries fast. A hash function converts a key into an index for near-instant lookups.

1969 • Associative Arrays in AWK

The AWK language introduced associative arrays — arrays indexed by strings instead of numbers — making key-value mapping accessible to everyday programmers for text processing.

1991 • Python 0.9 Includes Dictionaries

Guido van Rossum released the first version of Python, which included dictionaries as a built-in type from day one. This design choice reflected how essential key-value mappings are to real-world programming.

2010s • Big Data & Frequency Analysis

As data science exploded, frequency counting with dictionaries became a foundational skill. Counting word occurrences, analyzing survey responses, and building histograms are now standard tasks taught in introductory CS courses.

So here is the question this lesson answers: given a collection of items — letters in a word, scores in a gradebook, colors of cars in a parking lot — how do you efficiently count how many times each unique item appears, and then display those counts visually? The answer lies in Python's dictionary data structure.

SECTION 2

Core Principles & Definitions

Before you start writing code, you need a solid mental model of what a dictionary is and how frequency counting works. A dictionary in Python is a collection of key-value pairs, where each key is unique and maps to exactly one value. When you use a dictionary for frequency counting, the keys represent the items you are counting, and the values represent how many times each item has appeared.

1

Key-Value Pair

A dictionary stores data as pairs. The key identifies the item (e.g., the letter "a"), and the value stores its count (e.g., 3). Written in Python: {"a": 3}.
2

Frequency Counting

Frequency counting means iterating through a collection and tallying how many times each unique item appears. The dictionary starts empty and grows as new items are encountered.
3

The Counting Pattern

For each item: if the key exists, add 1 to its value; if not, create the key with value 1. This is the check-then-increment pattern, used in almost every frequency task.
4

Histogram

A histogram is a visual bar chart that shows the frequency of each item. In a text-based histogram, you print a row of repeated characters (like "*") whose length equals the count.
✦

KEY TAKEAWAY

Think of a dictionary like a class roster clipboard. Each student's name is a key, and the tally marks next to their name (tracking how many times they answered a question, for example) are the value. You scan through the class period, and each time someone speaks, you add a mark next to their name. If it is a new student, you write their name first, then add the mark. That is exactly how frequency counting with a dictionary works.

SECTION 3

Visual Explanation — How Frequency Counting Builds a Dictionary

The diagram below traces how a Python dictionary evolves as the program iterates through the string "banana" one character at a time. Each row represents one step of the loop. Notice how the dictionary starts empty and grows each time a new letter is encountered, while existing keys simply get their counts incremented.

Frequency Counting: Iterating Through "banana"StepCharacterActionDictionary State0bNew key → set to 1{"b": 1}1aNew key → set to 1{"b": 1, "a": 1}2nNew key → set to 1{"b": 1, "a": 1, "n": 1}3aKey exists → increment to 2{"b": 1, "a": 2, "n": 1}4nKey exists → increment to 2{"b": 1, "a": 2, "n": 2}5aKey exists → increment to 3{"b": 1, "a": 3, "n": 2}Final Result:{"b": 1, "a": 3, "n": 2}Text Histogram:b|★(1)a|★ ★ ★(3)n|★ ★(2)
The table traces each step of the loop through the string "banana". New keys are created at steps 0, 1, and 2. Steps 3–5 increment existing keys. The bottom shows the resulting text-based histogram.

Notice how the dictionary never contains duplicate keys. Each letter appears exactly once as a key, and its value represents the total number of occurrences. This is the fundamental property that makes dictionaries ideal for frequency counting: the uniqueness constraint on keys naturally groups identical items together, while the values accumulate the counts.

SECTION 4

How It Works — The Counting Pattern in Code

Python gives you several ways to implement the frequency counting pattern. Each approach has the same result, but they differ in how they handle the "what if the key doesn't exist yet?" problem. Let's look at the three main techniques, starting from the most explicit and moving to the most concise.

Technique 1: The if-else Check

The most straightforward approach uses an if statement to check whether the key already exists in the dictionary. If it does, you increment its value by 1. If it does not, you create a new entry with a value of 1. Here is the pattern:

IF-ELSE PATTERN

freq=foritemindata:ifiteminfreq:freq[item]=freq[item]+1else:freq[item]=1freq = {} for item in data: if item in freq: freq[item] = freq[item] + 1 else: freq[item] = 1

freq = the dictionary accumulating counts. data = any iterable (string, list, etc.). item = each element from data. The in keyword checks for key existence in O(1) average time.

Technique 2: The .get() Method

Python dictionaries have a built-in method called .get() that returns a default value if the key is missing, rather than raising an error. This eliminates the need for an if-else block and makes the code more compact.

GET METHOD PATTERN

freq=foritemindata:freq[item]=freq.get(item,0)+1freq = {} for item in data: freq[item] = freq.get(item, 0) + 1

freq.get(item, 0) returns the current count if item exists, or 0 if it doesn't. Adding 1 to the result handles both cases in a single line.

Technique 3: Building the Histogram

Once you have a frequency dictionary, you can visualize it as a text-based histogram by looping through the dictionary and printing a repeated character for each count. The string multiplication operator "*" * n repeats the asterisk character n times, producing a horizontal bar proportional to the frequency.

HISTOGRAM OUTPUT PATTERN

forkeyinfreq:print(key,"∗"∗freq[key])for key in freq: print(key, "*" * freq[key])

For each key in the dictionary, this prints the key followed by a row of asterisks. If freq["a"] is 3, it prints a ***. The visual length of each bar directly corresponds to the count.

✦

KEY TAKEAWAY

The .get() method is the Pythonic go-to for frequency counting. It is like asking a librarian, "How many copies of this book do you have?" If the book exists, you get the count; if not, the librarian politely says "zero" instead of giving you an error.

SECTION 5

Common Frequency Counting Patterns

Frequency counting appears in many different contexts. The diagram below shows four common patterns you will encounter in Python programming. Each pattern takes a different type of input but follows the same core logic: iterate, check, and count.

Four Frequency Counting Patterns① Count Characters in a StringInput:"hello"Code:for ch in word: freq[ch] = freq.get(ch,0)+1Result:{"h":1,"e":1,"l":2,"o":1}Histogram: l ★★ h ★ e ★ o ★② Count Items in a ListInput:["A","B","A","C","B","A"]Code:for grade in grades: freq[grade] = freq.get(grade,0)+1Result:{"A":3, "B":2, "C":1}Histogram: A ★★★ B ★★ C ★③ Count Words in a SentenceInput:"the cat sat on the mat"Code:for w in sentence.split(): freq[w] = freq.get(w,0)+1Result:{"the":2,"cat":1,"sat":1,...}Uses .split() to break into words④ Count Dice Rolls (Numbers)Input:[3, 5, 3, 2, 5, 5, 1]Code:for roll in rolls: freq[roll] = freq.get(roll,0)+1Result:{3:2, 5:3, 2:1, 1:1}Keys can be integers, not just stringsSame core pattern • Different data types • Same result structure
Four common applications of the frequency counting pattern. Note how the code in each box is nearly identical — only the variable names and input types change. The .get() method handles all data types uniformly.
PatternInput TypeKey TypeSplit Needed?
Count charactersstrstr (single char)No — iterating a string yields characters
Count list itemslistSame as element typeNo — iterating a list yields elements
Count wordsstrstr (word)Yes — use .split()
Count numberslistint or floatNo — iterate directly

Summary of frequency counting patterns by data type

SECTION 6

Worked Example — Counting and Displaying Letter Frequencies

Let's walk through a complete program that counts the frequency of each letter in a user-provided sentence and displays the results as a text-based histogram. We will use the .get() method and handle uppercase/lowercase by converting everything to lowercase first.

Letter Frequency Histogram

  1. 1

    Step 1 — Define the Input and Initialize

    We start with a sentence and create an empty dictionary to hold our frequency counts. We also convert the sentence to lowercase so that "A" and "a" are treated as the same letter. sentence = "Mississippi is a state" sentence = sentence.lower() freq = {}
    sentence is now "mississippi is a state" and freq is {}
  2. 2

    Step 2 — Loop Through Each Character

    We iterate through every character in the sentence. We only want to count letters, so we skip spaces using .isalpha(), which returns True only for alphabetic characters. for ch in sentence: if ch.isalpha(): freq[ch] = freq.get(ch, 0) + 1
    After the loop: {"m": 1, "i": 4, "s": 5, "p": 2, "a": 2, "t": 2, "e": 1}
  3. 3

    Step 3 — Sort the Dictionary by Count (Descending)

    To make the histogram more readable, we sort the keys by their frequency in descending order. The sorted() function with key=freq.get sorts by value, and reverse=True puts the highest count first. sorted_keys = sorted(freq, key=freq.get, reverse=True)
    sorted_keys = ["s", "i", "p", "a", "t", "m", "e"]
  4. 4

    Step 4 — Print the Histogram

    Finally, we loop through the sorted keys and print each letter followed by a bar of asterisks. We use Python's string multiplication to create bars of the right length. for key in sorted_keys: print(key, "*" * freq[key])
    Output: s ***** i **** p ** a ** t ** m * e *
💡

Pro Tip

You can make the histogram fancier by using f-strings for alignment: print(f"{key:>3} | {'*' * freq[key]}"). The :>3 right-aligns the key in a 3-character-wide space, keeping your bars neatly lined up.

SECTION 7

Dictionaries vs. Other Counting Approaches

You might wonder: why use a dictionary at all? Couldn't you just use a list, or count items one at a time with the .count() method? The table below compares three different approaches to frequency counting so you can see why dictionaries are usually the best choice.

ApproachStrengthsLimitations
Dictionary with .get()Counts all items in a single pass through the data. Efficient — O(n) time. Clean, Pythonic code. Works with any hashable type.Requires understanding of dictionaries and the .get() method. Unordered in older Python versions (before 3.7).
list.count() in a loopSimple to understand. No dictionary knowledge needed.Very slow — O(n²) time because .count() scans the entire list for every unique item. Also counts duplicates multiple times unless you track what you've already counted.
Parallel lists (keys + values)Does not require dictionary syntax. Two separate lists for items and counts.Tedious to manage. Must manually keep two lists in sync. Searching for a key requires scanning the items list — O(n) per lookup.

Comparison of frequency counting approaches in Python

✦

KEY TAKEAWAY

Using a dictionary for frequency counting is like having a filing cabinet with labeled folders. You open the correct folder in one step (that's the O(1) lookup), update the number inside, and move on. The alternatives are like searching through an unsorted pile of papers every time you need to update a count — it works, but it gets painfully slow as the pile grows.

SECTION 8

Connection to Advanced Tools

The manual frequency counting pattern you just learned is the foundation for more powerful tools built into Python's standard library and popular third-party packages. As you advance, you will encounter these tools that automate and extend what you can do by hand.

What You Know NowAdvanced VersionWhat It Adds
freq.get(item, 0) + 1collections.Counter(data)Counts all items in one line. Includes .most_common(n) to get the top n items, arithmetic between Counters, and more.
Text histogram with "*" * countmatplotlib.pyplot.bar()Creates professional graphical bar charts, pie charts, and other visualizations with colors, labels, and axes.
Manual if/else or .get()collections.defaultdict(int)A dictionary subclass that auto-creates missing keys with a default value (0 for int), eliminating the need for .get() entirely.
Sorting with sorted()pandas.Series.value_counts()Frequency counting integrated into the pandas data analysis library. Returns a sorted series of counts from a DataFrame column.

From manual counting to professional-grade tools

Even though these advanced tools exist, learning to write frequency counting logic manually is essential. It builds your understanding of iteration, conditionals, and dictionary operations — three pillars of Python programming. When you eventually use Counter or pandas, you will understand exactly what those tools are doing under the hood, which makes debugging far easier.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

Explain in your own words why a dictionary is a better data structure for frequency counting than a list. What specific property of dictionaries makes them ideal for this task?
Show answer
A dictionary is ideal for frequency counting because each key must be unique, which naturally groups identical items together. When you encounter an item, you can check whether it already exists as a key in O(1) average time (constant time), and if so, simply increment its value. A list, by contrast, does not inherently associate items with counts — you would need a separate mechanism to track which items have already been counted and what their current tally is. The key uniqueness and fast lookup properties of dictionaries make the counting pattern both simpler to write and faster to execute.

Question 2: BASIC CALCULATION

Trace through the following code by hand and write the final value of freq: data = ["red", "blue", "red", "green", "blue", "red"] freq = {} for color in data: freq[color] = freq.get(color, 0) + 1
Show answer
Starting with an empty dictionary, the loop processes each item: "red" → {"red": 1}, "blue" → {"red": 1, "blue": 1}, "red" → {"red": 2, "blue": 1}, "green" → {"red": 2, "blue": 1, "green": 1}, "blue" → {"red": 2, "blue": 2, "green": 1}, "red" → {"red": 3, "blue": 2, "green": 1}. The final dictionary is {"red": 3, "blue": 2, "green": 1}.

Question 3: INTERMEDIATE

Write a complete Python program that asks the user to input a sentence, then prints a text-based histogram of word frequencies (not character frequencies). Convert all words to lowercase so that "The" and "the" are counted together. Ignore punctuation for simplicity.
Show answer
Here is one correct solution: sentence = input("Enter a sentence: ").lower() words = sentence.split() freq = {} for word in words: freq[word] = freq.get(word, 0) + 1 for key in freq: print(key, '*' * freq[key]) The key steps are: (1) convert to lowercase with .lower(), (2) split into words with .split(), (3) count using the dictionary .get() pattern, and (4) display with string multiplication. For the input "the cat sat on the mat," the output would show "the" with two asterisks and all other words with one.

Question 4: APPLIED

A teacher stores quiz scores in a list: scores = [85, 92, 78, 85, 90, 92, 85, 78, 90, 92, 85, 100]. Write a Python program that (a) counts the frequency of each score, (b) finds which score appeared most often, and (c) prints a histogram sorted from highest score to lowest. Your output should show the score, the count, and a bar of asterisks.
Show answer
Here is a complete solution: scores = [85, 92, 78, 85, 90, 92, 85, 78, 90, 92, 85, 100] freq = {} for s in scores: freq[s] = freq.get(s, 0) + 1 most_common = max(freq, key=freq.get) print(f"Most frequent score: {most_common} ({freq[most_common]} times)") for key in sorted(freq, reverse=True): print(f"{key:>4} ({freq[key]}) {'*' * freq[key]}") The frequency dictionary is {85: 4, 92: 3, 78: 2, 90: 2, 100: 1}. The max(freq, key=freq.get) function finds the key with the highest value, which is 85 (appearing 4 times). The sorted output by score descending shows 100, 92, 90, 85, 78 with their respective bars.

Question 5: CRITICAL THINKING

Consider a program that reads a text file containing a novel and builds a word frequency dictionary. The dictionary ends up with 8,000 unique keys. A classmate suggests using list.count() instead of a dictionary because "it's simpler." If the novel has 80,000 words, estimate how many comparison operations each approach requires and explain which is more practical. Then describe one real-world application where word frequency analysis provides meaningful insight.
Show answer
With the dictionary approach using .get(), you make a single pass through all 80,000 words. Each dictionary lookup is O(1) on average, so the total work is approximately 80,000 operations. With list.count(), you would need to call .count() for each of the 8,000 unique words, and each call scans all 80,000 words. That is 8,000 × 80,000 = 640,000,000 operations — roughly 8,000 times slower. For a full novel, the dictionary approach finishes in milliseconds while the list approach could take noticeable seconds or even minutes. A real-world application is spam detection: email filters analyze word frequencies to identify patterns. If words like "free," "winner," and "click" appear far more frequently than in normal emails, the filter can flag the message as spam. Word frequency analysis is also central to search engines, plagiarism detection, and natural language processing.

SUMMARY

Lesson Summary

Summary

A Python dictionary stores key-value pairs where each key is unique. For frequency counting, the keys represent items being counted and the values store how many times each item appears. The .get() method provides the cleanest implementation: freq[item] = freq.get(item, 0) + 1 handles both new and existing keys in a single line. This pattern works with strings, lists, and any iterable collection. Once you have a frequency dictionary, you can build a text-based histogram by printing repeated characters using "*" * count.

The dictionary approach runs in O(n) time — one pass through the data — making it far more efficient than alternatives like list.count(). You can sort results using sorted() with key=freq.get to display items by frequency. This manual counting skill is the foundation for professional tools like collections.Counter and pandas.value_counts() that you will use in more advanced courses.

Varsity Tutors • Computer Programming 1 (Python) • Dictionaries for Frequency Counting