# -*- coding: utf-8 -*- """ Created on Thu Apr 16 16:08:00 2020 @author: Facundo Pugliese Esto tiene como objetivo ser un micro-tutorial, pero más llegando al final encontraran un repositorio de funciones utiles que pueden copy-pastear para sus propios usos. """ # %% Creo las variables a y b y me divierto operando a = 2 b = 5 # Los caracteres entre comillas dobles o simples se toman como literales (strings) print("Sumo a+b:", a+b) print("Resto a-b:", a-b) print("Multiplico a*b:", a*b) print("Divido b/a:", b/a) print("División entera b//a:", b//a) print("Resto de división b%a:", b%a) print("Comparo a>b:", a>b) print("Comparo a==b:", a==b) print("Comparo a<=b:", a<=b) # %% Quiero un codigo que me escriba todos los numeros hasta el 8 (sin incluir) num = 1 while num < 8: print(num) num = num + 1 # Ahora quiero que me diga si son pares o no # El if solo ejecuta su cuerpo si su condicion es True, sino ejecuta el cuerpo de else # (no es necesario que haya else, en cuyo casi no hace nada si la condicion es False) num = 1 while num < 8: if num % 2 == 0: print(num, "par") else: print(num, "impar") num = num + 1 # %% Listas y for # Una lista es una colección de elementos donde yo puedo poner lo que quiera mi_lista = [3.14, -8, "F3", True, [1,23]] print("Mi lista es ", mi_lista, "y tiene longitud", len(mi_lista)) # Con for yo puedo recorrer todos los elementos de una lista (o array) y aplicar un cuerpo for elemento in mi_lista: print(elemento) # Una lista muy util en genera es range, que me permite crear una lista de enteros equiespaciados for i in range(1, 8, 1): # Range genera todos los numeros entre 0 y 8 (sin incluir) saltando de a 1 print(i) # Sirve para solo los elementos pares, por ejemplo for i in range(0, len(mi_lista), 2): # Range genera todos los numeros entre 0 y 8 (sin incluir) saltando de a 1 print(mi_lista[i]) # Accedo al i-esimo elemento de mi_lista # Como construir listas usando ciclos (while o for) # Por ejemplo, quiero una lista con todos los cubos entre 1**3 y 8**3 (sin incluir) mis_cubos = [] i = 1 while i < 8: mis_cubos.append(i**3) i = i + 1 print(mis_cubos) # %% Defino una función que eleve al cuadrado def al_cuadrado(x): x_cuadrado = x**2 return x_cuadrado x1 = 3 x1_2 = al_cuadrado(x1) # Se reemplaza por lo que esta junto al "return" print("x1_2 =", x1_2) print("al_cuadrado(3)=", al_cuadrado(3)) print("al_cuadrado(a)=", al_cuadrado(a)) # %% Arranco con NumPy # Si no le digo a Python que lo quiero usar, no puedo acceder a sus funciones, # pero lo rebauticé np porque es más corto import numpy as np # Creo arrays, uso el prefijo np. para que sepa que son funciones de numpy A = np.array([-1, 2, 3.14]) B = np.zeros(3) # Crea un vector de 3 ceros print("A =", A) print("B =", B) print("Producto elemento a elemento A*B =", A*B) print("Suma elemento a elemento A+B =", A+B) # Me aburro! Pongamosle algún valor no nulo a B... B[0] = 3 # Seteo el primer elemento (se cuenta desde 0!) print("Potencia elemento a elemento A**B =", A**B) print("Le aplico al_cuadrado a B", al_cuadrado(B)) # %% Puedo crear arrays equiespaciados automáticamente Xs = np.linspace(0, 1, 6) # Crea un equiespaciado entre 0 y 1 (inclusive) de 6 elementos print("Xs =", Xs) Ys = np.arange(0, 1, 0.2) # Crea un equiespaciado entre 0 y 1 (sin incluir) sumando 0.2 print("Ys =", Ys) # Pero no los pudo sumar porque tienen distinta longitud! print("¿len(Xs) = len(Ys)?", len(Xs), "=", len(Ys), len(Xs) == len(Ys)) # Siempre puedo sumar, multiplicar, dividir, restar con constantes print("Xs-1 = ", Xs-1) print("Xs*10 = ", Xs*10) print("1/Xs = ", 1/Xs) print("NumPy (casi) que hasta maneja el infinito: Aparece si dividimos por 0!") # %% Matrices y como jugar con muchos indices M = np.zeros((3, 4)) # Crea una matriz nula de 3x4 print("Matriz nula\n", M) # Le pongo un valor en las esquinas M[0, 0] = 8 M[0, 3] = 8 M[2, 0] = 8 M[2, 3] = 8 print("Queda \n", M) # Le pongo un único valor a toda la 2da fila M[1, :] = -3 print("Queda \n", M) # Lleno los 0's de la primera fila con -8 M[0, 1:-1] = -10 print("Queda \n", M) # Le pido a M la 2da fila y su 3era columna print("Segunda fila:", M[1, :]) print("Tercera columna:", M[:, 2]) # %% Incluyo matplotlib para poder graficar import matplotlib.pyplot as plt def mi_funcion_rara(x): y = x*np.cos(x)*np.exp(-x/25) return y Xs = np.linspace(-np.pi, np.pi, 1000) # Quiero un espaciado bien fino Ys = mi_funcion_rara(Xs) # Calculo el array para poder graficar la funcion plt.figure() # Abro una figura vacía plt.plot(Xs, Ys) # Grafico! plt.show() # Le pido que me muestre # %% Para los manijas: funciones muy utiles de NumPy idx_min = np.argmin(Ys) # Devuelve el indice donde esta el menor valor de Ys print("El minimo está en Xs[idx_min]=", Xs[idx_min]) print("Y vale Ys[idx_min]=", Ys[idx_min]) # Pueden usar max en lugar de min de forma analoga # Más complicada, np.where les dice los índices en los que se cumple una dada condición idx_ceros = np.where(Ys < 0) # Busco donde la funcion es negativa print("La funcion es negativa en los indices", idx_ceros) print("Osea, en x ", Xs[idx_ceros]) # Cómo integrar: np.trapz # Para un array Ys=F(Xs), uso integral = np.trapz(Xs, Ys) # Si quiero integrar una funcion Zs = F(Xs, Ys) solo en una variable, tengo # que usar np.trapz para cada Xs. def mi_funcion_2D(x, y): z = x*np.cos(y*x) return z xs = np.linspace(0, 1, 100) ys = np.linspace(-np.pi, np.pi, 100) integral_en_ys = np.zeros(len(xs)) # Tengo una integral para cada xs for i in range(0, len(xs), 1): Zs_a_x_constante = mi_funcion_2D(Xs[i]*Ys) integral_en_ys[i] = np.trapz(Ys, Zs_a_x_constante) # Y ahora, si quisiera, podría integrar en x también aplicando trapz a integral_en_ys # Lenta y tediosa, pero es una forma de realizar integrales múltiples usando np.trapz # %% Para los TOC: Como tener un plot ATR # El tercer argumento de plt.plot me permite ajustar el tipo y color de linea # y el tipo de símbolo que marque los puntos Xs = np.linspace(-np.pi, np.pi, 40) Ys = mi_funcion_rara(Xs) plt.figure() plt.plot(Xs, Ys, "ro-") # Circulos rojos unidos por lineas rojas # Usando linewidth y markersize puedo modificar el grosor de las lineas # y el tamaño de los markers, respectivamente plt.figure() plt.plot(Xs, Ys, "ro-", linewidth=3, markersize=4) # Circulos rojos unidos por lineas rojas # Usando xlabel y ylabel puedo ponerle nombres a los ejes plt.xlabel("Tiempo [hs]") plt.ylabel("Interés en Python [??]") # Si quiero graficar 2 curvas en la misma figura, simplemente concateno los plots. # Definiendo su label puedo luego hacer una leyenda que los distinga plt.figure() plt.plot(Xs, Ys, "ro-", label="Interes") plt.plot(Xs, 1-Ys, "b^--", label="Cansancio") plt.legend() # Creo la leyenda, sino los label no aparecen # Tambien puedo ponerle un titulo al grafico y una grilla plt.title("Mi día") plt.grid() # Finalmente, uno puede modificar los rangos en x e y de la grilla usando plt.xlim(-np.pi, np.pi) plt.ylim(-3, 5)