xbe.at

Data visualisation

Stem-Leaf Plots in Python A Visual Representation of Data

9 min read

Introduction to Stem-Leaf Plots

A stem-leaf plot is a statistical method for organizing and displaying numerical data. It provides a visual representation of the distribution of data, making it easier to identify patterns, clusters, and outliers. This plot is particularly useful for smaller datasets and can help in understanding the shape and spread of the data.

import matplotlib.pyplot as plt

def stem_leaf_plot(data):
    # Sort the data
    sorted_data = sorted(data)
    
    # Extract stems and leaves
    stems = [str(x)[:-1] for x in sorted_data]
    leaves = [str(x)[-1] for x in sorted_data]
    
    # Create a dictionary to store leaves for each stem
    stem_leaf_dict = {}
    for stem, leaf in zip(stems, leaves):
        if stem in stem_leaf_dict:
            stem_leaf_dict[stem].append(leaf)
        else:
            stem_leaf_dict[stem] = [leaf]
    
    # Plot the stem-leaf plot
    fig, ax = plt.subplots(figsize=(10, 6))
    for stem, leaves in stem_leaf_dict.items():
        ax.text(0, int(stem), f"{stem} | {''.join(leaves)}")
    
    ax.set_ylim(min(map(int, stems))-1, max(map(int, stems))+1)
    ax.set_axis_off()
    plt.title("Stem-Leaf Plot")
    plt.show()

# Example data
data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30]
stem_leaf_plot(data)

Components of a Stem-Leaf Plot

A stem-leaf plot consists of two main components: stems and leaves. The stem represents the leading digit(s) of each data point, while the leaf represents the trailing digit. This structure allows for a compact representation of data while preserving individual values.

def create_stem_leaf(data):
    # Sort the data
    sorted_data = sorted(data)
    
    # Create stems and leaves
    stems = [str(x)[:-1] for x in sorted_data]
    leaves = [str(x)[-1] for x in sorted_data]
    
    # Create a dictionary to store leaves for each stem
    stem_leaf_dict = {}
    for stem, leaf in zip(stems, leaves):
        if stem in stem_leaf_dict:
            stem_leaf_dict[stem].append(leaf)
        else:
            stem_leaf_dict[stem] = [leaf]
    
    # Print the stem-leaf plot
    for stem, leaves in stem_leaf_dict.items():
        print(f"{stem} | {''.join(leaves)}")

# Example data
data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30]
create_stem_leaf(data)

Creating a Basic Stem-Leaf Plot

To create a stem-leaf plot, we first sort the data in ascending order. Then, we separate each number into its stem (leading digit(s)) and leaf (trailing digit). Finally, we arrange the leaves next to their corresponding stems.

def basic_stem_leaf(data):
    # Sort the data
    sorted_data = sorted(data)
    
    # Create stems and leaves
    stems = [str(x)[:-1] for x in sorted_data]
    leaves = [str(x)[-1] for x in sorted_data]
    
    # Print the stem-leaf plot
    unique_stems = sorted(set(stems))
    for stem in unique_stems:
        print(f"{stem} | ", end="")
        for i, s in enumerate(stems):
            if s == stem:
                print(leaves[i], end="")
        print()

# Example data
data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30]
basic_stem_leaf(data)

Interpreting a Stem-Leaf Plot

Stem-leaf plots provide valuable insights into data distribution. They allow us to quickly identify the median, mode, and range of the dataset. Additionally, we can easily spot clusters, gaps, and outliers in the data.

import numpy as np

def interpret_stem_leaf(data):
    # Calculate basic statistics
    median = np.median(data)
    mode = max(set(data), key=data.count)
    data_range = max(data) - min(data)
    
    print(f"Median: {median}")
    print(f"Mode: {mode}")
    print(f"Range: {data_range}")
    
    # Create and print the stem-leaf plot
    basic_stem_leaf(data)

# Example data
data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30, 20, 28]
interpret_stem_leaf(data)

Back-to-Back Stem-Leaf Plots

Back-to-back stem-leaf plots are useful for comparing two datasets. They display two stem-leaf plots facing each other, sharing a common stem. This arrangement allows for easy comparison of the distribution and spread of two datasets.

