杰瑞科技汇

Python pcolormesh如何自定义颜色映射?

Of course! pcolormesh is a powerful and commonly used function in Matplotlib for creating pseudo-color plots. It's particularly well-suited for visualizing 2D scalar fields on a regular or irregular grid.

Python pcolormesh如何自定义颜色映射?-图1
(图片来源网络,侵删)

Let's break it down, from a simple example to a detailed explanation of its parameters and best practices.

What is pcolormesh?

pcolormesh stands for "pseudo-color mesh". It takes a 2D array of values and creates a grid of colored rectangles (a "mesh"). The color of each rectangle is determined by the corresponding value in the array.

It's the go-to function for plotting:

  • Heatmaps
  • 2D data from simulations (e.g., temperature, pressure)
  • Statistical data (e.g., correlation matrices)
  • Images (though imshow is often more optimized for this)

Simple Example: The Basics

Let's start with the most basic use case: plotting a 2D array where the coordinates are implicitly defined by the array's indices.

Python pcolormesh如何自定义颜色映射?-图2
(图片来源网络,侵删)
import numpy as np
import matplotlib.pyplot as plt
# 1. Create some data
# A 2D array of shape (10, 10)
data = np.random.rand(10, 10)
# 2. Create a figure and axes
fig, ax = plt.subplots()
# 3. Create the pcolormesh plot
# The data is the only argument needed. Matplotlib infers the grid.
mesh = ax.pcolormesh(data)
# 4. Add a colorbar to show the scale
fig.colorbar(mesh, ax=ax)
# 5. Add labels and a title
ax.set_title("Simple pcolormesh Plot")
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
plt.show()

What's happening here?

  • data is a 10x10 NumPy array.
  • ax.pcolormesh(data) creates a grid of 10x10 colored cells.
  • The bottom-left corner of the first cell is at coordinate (0, 0).
  • The top-right corner of the last cell is at coordinate (10, 10).
  • The color of each cell is mapped from its value (between 0 and 1) to a color in the default colormap (viridis).

Controlling the Grid with X and Y

The real power of pcolormesh comes when you define your own coordinates for the grid using the X and Y arguments. These define the corners of the colored cells.

Crucial Point: The X and Y arrays define the corners of the cells, not the centers. This means their shape will be one larger than the data array along each dimension.

If your data array is shape(M, N), then:

Python pcolormesh如何自定义颜色映射?-图3
(图片来源网络,侵删)
  • X should have a shape of (M+1, N+1)
  • Y should have a shape of (M+1, N+1)

Let's see an example:

import numpy as np
import matplotlib.pyplot as plt
# 1. Create data (5x4 grid)
data = np.random.rand(5, 4)
# 2. Create the coordinate arrays for the cell corners
# x-coordinates for the vertical lines (left and right edges of cells)
x = np.array([0, 1, 2, 3, 4])  # 5 vertical lines for 4 columns of cells
# y-coordinates for the horizontal lines (bottom and top edges of cells)
y = np.array([10, 20, 30, 40, 50]) # 5 horizontal lines for 5 rows of cells
# To create a 2D grid of corners, we use meshgrid
X, Y = np.meshgrid(x, y)
# 3. Create the plot
fig, ax = plt.subplots()
mesh = ax.pcolormesh(X, Y, data)
# 4. Add a colorbar and labels
fig.colorbar(mesh, ax=ax, label='Data Value')
ax.set_title("pcolormesh with Defined X and Y Grid")
ax.set_xlabel("X-coordinate (columns)")
ax.set_ylabel("Y-coordinate (rows)")
ax.set_aspect('equal') # Ensures cells are square
plt.show()

What's happening here?

  • We have a 5x4 data array.
  • x = [0, 1, 2, 3, 4] defines the vertical boundaries.
  • y = [10, 20, 30, 40, 50] defines the horizontal boundaries.
  • np.meshgrid creates the full 2D coordinate arrays X and Y of shape (6, 5) (one larger than data in each dimension).
  • pcolormesh uses these corner coordinates to draw the cells in the correct physical locations.

Key Parameters and Their Differences

This is where most confusion arises. Let's clarify the main ways to specify the grid.

pcolormesh(C) vs pcolormesh(X, Y, C)

Parameter Description Shape of X, Y Shape of C (Data)
pcolormesh(C) Cell-centered (default). Matplotlib assumes the grid lines are at integer coordinates. The cell centers are then at (i+0.5, j+0.5). Not provided. (M, N)
pcolormesh(X, Y, C) Corner-defined. X and Y explicitly define the coordinates of the cell corners. (M+1, N+1) (M, N)

shading Parameter

