Superficie 3D en matplotlib

Superficie 3D con plot_surface

Una superficie 3D es la representación de un conjunto de datos de tres dimensiones, mostrando la relación entre una variable dependiente (Y) frente a dos variables independientes (X y Z). Este tipo de gráfico se puede crear con la función plot_surface, especificando una proyección 3D. Ten en cuenta que los gráficos de superficies son la representación 3D de los contour o curvas de nivel.

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
ax.plot_surface(X, Y, Z)

# plt.show()

Superficie 3D en matplotlib

Agregar un título y las etiquetas de los ejes

Cuando se usan gráficos 3D es muy importante especificar las etiquetas de los ejes para una mejor comprensión de los ejes. Puedes agregar las etiquetas de los ejes X, Y y Z con las funciones set_xlabel, set_ylabel y set_zlabel, respectivamente. También puedes agregar un título a la figura con la función title.

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
ax.plot_surface(X, Y, Z)

# Etiquetas de los ejes
ax.set_xlabel('Etiqueta del eje X')
ax.set_ylabel('Etiqueta del eje Y')
ax.set_zlabel('Etiqueta del eje Z')

# Título
plt.title("Superficie 3D")

# plt.show()

Superficie 3D en matplotlib con título y etiquetas de los ejes

Personalización del color

El color de la superficie es azul por defecto, pero especificando un nuevo color al argumento color de la función puedes personalizarlo. En el ejemplo siguiente cambiamos el color a 'lightgreen'.

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D en verde claro
ax.plot_surface(X, Y, Z, color = 'lightgreen')

# plt.show()

Color de la superficie hecha con la función plot_surface de matplotlib

Transparencia

La superficie 3D no es completamente opaca, pero si quieres hacerla más transparente puedes usar el argumento alpha. Ten en cuenta que también puedes hacer la superficie opaca estableciendo antialiased = False.

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
ax.plot_surface(X, Y, Z, alpha = 0.7)

# plt.show()

Transparencia de la superfice 3D hecha con Python

Grosor y color de las líneas

Si hiciste tu superficie más transparente puede que quieras que las líneas sean más visibles. En este caso puedes personalizar tanto el color como el grosor de las mismas con edgecolor y linewidth, respectivamente.

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
ax.plot_surface(X, Y, Z, alpha = 0.7,
                linewidth = 0.3, edgecolor = 'black')

# plt.show()

Grosor y color de línea de la superficie 3D de matplotlib

Paleta de colores

El color de la superficie también se puede basar en los valores de una variable continua, de modo que los valores más altos tendrán un color diferente a los valores más bajos. Puedes especificar una paleta de colores con el argumento cmap de la función, como la paleta 'Spectral_r' de matplotlib.

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
ax.plot_surface(X, Y, Z, cmap = 'Spectral_r')

# plt.show()

Cambiar la paleta de colores del gráfico de superficie 3D de con cmap

Leyenda

Considerando que tu superficie se ha coloreado con una paleta de colores, puede que quieras agregar una barra de color como leyenda. Para ello tendrás que utilizar la función colorbar como en el ejemplo siguiente. Ten en cuenta que puedes personalizar el tamaño de la leyenda con los argumentos shrink y aspect de la función.

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
plot = ax.plot_surface(X, Y, Z, cmap = 'bwr')
fig.colorbar(plot, ax = ax, shrink = 0.5, aspect = 10)

# plt.show()

Superficie 3D con leyenda en Python y matplotlib

Superficies y curvas de nivel

Las superficies 3D son gráficos complementarios a las curvas de nivel. Puedes agregar ambos gráficos a la misma figura agregando un contour al gráfico 3D. Ten en cuenta que tendrás que especificar el desplazamiento de las curvas de nivel con offset en base a tus datos. También puedes personalizar los límites del eje Z en caso de ser necesario.

Superficie 3D con curvas de nivel en Python

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
ax.plot_surface(X, Y, Z, cmap = 'viridis')

# Contour
ax.contour(X, Y, Z, lw = 3, cmap = 'viridis', offset = -1)

# Límites del eje Z
ax.set(zlim = (-1, 0.8))

# plt.show()

Superficie 3D con curvas de nivel en la dirección de los ejes X e Y

Las curvas de nivel también se pueden mostrar en las direcciones X e Y haciendo uso del argumento zdir de la función contour. Tendrás que especificar el desplazamiento con offset como el valor máximo de cada eje.

Contour para las direcciones X e Y de una superficie 3D hecha con matplotlib

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
ax.plot_surface(X, Y, Z, cmap = 'autumn_r')

# Curvas de nivel para los ejes X e Y
ax.contour(X, Y, Z, lw = 3, cmap = 'autumn_r', offset = np.max(X), zdir = 'x')
ax.contour(X, Y, Z, lw = 3, cmap = 'autumn_r', offset = np.max(Y), zdir = 'y')

# plt.show()

Superficie 3D con curvas de nivel coloreadas

Si quieres añadir curvas de nivel coloreadas el proceso es el mismo pero con la función contourf. En el ejemplo siguiente agregamos un contour con sus áreas coloreadas para entender mejor los datos.

Superficie 3D con curvas de nivel coloreadas en Python y matplotlib hecho con la función plot_surface

import matplotlib.pyplot as plt
import numpy as np

# Datos de muestra
X, Y = np.meshgrid(np.linspace(-8, 8), 
                   np.linspace(-8, 8))
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R) / R

fig = plt.figure()
ax = fig.add_subplot(projection = '3d')

# Superficie 3D
ax.plot_surface(X, Y, Z, cmap = 'Spectral_r', alpha = 0.9)

# Curvas de nivel coloreadas
ax.contour(X, Y, Z, lw = 2, colors = 'black', offset = -1)
ax.contourf(X, Y, Z, cmap = 'Spectral_r', offset = -1, alpha = 0.75)

# Límites del eje Z
ax.set(zlim = (-1, 0.8))

# plt.show()
Better Data Visualizations

A Guide for Scholars, Researchers, and Wonks

Comprar en Amazon

También te puede interesar