def back_to_back_stem_leaf(data1, data2):
    # Combine and sort both datasets
    all_data = sorted(data1 + data2)
    
    # Create stems and leaves
    stems = [str(x)[:-1] for x in all_data]
    leaves1 = [str(x)[-1] if x in data1 else '' for x in all_data]
    leaves2 = [str(x)[-1] if x in data2 else '' for x in all_data]
    
    # Print the back-to-back stem-leaf plot
    unique_stems = sorted(set(stems), reverse=True)
    for stem in unique_stems:
        left_leaves = ''.join(leaves1[i] for i, s in enumerate(stems) if s == stem)
        right_leaves = ''.join(leaves2[i] for i, s in enumerate(stems) if s == stem)
        print(f"{left_leaves:>10} | {stem} | {right_leaves}")

# Example data
data1 = [23, 29, 20, 32, 27, 25, 28]
data2 = [31, 24, 26, 22, 30, 33, 35]
back_to_back_stem_leaf(data1, data2)

Handling Large Datasets

For larger datasets, we may need to adjust our stem-leaf plot to maintain readability. One approach is to use larger stem intervals or to split stems when there are too many leaves for a single stem.

def large_dataset_stem_leaf(data, stem_interval=10):
    # Sort the data
    sorted_data = sorted(data)
    
    # Create stems and leaves
    stems = [str(x // stem_interval) for x in sorted_data]
    leaves = [str(x % stem_interval) for x in sorted_data]
    
    # Print the stem-leaf plot
    unique_stems = sorted(set(stems))
    for stem in unique_stems:
        print(f"{int(stem) * stem_interval:3d} | ", end="")
        for i, s in enumerate(stems):
            if s == stem:
                print(f"{leaves[i]:2s}", end=" ")
        print()

# Example data (larger dataset)
import random
data = [random.randint(0, 199) for _ in range(50)]
large_dataset_stem_leaf(data)

Stem-Leaf Plot with Outlier Detection

Stem-leaf plots can be enhanced to highlight outliers in the dataset. We can use statistical methods like the Interquartile Range (IQR) to identify and mark potential outliers.

import numpy as np

def stem_leaf_with_outliers(data):
    # Calculate Q1, Q3, and IQR
    q1, q3 = np.percentile(data, [25, 75])
    iqr = q3 - q1
    lower_bound = q1 - 1.5 * iqr
    upper_bound = q3 + 1.5 * iqr
    
    # Sort the data
    sorted_data = sorted(data)
    
    # Create stems and leaves
    stems = [str(x)[:-1] for x in sorted_data]
    leaves = [str(x)[-1] for x in sorted_data]
    
    # Print the stem-leaf plot with outlier detection
    unique_stems = sorted(set(stems))
    for stem in unique_stems:
        print(f"{stem} | ", end="")
        for i, s in enumerate(stems):
            if s == stem:
                if lower_bound <= sorted_data[i] <= upper_bound:
                    print(leaves[i], end="")
                else:
                    print(f"*{leaves[i]}*", end="")  # Mark outliers with asterisks
        print()

# Example data with outliers
data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30, 15, 40]
stem_leaf_with_outliers(data)

Colored Stem-Leaf Plot

We can enhance the visual appeal and interpretability of stem-leaf plots by adding color. This can be particularly useful for highlighting different ranges or categories within the data.

import matplotlib.pyplot as plt
import numpy as np

def colored_stem_leaf(data):
    # Sort the data
    sorted_data = sorted(data)
    
    # Create stems and leaves
    stems = [str(x)[:-1] for x in sorted_data]
    leaves = [str(x)[-1] for x in sorted_data]
    
    # Create a dictionary to store leaves for each stem
    stem_leaf_dict = {}
    for stem, leaf in zip(stems, leaves):
        if stem in stem_leaf_dict:
            stem_leaf_dict[stem].append(leaf)
        else:
            stem_leaf_dict[stem] = [leaf]
    
    # Plot the colored stem-leaf plot
    fig, ax = plt.subplots(figsize=(10, 6))
    colors = plt.cm.viridis(np.linspace(0, 1, len(stem_leaf_dict)))
    
    for i, (stem, leaves) in enumerate(stem_leaf_dict.items()):
        ax.text(0, int(stem), f"{stem} | {''.join(leaves)}", color=colors[i])
    
    ax.set_ylim(min(map(int, stems))-1, max(map(int, stems))+1)
    ax.set_axis_off()
    plt.title("Colored Stem-Leaf Plot")
    plt.show()

# Example data
data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30]
colored_stem_leaf(data)

