<jupyter_start><jupyter_text>Universidad de Costa Rica Facultad de Ciencias Escuela de Química Sección de Fisicoquímica Qu-0560 Tópicos de Química Física: Herramientas Computacionales para Química Profesor Gutiérrez Asistente no oficial: <NAME>  Aplicación II: RegresionesEn esta sección aprenderás a hacer regresiones y gráficos con Python! Hasta ahora has aprendido sobre las primitivas básicas: strings, boleans, integers, floats y listas. Así mismo podes hacer cálculos básicos de matemática elemental y usar variables como contenedores de valores Con lo anterior, ya podemos hacer regresiones lineales y no lineales! Tema fundamental en el mundo científico, pues en última instancia queremos medir usando algún modelo y realizar predicciones. En este modulo emplearemos los siguientes recursos:* [match](https://docs.python.org/2/library/math.html) Para cálculo de funciones básicas de matemática elemental * [uncertainties](https://pythonhosted.org/uncertainties/) Para manejo de propagación de incertidumbres * [Numpy](http://www.numpy.org/) para manejar arrays, vectores, columnnas y hacer cálculos numéricos * [scikit-learn](http://scikit-learn.org/) para realizar regresiones lineales y no lineales * [statsmodels](http://www.statsmodels.org/stable/index.html) para manejar estadística y realizar regresiones ]* [GEKKO](https://gekko.readthedocs.io/en/latest/) para optimización algebraica de ecuaciones diferenciales e integrales* [matplolib](https://matplotlib.org/) Para realizar gráficos * [scypython](https://www.scipy.org/)  Regresión Lineal con ScypythonScypython es un conjunto de librerias enfocadas en el cálculo científico y manejo numérico. Al instalarlo, viene con paquetescomo Numpy , Matplotlib, SiPython y Pandas. Así mismo librerias extra para realizar diferentes cálculos. Haremos uso de Scypython para ejemplificar nuestra primer regresión De forma general en Analitica I y II estarás trabajando con regresiones lineales mediante el método de mínimos cuadrados. De hecho, te pedirán que crees una hoja de excel para realizar las regresiones. En Fisicoquímica harás uso de regresiones lineales pero también no lineales. Sin embargo se busca que el estudiante use un software que automatice el modelado, pues hacerlo manual en excel puede llevar su tiempo. Te recordarás que un modelo lineal tiene la forma $$ y(x) = mx + b(1)$$Donde __m__ es la pendiente y __b__ el intercepto.y(x) es tu variable dependientex es tu variable independientesEste modelo de permite predecir como afecta la variable X a las Y de manera lineal.En analítica lo usarás para curvas de calibración. Nuestra misión en este primer modelo es obtener el $R^{2}$ que nos habla de la correlación o que tan bien se ajustan los datosal modelo, queremos sabe la pendiente __m__ y su error asociado y así mismo el intercepo __b__En el laboratorio, tomamos una serie de medidas y ajustamos.Para realizar la muestra de regresión, haremos uso del siguiente set datos.  Ejemplo 1![presion-volumen.PNG](attachment:presion-volumen.PNG)  Paso 1. Define tus variables dependiente e independiente.En nuestro caso nuestra __x__ será la presión en atm y nuestra __y__ serán los logarimos naturales de los volúmenes en litros Siguiendo el siguiente modelo $$ln(V) = -\kappa*P + b $$ $\kappa$ representa el factor de compresión isotermica. Una propiedad física de los materiales. En este caso será nuestra pendiente volumen = [8.99 , 17.65 , 34.10 , 41.92 , 49.50 , 58.86 , 64.02] presion = [2.000 , 1.000 , 0.500 , 0.400 , 0.333 , 0.286 , 0.250]<jupyter_code># P de presión y V de volumen
presion = [8.99 , 17.65 , 34.10 , 41.92 , 49.50 , 58.86 , 64.02]
volumen = [2.000 , 1.000 , 0.500 , 0.400 , 0.333 , 0.286 , 0.250]<jupyter_output><empty_output><jupyter_text>Paso 2. Elige que paquete de Python deseas utilizar para optimizar y ajustar e importaloEn nuestro primer caso será Scipython que ya viene incluido en Jupyter Notebooks.Para hacer la regresión importaremos Numpy y Matplotlib* Importaremos matplotlib como plt* Importaremos numpy como np* Importaremos el paquete estadístico de Scipython Importamos el paquete de gráficos ( no te preocupes por ahora, en el siguiente módulo te enseñaremos mas sobre el)<jupyter_code>import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>Le estamos diciendo a Python... Hey Python en Jupyter Notebooks existe un paquete llamado __matplotlib__ Dentro de ese paquete quiero que busques la gráfica __pyplot__ que es una gráfica del tipo __dispersión__  como las de ExcelY cuando yo la use, quiero usarla con el siguiente nombre __plt__  Importamos el paquete numérico Numpy<jupyter_code>import numpy as np
import math<jupyter_output><empty_output><jupyter_text>Le estamos diciendo a Python Hey Python en Jupyter Notebooks existe un paquete llamado Numpy para cálculos números y vectores. Y cuando yo la use, quiero usarla con el siguiente nombre __np__ A su vez, importamos el maquete matemático  Importamos el paquete estadístico de Scipython<jupyter_code>from scipy import stats<jupyter_output><empty_output><jupyter_text>Pues le acamos de enseñar a Python lo básico de estadística  Paso 3. Defina sus variables dependiente e independientes en términos de un numpy arrayNumpy te permite manejar vectores y matrices de forma numérica! Es increible! Se puede decir que es un paso mas allás que las __listas__ La razón? Suponga que tenes una listaA = [300 , 400 , 500 , 600] Y queres multiplicar cada elemento por 3.45 Veamos que sucede<jupyter_code>#Definimos la lista
listaA = [300 , 400 , 500 , 600]
#Efectuemos la multiplicación de la listaA * 3.45
listaA * 3.45<jupyter_output><empty_output><jupyter_text>¿Te tiró error verdad? :(Exacto!Ese es el problema de las lista en Python.Para poder modificarlas, tendrías que hacer el cambio uno a unoOsea tendrias que decir, el nuevo elemento cero de la lista es el antiguo elemento por 3.45<jupyter_code>listaA[0] = listaA[0]* 3.45<jupyter_output><empty_output><jupyter_text>Y luego hacer lo mismo para los siguientes<jupyter_code>listaA[1] = listaA[1]* 3.45
listaA[2] = listaA[2]* 3.45
listaA[3] = listaA[3]* 3.45
listaA<jupyter_output><empty_output><jupyter_text>Talvez no sea tan tendioso por que son sólo 4 elemenetos.... Pero ahora imagínatelo con cientos o miles... Numpy al rescate  Creemos un numpy arrary a partir de la listA<jupyter_code>numpyA = np.array([300 , 400, 500 , 600])<jupyter_output><empty_output><jupyter_text>Viste? Es como crear una lista, pero encerrada entre paréntesis y antesedida por la palabra __np.array__ Que sucede sí hacemos la multiplicación numpyA*3.45 y lo guardamos en un nuevo array llamado __numpyB__<jupyter_code>numpyB = numpyA*3.45
numpyB<jupyter_output><empty_output><jupyter_text>Y eso es la maravilla de Numpy! Te permite simplificar muchos cálculos!Para los siguientes módulos, aprenderás mas sobre numpy.  Volviendo a la regresión que haciamos ...Definamos nustros ejes P presión y logarimo natural V de volumen en términos de numpy<jupyter_code>V= np.array(volumen)
P = np.array(presion)<jupyter_output><empty_output><jupyter_text>Pero queremos el logaritmo natural de V<jupyter_code>lnV = np.log(V)
lnV
P<jupyter_output><empty_output><jupyter_text>Paso 4.Siguiendo las reglas del paquete que escogiste. Hagamos la regresión.Para hacer la regresión en Scypython se usa la siguiente línea de código* slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)Donde x y y en nuestro caso son el volumen V y la presion P<jupyter_code>slope, intercept, r_value, p_value, std_err = stats.linregress(P, lnV)<jupyter_output><empty_output><jupyter_text>Listo. Ya hiceste la regresión! En la __celda 28__ creaste un modelo lineal, por lo cual le preguntaste a Python que calculase 1. La pendiente slope2. Intercepto intercept3. El valor de R4. Valor p5. El error estandar del intercepto y la pendienteAhora simplemente tenes que preguntarle a Python por dichos valores!<jupyter_code>## Si queremos el R cuadrado, simplemente elevamos al cuadrado el r_value
print("r-squared:", r_value**2)<jupyter_output><empty_output><jupyter_text>El $R^{2}$ da un valor cercano a 1 por lo tanto nuestro modelo se ajusta a una linea recta.Preguntemos ahora por el intercepto y la pendiente<jupyter_code>intercept
slope
## Error estardar de la pendiente
std_err<jupyter_output><empty_output><jupyter_text>Para que podas ver mejor el ajuste, veamos un gráfico sencillo<jupyter_code>plt.plot(P, lnV, 'o', label='Datos experimentales')
plt.plot(P, intercept + slope*P, 'r', label='Regresión Lineal')
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>Por ahora el gráfico está un poco profesional Sin embargo en los próximos módulos de enseñaremos a sacarle mas provecho a matplotlib!La idea es que te des una idea de como se ve....Que tal si haces lo mismo pero en Excel y luego Origin  Resumen génerico de Regresiones Lineales con Scypythonimport matplotlib.pyplot as plt import numpy as np from scipy import stats x = np.array( pon acá tu array X) y = np.arryarandom(pon aca tu array Y) slope, intercept, r_value, p_value, std_err = stats.linregress(x, y) print("r-squared:", r_value**2) plt.plot(x, y, 'o', label='original data') plt.plot(x, intercept + slope*x, 'r', label='fitted line') plt.legend() plt.show()   Regresión Lineal con StatsmodelSí querés un algoritmo mas estadísticos, nos encontramos con Stats model. Stats model está enfocado en regresión lineal y multilineal Pasos 1.  Instale el paquete statsmodel Comando __!pip install -U statsmodels__ 2.  Importe el paquete a su hoja de cálculo Comando __import statsmodels.api as sm__ 3.  Defina dos listas __x__ y __y__ que representan sus ejes 4.  Defina su eje X y eje X en términos de numpy array. Comando __X = np.array(x) Y = np.array(y)__ donde y y x representan listas previamente definidas 5. Agregue su constante o intercepto a X. Código __X = sm.add_constant(X)__ 6. Defina su modelo Código __modelo = sm.OLS(Y,X).fit()__ 7. Imprimia resultados de regresión. Código __print(model.summary())__ Volvamos a hacer el ejemplo pasado. Siguiendo pasos anteriores   Paso 1. Instalar el paquete statsmodels.<jupyter_code>!pip install -U statsmodels<jupyter_output><empty_output><jupyter_text>Paso 2. Importar el paquete.<jupyter_code>import statsmodels.api as sm<jupyter_output><empty_output><jupyter_text>Con el comando anterior le decís a Python! Hey Python, yo acabo de instalar un paquete en Jupyter Ahora, quiero importarlo en esta hoja de cálculo porque lo deseo usar. Así mismo lo quiero usar como __sm__ ( lo bautizaste así) Pudiste decir import statsmodels.api as Guapo Por ejemplo  Paso 3 y 4. Definiendo listas que contentan nuestros datos y luego convertirlas a Numpy array.En esta parte.__x__ es presion __y__ es volumen __X__ es p __Y__ es v<jupyter_code># P de presión y V de volumen
presion = [8.99 , 17.65 , 34.10 , 41.92 , 49.50 , 58.86 , 64.02]
volumen = [2.000 , 1.000 , 0.500 , 0.400 , 0.333 , 0.286 , 0.250]

presion = np.array(presion)
v = np.log(volumen) # RECUERDA. Para esta regresión ocupamos el logarimo de V según el modelo.<jupyter_output><empty_output><jupyter_text>Paso 5. Agregar intercepto o constantePor alguna razón de la vida. Los programadores del paquete no incluyeron por defecto el intercepto __b__ de la recta. Hay que agregarlo<jupyter_code>p = sm.add_constant(presion)<jupyter_output><empty_output><jupyter_text>Paso 6. Modelado linealRecuerde!! Primero va su eje y luego x en el código sm.OLS(Y,X).fit()<jupyter_code>modelo = sm.OLS(v,p).fit()<jupyter_output><empty_output><jupyter_text>Paso 7. Resultados<jupyter_code>print(modelo.summary())<jupyter_output><empty_output><jupyter_text>Veamos los datos que nos interesan y comparemos respecto al paquete anterior... statsmodesl reporta un $R^{2}$  R-squared: 0.941 , mientras tanto scipython reportaba 0.9407068590556042 statsmodels reporta un intecepto (const) de 0.7361 con error de (std err) de 0.175, mientras scipython reporta un valor de 0.7360696712998822 sin incertidumbre statsmodels reporta una pendiente (x1) de -0.0357 con error de (std err) de 0.004, mientras scipython reporta una slope o pendiente de -0.03565462859677574 con error de 0.00400318801554946 En resumen valores muy similares. Sin embargo el algoritmo de statsmodels es más robusto y tira mayor información<jupyter_code>## Sí querés el gráfico recuerda el código de matploblib
const = 0.7361
x1 = -0.0357
model = const + x1*presion
plt.plot(presion, v, 'x', label='Datos experimentales')
plt.plot(presion, model  , 'r', label='Regresión Lineal con Statsmodels')
plt.legend()
plt.show()<jupyter_output><empty_output><jupyter_text>Resumen Código Genérico para hacer regresión lineal con stats modeles 1.  Instale el paquete statsmodel Comando __!pip install -U statsmodels__ 2.  Importe el paquete a su hoja de cálculo Comando __import statsmodels.api as sm__ 3.  Defina dos listas __x__ y __y__ que representan sus ejes 4.  Defina su eje X y eje X en términos de numpy array. Comando __X = np.array(x) Y = np.array(y)__ donde y y x representan listas previamente definidas 5. Agregue su constante o intercepto a X. Código __X = sm.add_constant(X)__ 6. Defina su modelo Código __modelo = sm.OLS(Y,X).fit()__ 7. Imprimia resultados de regresión. Código __print(model.summary())__  [Volver al índice](https://notebooks.azure.com/jeff0994/libraries/QU-0560-1-1/html/01Introducci%C3%B3n-Indice.ipynb)<jupyter_code><jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.07135933189173067, 'fraction_numerical': 0.030124524643948998, 'mean_word_length': 5.398854961832061, 'pattern_counts': {'":': 0, '<': 94, '<?xml version=': 0, '>': 94, 'https://': 6, 'lorem ipsum': 0, 'www.': 3, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '23', 'dir': 'jupyter-structured-clean-dedup', 'id': '351397', 'license': 'MIT', 'n_tokens_mistral': 4980, 'n_tokens_neox': 4659, 'n_words': 1683, 'path': '06AplicaciónRegresiones.ipynb', 'repo_name': 'jeff0994/Qu-00560', 'size': '13416'}