Unit 11: Data visualization

ECAP776 6 min read

I. Orientation — Representing Data Graphically

Data visualization is the graphical representation of data so that patterns, comparisons, distributions, relationships, and unusual observations can be understood efficiently. In Python, Matplotlib—first released by John D. Hunter in 2003—is a foundational plotting library used directly and by higher-level libraries such as pandas and Seaborn.

A. Introduction to matplotlib

Matplotlib creates figures containing one or more coordinate systems on which data is plotted.

  • Installation: Matplotlib can be installed from the command line with a package manager.
    BASH
      python -m pip install matplotlib
  • Import convention: The pyplot module is conventionally imported as plt.
    PYTHON
      import matplotlib.pyplot as plt
  • Figure: A Figure is the complete drawing area or output image; it may contain several plots.
  • Axes: An Axes object is an individual plotting region containing an x-axis, a y-axis, titles, labels, and plotted data.
  • Axis: An Axis manages the scale, tick marks, and tick labels for one dimension; it is distinct from an Axes.
  • Basic workflow:
    1. Prepare values, usually in lists or NumPy arrays.
    2. Create a figure and axes with plt.subplots().
    3. Call a plotting method such as ax.plot() or ax.bar().
    4. Add labels, a title, and other explanatory elements.
    5. display or save the completed figure.
      PYTHON
        fig, ax = plt.subplots()
        ax.plot([1, 2, 3], [2, 4, 3])
        ax.set(xlabel="Input", ylabel="Output", title="Sample Plot")
        plt.show()
  • Object-oriented interface: Calling methods on fig and ax makes the target of each operation explicit and is especially useful for multi-plot figures.
  • Output: plt.show() displays a figure, while fig.savefig("plot.png", dpi=300, bbox_inches="tight") saves it at 300 dots per inch with reduced outer whitespace.
  • Communication principle: Every visualization should use an appropriate plot type, readable labels, meaningful units, and restrained colors rather than unnecessary decoration.

II. Line Plot — Change and Continuity

A line plot joins ordered data points and is most suitable for displaying change over a continuous or naturally ordered variable, especially time.

A. Line plot

A line plot emphasizes trends, rates of change, peaks, and repeated movement across sequential observations.

  • Construction: ax.plot(x, y) plots coordinate pairs ((x_i,y_i)) and connects consecutive points.
    PYTHON
      days = [1, 2, 3, 4, 5]
      temperature = [21, 23, 22, 25, 27]
    
      fig, ax = plt.subplots()
      ax.plot(days, temperature, marker="o", color="navy",
              linestyle="-", label="Temperature")
      ax.set(xlabel="Day", ylabel="Temperature (°C)",
             title="Daily Temperature")
      ax.legend()
      ax.grid(alpha=0.3)
      plt.show()

    Here, (x_i) is a day number and (y_i) is temperature in degrees Celsius.
  • Appearance: color controls line color, linestyle controls patterns such as "-" or "--", and marker="o" marks measured observations.
  • Multiple series: Repeated ax.plot() calls place several lines on the same axes; distinct labels and styles identify them through ax.legend().
  • Interpretation: A rising segment indicates an increase between adjacent x-values, but it does not by itself prove a causal relationship.
  • Limitation: Joining unordered categories implies continuity that does not exist; a bar chart is usually more appropriate for categories.

III. Figure Layout — Coordinating Related Views

Subplots divide one figure into separate axes, allowing related visualizations to be compared without placing every series on the same coordinate system.

A. Multiple subplots in one figure

Multiple subplots organize distinct but related plots into a specified grid of rows and columns.

  • Grid creation: plt.subplots(r, c) returns one figure and axes arranged in (r) rows and (c) columns.
    PYTHON
      x = [1, 2, 3, 4]
      sales = [12, 18, 16, 24]
      costs = [8, 11, 12, 15]
    
      fig, axes = plt.subplots(1, 2, figsize=(9, 4))
      axes[0].plot(x, sales, marker="o")
      axes[0].set_title("Sales")
      axes[1].bar(x, costs)
      axes[1].set_title("Costs")
    
      for ax in axes:
          ax.set_xlabel("Quarter")
    
      fig.suptitle("Quarterly Performance")
      fig.tight_layout()
      plt.show()

    Here, axes[0] and axes[1] refer to the left and right plotting regions.
  • Two-dimensional access: For a (2 \times 2) arrangement, an axes position is selected as axes[row, column], with zero-based indexes.
  • Figure sizing: figsize=(9, 4) specifies width and height in inches, helping prevent labels from overlapping.
  • Shared scales: sharex=True or sharey=True applies common axis scales, making visual comparisons more reliable.
  • Layout control: fig.tight_layout() adjusts spacing, while layout="constrained" may be passed when creating subplots for automatic arrangement.
  • Distinction: ax.set_title() titles one subplot; fig.suptitle() titles the complete figure.

IV. Bar Chart — Comparing Categories

A bar chart represents each category with a rectangular bar whose length or height is proportional to its associated numerical value.

A. Bar chart

Bar charts are designed for comparisons among discrete categories rather than continuous measurements.

  • Vertical bars: ax.bar(categories, values) places categories on the x-axis and measurements on the y-axis.
    PYTHON
      products = ["A", "B", "C", "D"]
      units = [35, 52, 41, 28]
    
      fig, ax = plt.subplots()
      bars = ax.bar(products, units, color="steelblue")
      ax.set(xlabel="Product", ylabel="Units sold", title="Product Sales")
      ax.bar_label(bars)
      plt.show()
  • Horizontal bars: ax.barh(categories, values) is useful when category names are long or when ranking many categories.
  • Baseline: A quantitative bar axis should normally begin at zero because viewers compare bar lengths; truncating the axis exaggerates differences.
  • Grouped bars: Bars for several series can be offset around each category, such as separate 2025 and 2026 values for Product A.
  • Stacked bars: Passing bottom=previous_values stacks one series above another, showing totals and composition simultaneously.
  • Width and color: width controls bar thickness, while consistent colors clarify grouping; too many unrelated colors can distract from magnitude.
  • Limitation: A bar chart summarizes category values but does not reveal the underlying distribution of individual observations.

V. Histogram — Examining a Distribution

A histogram groups continuous numerical observations into intervals called bins and displays the frequency or density within each interval.

A. Histogram

A histogram reveals distributional features such as center, spread, skewness, multiple peaks, and possible extreme values.

  • Construction: ax.hist(data, bins=n) divides the data range into (n) intervals and counts observations in each.
    PYTHON
      scores = [48, 55, 57, 61, 62, 65, 67, 69, 72, 74,
                76, 78, 81, 83, 85, 88, 91, 94]
    
      fig, ax = plt.subplots()
      ax.hist(scores, bins=5, edgecolor="black", color="cornflowerblue")
      ax.set(xlabel="Score", ylabel="Frequency",
             title="Distribution of Test Scores")
      plt.show()
  • Frequency definition: For bin (j), its frequency is
    [
    f_j=#{x_i:b_j\leq xi<b{j+1}},
    ]
    where (x_i) is an observation and (bj,b{j+1}) are consecutive bin boundaries.
  • Bin choice: Too few bins conceal structure, whereas too many bins make random variation appear important; results should be checked across reasonable widths.
  • Density scale: density=True rescales bar areas so their total area equals 1, enabling comparison between datasets of different sizes.
  • Bar adjacency: Histogram bars normally touch because bins represent adjacent intervals; categorical bar-chart bars are normally separated.
  • Interpretation: A long right tail indicates positive skew, while two clear peaks may indicate two underlying subgroups.
  • Limitation: Exact individual values are not retained visually because all observations within one bin are aggregated.

VI. Box-and-Whisker Plot — Compact Distribution Summary

A box-and-whisker plot summarizes a numerical distribution through quartiles, the median, whiskers, and individually marked potential outliers.

A. Box and whisker plot

