zeros functions python numpy

functions - python numpy doc



gotchas donde Numpy se diferencia de python recta? (15)

Gente

¿Existe una colección de errores en la que Numpy se diferencie de python, puntos que hayan desconcertado y hayan costado tiempo?

"¡El horror de ese momento que nunca olvidaré!"
"Lo harás, sin embargo", dijo la reina, "si no haces un memorándum de eso".

Por ejemplo, los NaN siempre son problemas, en cualquier lugar. Si puedes explicar esto sin ejecutarlo, date un punto:

from numpy import array, NaN, isnan pynan = float("nan") print pynan is pynan, pynan is NaN, NaN is NaN a = (0, pynan) print a, a[1] is pynan, any([aa is pynan for aa in a]) a = array(( 0, NaN )) print a, a[1] is NaN, isnan( a[1] )

(No estoy dando muchas vueltas, hay mucho buen trabajo allí, solo creo que sería útil una FAQ o Wiki de errores).

Edit: esperaba coleccionar media docena de errores (sorpresas para las personas que aprenden Numpy).
Luego, si hay errores comunes o, mejor, explicaciones comunes, podríamos hablar sobre agregarlos a una comunidad Wiki (¿dónde?) No parece que tengamos suficiente hasta ahora.


(Relacionado, pero un número NumPy vs. SciPy gotcha, en lugar de NumPy vs Python)

Cortar más allá del tamaño real de una matriz funciona de manera diferente:

>>> import numpy, scipy.sparse >>> m = numpy.random.rand(2, 5) # create a 2x5 dense matrix >>> print m[:3, :] # works like list slicing in Python: clips to real size [[ 0.12245393 0.20642799 0.98128601 0.06102106 0.74091038] [ 0.0527411 0.9131837 0.6475907 0.27900378 0.22396443]] >>> s = scipy.sparse.lil_matrix(m) # same for csr_matrix and other sparse formats >>> print s[:3, :] # doesn''t clip! IndexError: row index out of bounds

Por lo tanto, al scipy.sparse matrices scipy.sparse , debe asegurarse manualmente de que sus límites de scipy.sparse estén dentro del rango. Esto difiere de cómo funcionan tanto NumPy como Python simple.


Cortar crea vistas, no copias.

>>> l = [1, 2, 3, 4] >>> s = l[2:3] >>> s[0] = 5 >>> l [1, 2, 3, 4] >>> a = array([1, 2, 3, 4]) >>> s = a[2:3] >>> s[0] = 5 >>> a array([1, 2, 5, 4])


Creo que este es gracioso:

>>> import numpy as n >>> a = n.array([[1,2],[3,4]]) >>> a[1], a[0] = a[0], a[1] >>> a array([[1, 2], [1, 2]])

Para las listas de Python, por otro lado, esto funciona como se pretende:

>>> b = [[1,2],[3,4]] >>> b[1], b[0] = b[0], b[1] >>> b [[3, 4], [1, 2]]

Nota graciosa: el mismo numpy tenía un error en la función de shuffle , porque usaba esa notación :-) (ver here ).

La razón es que en el primer caso estamos tratando con vistas de la matriz, por lo que los valores se sobrescriben en el lugar.


Debido a que __eq__ no devuelve un bool, el uso de matrices numpy en cualquier tipo de contenedores evita las pruebas de igualdad sin una solución específica del contenedor.

Ejemplo:

>>> import numpy >>> a = numpy.array(range(3)) >>> b = numpy.array(range(3)) >>> a == b array([ True, True, True], dtype=bool) >>> x = (a, ''banana'') >>> y = (b, ''banana'') >>> x == y Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Este es un problema horrible. Por ejemplo, no puede escribir TestCase.assertEqual() para contenedores que usan TestCase.assertEqual() y, en cambio, debe escribir funciones de comparación personalizadas. Supongamos que escribimos una función de work-around special_eq_for_numpy_and_tuples . Ahora podemos hacer esto en una prueba de unidad:

