MÓDULO NumPy

PROCESADO DE DATOS MEDIANTE ARRAYS

Los arrays realizan una gestión de la memoria mucho más eficiente que las listas y por tanto se mejora el rendimiento.

  • Se realizan muchas operaciones mediante expresiones sobre arrays que en otros casos requerirían múltiples y costosos loops. A esto se le llama vectorización.
  • Las funciones de NumPy se ejecutan de forma tan eficiente como se ejecutarían en otros lenguajes como por ejemplo Fortran, C y C++.
  • Para los casos en los que la ejecución sea más eficiente en otros lenguajes, como por ejemplo Fortran, existen herramientas que nos permiten ejecutar desde Python nuestros códigos en otros lenguajes como f2py.

EXPRESIONES CONDICIONALES

La función where() es la versión vectorizada de la expresión ternaria x if cond else y que ya hemos visto anteriormente.

Supongamos que tenemos los tres arrays:


In [3]:
# Importamos la libería numpy
import numpy as np
# Creamos dos arrays [inicio,fin,salto]
x = np.arange(1,5)
y = np.arange(5,9)
# Creamos un array máscara
cond = np.array([True, False, False, True])
x, y


Out[3]:
(array([1, 2, 3, 4]), array([5, 6, 7, 8]))

Supongamos que queremos obtener el valor de x cuando se cumpla la condición en cond. Queremos obtener por tanto el array [1,6,7,4].


In [4]:
# Primera versión sin operacion vectorizada where()
# Se realiza mediante una expresión ternaria de un bucle for
z1 = np.array([x if cond else y for x, y, cond in zip(x, y, cond)])
z1


Out[4]:
array([1, 6, 7, 4])

In [5]:
# Segunda versión - operación vectorizada where()
z2 = np.where(cond, x, y)
z2


Out[5]:
array([1, 6, 7, 4])

Los dos últimos argumentos de la operación where no tienen por qué ser arrays, pueden ser escalares.

En análisis de datos la operación where se utiliza mucho para crear nuevos arrays a partir de los datos de otros. Supongamos que tenemos un array a de dos dimensiones y queremos construir otro array r tal que:

$$r(x,y) = \begin{cases} 1 &\mbox{if } a(x,y) \ge 0 \\-1 &\mbox{if } a(x,y) \lt 0. \end{cases}$$

In [19]:
# Creamos un array de valores aleatorios con la función randn()
a = np.random.randn(3,5)
a


Out[19]:
array([[ 0.98146166, -0.50549399,  0.2474071 , -0.1036888 , -0.07356249],
       [-1.25356607, -0.82140967,  0.65095668, -0.39064603, -1.14922838],
       [-1.14161655,  0.95304098,  0.21241068, -2.30332245,  0.08933535]])

In [22]:
# Uso de la función where()
# Cuando el valor de 'a' sea menor o igual a 0, muestra un 1, sino un 0
r = np.where( a >= 0, 1, 0)
r


Out[22]:
array([[1, 0, 1, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 1, 1, 0, 1]])

Supongamos ahora que el array r es tal que:

$$r(x,y) = \begin{cases} a(x,y)*10 &\mbox{if } a(x,y) \ge 0 \\ 0 & \mbox{if } a(x,y) \lt 0 \end{cases}$$

In [24]:
# Uso de la función where()
# Cuando el valor de 'a' sea mayor o igual a 0, multiplica el valor por 10, sino un muestra un 0
r = np.where( a >= 0, a * 10 , 0)
r


Out[24]:
array([[ 9.81461656,  0.        ,  2.47407096,  0.        ,  0.        ],
       [ 0.        ,  0.        ,  6.5095668 ,  0.        ,  0.        ],
       [ 0.        ,  9.53040981,  2.12410683,  0.        ,  0.89335348]])

Pero también podemos tener expresiones más complicadas. Por ejemplo:

$$r(x,y) = \begin{cases} 1 &\mbox{if } a(x,y) \gt 0 \\ 0 &\mbox{if } a(x,y) \lt 0 \\ -1 &\mbox{if } a(x,y) = 0 \end{cases}$$

In [25]:
# Uso de la función where()
# Transformamos el array 'a' en uno de tipo int32
a = a.astype(np.int32)
print(a)
# Cuando el valor de 'a' sea mayor que 0, muestra 1
# Cuando el valor de 'a' sea menor que 0, muestra 0
# Cuando el valor de 'a' sea igual a 0, muestra -1
r = np.where(a > 0, 1 , np.where( a < 0, -1 , 0))
r


[[ 0  0  0  0  0]
 [-1  0  0  0 -1]
 [-1  0  0 -2  0]]
Out[25]:
array([[ 0,  0,  0,  0,  0],
       [-1,  0,  0,  0, -1],
       [-1,  0,  0, -1,  0]])


MÉTODOS MATEMÁTICOS Y ESTADÍSTICOS

El módulo NumPy proporciona métodos que permiten realizar otras operaciones, como el mínimo elemento de un array, el máximo, la media de los elementos de un array, etc.

  • sum
  • cumsum
  • cumprod
  • max
  • argmax
  • min
  • argmin
  • mean
  • var
  • std

