En este notebook veremos como las principales características de los arrays de NumPy y cómo mejoran la eficiencia de nuestro código.
El objeto tipo array que proporciona NumPy (Python ya dispone de un tipo array que sirve para almacenar elementos de igual tipo pero no proporciona toda la artillería matemática necesaria como para hacer operaciones de manera rápida y eficiente) se caracteriza por:
Comencemos viendo que ocurre con las listas:
import numpy as np
lista = [ 1, 1+2j, True, 'aerodinamica', [1, 2, 3] ]
lista
[1, (1+2j), True, 'aerodinamica', [1, 2, 3]]
En el caso de los arrays:
array = np.array([ 1, 1+2j, True, 'aerodinamica'])
array
array(['1', '(1+2j)', 'True', 'aerodinamica'], dtype='<U64')
¿Todo bien? Pues no. Mientras que en la lista cada elemento conserva su tipo, en el array, todos han de tener el mismo y NumPy ha considerado que todos van a ser string.
¡Tranquilo! los allocate son automáticos...
Igual que en el caso anterior, comencemos con la lista:
print(id(lista))
lista.append('fluidos')
print(lista)
print(id(lista))
140477819683784 [1, (1+2j), True, 'aerodinamica', [1, 2, 3], 'fluidos'] 140477819683784
print(id(array))
array = np.append(array, 'fluidos')
print(array)
print(id(array))
140478587822928 ['1' '(1+2j)' 'True' 'aerodinamica' 'fluidos'] 140477819836496
Si consultamos la ayuda de la función np.append
escribiendo en una celda help(np.append)
podemos leer:
Returns
-------
append : ndarray
A copy of `arr` with `values` appended to `axis`. Note that `append` does not occur in-place: a new array is allocated and filled. If `axis` is None, `out` is a flattened array.
Hasta el momento los arrays han demostrado ser bastante menos flexibles que las listas, luego olvidemos estos últimos 10 minutos y manejemos siempre listas... ¿no? ¡Pues no! Los arrays realizan una gestión de la memoria mucho más eficiente que mejora el rendimiento.
Prestemos atención ahora a la velocidad de ejecución gracias a la función mágica %%timeit
, que colocada al inicio de una celda nos indicará el tiempo que tarda en ejecutarse.
lista = list(range(0,100000))
type(lista)
list
%%timeit
sum(lista)
1000 loops, best of 3: 1.2 ms per loop
array = np.arange(0, 100000)
%%timeit
np.sum(array)
The slowest run took 9.08 times longer than the fastest. This could mean that an intermediate result is being cached. 10000 loops, best of 3: 67.2 µs per loop
Como ves, las mejoras en este caso son de 2 órdenes de magnitud. NumPy nos ofrece funciones que se ejecutan prácticamente en tiempos de lenguaje compilado (Fortran, C, C++) y optimizado, pero escribiendo mucho menos código y con un nivel de abstracción mayor. Conociendo una serie de buenas prácticas, podremos competir en velocidad con nuestros códigos en Python. Para casos en los que no sea posible, existen herramientas que nos permiten ejecutar desde Python nuestros códigos en otros lengujes como f2py. Este tema puede resultarte algo avanzado a estas alturas, pero bastante útil; puedes consultar este artículo de pybonacci si lo necesitas.
Para recordar los primeras lecciones vamos a implementar nuestra propia función linspace
usando un bucle (estilo FORTRAN) y usando una list comprehension (estilo pythonico). Después compararemos el rendimiento comparado con la de NumPy.
def my_linspace_FORTRAN(start, stop, number=50):
x = np.empty(number)
step = (stop - start) / (number - 1)
for ii in range(number):
x[ii] = ii * step
x += start
return x
def my_linspace_PYTHONIC(start, stop, number=50):
step = (stop - start) / (number - 1)
x = np.array([ii * step for ii in range(number)]) #esto es una list comprehension
x += start
return x
%%timeit
np.linspace(0,100,1000000)
%%timeit
my_linspace_FORTRAN(0,100,1000000)
%%timeit
my_linspace_PYTHONIC(0,100,1000000)
___Hemos aprendido:___
En definitiva:
__¡Quiero más!__Algunos enlaces:
Algunos enlaces en Pybonacci:
Algunos enlaces en otros sitios:
Las siguientes celdas contienen configuración del Notebook
Para visualizar y utlizar los enlaces a Twitter el notebook debe ejecutarse como seguro
File > Trusted Notebook
# Esta celda da el estilo al notebook
from IPython.core.display import HTML
css_file = '../styles/aeropython.css'
HTML(open(css_file, "r").read())