Matplotlib Plot Styling and Customization Techniques
Plot Creation Methods
Matplotlib provides multiple approaches for creating plots:
# Method 1: Basic figure and plot
figure = plt.figure(figsize=(12, 8))
plt.plot(data_x, data_y, linestyle='--', color='red', linewidth=2,
marker='o', markerfacecolor='blue', markersize=8, zorder=3)
# Method 2: Subplot indexing
figure = plt.figure(figsize=(12, 8))
plt.subplot(3, 3, index)
plt.plot(...)
axis = plt.subplot(3, 3, index)
axis.plot(...)
# Method 3: Subplots with gridspec
fig, axes = plt.subplots(3, 3, figsize=(12, 8))
fig, axes = plt.subplots(3, 1, figsize=(12, 10),
gridspec_kw={'height_ratios': [1, 1, 1]})
axes[0, 0].plot(...)
# Method 4: Single axis
fig, ax = plt.subplots(figsize=(12, 8))
ax.plot(...)
plt.plot(...)
Style Configuration
axes[i,j].set_xlabel('Recall', fontsize=14, fontweight='bold', loc="center", labelpad=20)
axes[i,j].set_ylabel('Precision', fontsize=14, fontweight='bold')
axes[i,j].set_title(f'OvR Precision-Recall Curve ({feature_type}-Ch{channel})',
fontsize=14, fontweight='bold')
axes[i,j].legend(loc="best", fontsize=12)
axes[i,j].set_xlim([0.0, 1.05])
axes[i,j].set_ylim([0.0, 1.05])
# Configure tick parameters
axes[i,j].tick_params(axis='both', which='both', width=2, labelsize=14)
axes[i,j].spines['top'].set_linewidth(2)
axes[i,j].spines['bottom'].set_linewidth(2)
axes[i,j].spines['left'].set_linewidth(2)
axes[i,j].spines['right'].set_linewidth(2)
fig, ax = plt.subplots(figsize=(10, 6))
plt.xlabel('Recall', fontsize=14, fontweight='bold')
plt.ylabel('Precision', fontsize=14, fontweight='bold')
plt.title(f'Micro-Averaged Precision-Recall Curve ({feature_type})',
fontsize=14, fontweight='bold')
plt.legend(loc="lower left", fontsize=12)
plt.legend(loc="upper right", fontsize=12)
plt.tick_params(axis='both', which='both', width=2, labelsize=14)
ax.spines['top'].set_linewidth(2)
ax.spines['bottom'].set_linewidth(2)
ax.spines['left'].set_linewidth(2)
ax.spines['right'].set_linewidth(2)
plt.xlim([0.0, 1.05])
plt.ylim([0.0, 1.05])
plt.grid(True)
plt.tight_layout()
plt.savefig(f"{output_directory}/{timestamp}_figure1.png")
plt.show()
plt.close()
Export Formats
Matplotlib supports various file formats for saving visualizations:
- PNG - Lossless compression for web and applications
- JPEG - Lossy compression for photographic content
- SVG - Vector format for scalible graphics
- PDF - High-quality print and archival format
- PS/EPS - PostScript formats for publishing
- TIFF - Versatile raster format for professional use
Text Annotation
plt.text(x_coord, y_coord, text_string, **kwargs)
# Examples
axis[0].text(3, 5, "Coordinate (3, 5)", fontsize=12, color='red')
plt.text(3, 5, "Coordinate (3, 5)", fontsize=12, color='red')
plt.text(3, 5, "Coordinate (3, 5)", fontsize=12, color='blue',
font="arial", style='italic', weight='bold')
plt.text(3, 5, "Rotated Annotation", fontsize=12, color='green', rotation=45)
plt.text(0.5, 0.95, f'ARI: {ari_value:.3f}, NMI: {nmi_value:.3f}',
ha='center', va='center', transform=plt.gca().transAxes)
axis[0].text(0.5, 0.95, f'ARI: {ari_value:.3f}, NMI: {nmi_value:.3f}',
ha='center', va='center', transform=axis[0].transAxes)
Subplot Labeling
import matplotlib.pyplot as plt
# Create 2x2 subplot grid
fig, axes = plt.subplots(2, 2, figsize=(10, 8))
# Generate sequential labels
label_count = 4
labels = [f'({chr(97 + i)})' for i in range(label_count)]
# Apply labels to each subplot
for idx, ax in enumerate(axes.flatten()):
ax.text(-0.1, 1.1, labels[idx], transform=ax.transAxes,
font="arial", fontsize=18, fontweight='bold', va='top')
plt.show()
Transparency Control
import matplotlib.pyplot as plt
import numpy as np
# Line transparency
x_values = [0, 1, 2, 3, 4]
y_values = [0, 2, 4, 6, 8]
plt.plot(x_values, y_values, alpha=0.5)
# Scatter plot transparency
plt.scatter(x_values, y_values, alpha=0.3)
# Bar plot transparency
plt.bar(x_values, y_values, alpha=0.7)
# Area fill transparency
plt.fill_between(x_values, y_values, alpha=0.2)
# Histogram transparency
sample_data = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
plt.hist(sample_data, alpha=0.6)
# Combined transparency example
x_range = np.linspace(0, 10, 100)
y_sine = np.sin(x_range)
y_cosine = np.cos(x_range)
plt.plot(x_range, y_sine, label='sin(x)', alpha=0.5)
plt.plot(x_range, y_cosine, label='cos(x)', alpha=0.7)
plt.fill_between(x_range, y_sine, y_cosine, alpha=0.3, color='gray')
plt.scatter(x_range[::10], y_sine[::10], alpha=0.6)
plt.legend()
plt.show()
Element Stacking Order
import matplotlib.pyplot as plt
import numpy as np
# Generate sample data
x_data = np.linspace(0, 10, 100)
y_data = np.sin(x_data)
# Create plot with controlled z-order
plt.figure()
plt.plot(x_data, y_data, label='Sin(x)', zorder=3)
plt.grid(True, zorder=2)
plt.legend(loc='upper right', zorder=4)
plt.title("Z-Order Control Example")
plt.show()
# Complex z-order example
x_points = np.arange(10)
y_points = 2.5 * np.sin(x_points / 20 * np.pi)
error_values = np.linspace(0.05, 0.2, 10)
plt.figure()
plt.bar(x_points, y_points + 3, color='blue', label='Bar', zorder=3)
plt.errorbar(x_points, y_points, yerr=error_values, label='Error Bar',
fmt='-o', zorder=4)
plt.scatter(x_points, y_points - 3, color='red', label='Scatter', zorder=5)
plt.grid(True, zorder=2)
plt.legend(loc='upper right', zorder=6)
plt.title("Multi-Element Z-Order Example")
plt.show()
Utility Functions
def format_axis(axis, x_label, y_label, x_limits=None, y_limits=None,
plot_title=None, enable_grid=True, show_legend=True,
legend_position="upper right"):
"""
Configures axis formatting with labels, titles, and styling.
Parameters:
axis : matplotlib.axes.Axes - Target axis object
x_label : str - X-axis label text
y_label : str - Y-axis label text
x_limits : tuple, optional - X-axis range (min, max)
y_limits : tuple, optional - Y-axis range (min, max)
plot_title : str, optional - Plot title text
enable_grid : bool, optional - Grid display toggle
show_legend : bool, optional - Legend display toggle
legend_position : str, optional - Legend placement
"""
axis.set_xlabel(x_label, fontsize=14, fontweight='bold')
axis.set_ylabel(y_label, fontsize=14, fontweight='bold')
if x_limits is not None:
axis.set_xlim(x_limits)
if y_limits is not None:
axis.set_ylim(y_limits)
if plot_title is not None:
axis.set_title(plot_title, fontsize=12)
if show_legend:
axis.legend(loc=legend_position, fontsize=12)
if enable_grid:
axis.grid(enable_grid, zorder=0)
axis.tick_params(axis='both', which='both', width=2, labelsize=14)
axis.spines['top'].set_linewidth(2)
axis.spines['bottom'].set_linewidth(2)
axis.spines['left'].set_linewidth(2)
axis.spines['right'].set_linewidth(2)
def add_sequential_labels(axes_array, label_x=-0.1, label_y=1.1, start_char='a'):
"""
Applies sequential labels to subplots.
Parameters:
axes_array : numpy array - Array of axis objects
label_x : float, optional - X coordinate for label placement
label_y : float, optional - Y coordinate for label placement
start_char : str, optional - Starting character for sequence
"""
label_count = len(axes_array)
labels = [f'({chr(ord(start_char) + i)})' for i in range(label_count)]
axes_flat = axes_array.flatten() if hasattr(axes_array, 'flatten') else axes_array
for idx, ax in enumerate(axes_flat):
ax.text(label_x, label_y, labels[idx], transform=ax.transAxes,
font="arial", fontsize=18, fontweight='bold', va='top')
Subplot Layout Management
import matplotlib.pyplot as plt
from matplotlib import gridspec
# subplots_adjust method
fig, ax = plt.subplots(2, 2)
plt.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9,
wspace=0.5, hspace=0.5)
# tight_layout method
fig, ax = plt.subplots(2, 2)
plt.tight_layout()
# constrained_layout method
fig, ax = plt.subplots(2, 2, constrained_layout=True)
# GridSpec for complex layouts
fig = plt.figure()
gs = gridspec.GridSpec(2, 2, figure=fig, width_ratios=[1, 2],
height_ratios=[4, 1], wspace=0.5, hspace=0.5)
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1])
ax3 = fig.add_subplot(gs[1, :])
# add_subplot method
fig = plt.figure(figsize=(10, 6))
ax1 = fig.add_subplot(3, 2, 1)
ax2 = fig.add_subplot(3, 2, 3)
ax3 = fig.add_subplot(3, 2, 5)
fig.tight_layout()
# subplot2grid method
fig = plt.figure(figsize=(10, 6))
ax1 = plt.subplot2grid((3, 3), (0, 0), rowspan=3, colspan=2)
ax2 = plt.subplot2grid((3, 3), (0, 2), rowspan=2, colspan=1)
ax3 = plt.subplot2grid((3, 3), (2, 2))
plt.show()
Line and Marker Styling
import matplotlib.pyplot as plt
# Sample data
x_data = [1, 2, 3, 4, 5]
y_data = [2, 3, 5, 7, 11]
# Line style options
plt.plot(x_data, y_data, linestyle='--') # Dashed
plt.plot(x_data, y_data, linestyle='-.') # Dash-dot
plt.plot(x_data, y_data, linestyle=':') # Dotted
# Color specification
plt.plot(x_data, y_data, color='red')
plt.plot(x_data, y_data, color='#FF5733') # Hex code
# Marker configuration
plt.plot(x_data, y_data, marker='o') # Circle
plt.plot(x_data, y_data, marker='s') # Square
plt.plot(x_data, y_data, marker='^') # Triangle
# Marker styling
plt.plot(x_data, y_data, marker='o', markerfacecolor='blue',
markeredgecolor='black', markersize=8)
# Line width control
plt.plot(x_data, y_data, linewidth=2)
# Combined styling
plt.plot(x_data, y_data, linestyle='--', color='red', linewidth=2,
marker='o', markersize=8)
plt.xlabel('X-axis')
plt.ylabel('Y-axis')
plt.title('Styled Plot Example')
plt.show()
Reference Lines
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(range(10), range(10))
# Horizontal reference line
ax.axhline(y=5, color='r', linestyle='--', linewidth=2)
# Vertical reference line
ax.axvline(x=5, color='b', linestyle=':', linewidth=2)
# Limited span horizontal line
ax.axhline(y=0.5, xmin=0.25, xmax=0.75, color='green',
linestyle='-', linewidth=3)
plt.show()
Legend Configuration
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.lines import Line2D
x_range = np.linspace(0, 10, 100)
y_sine = np.sin(x_range)
y_cosine = np.cos(x_range)
# Basic legend
plt.plot(x_range, y_sine, label='sin(x)')
plt.plot(x_range, y_cosine, label='cos(x)')
plt.legend()
# Customized legend
plt.plot(x_range, y_sine, '-b', label='sin(x)')
plt.plot(x_range, y_cosine, '-r', label='cos(x)')
plt.legend(loc='upper right', frameon=False, title='Functions',
fontsize='large')
# Custom legend handles
custom_lines = [Line2D([0], [0], color='b', lw=4),
Line2D([0], [0], color='r', lw=4)]
plt.plot(x_range, y_sine, '-b')
plt.plot(x_range, y_cosine, '-r')
plt.legend(custom_lines, ['sin(x)', 'cos(x)'], loc='best')
# External legend placement
fig, axes = plt.subplots(3, 3, figsize=(12, 10))
fig.legend(labels=unique_labels, bbox_to_anchor=(0.5, 0),
loc='lower center', ncol=5, fontsize=12)
plt.subplots_adjust(left=0.08, right=0.98, bottom=0.12, top=0.95,
wspace=0.35, hspace=0.4)
plt.show()
Axis Tick Management
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, MaxNLocator, FuncFormatter
import numpy as np
# Basic tick access
fig, ax = plt.subplots()
ax.plot(range(10))
print("X tick labels:", [tick.get_text() for tick in ax.get_xticklabels()])
print("Y tick labels:", [tick.get_text() for tick in ax.get_yticklabels()])
# Custom tick labels
fig, ax = plt.subplots()
ax.plot(range(10))
ax.set_xticklabels(['zero', 'one', 'two', 'three', 'four', 'five',
'six', 'seven', 'eight', 'nine'], rotation=45)
ax.set_yticklabels(['0%', '10%', '20%', '30%', '40%', '50%',
'60%', '70%', '80%', '90%'])
# Tick positioning
fig, ax = plt.subplots()
ax.plot(range(100))
ax.xaxis.set_major_locator(MultipleLocator(20))
ax.yaxis.set_major_locator(MultipleLocator(10))
# Advanced tick configuration
def square_formatter(value, position):
return f'{int(value**2)}'
fig, ax = plt.subplots()
x_values = np.linspace(0, 10, 100)
y_values = np.sin(x_values) * 100
ax.plot(x_values, y_values, label='100 * sin(x)')
ax.xaxis.set_major_locator(MultipleLocator(1))
ax.yaxis.set_major_locator(MaxNLocator(5))
ax.xaxis.set_major_formatter(FuncFormatter(square_formatter))
ax.tick_params(axis='x', direction='out', length=6, width=2, colors='blue',
grid_color='gray', grid_alpha=0.5, labelsize='medium',
labelcolor='green', rotation=45)
ax.tick_params(axis='y', direction='inout', length=12, width=2, colors='red',
grid_alpha=0.5, labelsize='small', labelcolor='purple', rotation=0)
ax.grid(True)
ax.legend()
plt.show()
Axis Position Adjustment
import matplotlib.pyplot as plt
import numpy as np
x_data = np.linspace(0, 10, 100)
y_data = np.sin(x_data)
fig, ax = plt.subplots()
ax.plot(x_data, y_data)
# Move y-axis to right side
ax.yaxis.set_ticks_position('right')
ax.yaxis.set_label_position('right')
ax.spines['right'].set_position(('outward', 0))
ax.spines['left'].set_position(('axes', 1.02))
ax.spines['left'].set_visible(False)
ax.set_ylabel('Amplitude', fontsize=14, fontweight='bold', labelpad=20)
plt.show()
Color Bar Implementation
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import FuncFormatter
# Basic color bar
data = np.random.rand(10, 10)
fig, ax = plt.subplots()
color_axis = ax.imshow(data, cmap='viridis')
color_bar = fig.colorbar(color_axis, ax=ax)
# Customized color bar
def percentage_format(x, pos):
return f'{x:.1%}'
data = np.random.rand(10, 10)
fig, ax = plt.subplots()
color_axis = ax.imshow(data, cmap='viridis')
color_bar = fig.colorbar(color_axis, ax=ax, orientation='horizontal')
color_bar.set_label('Intensity Scale')
color_bar.set_ticks([0.1, 0.3, 0.5, 0.7, 0.9])
color_bar.set_ticklabels(['Very Low', 'Low', 'Medium', 'High', 'Very High'])
color_bar.set_formatter(FuncFormatter(percentage_format))
plt.show()
Bar Chart Creation
import matplotlib.pyplot as plt
import numpy as np
# Basic bar chart
categories = ['Category A', 'Category B', 'Category C', 'Category D']
values = [10, 15, 7, 12]
plt.bar(categories, values, color='blue', edgecolor='black')
plt.title('Basic Bar Chart')
plt.xlabel('Categories')
plt.ylabel('Values')
plt.show()
# Grouped bar chart
categories = ['A', 'B', 'C', 'D']
values1 = [10, 15, 7, 10]
values2 = [5, 3, 9, 11]
x_positions = np.arange(len(categories))
bar_width = 0.35
fig, ax = plt.subplots()
bars1 = ax.bar(x_positions - bar_width/2, values1, bar_width, label='Group 1')
bars2 = ax.bar(x_positions + bar_width/2, values2, bar_width, label='Group 2')
ax.set_xlabel('Categories')
ax.set_ylabel('Values')
ax.set_title('Grouped Bar Chart')
ax.set_xticks(x_positions)
ax.set_xticklabels(categories)
ax.legend()
plt.show()
# Bar chart with error bars
errors = [0.5, 1.0, 0.5, 1.2]
plt.bar(categories, values, color='skyblue', yerr=errors, capsize=5)
plt.show()
Text Object Management
import matplotlib.pyplot as plt
# Basic text addition
plt.plot([1, 2, 3], [4, 5, 6])
plt.text(2, 5, 'Sample Text')
# Text customization
plt.plot([1, 2, 3], [4, 5, 6])
plt.text(2, 5, 'Styled Text', fontsize=12, color='red',
ha='center', va='bottom', rotation=45)
# Text object manipulation
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
text_obj = ax.text(2, 5, 'Dynamic Text', fontsize=12, color='blue')
text_obj.set_fontsize(14)
text_obj.set_color('green')
# Text search and modification
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
text1 = ax.text(1, 4, 'First Annotation', fontsize=12, color='blue')
text2 = ax.text(2, 5, 'Second Annotation', fontsize=12, color='red')
text3 = ax.text(3, 6, 'Third Annotation', fontsize=12, color='green')
def modify_text(axis, search_text, new_text, new_color='black', new_size=14):
for text_element in axis.findobj(match=plt.Text):
if text_element.get_text() == search_text:
text_element.set_text(new_text)
text_element.set_color(new_color)
text_element.set_fontsize(new_size)
break
modify_text(ax, 'Second Annotation', 'Updated Text',
new_color='purple', new_size=16)
# Text with bounding box
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [4, 5, 6])
text_element = ax.text(2, 5, 'Highlighted Text', fontsize=12, color='blue',
ha='center', va='bottom', rotation=45)
text_element.set_bbox(dict(facecolor='yellow', alpha=0.5, edgecolor='red'))
plt.show()
Mathematical Notation
import matplotlib.pyplot as plt
# Superscript and subscript
plt.figure()
plt.plot([1, 2, 3, 4, 5], [1, 4, 9, 16, 25])
plt.title(r'$y = x^2$')
plt.xlabel(r'$x_1$')
plt.ylabel(r'$x_{in}^2$')
plt.annotate(r'$Coordinate\ (x_1^3)$', (3, 9), textcoords="offset points",
xytext=(0,10), ha='center')
# Regular text in math expressions
plt.figure()
plt.plot([1, 2, 3], [1, 4, 9])
plt.title(r'$\alpha^2 + \beta^2 = \mathregular{constant}$')
plt.xlabel(r'$\mathregular{Time (seconds)}$')
plt.ylabel(r'$\mathregular{Distance (meters)}$')
plt.show()