x = (array1, ''deserialized'') y = (array2, ''deserialized'') self.failUnless( special_eq_for_numpy_and_tuples(x, y) )

Ahora debemos hacer esto para cada tipo de contenedor que podamos usar para almacenar matrices numpy. Además, __eq__ podría devolver un bool en lugar de una matriz de bools:

>>> a = numpy.array(range(3)) >>> b = numpy.array(range(5)) >>> a == b False

Ahora cada una de nuestras funciones de comparación de igualdad de contenedores específicos también debe manejar ese caso especial.

Tal vez podamos parchear esta verruga con una subclase?

>>> class SaneEqualityArray (numpy.ndarray): ... def __eq__(self, other): ... return isinstance(other, SaneEqualityArray) and self.shape == other.shape and (numpy.ndarray.__eq__(self, other)).all() ... >>> a = SaneEqualityArray( (2, 3) ) >>> a.fill(7) >>> b = SaneEqualityArray( (2, 3) ) >>> b.fill(7) >>> a == b True >>> x = (a, ''banana'') >>> y = (b, ''banana'') >>> x == y True >>> c = SaneEqualityArray( (7, 7) ) >>> c.fill(7) >>> a == c False

Eso parece hacer lo correcto. La clase también debe exportar explícitamente la comparación elemental, ya que a menudo es útil.


El valor de verdad de una matriz de Numpy difiere del de un tipo de secuencia de python, donde cualquier secuencia no vacía es verdadera.

>>> import numpy as np >>> l = [0,1,2,3] >>> a = np.arange(4) >>> if l: print "Im true" ... Im true >>> if a: print "Im true" ... Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() >>>

Los tipos numéricos son verdaderos cuando no son cero y como una colección de números, la matriz Nupy hereda esta definición. Pero con una colección de números, la verdad podría significar razonablemente que "todos los elementos son distintos de cero" o "al menos un elemento es distinto de cero". Numpy se niega a adivinar qué definición significa y plantea la excepción anterior. El uso de los métodos .any () y .all () permite especificar el significado de verdadero.

>>> if a.any(): print "Im true" ... Im true >>> if a.all(): print "Im true" ... >>>


Encontré el hecho de que multiplicar las listas de elementos simplemente crea una vista de los elementos que me sorprendieron.

>>> a=[0]*5 >>>a [0,0,0,0,0] >>>a[2] = 1 >>>a [0,0,1,0,0] >>>b = [np.ones(3)]*5 >>>b [array([ 1., 1., 1.]), array([ 1., 1., 1.]), array([ 1., 1., 1.]), array([ 1., 1., 1.]), array([ 1., 1., 1.])] >>>b[2][1] = 2 >>>b [array([ 1., 2., 1.]), array([ 1., 2., 1.]), array([ 1., 2., 1.]), array([ 1., 2., 1.]), array([ 1., 2., 1.])]

Entonces, si creas una lista de elementos como este y pretendes realizar diferentes operaciones en ellos, estás sorprendido ...

Una solución sencilla es crear de forma iterativa cada uno de los arreglos (usando un ''bucle for'' o una comprensión de lista) o usar un arreglo dimensional más alto (donde, por ejemplo, cada uno de estos arreglos 1D es una fila en su arreglo 2D, que generalmente es más rápido).


Lo que más me gustó fue que casi todos los operadores estándar están sobrecargados para distribuir en todo el arreglo.

Definir una lista y una matriz.

>>> l = range(10) >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> import numpy >>> a = numpy.array(l) >>> a array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

La multiplicación duplica la lista de python, pero se distribuye sobre la matriz numpy

>>> l * 2 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> a * 2 array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])

La adición y la división no están definidas en las listas de python

>>> l + 2 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "int") to list >>> a + 2 array([ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) >>> l / 2.0 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for /: ''list'' and ''float'' >>> a / 2.0 array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])

Numpy sobrecargas para tratar listas como matrices a veces

>>> a + a array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18]) >>> a + l array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])


Nadie parece haber mencionado esto hasta ahora:

