2011-03-03 23 views
14

¿Hay alguna biblioteca de Python que me permita representar z = f (x, y) donde z se representa como el color en una imagen densamente rasterizada (a diferencia del color de un grupo de puntos de gráfico de dispersión)? Si es así, ¿qué función uso?Cómo trazar la función 3D como mapa de color 2D en python?

Parece que algunas de las funciones de contorno en matplotlib.pyplot se acercan a lo que quiero, pero dibujan líneas de contorno y no quiero eso.

Respuesta

8

Eche un vistazo a la documentación para pcolor o imshow en matplotlib.

Otro buen lugar para empezar es echar un vistazo a la galería matplotlib y ver si hay un tipo de gráfico que coincide con lo que busca y luego utilizar el código de ejemplo como punto de saltar fuera de su propio trabajo:

http://matplotlib.sourceforge.net/gallery.html

+0

esos o 'matshow'. – Autoplectic

+0

No recomendaría imshow para una matriz 3d. –

8

aquí es un ejemplo sencillo de hormigón (funciona también para funciones que no pueden tomar argumentos de matriz para x y y):

# the function to be plotted 
def func(x,y):  
    # gives vertical color bars if x is horizontal axis 
    return x 

import pylab 

# define the grid over which the function should be plotted (xx and yy are matrices) 
xx, yy = pylab.meshgrid(
    pylab.linspace(-3,3, 101), 
    pylab.linspace(-3,3, 111)) 

# indexing of xx and yy (with the default value for the 
# 'indexing' parameter of meshgrid(..)) is as follows: 
# 
# first index (row index) is y coordinate index 
# second index (column index) is x coordinate index 
# 
# as required by pcolor(..) 

# fill a matrix with the function values 
zz = pylab.zeros(xx.shape) 
for i in range(xx.shape[0]): 
    for j in range(xx.shape[1]): 
     zz[i,j] = func(xx[i,j], yy[i,j]) 

# plot the calculated function values 
pylab.pcolor(xx,yy,zz) 

# and a color bar to show the correspondence between function value and color 
pylab.colorbar() 

pylab.show() 
+1

El código de bucle es incorrecto: está iterando a través de los objetos incorrectos. Solo funciona porque xx y yy tienen la misma longitud. Pruebe con otros valores en lugar de 101 para ver a qué me refiero. – marcv81

+0

gracias por señalar eso, eso debería arreglarse ahora –

+1

Parece que funciona, gracias por tomarse el tiempo para volver a visitar su respuesta. Yo personalmente prefiero el enfoque algo simple 'xx = pylab.linspace (-3,3, 101)', lo mismo para 'yy', luego iterar con' for i in xrange (len (xx)) 'y' for j in xrange (len (yy)) ', y use' zz [i, j] = func (xx [i], yy [j]) '. – marcv81

1

dar crédito donde es debido: esta es solo una pequeña variación en la respuesta de Andre Holzner. ¡Por favor véndele si es necesario!

import pylab 

def f(x, y): 
    return pylab.cos(x) + pylab.sin(y) 

xx = pylab.linspace(-5, 5, 100) 
yy = pylab.linspace(-5, 5, 100) 
zz = pylab.zeros([len(xx), len(yy)]) 

for i in xrange(len(xx)): 
    for j in xrange(len(yy)): 
     zz[j, i] = f(xx[i], yy[j]) 

pylab.pcolor(xx, yy, zz) 
pylab.show() 

La sintaxis es tal vez más fácil de leer con el mínimo estricto de las dimensiones e índices de la matriz. Se basa en el siguiente punto (citado del documento).

If either or both of X and Y are 1-D arrays or column vectors, they will be expanded as needed into the appropriate 2-D arrays, making a rectangular grid.

+0

El bucle doble, el tuyo y el de Andre, es innecesario e infame porque simplemente puedes escribir 'zz = func (xx, yy)' que es posiblemente órdenes de magnitud más rápidas. – gboffi

+0

¡De hecho, intenté algo así pero no pude hacerlo funcionar! Con o sin inicializar zz con ceros (línea antes de los bucles anidados) no hace ninguna diferencia. ¿Puedes hacer que funcione? – marcv81

+0

Ver mi pseudo respuesta debajo de – gboffi

1

ampliar mi comentario anterior, aquí hay algunas posibles maneras de calcular una función en una cuadrícula

[email protected]:~/Documents/tmp$ cat grid.py 
import numpy as np 

def z(x,y): 
    return np.sin(np.sqrt(x*x+y*y)) 

x = np.linspace(-1,1,11) 
y = np.linspace(-2,2,21) 

# naive 

Z0 = np.zeros((len(y), len(x))) 
for i, X in enumerate(x): 
    for j, Y in enumerate(y): 
     Z0[j,i] = z(X,Y) 

# trampoline on a double list comprehension, 
# it is possibly faster, sure it uses more memory 

Z1 = np.array([[z(X,Y) for X in x] for Y in y]) 

# numpy has meshgrid, 
# meshgrid uses twice memory as the result matrix but 
# if used _correctly_ it's FAST 

X, Y = np.meshgrid(x, y) 

# numpy can avoid you explicit looping, 
# but if you are so inclined... 

Z2 = np.zeros((len(y), len(x))) 
for r in range(len(y)): 
    for c in range(len(x)): 
     Z2[r, c] = z(X[r, c], Y[r, c]) 

# numpy has ufuncs, and 
# t h i s i s t h e w a y t o g o 

Z3 = z(X, Y) 

# numpy has broadcasting (it's slower than Z = z(X, Y), less memory) 

Z4 = z(x, y[:,None]) 

# note that x is still a _row_ of numbers, indexed by _columns_, 
# while y[:,None] is now a _column_ of numbers, indexed by _rows_, 
# so that Z4[row,column] <-- z(x[column], y[row]) 

# a bit of testing 

# in previous answers, Z2 (i.e., explicit loops) 
# is the preferred method --- here we show that the other four 
# possible methods give you exactly the same result 

print np.all(Z2==Z0) 
print np.all(Z2==Z1) 
print np.all(Z2==Z3) 
print np.all(Z2==Z4) 
[email protected]:~/Documents/tmp$ python2 grid.py 
True 
True 
True 
True 
[email protected]:~/Documents/tmp$ 
+0

OK, me faltaba meshgrid. ¡Gracias! – marcv81

Cuestiones relacionadas