Matplotlib plot_surface自定义facecolors报错,仅支持基础颜色?
The root of your problem lies in how NumPy handles string arrays by default. When you create colors = np.empty(X.shape, dtype=str), NumPy defaults to a single-character Unicode string dtype (U1). This means any longer color name or hex code gets truncated to its first character, which is why you see errors like Invalid RGBA argument: '#' or 'o'—those are the first characters of your truncated color values.
Solution: Use a Flexible String Dtype
Change the dtype of your colors array to either:
dtype=object: Stores full Python strings of any length (most flexible)- A fixed-length string dtype like
dtype='U20': Accommodates color names or hex codes up to 20 characters
Here's how to update your code for both scenarios:
Example 1: Using Hex Codes
import matplotlib.pyplot as plt from matplotlib.ticker import LinearLocator import numpy as np fig = plt.figure() ax = fig.gca(projection='3d') # Make data X = np.arange(-5, 5, 0.25) xlen = len(X) Y = np.arange(-5, 5, 0.25) ylen = len(Y) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) # Create color array with object dtype to store full hex codes colortuple = ('#ff7f0e', '#2ca02c') colors = np.empty(X.shape, dtype=object) # This is the key fix! for y in range(ylen): for x in range(xlen): colors[x, y] = colortuple[(x + y) % len(colortuple)] # Plot the surface surf = ax.plot_surface(X, Y, Z, facecolors=colors, linewidth=0) # Customize z-axis ax.set_zlim(-1, 1) ax.zaxis.set_major_locator(LinearLocator(6)) plt.show()
Example 2: Using Full Color Names
import matplotlib.pyplot as plt from matplotlib.ticker import LinearLocator import numpy as np fig = plt.figure() ax = fig.gca(projection='3d') # Make data X = np.arange(-5, 5, 0.25) xlen = len(X) Y = np.arange(-5, 5, 0.25) ylen = len(Y) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = np.sin(R) # Create color array with object dtype to store full color names colortuple = ('gray', 'orange') colors = np.empty(X.shape, dtype=object) # Key fix here too! for y in range(ylen): for x in range(xlen): colors[x, y] = colortuple[(x + y) % len(colortuple)] # Plot the surface surf = ax.plot_surface(X, Y, Z, facecolors=colors, linewidth=0) # Customize z-axis ax.set_zlim(-1, 1) ax.zaxis.set_major_locator(LinearLocator(6)) plt.show()
Alternative Approach: Use RGBA Arrays
If you prefer, you can convert your color strings directly to RGBA arrays using matplotlib.colors.to_rgba, which avoids string truncation entirely:
from matplotlib.colors import to_rgba # Convert color tuple to RGBA values colortuple = (to_rgba('#ff7f0e'), to_rgba('#2ca02c')) colors = np.empty(X.shape + (4,), dtype=np.float32) # 4 channels for RGBA for y in range(ylen): for x in range(xlen): colors[x, y] = colortuple[(x + y) % len(colortuple)]
This approach is more explicit and avoids any string-related issues, but requires creating a 3D array for RGBA values.
内容的提问来源于stack exchange,提问作者ch.A