Real-Life Example: Student Heights

Let's create a stem-leaf plot to visualize the distribution of heights (in centimeters) for a group of students in a classroom.

def student_heights_stem_leaf(heights):
    # Sort the heights
    sorted_heights = sorted(heights)
    
    # Create stems and leaves
    stems = [str(x)[:-1] for x in sorted_heights]
    leaves = [str(x)[-1] for x in sorted_heights]
    
    # Print the stem-leaf plot
    unique_stems = sorted(set(stems))
    for stem in unique_stems:
        print(f"{stem} | ", end="")
        for i, s in enumerate(stems):
            if s == stem:
                print(leaves[i], end="")
        print()

# Example student heights (in cm)
heights = [158, 162, 165, 170, 171, 173, 175, 176, 178, 180, 182, 185]
print("Student Heights (cm) Stem-Leaf Plot:")
student_heights_stem_leaf(heights)

Real-Life Example: Daily Temperature Readings

Let's create a stem-leaf plot to visualize daily temperature readings (in Celsius) for a month.

import random

def temperature_stem_leaf(temperatures):
    # Sort the temperatures
    sorted_temps = sorted(temperatures)
    
    # Create stems and leaves
    stems = [str(x)[:-1] for x in sorted_temps]
    leaves = [str(x)[-1] for x in sorted_temps]
    
    # Print the stem-leaf plot
    unique_stems = sorted(set(stems))
    for stem in unique_stems:
        print(f"{stem} | ", end="")
        for i, s in enumerate(stems):
            if s == stem:
                print(leaves[i], end="")
        print()

# Generate random temperature data for a month (in Celsius)
temperatures = [random.randint(15, 35) for _ in range(30)]
print("Daily Temperature Readings (°C) Stem-Leaf Plot:")
temperature_stem_leaf(temperatures)

Stem-Leaf Plot with Summary Statistics

We can enhance our stem-leaf plot by including summary statistics such as mean, median, and mode. This provides a more comprehensive view of the data distribution.

import numpy as np

def stem_leaf_with_stats(data):
    # Calculate summary statistics
    mean = np.mean(data)
    median = np.median(data)
    mode = max(set(data), key=data.count)
    
    # Create and print the stem-leaf plot
    basic_stem_leaf(data)
    
    # Print summary statistics
    print("\nSummary Statistics:")
    print(f"Mean: {mean:.2f}")
    print(f"Median: {median}")
    print(f"Mode: {mode}")

# Example data
data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30, 20, 28]
stem_leaf_with_stats(data)

Interactive Stem-Leaf Plot

Creating an interactive stem-leaf plot allows users to explore the data more dynamically. Here's a simple example using ipywidgets for Jupyter notebooks.

import ipywidgets as widgets
from IPython.display import display

