Skip to content

Instantly share code, notes, and snippets.

@robintux
Last active February 15, 2022 03:48
Show Gist options
  • Save robintux/4d32b67b368d341edf7cd92ad357f6f3 to your computer and use it in GitHub Desktop.
Save robintux/4d32b67b368d341edf7cd92ad357f6f3 to your computer and use it in GitHub Desktop.
Una lista de celdas para Spyder (IPython) sobre algunas funcionalidades (basicas) de numpy
# =============================================================================
# Abraham Zamudio [GMMNS]
# 2020/05/20
# Lima-Peru
# =============================================================================
#%%
# =============================================================================
# Numpy : Algunos ejemplos [PIT2020II]
# =============================================================================
import numpy as np
# # Motivacion :
# Para datos numericos : Los arrays son mas rapidos y mas eficientes que las listas
#%% MatMul:Python
# =============================================================================
# Modulos :
# random : https://docs.python.org/3/library/random.html
# time : https://docs.python.org/3/library/time.html
# Multiplicacion de matrices : usando python puro (Listas)
# =============================================================================
import random
import time
start = time.time()
n = 200
A = []
for i in range(n):
row = []
for j in range(n):
row.append(random.random())
A.append(row)
B = []
for i in range(n):
row = []
for j in range(n):
row.append(random.random())
B.append(row)
C = []
for i in range(n):
row = []
for j in range(n):
sum = 0
for k in range(n):
sum += A[i][k] * B[k][j]
row.append(sum)
C.append(row)
stop = time.time()
print(stop - start)
#%% MatMul:Numpy
# Multiplicacion de matrices usando numpy
start = time.time()
n = 1000
A = np.random.random((n, n))
B = np.random.random((n, n))
C = A @ B
stop = time.time()
print(stop - start)
#%%
# Creacion de arrays
# Existen varios caminos para crear arrays
# Usando listas
# Creamos una lista
vals_list = [1, 3, 2, 8]
# Creamos un objeto ndarray a partir de la lista
vals_array = np.array(vals_list)
print("vals_list: ", vals_list)
print("vals_array: ", vals_array)
# ndarray to list : metodo tolist
print(vals_array.tolist())
#%%
# Existen muchas funciones para crear objetos ndarray
# np.arange : https://numpy.org/doc/1.18/reference/generated/numpy.arange.html
# np.linspace : https://numpy.org/doc/1.18/reference/generated/numpy.linspace.html
# Accedemos a la ayuda de la funcion arange :
help(np.arange)
# Rutinas para la creacion de arrays :
# https://numpy.org/doc/1.18/reference/routines.array-creation.html
#%%
# Otra forma de acceder a la ayuda
get_ipython().magic('pinfo np.arange')
get_ipython().magic('pinfo np.linspace')
#%%
# np.arange
# creamos un array con enteros : 0,1,...,9
start = 0
end = 10 # neesario para llegar al 0
np.arange(start,end)
# Note la diferencia con imprimir usando la funcion print
print(np.arange(start,end))
# Podemos omitir el argumento start si deseamos empezar en cero
end = 12
print(np.arange(end))
#%%
# Podemos modificar el tercer argumento (step size) mayor a 1
# Preste atencion al resultado
start = 5
end = 21 # Esto es : 17 + 4
step = 4
print(np.arange(start,end,step))
#%%
# no es necesario ir hasta el 21, 18 estaría bien
start = 5
end = 18
step = 4
print(np.arange(start,end,step))
#%%
# np.linspace
start = 0
end = 1
num_points = 11
print(np.linspace(start,end,num_points))
print()
print(np.linspace(0,28,12))
#%%
# Inicializamos arrays con algunos valores fijos
print(np.zeros(5))
print()
print(np.ones(7))
print()
print(np.empty(3))
#%%
# Arrays de varias dimensiones
# Arrays (matrices) de dimensiones 5x5
dim = (5,5) # Definimos una tupla
print(np.zeros(dim))
print()
print(np.zeros((5,5)))
#%%
# Array 3D de dimension : 4x3x2
dim = (4,3,2)
print(np.zeros(dim))
#%%
# Tambien funciona en np.empty
# Data Types
# Recordemos que python es un lenguaje de programacion de tipado dinamico
# el tipo de dato de una variable puede ser modificado como se necesite
#
# .... que ocurre con los arrays de NUmpy ?
# .... Los objetos ndarray son tipados de manera estatica
#
# Entonces,
# ¿cuáles son los tipos de datos de las matrices que creamos anteriormente?
# ¿Cuáles son los tipos de datos disponibles?
# ¿Cómo especificamos qué tipo de datos queremos?
vals_list = [1,3,2,8]
vals_array = np.array(vals_list)
vals_arrayf = np.array(vals_list, dtype=np.float64)
print("vals_array: ", vals_array)
print("vals_arrayf: ", vals_arrayf)
print(type(vals_list))
print(type(vals_array))
print(type(vals_arrayf))
# El argumento dtype es valido para muchas de las funciones de creacion de arrays
# Basta con acceder a la ayuda de cada una de las funciones para ver la funcionalidad
# de los argumentos
#%%
print('Enteros: ', vals_array)
print('Mas enteros: ', vals_array * 3)
print('Punto flotantes: ', vals_array / 3)
# También puede copiar un array y cambiar el dtype.
#%%
arr = np.arange(10.0) # no son enteros
x = arr.astype(int) # son enteros
print('arr: ', arr)
print('x: ', x)
#%%
# Accesando a los elementos de un array
# Ahora que tenemos vectores/matrices, ¿cómo obtenemos cosas de ellas?
# Indexado desde 0
# Corchetes para acceder a los elementos
vals_arrayf = np.array([1, 3, 2, 8, 24, 0, -1, 12])
print(vals_arrayf)
print()
print(vals_arrayf[0]) # this selects 0th element
print(vals_arrayf[3])
# El uso de indices negativos tambien estan permitidos
print(vals_arrayf)
print(vals_arrayf[-1])
print(vals_arrayf[-3])
# ¿Qué pasa si quiero una sección/porcion de un vetor/matriz?
# Slicing de arrays
start_index = 1
end_index = 4 # will stop BEFORE this index - think about np.arange
print(vals_arrayf)
print()
print(vals_arrayf[start_index:end_index])
print(vals_arrayf[1:2])
print(vals_arrayf)
print()
# esto te dará todos los elementos estrictamente entre 1 y 1
print(vals_arrayf[1:1]) # ningun elemento
#%%
start = 2
end = 37 # ir demasiado lejos está bien
print(vals_arrayf)
print()
print(vals_arrayf[start:end])
# Si comienza desde el principio, no necesita poner 0:
print(vals_arrayf[0:3])
print(vals_arrayf[:3])
# Similar si quieres terminar en el último elemento:
print(vals_arrayf[1:8])
print(vals_arrayf[1:])
# ¡También puedes usar índices negativos!
print(vals_arrayf)
print()
print(vals_arrayf[2:-1])
print()
print(vals_arrayf[:-2])
# Además de un inicio y un final, también puede elegir un paso para el segmento.
start = 0
end = 6
step = 2
print(vals_arrayf)
print()
print(vals_arrayf[start:end:step])
# Las siguientes dos llamadas hacen lo mismo:
print(vals_arrayf[0:8:2])
print(vals_arrayf[::2])
# ¿Qué están haciendo estos dos ejemplos siguientes?
print(vals_arrayf)
print()
print(vals_arrayf[1::2])
print(vals_arrayf[::-1])
#%%
# Copias vs. Views (Cambiar accidentalmente el dato (matriz))
# Debe tener cuidado con las matrices `numpy` si desea
# tratando de copiar parte de una matriz, o
# pasar un vector/matriz a una función
#
# Puede que te lleves una sorpresa desagradable si cambias un elemento.
simple = np.arange(5)
small = simple[:2]
print(simple)
print('')
print(small)
print('')
small[0] = 7
print(small)
print('')
print(simple) # no debería haber cambiado, ¿verdad?
# Esto sucede porque small es algo llamado una "vista (view)" de "simple", en
# lugar de una copia. Esto ayuda a numpy a ahorrar memoria y a acelerar su
# programa, pero puede generar errores difíciles de comprender si no es su
# intención. En general, puede ser difícil saber si algo será una "vista"
# o una copia.
#%%
# Las funciones tampoco hacen copias de sus matrices de entrada.
def Algo(x): # no se retorna x
x[0] = 100
Algo(simple)
print(simple)
# Si cree que está cambiando accidentalmente su matriz en otra parte de su código,
# puede copiarla para que sea segura. Esto ralentiza su programa y usa más memoria,
# pero puede ayudar a depurar y ahorrar muchos dolores de cabeza.
simple = np.arange(5)
print('before:')
print(simple)
my_copy = simple[:2].copy()
my_copy[1] = 10
Algo(simple.copy())
print('after:')
print(simple)
#%%
# Arrays (matrices) de varias dimensiones
# Nota: Hay una clase numpy.matrix, pero debe evitar usarla. Utilice matrices
# bidimensionales en su lugar.
# ¿Cómo creamos matrices multidimensionales?
# creacion desde listas multidimensionales
mat = np.array([[1,4,8],[3,2,9],[0,5,7]], float)
print(mat)
print('')
#%%
# Creacion de matrices especiales
print(np.zeros((2,3), dtype=float)) # ya viste esto ... pero esta vez estamos especificando el tipo
print('')
print(np.zeros_like(mat))
print('')
# np.zeros_like crea na matriz con la misma forma, dimension, y tipo de datos
# de una matriz ya existente
print(np.identity(3, dtype=float))
#%%
# ¿Cómo accedemos a los elementos de matrices multidimensionales?
print(mat)
print(mat[1,2])
#%%
print(mat[0,0], mat[1,1], mat[2,2])
print(mat)
print()
print(mat[2])
# Puede hacer lo mismo con el slicing de la matriz:
print(mat[2,:])
print(mat[:,1])
print()
# lo obligamos a ser un vector de columna ...
print(mat[:,1:2])
print()
print(mat[:,[1]])
# Interpreta la siguiente linea de codigo
print(mat[:,:2])
#%%
# puedes hacer esto con np.ones o np.zeros y slicing
N = 8 # Crea una matriz de tamaño NxN
# ¿Qué pasa si queremos una matriz de una forma (dimension) diferente?
# Esta puede ser una forma conveniente de inicializar matrices.
arr = np.arange(8)
two_four = arr.reshape(2, 4)
four_two = arr.reshape(4, 2)
eight_none = four_two.flatten()
print('array:')
print(arr.shape)
print('')
print('2 x 4:')
print(two_four)
print('')
print('4 x 2:')
print(four_two)
print('')
print('Regresamos al array:')
print(eight_none)
print(eight_none.shape)
#%%
# Algunos metodos de los objetos ndarray
# Veremos algunas funciones de arrays (objetos de tipo ndarray). Hay muchos más disponibles.
# La mejor manera de encontrar la función que desea es buscar en Google lo que desea y
# encontrar la documentación correspondiente (probablemente haya una función que haga lo
# que desea hacer, o en el peor de los casos tenga que combinar funcionalidad de varias
# funciones ).
new_mat = mat[:,:2]
print(new_mat)
# Shape (forma o dimension) del objeto ndarray
print(new_mat.shape) # en realidad no es una función, sino un metodo (atributo)
# Ordenacion de un array
# Dos diferentes metodos
# np.sort : https://numpy.org/doc/1.18/reference/generated/numpy.sort.html
# np.ndarray.sort : https://numpy.org/doc/1.18/reference/generated/numpy.ndarray.sort.html
# Una es una función numpy (llamada np.sort ()) y devuelve una copia de la matriz en orden ordenado.
# La otra es un metodo (atributo) que se le aplica al array y la ordena (en si misma)
#
# NOTAS Importantes
# Algunas funciones trabajan solo el mismo objeto ndarray, mientras que otras devuelven copias.
# Siempre recordar usar type, dir y mas comunmente leer/estudiar la documentacion
#%%
# Ejemplo de ordenacion
vals_arrayf = np.array([1, 3, 2, 8, 24, 0, -1, 12])
print(np.sort(vals_arrayf)) # retorna una copia
print(vals_arrayf)
vals_arrayf.sort() # ordenamiento inplace
print(vals_arrayf)
#%%
# Verificamos pertenencia
print(9 in mat)
print(9 in vals_arrayf)
# Muchas operaciones elemento a elemento (elementwise) se realizan automáticamente
# con arrays. Éstas incluyen:
# adicion
# sustraccion
# multiplicacion
# division
# comparaciones
#%%
mat_2 = np.array([[1,3],[2,5]], float)
id_2 = np.identity(2, float)
print(mat_2)
print('')
print(id_2)
print('')
print('sum:')
print(mat_2 + id_2)
print('')
print('difference:')
print(mat_2 - id_2)
print('')
print('product:')
print(mat_2 * id_2) # OJO : NO es una multiplicacion matricial
print('')
print('quotient:')
print(id_2 / mat_2)
print('power:')
print(mat_2**3)
#%%
# Tambien puedes comparar valores
print(mat_2 == id_2)
print(' ')
print(mat_2 > id_2)
#%%
# Funciones variadas : Notar las operaciones elemento a elemento
print(np.exp(id_2))
print()
print(np.abs(vals_arrayf))
print()
print(np.log2(mat_2))
print()
print(np.reciprocal(mat_2))
#%%
# Funciones trigonometricas :
print(np.sin(mat_2))
print(np.tan(id_2))
#%%
# redondeo :
help(np.round)
print(np.round(np.sin(mat_2), 2))
#%%
# También puede realizar operaciones entre arrays y números (variables escalares):
print(mat_2)
print()
print(mat_2 - 3) # restamos 3 a cada elemento de mat_2
print()
print(mat_2*8) # Multiplicamos por 8 cada elemento de mat_2
#%%
x = np.linspace(-1,1,30)
# Recordemos las matrices de comparación:
print(mat_2)
print(id_2)
print()
print(mat_2 == id_2)
print(' ')
print(mat_2 > id_2)
# Puede comparar matrices y usar la matriz booleana resultante para manipular
# las entradas de otra matriz
z = mat_2 > id_2
print(z)
print()
print(mat_2)
print()
print(mat_2 * z)
# Esto podría ayudarlo a comprender lo que sucedió:
print(z*1)
#%%
x = np.linspace(-1,1,30)
# Broadcasting (Operaciones basadas en elementos en arrays de diferentes dimensiones
# No es necesario para esta demostracion, pero échale un vistazo si estás interesado.
# Cada operación de "broadcast" (transmision) se puede hacer usando bucles, pero la
# operacion de Broadcasting es más rápida.
# Ver : A Gentle Introuction to Broadcasting with Numpy Arrays
# https://machinelearningmastery.com/broadcasting-with-numpy-arrays/
# para una detallada explicacion
# El caso más simple de broadcasting es sumar un solo número a cada elemento de una matriz
# Aquí está la forma matemáticamente correcta de agregar un número a cada elemento de
# una matriz
bmat = np.arange(12).reshape(4, 3)
print(bmat)
print()
z = 3*np.ones_like(bmat) # what is this doing?
print(z)
print()
print(bmat + z)
#%%
# Pero vimos que puede agregar un número directamente ... Numpy está
# "transmitiendo" (broadcasting) el valor
print(bmat)
print()
z = 3
print(z)
print()
print(bmat + z)
# Consejo: familiarízate con Python y Numpy, y preocúpate por hacer el broadcasting
# más tarde. Solo recuerda que puedes agregar un solo número a una matriz, y que hay
# algo detrás de escenas
#%%
# Operaciones matematicas como metodos a objetos ndarray
bmat = np.array([6, 7, -12, 0, 3, 4, 21, 1, 1, 0, 2, 5]).reshape(4,3)
print(bmat)
print()
print(bmat.min())
print(bmat.max())
print(bmat.sum())
# ¿Qué pasa si quiero el número más pequeño en cada fila?
# Todas estas operaciones de reducción toman un argumento opcional 'axis' que nos
# permite apuntar a una dimensión particular de la matriz.
print('Minimo para filas:')
print(bmat.min(axis=1))
print('Minimo para columnas:')
print(bmat.max(axis=0))
print('Suma (filas):')
print(bmat.sum(axis = 1))
# Tenga en cuenta que cuando pasamos un argumento `axis`, perdemos esa dimensión de
# nuestra matriz, pero la forma no cambia. Entonces, una matriz (4, 3) se convierte
# en una matriz (3,) si pasamos `axis = 0`, y se convierte en una matriz (4,) si
# pasamos` axis = 1`.
# Otras reducciones
print(bmat)
print()
print('promedio aritmetico:')
print(bmat.mean())
print()
print('Media (columnas):')
print(bmat.mean(axis = 0))
#%%
print(bmat)
print()
print('producto:')
print(bmat.prod())
print('producto - columna:')
print(bmat.prod(axis = 0))
#%%
# Tratar arrays como matrices y vectores
# multiplicacion matricial y producto punto :
print(np.dot(mat_2, id_2))
print('')
print(mat_2 @ id_2)
print('')
print(np.dot(vals_arrayf, np.array([0,2,6,1, 1, 2, 3, 4])))
# Transpuesta
print(mat_2)
print()
print(np.transpose(mat_2))
print()
print(mat_2.T)
#%%
# COnstantes de numpy
# LIsta de constantes:
# https://numpy.org/doc/stable/reference/constants.html
print(np.pi) # el famoso numero irracional
print(np.e) # numero de euler : np.exp(1)
print(np.inf) # infinit
print(np.NINF) # infinito negativo
print(np.nan) # not a number
#%%
# Numeros Pseudoaleatorios
# A menudo necesitaremos saber generar numeros pseudoaleatorios
# NUmpy puede generar numeros de una variedad de distribuciones
# inclusive puede generar vectores con las dimensiones que uno desee
# https://numpy.org/doc/1.18/reference/random/index.html
# Algunas funciones comunmente usadas son :
# np.random.rand
# np.random.randn
# np.random.randint
# Todas estas rutinas le dan la opción de generar una matriz de una dimension específica.
uniform_nums = np.random.rand(10)
print(uniform_nums)
print('')
normal_nums = np.random.randn(3, 5)
print(normal_nums)
print('')
integers = np.random.randint(0, 10, (4, 2))
print(integers)
print('')
#%%
# =============================================================================
# # Qué más hay en Numpy
# # ¡Hay muchas más funciones en Numpy!
# # Lea la documentación y busque las cosas en Google
# # ¡Probablemente alguien ya hizo su pregunta sobre Stack Exchange o Stack Overflow!
# =============================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment