Unit 12: Data visualization

ECAP776 9 min read

I. Orientation: Statistical Data Visualization

Data visualization converts data into graphical marks so that patterns, distributions, relationships, and uncertainty can be interpreted efficiently. In Python, Seaborn provides a high-level interface for statistical graphics while relying on Matplotlib for the underlying figures, axes, and rendering.

  • Governing principle: A visualization should match the graphical encoding to the analytical question—for example, position on a scatter plot can represent two quantitative variables, while color can distinguish categories.
  • Data-to-visual mapping: Variables are mapped to visual properties such as:
    • Position: x and y coordinates.
    • Color: the hue semantic.
    • Marker or line pattern: the style semantic.
    • Magnitude: the size semantic.
  • Statistical purpose: Graphs may display raw observations, aggregates such as means, estimated trends, confidence intervals, or complete distributions.
  • Data convention: Seaborn works especially well with tidy data, where each row is an observation, each column is a variable, and each cell contains one value.
  • Figure structure: Matplotlib supplies the Figure container and Axes plotting area; Seaborn creates and configures these objects through higher-level functions.
  • Design requirement: Titles, labels, units, scales, legends, and accessible colors must make the graphic interpretable without relying on surrounding code.
  • Analytical caution: A graph can mislead through truncated axes, inappropriate aggregation, hidden missing values, overplotting, or an unsuitable chart type.

II. Seaborn — A High-Level Statistical Visualization Library

A. Introduction to seaborn

Seaborn is an open-source Python library, created by Michael Waskom, that simplifies the production of informative statistical graphics.

  • Foundation: Seaborn is built on Matplotlib and normally imported alongside it:
    PYTHON
      import seaborn as sns
      import matplotlib.pyplot as plt

    Here, sns is the conventional alias for Seaborn, while plt exposes Matplotlib’s plotting interface.
  • Data integration: Most functions accept a pandas DataFrame through data and refer to its columns by name through parameters such as x, y, and hue.
  • Semantic mappings: A single function can encode several variables:
    • x="height" maps height to horizontal position.
    • y="weight" maps weight to vertical position.
    • hue="group" assigns colors according to group.
    • style="category" assigns different marker shapes or line styles.
  • Statistical operations: Certain functions calculate values before drawing them. For example, sns.regplot() estimates a regression line, while sns.barplot() displays an estimator—mean by default—for each category.
  • Consistent themes: sns.set_theme() controls background, grid lines, fonts, and palette defaults:
    PYTHON
      sns.set_theme(style="whitegrid", context="notebook")

    The style argument controls the axes background, and context scales visual elements for settings such as notebooks, papers, talks, or posters.
  • Two interface levels:
    • Axes-level functions: Functions such as scatterplot(), histplot(), and boxplot() draw on one Matplotlib Axes and return that Axes.
    • Figure-level functions: Functions such as relplot(), displot(), and catplot() manage an entire figure, support faceting, and return grid objects such as FacetGrid.
  • Introductory example: The following plot displays the relationship between study time and score, with teaching method encoded by color:
    PYTHON
      import pandas as pd
      import seaborn as sns
      import matplotlib.pyplot as plt
    
      results = pd.DataFrame({
          "hours": [1, 2, 3, 4, 5, 6],
          "score": [48, 55, 63, 68, 78, 84],
          "method": ["A", "A", "B", "A", "B", "B"]
      })
    
      sns.set_theme(style="whitegrid")
      ax = sns.scatterplot(
          data=results, x="hours", y="score",
          hue="method", style="method", s=90
      )
      ax.set(title="Study Time and Score",
             xlabel="Study time (hours)",
             ylabel="Score (%)")
      plt.show()

    Each row supplies one point; hue and style make the two methods distinguishable by both color and marker.

B. Applications and limitations

Seaborn is most effective for exploratory and statistical graphics, but its defaults do not replace analytical judgment.

  • Suitable applications: It supports rapid exploration of relationships, grouped distributions, categorical comparisons, regressions, and correlation matrices.
  • Efficient defaults: Automatic legends, coordinated palettes, sensible spacing, and statistical estimates reduce repetitive formatting code.
  • Customization route: Because output is based on Matplotlib, methods such as ax.set(), ax.legend(), and plt.savefig() can refine or export a Seaborn plot.
  • Default statistics: An automatically drawn mean, fitted line, or error interval may not answer the intended question; the estimator and uncertainty method must be checked explicitly.
  • Large datasets: Millions of points can produce slow rendering and overplotting. Sampling, aggregation, transparency, binning, or density plots may be preferable.
  • Specialized graphics: Highly interactive dashboards, geographic maps, and unusual publication layouts generally require other libraries or substantial Matplotlib customization.

III. Comparing Python Visualization Interfaces

A. Seaborn vs matplotlib