def interactive_stem_leaf(data):
    def update_plot(stem_width):
        stems = [str(x // stem_width) for x in sorted(data)]
        leaves = [str(x % stem_width) for x in sorted(data)]
        
        unique_stems = sorted(set(stems))
        output = []
        for stem in unique_stems:
            stem_line = f"{int(stem) * stem_width:3d} | "
            stem_line += " ".join(leaves[i] for i, s in enumerate(stems) if s == stem)
            output.append(stem_line)
        
        plot_output.value = "\n".join(output)
    
    stem_width_slider = widgets.IntSlider(min=1, max=20, step=1, value=10, description="Stem Width:")
    plot_output = widgets.Textarea(layout={'width': '400px', 'height': '300px'})
    
    widgets.interactive(update_plot, stem_width=stem_width_slider)
    display(stem_width_slider, plot_output)

# Example data
data = [random.randint(0, 199) for _ in range(50)]
interactive_stem_leaf(data)

Stem-Leaf Plot vs. Histogram

While stem-leaf plots and histograms are both used to visualize data distribution, they have different strengths. Let's compare them using the same dataset.

import matplotlib.pyplot as plt
import numpy as np

def compare_stem_leaf_histogram(data):
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
    
    # Stem-leaf plot
    sorted_data = sorted(data)
    stems = [str(x)[:-1] for x in sorted_data]
    leaves = [str(x)[-1] for x in sorted_data]
    
    for stem in set(stems):
        ax1.text(0, int(stem), f"{stem} | {''.join([l for s, l in zip(stems, leaves) if s == stem])}")
    
    ax1.set_ylim(min(map(int, stems))-1, max(map(int, stems))+1)
    ax1.set_title("Stem-Leaf Plot")
    ax1.set_axis_off()
    
    # Histogram
    ax2.hist(data, bins='auto', edgecolor='black')
    ax2.set_title("Histogram")
    ax2.set_xlabel("Value")
    ax2.set_ylabel("Frequency")
    
    plt.tight_layout()
    plt.show()

# Example data
data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30, 20, 28]
compare_stem_leaf_histogram(data)

Limitations and Considerations

While stem-leaf plots are useful, they have limitations. They work best for small to medium-sized datasets and can become unwieldy for large datasets or those with a wide range of values. In such cases, other visualization methods like histograms or box plots might be more appropriate.

def stem_leaf_limitations(data):
    if len(data) > 100:
        print("Warning: Large dataset. Consider using a histogram instead.")
        return
    
    range_of_data = max(data) - min(data)
    if range_of_data > 100:
        print("Warning: Wide range of values. Consider using larger stem intervals.")
    
    # Proceed with stem-leaf plot
    basic_stem_leaf(data)

# Example data
small_data = [23, 29, 20, 32, 27, 25, 28, 31, 24, 26, 22, 30]
large_data = list(range(1, 200))

print("Small dataset:")
stem_leaf_limitations(small_data)

print("\nLarge dataset:")
stem_leaf_limitations(large_data)

Additional Resources

For those interested in diving deeper into stem-leaf plots and data visualization techniques, here are some valuable resources:

  1. "Visualizing Data Patterns with Micromaps" by Daniel B. Carr and Linda Williams Pickle (2010) ArXiv reference: https://arxiv.org/abs/1005.1937
  2. "Statistical Graphics Procedures by Example: Effective Graphs Using SAS" by Sanjay Matange and Dan Heath (2011) While not on ArXiv, this book provides comprehensive examples of various statistical graphics, including stem-leaf plots.
  3. "The Grammar of Graphics" by Leland Wilkinson (2005) This seminal work discusses the principles behind effective data visualization techniques.

Remember to verify these resources and their availability, as they may have been updated or moved since the last knowledge update.

More in Data visualisation

  1. Time Series Visualization in Python From Raw Data to Insights8 min

    Time series visualization is a powerful tool for understanding and analyzing data that changes over time. It allows us to identify patterns, trends, and...

  2. Raincloud Plots Visualizing Data Distributions in Python12 min

    Raincloud plots are an innovative data visualization technique that combines aspects of box plots, violin plots, and scatter plots. They provide a...

  3. Understanding Skewness in Data Visualization11 min

    Skewness measures the asymmetry of a probability distribution, indicating whether data leans left or right. In statistical analysis, understanding skewness...

  4. Python Visualizations Waffle Charts, Word Clouds, and Regression Plots13 min

    Master Waffle Charts are a visually appealing alternative to pie charts, displaying data in a grid of squares. Each square represents a portion of the whole...

  5. Visual Demonstration of DBSCAN Clustering6 min

    DBSCAN (Density-Based Spatial Clustering of Applications with Noise) is a powerful clustering algorithm that groups data points based on density. Unlike...

  6. Precision-Recall Plot Evaluating Classifier Performance5 min

    Precision and recall are fundamental metrics in binary classification problems. Precision measures the accuracy of positive predictions, while recall...