Numpy¶

Introducción¶
NumPy es el paquete fundamental para la computación científica con Python. Contiene entre otras cosas:
- un poderoso objeto de matriz N-dimensional
- funciones sofisticadas (de transmisión)
- herramientas para integrar código C / C ++ y Fortran
- Álgebra lineal útil, transformada de Fourier y capacidades de números aleatorios
Además de sus obvios usos científicos, NumPy también se puede utilizar como un eficiente contenedor multidimensional de datos genéricos. Se pueden definir tipos de datos arbitrarios. Esto permite que NumPy se integre sin problemas y rápidamente con una amplia variedad de bases de datos.
NumPy tiene licencia bajo la licencia BSD, lo que permite su reutilización con pocas restricciones.
¿ Por qué usar Numpy ?¶
Las razones por las que debería usar NumPy en lugar de cualquier otro objeto _iterable en Python son:
- NumPy proporciona una estructura de ndarray para almacenar datos numéricos de manera contigua.
- También implementa operaciones matemáticas rápidas en ndarrays, que explotan esta contigüidad.
- Brevedad de la sintaxis para las operaciones de matriz.
import numpy as np
# vector
vector = np.array([1,2,3,4,5])
print(vector)
[1 2 3 4 5]
# matriz
matriz = np.array([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])
print(matriz)
[[ 1 2 3 4] [ 5 6 7 8] [ 9 10 11 12]]
### tipo
type(matriz)
numpy.ndarray
### Escoger filas y columnas
print(f"first row: \n {matriz[0]} \n")
print(f"first col: \n {matriz[:,0]} \n")
print(f"first and second rows: \n {matriz[:2]} \n")
print(f"first and second cols: \n {matriz[:,:2]} \n")
first row: [1 2 3 4] first col: [1 5 9] first and second rows: [[1 2 3 4] [5 6 7 8]] first and second cols: [[ 1 2] [ 5 6] [ 9 10]]
Operaciones Básicas¶
Operaciones matemáticas básicas de matrices La mayoría de las operaciones realizadas en NumPy se manejan por elementos, es decir, calcular $C = A + B$ se traducirá en $ C [i, j] = A [i, j] + B [i, j] $.
A continuación hay una lista con las operaciones matemáticas más comunes.
# crear dos arreglos
A = np.array([
[1,2,3],
[4,5,6],
[7,8,9]
])
B = np.array([[9,8,7],[6,5,4],[3,2,1]])
print(f"Matrix A: \n {A} \n")
print(f"Matrix B: \n {B}")
Matrix A: [[1 2 3] [4 5 6] [7 8 9]] Matrix B: [[9 8 7] [6 5 4] [3 2 1]]
# suma
print("Sum:")
print( A+B )
Sum: [[10 10 10] [10 10 10] [10 10 10]]
# resta
print("\nSubtraction")
print( A-B )
Subtraction [[-8 -6 -4] [-2 0 2] [ 4 6 8]]
# producto uno a uno
print("\nProduct")
print( A*B )
Product [[ 9 16 21] [24 25 24] [21 16 9]]
# producto matricial
print("\nMatricial Product")
print( np.dot(A,B) )
Matricial Product [[ 30 24 18] [ 84 69 54] [138 114 90]]
# potencia
print("\n Power")
print( A**2 )
Power [[ 1 4 9] [16 25 36] [49 64 81]]
# algunas funciones comunes
print("\n np.exp()")
print( np.exp(A) )
print("\n np.sin()")
print( np.sin(A) )
print("\n np.cos()")
print( np.cos(A))
print("\n np.tan()")
print( np.tan(A) )
np.exp() [[2.71828183e+00 7.38905610e+00 2.00855369e+01] [5.45981500e+01 1.48413159e+02 4.03428793e+02] [1.09663316e+03 2.98095799e+03 8.10308393e+03]] np.sin() [[ 0.84147098 0.90929743 0.14112001] [-0.7568025 -0.95892427 -0.2794155 ] [ 0.6569866 0.98935825 0.41211849]] np.cos() [[ 0.54030231 -0.41614684 -0.9899925 ] [-0.65364362 0.28366219 0.96017029] [ 0.75390225 -0.14550003 -0.91113026]] np.tan() [[ 1.55740772 -2.18503986 -0.14254654] [ 1.15782128 -3.38051501 -0.29100619] [ 0.87144798 -6.79971146 -0.45231566]]
Broadcasting¶
Unas de las ventajas de numpy es que podemos hacer broadcasting, es to significa que numpy permite realizar operaciones binarias con arreglos de distintos tamaños.