The shading parameter controls how the colors are rendered and is very important for appearance and performance.

  • 'auto' (default): Matplotlib chooses the best shading. For regular grids, it's often 'flat'. For irregular grids, it's 'gouraud'.
  • 'flat': Each cell has a single, solid color. This is the most common and fastest method. It corresponds to the value at the cell's center.
  • 'gouraud': Colors are interpolated smoothly between the four corners of each cell. This can be useful for irregular grids to create a smoother appearance, but it's slower and can hide the underlying cell structure.

Example of shading effects:

import numpy as np
import matplotlib.pyplot as plt
# Create data
x = np.arange(-5.0, 5.0, 0.1)
y = np.arange(-5.0, 5.0, 0.1)
X, Y = np.meshgrid(x, y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))
# --- Flat shading (default) ---
mesh1 = ax1.pcolormesh(X, Y, Z, shading='flat')
ax1.set_title("shading='flat'")
fig.colorbar(mesh1, ax=ax1)
# --- Gouraud shading ---
mesh2 = ax2.pcolormesh(X, Y, Z, shading='gouraud')
ax2.set_title("shading='gouraud'")
fig.colorbar(mesh2, ax=ax2)
plt.tight_layout()
plt.show()

When to Use pcolormesh vs. imshow

This is a classic question. Here’s a quick guide:

Feature pcolormesh imshow
Primary Use Irregularly spaced data. Data on a non-rectilinear grid. Regularly spaced data. Data on a pixel-like grid.
Coordinates Explicit control. Can define arbitrary X and Y corner coordinates. Implicitly defined. Assumes data pixels are aligned on a regular grid.
Data Orientation Data-as-is. The first row of the array is plotted at the bottom. Flipped by default. The first row of the array is plotted at the top.
Performance Slower, especially for large arrays and with shading='gouraud'. Highly optimized, very fast for large arrays.
Interpolation No built-in interpolation between pixels. Excellent built-in interpolation (nearest, bilinear, bicubic, etc.).

Rule of Thumb:

  • If your (x, y) coordinates form a perfect, regular grid, use imshow. It's faster and more idiomatic.
  • If your (x, y) coordinates are irregular, or if you need fine-grained control over the cell boundaries, use pcolormesh.

Complete Example: Plotting a Mathematical Function

Let's combine everything to plot a 2D function z = sin(x) * cos(y) over a specific domain.

import numpy as np
import matplotlib.pyplot as plt
# 1. Define the domain
x = np.linspace(-np.pi, np.pi, 100)  # 100 points from -pi to pi
y = np.linspace(0, 2 * np.pi, 100)   # 100 points from 0 to 2*pi
# 2. Create the grid of coordinates for the cell centers
X, Y = np.meshgrid(x, y)
# 3. Calculate the data at the cell centers
Z = np.sin(X) * np.cos(Y)
# 4. Create the corner coordinates for pcolormesh
# The corners are one step beyond the centers
X_corners, Y_corners = np.meshgrid(x, y, indexing='ij')
X_corners = np.append(X_corners, X_corners[-1, -1] + (X_corners[0,1] - X_corners[0,0])) # Add last edge
Y_corners = np.append(Y_corners, Y_corners[-1, -1] + (Y_corners[1,0] - Y_corners[0,0])) # Add last edge
# A simpler way to get corner coordinates:
X_corners, Y_corners = np.meshgrid(x, y, indexing='ij')
X_corners = np.append(X_corners, X_corners[-1,-1] + (x[1]-x[0]))
Y_corners = np.append(Y_corners, Y_corners[-1,-1] + (y[1]-y[0]))
# A much better way is to use np.linspace again for the edges
x_edges = np.linspace(-np.pi, np.pi, 101) # 101 edges for 100 cells
y_edges = np.linspace(0, 2 * np.pi, 101)
X_edges, Y_edges = np.meshgrid(x_edges, y_edges)
# 5. Create the plot
fig, ax = plt.subplots(figsize=(8, 6))
# Use the corner coordinates (X_edges, Y_edges) and the data (Z)
mesh = ax.pcolormesh(X_edges, Y_edges, Z, shading='flat', cmap='plasma')
# 6. Add colorbar, labels, and title
fig.colorbar(mesh, ax=ax, label='Value of sin(x)cos(y)')
ax.set_title("2D Function Visualization with pcolormesh")
ax.set_xlabel("x-axis")
ax.set_ylabel("y-axis")
ax.set_aspect('equal', adjustable='box') # Adjust aspect ratio
plt.show()

This final example demonstrates the complete workflow: defining a domain, creating data, generating the necessary coordinate grids (both for centers and corners), and plotting with custom styling.

分享:
扫描分享到社交APP
上一篇
下一篇