>>> all(False for i in range(3)) False >>> from numpy import all >>> all(False for i in range(3)) True >>> any(False for i in range(3)) False >>> from numpy import any >>> any(False for i in range(3)) True

Numpy es any y no juega bien con los generadores, y no genera ningún error que le advierta que no lo hacen.


No es un gran problema: con el corte booleano, a veces desearía poder hacerlo

x[ 3 <= y < 7 ]

Como la doble comparación de Python. En cambio, tengo que escribir

x[ np.logical_and(3<=y, y<7) ]

(A menos que sepas algo mejor?)

Además, np.logical_and y np.logical_or solo toman dos argumentos cada uno, me gustaría que tomen un número variable, o una lista, para poder incluir más de dos cláusulas lógicas.

(Numpy 1.3, tal vez todo esto haya cambiado en versiones posteriores).


Una matriz 0-d de Ninguno se parece a Ninguna pero no es lo mismo:

In [1]: print None None In [2]: import numpy In [3]: print numpy.array(None) None In [4]: numpy.array(None) is None Out[4]: False In [5]: numpy.array(None) == None Out[5]: False In [6]: print repr(numpy.array(None)) array(None, dtype=object)


Una sorpresa con la asignación *= en combinación con numpy.array :

>>> from numpy import array >>> a = array([1, 2, 3]) >>> a *= 1.1 >>> print(a) [1 2 3] # not quite what we expect or would like to see >>> print(a.dtype) int64 # and this is why >>> a = 1.1 * a # here, a new array is created >>> print(a, a.dtype) [ 1.1 2.2 3.3] float64 # with the expected outcome

Sorprendente, molesta, pero comprensible. El operador *= no cambiará el tipo de datos de la array , por lo que la multiplicación de una array int por un float fallará en el significado convencional de esta multiplicación. La versión de Python a = 1; a *= 1.1 a = 1; a *= 1.1 en la otra parte funciona como se espera.


de Neil Martinsen-Burrell en una numpy-discussion 7 de septiembre -

El tipo ndarray disponible en Numpy no es conceptualmente una extensión de los iterables de Python. Si desea ayudar a otros usuarios de Numpy con este problema, puede editar la documentación en el editor de documentación en línea en numpy-docs


NaN no es un singleton como None , por lo que realmente no se puede usar el cheque. Lo que lo hace un poco complicado es que NaN == NaN es False como lo requiere IEEE-754. Es por eso que necesita usar la función numpy.isnan() para verificar si un flotador no es un número. O la biblioteca estándar math.isnan() si está usando Python 2.6+.


In [1]: bool([]) Out[1]: False In [2]: bool(array([])) Out[2]: False In [3]: bool([0]) Out[3]: True In [4]: bool(array([0])) Out[4]: False

Así que no pruebe el vacío de una matriz comprobando su valor de verdad. Utilice size(array()) .

Y no uses len(array()) , tampoco:

In [1]: size(array([])) Out[1]: 0 In [2]: len(array([])) Out[2]: 0 In [3]: size(array([0])) Out[3]: 1 In [4]: len(array([0])) Out[4]: 1 In [5]: size(array(0)) Out[5]: 1 In [6]: len(array(0)) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-6-5b2872696128> in <module>() ----> 1 len(array(0)) TypeError: len() of unsized object


print pynan is pynan, pynan is NaN, NaN is NaN

Esto prueba la identidad, es decir, si es el mismo objeto. El resultado debería ser obviamente verdadero, falso, verdadero, porque cuando haces flotar (lo que sea) estás creando un nuevo objeto flotante.

a = (0, pynan) print a, a[1] is pynan, any([aa is pynan for aa in a])

No sé qué es lo que encuentras sorprendente con esto.

a = array(( 0, NaN )) print a, a[1] is NaN, isnan( a[1] )

Esto tuve que correr. :-) Cuando se pega NaN en una matriz, se convierte en un objeto numpy.float64, por lo que un [1] es NaN falla.

Todo esto me parece bastante sorprendente. Pero entonces realmente no sé mucho acerca de NumPy. :-)