# example 01
a = np.arange(3)+ 5
print(f"np.arange(3)+ 5:\n{a}" )
np.arange(3)+ 5: [5 6 7]
# example 02
b = np.ones((3,3))+np.arange(3)
print(f"np.ones((3,3))+np.arange(3):\n{b}" )
np.ones((3,3))+np.arange(3): [[1. 2. 3.] [1. 2. 3.] [1. 2. 3.]]
# example 03
c = np.arange(3).reshape((3,1)) + np.arange(3)
print(f"np.arange(3).reshape((3,1)) + np.arange(3):\n{c }" )
np.arange(3).reshape((3,1)) + np.arange(3): [[0 1 2] [1 2 3] [2 3 4]]
Python Lists vs. Numpy Arrays¶
La librería principal de Python son las listas. Una lista es el equivalente a Python de una matriz, pero es redimensionable y puede contener elementos de diferentes tipos.
Una pregunta común para principiantes es cuál es la verdadera diferencia aquí. La respuesta es el rendimiento. Las estructuras de datos de Numpy funcionan mejor en:
- Tamaño: las estructuras de datos de Numpy ocupan menos espacio
- Rendimiento: necesitan velocidad y son más rápidos que las listas
- Funcionalidad: SciPy y NumPy tienen funciones optimizadas, como las operaciones de álgebra lineal integradas.
Memoria¶
Los principales beneficios del uso de matrices NumPy deberían ser un menor consumo de memoria y un mejor comportamiento en tiempo de ejecución.
Para las listas de Python: podemos concluir de esto que para cada elemento nuevo, necesitamos otros ocho bytes para la referencia al nuevo objeto. El nuevo objeto entero en sí consume 28 bytes. El tamaño de una lista lst sin el tamaño de los elementos se puede calcular con:
64 + 8 * len (lst) + + len (lst) * 28

NumPy ocupa menos espacio. Esto significa que una matriz entera arbitraria de longitud n en necesidades numpy se calcula por:
96 + n * 8 bytes

Para convensernos de esto, ejecutemos un ejemplo:
# example
import time
import sys
# class: array
class Array:
"""
Clase array que da como rsultado el tiempo y espacio en
memoria de los objetos list y numpy array
"""
def __init__(self, size_of_vec):
self.size_of_vec = size_of_vec
def pure_python_version(self):
"""
Tiempo y espacio en memoria para objeto list
"""
t1 = time.time()
X = range(self.size_of_vec)
Y = range(self.size_of_vec)
Z = [X[i] + Y[i] for i in range(len(X)) ]
return (time.time() - t1,sys.getsizeof(Z) )
def numpy_version(self):
"""
Tiempo y espacio en memoria para objeto numpy array
"""
t1 = time.time()
X = np.arange(self.size_of_vec)
Y = np.arange(self.size_of_vec)
Z = X + Y
return (time.time() - t1,sys.getsizeof(Z) )
# parameters
size_of_vec = 1000000
class_array = Array(size_of_vec)
t1, size1 = class_array.pure_python_version()
t2, size2 = class_array.numpy_version()
# results
print(f"python list -- time: {round(t1,8)} seg, size: {size1} bytes")
print(f"numpy array -- time: {round(t2,8)} seg, size: {size2} bytes")
python list -- time: 0.21736741 seg, size: 8697456 bytes numpy array -- time: 0.00199819 seg, size: 4000112 bytes
Ejemplo¶
Lista de precios:
El precio de venta de 3 artículos en la venta de pasteles es: 2 dolares por un brownie, 1 dolar por una galleta y 10 dolares por un pastel.
Asignen estos valores a una lista denominada price (precio).
price = [2, 1, 10]
type(price)
list
Lista de cantidad:
El club vende 17 brownies, 40 galletas y un pastel.
Asignen estos valores a una lista denominada quantity_sold (cantidades vendidas).
quantity_sold = [17, 40, 1]
type(quantity_sold)
list
No podemos realizar cálculos entre las listas
Ahora debemos encontrar el dinero recaudado para cada tipo de elemento. Queremos el precio * cantidad para cada elemento. Tratemos de multiplicar nuestras listas:
price * quantity_sold
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Input In [20], in <cell line: 1>() ----> 1 price * quantity_sold TypeError: can't multiply sequence by non-int of type 'list'
Convertir una lista a un array de NumPy
Puesto que ya creamos listas para el precio y cantidad, podemos convertir estos a arrays usando el siguiente código:
price_array = np.array(price)
quantity_sold_array = np.array(quantity_sold)
type(price_array)
numpy.ndarray
Podemos realizar cálculos con arrays
Ahora regresemos a nuestro problema original: encontrar el dinero recaudado para cada tipo de elemento. Queremos el precio * cantidad para cada elemento. Tratemos de multiplicar nuestros arrays.
price_array * quantity_sold_array
array([34, 40, 10])
Cálculos por elementos
Creen un array de NumPy que corresponda al costo de fabricación de cada uno de los artículos vendidos en la venta de pasteles. Digamos que cuesta 0.25 dolares para hacer un brownie, una galleta, 0.50 dolares y un pastel, 5.00 dolares.
cost_array = np.array([0.25, 0.50, 5.00])
Para encontrar la ganancia de cada artículo, queremos restar el costo del precio. Una matriz NumPy realizará la resta por elementos como se muestra:
profit_array = price_array - cost_array
print(profit_array)
[1.75 0.5 5. ]
Booleanos elementwise
Supongamos que quieren identificar qué elementos obtuvieron un beneficio superior a 2 dolares por elemento. Pueden usar el siguiente código para preguntar si la declaración es True (verdadera) o False (falsa) para cada elemento en el array.
profit_array > 2.00
array([False, False, True])
Otras Operaciones
# adicion
price_array2 = price_array + 7
print(price_array2)
[ 9 8 17]
# agregar elementos
price_array = np.append(price_array, [4.50, 3, 4, 9])
print(price_array)
[ 2. 1. 10. 4.5 3. 4. 9. ]
# Eliminar
price_array = np.delete(price_array, -1)
print(price_array)
[ 2. 1. 10. 4.5 3. 4. ]
# reemplazar
price_array[2] = 12
print(price_array)
[ 2. 1. 12. 4.5 3. 4. ]