When trying to plot a 3D normal distribution recently, I encountered the following error:
TypeError Traceback (most recent call last)
<ipython-input-10-ee1b0cd4b744> in <cell line: 32>()
30 fig = plt.figure()
31
---> 32 ax = fig.gca(projection='3d')
33
34 # create a 3D surface plot of the multivariate normal distribution
π TypeError: FigureBase.gca() got an unexpected keyword argument 'projection' π€
<Figure size 640x480 with 0 Axes>
This happened after running the following code snippet — see the highlighted line:
ax = fig.gca(projection='3d')
Here’s the full context in case you want to reproduce the error: π
# import necessary libraries import numpy as np import matplotlib.pyplot as plt from scipy.stats import multivariate_normal from mpl_toolkits.mplot3d import Axes3D # define parameters for x and y distributions mu_x = 0 # mean of x variance_x = 3 # variance of x mu_y = 0 # mean of y variance_y = 15 # variance of y # define a grid for x and y values x = np.linspace(-10, 10, 500) # generate 500 points between -10 and 10 for x y = np.linspace(-10, 10, 500) # generate 500 points between -10 and 10 for y X, Y = np.meshgrid(x, y) # create a grid for (x,y) pairs # create an empty array of the same shape as X to hold the (x, y) coordinates pos = np.empty(X.shape + (2,)) # fill the pos array with the x and y coordinates pos[:, :, 0] = X pos[:, :, 1] = Y # create a multivariate normal distribution using the defined parameters rv = multivariate_normal([mu_x, mu_y], [[variance_x, 0], [0, variance_y]]) # create a new figure for 3D plot fig = plt.figure() ax = fig.gca(projection='3d') # create a 3D surface plot of the multivariate normal distribution ax.plot_surface(X, Y, rv.pdf(pos), cmap='viridis', linewidth=0) # set labels for the axes ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') # display the 3D plot plt.show()
I experienced this error when creating the code as explained in my other blog article on creating a 3D normal distribution plot in Python.
But now let’s dive into the solution: π
Solution
The simple solution is to replace the line:
ax = fig.gca(projection='3d')
with the line
ax = fig.add_subplot(projection='3d')
And voila, it’ll work!
This error appears because, in Matplotlib 3.4 and later versions, the function gca()
no longer takes keyword arguments. However, many code snippets on the web still have the same old and stale recommendations.
Here’s the updated code snippet with the line swapped, i.e., I replaced fig.gca(projection='3d')
with fig.add_subplot(projection='3d')
.
# import necessary libraries import numpy as np import matplotlib.pyplot as plt from scipy.stats import multivariate_normal from mpl_toolkits.mplot3d import Axes3D # define parameters for x and y distributions mu_x = 0 # mean of x variance_x = 3 # variance of x mu_y = 0 # mean of y variance_y = 15 # variance of y # define a grid for x and y values x = np.linspace(-10, 10, 500) # generate 500 points between -10 and 10 for x y = np.linspace(-10, 10, 500) # generate 500 points between -10 and 10 for y X, Y = np.meshgrid(x, y) # create a grid for (x,y) pairs # create an empty array of the same shape as X to hold the (x, y) coordinates pos = np.empty(X.shape + (2,)) # fill the pos array with the x and y coordinates pos[:, :, 0] = X pos[:, :, 1] = Y # create a multivariate normal distribution using the defined parameters rv = multivariate_normal([mu_x, mu_y], [[variance_x, 0], [0, variance_y]]) # create a new figure for 3D plot fig = plt.figure() # add a 3D subplot to the figure ax = fig.add_subplot(projection='3d') # create a 3D surface plot of the multivariate normal distribution ax.plot_surface(X, Y, rv.pdf(pos), cmap='viridis', linewidth=0) # set labels for the axes ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') # display the 3D plot plt.show()
The beautiful result when it works π₯³ π
I’d love to see you on my email list — join 150k coders that learn and improve their skills together. We also have cheat sheets:
Come join us! π€