A box plot supports compact comparisons of center, variability, skewness, and unusual values across one or more groups.

  • Five-number basis: The important quantities are minimum, first quartile (Q_1), median (Q_2), third quartile (Q_3), and maximum, although whiskers do not always extend to the actual extremes.
  • Interquartile range:
    [
    IQR=Q_3-Q_1
    ]
    where (Q_1) is the 25th percentile and (Q_3) is the 75th percentile.
  • Outlier convention: Matplotlib’s default whiskers extend to the most extreme observed points within (Q_1-1.5IQR) and (Q_3+1.5IQR); farther observations are plotted separately.
    PYTHON
      group_a = [12, 14, 15, 15, 17, 18, 19, 30]
      group_b = [10, 11, 13, 16, 18, 20, 21, 22]
    
      fig, ax = plt.subplots()
      ax.boxplot([group_a, group_b], tick_labels=["A", "B"])
      ax.set(ylabel="Processing time (minutes)",
             title="Processing-Time Distributions")
      plt.show()
  • Visual components: The box spans (Q_1) to (Q_3), its internal line marks the median, and whiskers show the default non-outlier range.
  • Comparison: A higher median line indicates a higher typical value, while a taller box indicates a larger middle-50% spread.
  • Limitation: Different distribution shapes can produce similar box plots, so a histogram or scatter-based display may provide useful additional detail.

VII. Scatter Plot — Relationships Between Variables

A scatter plot displays paired numerical observations as unconnected points, making it suitable for investigating relationships between two quantitative variables.

A. Scatter plot

Scatter plots reveal direction, form, strength, clusters, and unusual observations in bivariate data.

  • Coordinates: Each point represents one pair ((x_i,y_i)), such as hours studied and test score for student (i).
    PYTHON
      hours = [1, 2, 2.5, 3, 4, 5, 6]
      scores = [52, 58, 61, 65, 72, 80, 86]
    
      fig, ax = plt.subplots()
      ax.scatter(hours, scores, s=60, color="darkgreen", alpha=0.75)
      ax.set(xlabel="Hours studied", ylabel="Score",
             title="Study Time and Score")
      plt.show()
  • Direction: An upward pattern indicates positive association; a downward pattern indicates negative association.
  • Strength and form: Points tightly concentrated around a line suggest a strong linear relationship, while a curved pattern suggests a nonlinear relationship.
  • Encoding variables: s controls marker area, c can map color to another variable, and alpha controls transparency from 0 to 1.
  • Overplotting: Transparency, smaller markers, or slight jitter can expose dense regions where many points overlap.
  • Caution: Association does not establish causation; a third variable may influence both plotted variables.
  • Limitation: Connecting scatter points is inappropriate unless the observations possess a meaningful sequence.

VIII. Pie Chart — Showing Parts of a Whole

A pie chart divides a circle into sectors whose angles and areas represent non-negative parts of a complete total.

A. Pie charts

Pie charts communicate simple part-to-whole composition when the number of categories is small and differences are sufficiently large.

  • Proportion: For category (i),
    [
    p_i=\frac{vi}{\sum{j=1}^{k}v_j},\qquad
    \theta_i=360^\circ p_i,
    ]
    where (v_i) is its value, (k) is the number of categories, (p_i) is its proportion, and (\theta_i) is its sector angle.
    PYTHON
      labels = ["Rent", "Food", "Transport", "Other"]
      costs = [1200, 500, 200, 300]
    
      fig, ax = plt.subplots()
      ax.pie(costs, labels=labels, autopct="%1.1f%%",
             startangle=90)
      ax.set_title("Monthly Expenses")
      plt.show()
  • Percentage labels: autopct="%1.1f%%" displays percentages to one decimal place.
  • Starting angle: startangle=90 begins the first sector at the top, often making orientation easier to read.
  • Whole-total requirement: Values should represent mutually exclusive parts of one meaningful total; overlapping categories invalidate the composition.
  • Readability: A legend or direct labels identify sectors, while a consistent ordering helps readers locate categories.
  • Limitation: Humans compare lengths more accurately than angles or areas, so a sorted bar chart is preferable for many categories or small differences.