Seaborn and Matplotlib are complementary: Matplotlib provides detailed low-level control, whereas Seaborn provides concise, data-aware statistical plotting.

  1. Matplotlib

    • Abstraction level: Commands directly control graphical objects such as figures, axes, lines, ticks, and annotations.
    • Input style: Plotting functions commonly receive arrays or sequences, as in ax.plot(x_values, y_values).
    • Control: It is well suited to custom layouts, uncommon chart structures, precise annotations, and detailed formatting.
    • Cost: Grouping categories, choosing coordinated colors, calculating summaries, and constructing legends can require more code.
  2. Seaborn

    • Abstraction level: Commands describe statistical relationships through named variables and semantic parameters.
    • Input style: A complete DataFrame can be passed once, after which column names define the mappings.
    • Statistical support: Distribution estimation, categorical aggregation, regression fitting, and faceting are built into major plot families.
    • Cost: High-level defaults can make uncommon layouts harder to construct without accessing the underlying Matplotlib objects.
  • Direct comparison: The same grouped scatter plot requires manual filtering and labeling in Matplotlib but automatic semantic mapping in Seaborn:
    PYTHON
      # Matplotlib
      fig, ax = plt.subplots()
      for method, group in results.groupby("method"):
          ax.scatter(group["hours"], group["score"], label=method)
      ax.legend(title="method")
    
      # Seaborn
      sns.scatterplot(
          data=results, x="hours", y="score", hue="method"
      )
  • Shared object model: Seaborn does not replace Matplotlib. An axes-level call can receive ax=ax, and its result can then be modified with Matplotlib methods.
  • Practical choice:
    • Use Seaborn for fast exploration, tidy-data grouping, distributions, and statistical comparisons.
    • Use Matplotlib for complete control over axes, annotations, multipanel arrangements, and specialized graphics.
    • Use both together for a statistical plot with precise presentation-level formatting.

B. Selection criteria and limitations

The appropriate interface depends on the data structure, required statistical processing, and desired level of graphical control.

  • Choose by purpose: sns.boxplot() is concise for comparing distributions, while Matplotlib is preferable when every box, label, or annotation requires independent positioning.
  • Choose by structure: Seaborn’s named-variable interface is most convenient for long-form data; raw numerical arrays may fit Matplotlib more naturally.
  • Avoid false opposition: Since Seaborn returns or contains Matplotlib objects, a common workflow starts with Seaborn and finishes with Matplotlib.
  • Version awareness: Parameters can change between releases; for example, modern Seaborn categorical functions use errorbar to configure uncertainty intervals.
  • Output consistency: Themes affect subsequent plots in the same Python session, so a project should establish styling once and override only intentional exceptions.

IV. Constructing Statistical Graphics

A. Data visualization using seaborn

Data visualization using Seaborn follows a sequence of preparing tidy data, selecting a plot family, mapping variables, and refining the resulting figure.

  • Relational plots: scatterplot() displays relationships between quantitative variables, while lineplot() emphasizes ordered change such as measurements over time.
  • Distribution plots:
    • histplot() divides values into intervals and displays frequency or density.
    • kdeplot() estimates a smooth probability density.
    • ecdfplot() displays the proportion of observations less than or equal to each value.
  • Categorical plots:
    • stripplot() and swarmplot() show individual observations.
    • boxplot() shows the median, quartiles, whiskers, and potential outliers.
    • violinplot() combines category comparison with estimated distribution shape.
    • barplot() displays an estimated value and, by default, an uncertainty interval rather than raw frequencies.
    • countplot() displays the number of observations in each category.
  • Regression plots: regplot() combines a scatter plot with a fitted regression model; lmplot() extends this approach with figure-level faceting.
  • Matrix plots: heatmap() encodes matrix values as colors and is commonly applied to a correlation matrix produced by DataFrame.corr(numeric_only=True).
  • Faceting: Figure-level functions can split observations across panels using row and col, allowing the same relationship to be compared across categories.
  • Integrated workflow example: This visualization compares penguin measurements across species and islands:
    PYTHON
      import pandas as pd
      import seaborn as sns
      import matplotlib.pyplot as plt
    
      penguins = pd.read_csv("penguins.csv")
      plot_data = penguins.dropna(
          subset=["bill_length_mm", "flipper_length_mm",
                  "species", "island"]
      )
    
      sns.set_theme(style="ticks", palette="colorblind")
      g = sns.relplot(
          data=plot_data,
          x="bill_length_mm",
          y="flipper_length_mm",
          hue="species",
          style="species",
          col="island",
          kind="scatter",
          height=3.5,
          aspect=0.9,
          alpha=0.75
      )
      g.set_axis_labels("Bill length (mm)", "Flipper length (mm)")
      g.set_titles("Island: {col_name}")
      g.figure.suptitle("Penguin Measurements by Island", y=1.05)
      g.savefig("penguin_measurements.png", dpi=300,
                bbox_inches="tight")
      plt.show()

    dropna() removes only rows missing required plotting variables; position represents two measurements, hue and style encode species, and col creates one panel per island.

B. Interpretation, presentation, and limitations

A technically correct Seaborn command still requires careful interpretation and presentation to produce a trustworthy visualization.

  • Labels and units: Axis labels should state concrete measurements, such as “Flipper length (mm),” rather than merely repeat a column name.
  • Scale integrity: Logarithmic scales can clarify multiplicative patterns but must be identified; truncated bar-chart axes can exaggerate small differences.
  • Overplotting control: Parameters such as alpha=0.4, smaller markers, faceting, or histplot() can reveal patterns hidden by overlapping points.
  • Color accessibility: A palette such as "colorblind" should be combined with marker shape or line style when category distinctions are important.
  • Missing data: Rows omitted because of null values may represent a systematic subgroup, so their number and cause should be examined before plotting.
  • Aggregation awareness: A bar showing a mean can conceal skew, clusters, and outliers; a box, violin, or raw-point layer provides distributional context.
  • Uncertainty interpretation: Error bars describe an estimated interval under specific assumptions or resampling procedures; they are not automatically the range of the observations.
  • Export quality: savefig() should specify an appropriate resolution such as dpi=300 for raster publication, while SVG or PDF preserves scalable vector graphics.