Se puede encontrar la lista de funciones en ScyPy.org


In [27]:
# 6 valores aleatorios en el intervalo [0,1)
a = np.random.rand(6)
print("a: ",a)

print('Suma: ',a.sum())
print('Valor mínimo: ',a.min())
print('Valor máximo: ',a.max())


a:  [ 0.68579108  0.42166601  0.21625584  0.84511839  0.30879356  0.65351046]
Suma:  3.13113532874
Valor mínimo:  0.216255840903
Valor máximo:  0.845118387349

Las operaciones anteriores se han realizado para todos los valores del array, independientemente de su forma.

  • Si tenemos un array bidimensional, es posible calcular la suma de las columnas, o de las filas.

  • Lo que tenemos que hacer es indicarlo mediante el parámetro axis en el método.


In [32]:
# 6 valores en el intervalo [0,6)
a = np.arange(6)
print("a: ",a)
# 'b' se define a partir de los valores de 'a', distribuyendo los valores en 2 filas, 3 columnas
b = a.reshape(2,3)
print( "b: ")
print(b)


a:  [0 1 2 3 4 5]
b: 
[[0 1 2]
 [3 4 5]]

In [33]:
print ( b.sum(axis = 0)  )   # suma por columnas
print ( b.sum(axis = 1)  )   # suma por filas


[3 5 7]
[ 3 12]


OPERACIONES LÓGICAS

Supongamos que queremos contar el número de elementos positivos en un array multidimensional.

  • Podemos hacer uso de que True tiene valor 1 y False vale -1

In [37]:
# Valores aleatorios con distribución gaussiana, 4 filas, 5 columnas
a = np.random.randn(4,5)
a


Out[37]:
array([[ 1.43593991,  0.55824963, -0.94176648,  0.88032657, -0.25371988],
       [ 0.52838827,  0.61306536, -0.568726  ,  0.84266993,  0.19369304],
       [-0.24110705,  0.14650658,  0.22722235,  0.44706449, -0.36159732],
       [-1.78945166,  0.12842739, -0.61073518,  0.68344862, -1.38798275]])

In [47]:
# Muestra 'True' si se cumple la condición, sino 'False'
(a>0)


Out[47]:
array([[ True,  True, False,  True, False],
       [ True,  True, False,  True,  True],
       [False,  True,  True,  True, False],
       [False,  True, False,  True, False]], dtype=bool)

In [50]:
# Suma todos los 'True' = 1
(a>0).sum()


Out[50]:
12

Los métodos all y any son útiles para trabajar con arrays de booleanos.


In [52]:
# Devuelve 'True' si todos son 'True'
b = (a > 0)
b.all()


Out[52]:
False

In [53]:
# Devuelve 'True' si algunos son 'True'
b.any()


Out[53]:
True


OPERACIONES SOBRE CONJUNTOS

La operación unique aplicado a un array A devuelve un array ordenado de valores en A sin repetición:


In [57]:
# Ordena los valores del array 'a' y elimina los elementos repetidos
a = np.array([1,5,6,4,1,4,5,3,1,1,4,4,4,3,2,2,2,2])
# No se modifica el array original 'a'
np.unique(a)


Out[57]:
array([1, 2, 3, 4, 5, 6])

La función in1d comprueba si los valores de un array están contenidos en otro conjunto de valores. El valor devuelto es un array de booleanos.


In [58]:
# Redimensionamos el array 'b' como 6 filas, 3 columnas
b = a.reshape(6,3)
b


Out[58]:
array([[1, 5, 6],
       [4, 1, 4],
       [5, 3, 1],
       [1, 4, 4],
       [4, 3, 2],
       [2, 2, 2]])

In [59]:
np.in1d(b, [1,2,3])


Out[59]:
array([ True, False, False, False,  True, False, False,  True,  True,
        True, False, False, False,  True,  True,  True,  True,  True], dtype=bool)


LECTURA Y ESCRITURA DE ARRAYS EN FICHEROS

Formato binario

NumPy dispone de las funciones save y load para grabar y cargar arrays en disco en formato formato binario.


In [60]:
# Creamos un array unidimensional
y = np.array([2.,4.,6.,8.])
print(y)


[ 2.  4.  6.  8.]

In [61]:
# Se guarda en formato binario con extensión .npy
np.save('mi_array', y)

In [62]:
# Para cargar el fichero guardado
a = np.load('mi_array.npy')
a


Out[62]:
array([ 2.,  4.,  6.,  8.])


Formato txt

Las operaciones savetxt y loadtxt son las equivalentes a save y load.


In [70]:
# Creamos un array 2x2 a partir de 'a'
b = a.reshape(2,2)
# Lo guardamos en formato txt
np.savetxt("mi_otro_array.txt", b, fmt='%d', delimiter=',')
# Lo cargamos y visualizamos
c = np.loadtxt('mi_otro_array.txt', delimiter=',')
c


Out[70]:
array([[ 2.,  4.],
       [ 6.,  8.]])

In [ ]: