<jupyter_start><jupyter_text>![img](https://ddfoqzqsu0zvp.cloudfront.net/media/documents/Tecnologico_de_Monterrey_LockUp_horizontal_RGB.png)  Equipo 1- <NAME> - A01656257- <NAME> - A01656159- <NAME> - A01654725- <NAME> - A01338074 [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MauricioRR-Tec/AprendizajeAutomatico/blob/master/Tema_3_Preprocesamiento/notebook/01Intro2PPwoAns.ipynb) Intro al Pre-procesamiento---  Contenido de la Sesión1.   Introducción al Pre-procesamiento de Datos          1.1. Tipos de PP.2.   Exploración Visual de los Datos          2.1. Histogramas.            2.1.1. Joyplot          2.2. Diagramas de Dispersión. Literatura recomendada:1. <NAME>., <NAME>., & <NAME>. (2015). Data preprocessing in data mining (pp. 195-243). Cham, Switzerland: Springer International Publishing.---  Introducción al Pre-procesamiento (PP) de Datos.El **preprocesamiento** de datos dentro de la Ciencia de Datos es FUNDAMENTAL. Según el Foro Económico Mundial, **¡para 2025 generaremos alrededor de 463 exabytes ($463*10^{18}$ bytes = 463 milliones de TB) de datos a nivel mundial por día!**. Entonces, deberiamos preguntarnos*   ¿todos los datos son adecuados para ser utilizados por los algoritmos de aprendizaje automático?*   ¿Cómo decidimos eso?El **preprocesamiento** es el primer paso a realizarse antes de comenzar a aprender cualquier tipo de modelo, ya que la calidad de los datos y la información útil que puede derivarse de estos afectará directamente la capacidad de nuestros modelos.>> **Garbage In, Garbage Out**![](https://docs.google.com/uc?export=download&id=1U5EKW0k-YdYso4sid8SDVZIlCuLAIqVP)Tomado de: https://www.kdnuggets.com/2016/03/data-science-process.html --- Entonces, ¿qué es el PP de datos?Cuando hablamos de datos, generalmente pensamos en conjuntos de datos en **forma  tabular o tablas de excel** (filas y columnas) con valores que una computadora es capáz de asimilar (números continuos) y sin datos faltantes.  Por ejemplo, consideremos un conjunto de datos de aprobación crediticia.Dicho conjunto consta de:650 clientes (filas), 15 variables explicativas (nominales/categóricas y númericas) así como una clase (en total 16 columnas).>> pregunta: **¿Una computadora puede analizar variables nominales?**>> En el caso negativo, **¿cómo podriamos convertir la variable para que la computadora pueda interpretar dicha variable?**>> **¿Qué se debe hacer cuando una variable presenta un dato faltante?**<jupyter_code>import pandas as pd
import matplotlib.pyplot as plt

#from google.colab import data_table

url = 'https://raw.githubusercontent.com/MauricioRR-Tec/AprendizajeAutomatico/main/Tema_3_Preprocesamiento/data/CreditApproval/creditApproval_dataset.csv'
df = pd.read_csv(url)

#data_table.DataTable(df, include_index=True, num_rows_per_page=10)
#data_table.DataTable? #How to display help regarding a function<jupyter_output><empty_output><jupyter_text>¿Cómo identificarían si una variable, por ejemplo **A4** tiene valores faltantes? Considere que las variables con datos faltantes estan marcadas con un '?'<jupyter_code>a = df['A4'].unique()
a[0]<jupyter_output><empty_output><jupyter_text>Lastima que Python no es R, de otra forma tendrian por defecto una función llamada *which()*<jupyter_code>def which(self):
    try:
        self = list(iter(self))
    except TypeError as e:
        raise Exception("""'which' method can only be applied to iterables.
        {}""".format(str(e)))
    indices = [i for i, x in enumerate(self) if bool(x) == True]
    return(indices)
which(df.A4 == a[2])<jupyter_output><empty_output><jupyter_text>De esta forma, podemos hacer un *splicing* (partición) de toda la base, obteniendo solo aquellos renglones con los elementos de interes.<jupyter_code>ixes = which(df.A4 =='?')
df.iloc[ixes,:]<jupyter_output><empty_output><jupyter_text>Bueno, bueno, pero el *splicing* de Python es bastante efectivo y más legible.<jupyter_code>lugares = df.A4 == a[2]
df[lugares]<jupyter_output><empty_output><jupyter_text>---Si bien mucha información se encuentra en un formato tabular o algún otro compatible, no siempre es el caso. Los **datos pueden tener muchas formas diferentes: tablas estructuradas, imágenes, archivos de audio, videos, etc**.Las máquinas no entienden los datos de texto, imagen o video **tal como son**, entienden los 1 y los 0. Por lo tanto, no es suficiente con hacer una presentación de diapositivas de todas nuestras imágenes y esperar que nuestro modelo de aprendizaje automático se entrene solo con eso.![](https://imgs.xkcd.com/comics/machine_learning.png)  Por ejemplo, en el caso de una imagen correspondiente al dígito **6** escrito a mano ¿Cómo podemos representarla para que una máquina entienda una imagen?<jupyter_code>from matplotlib import image as img
from matplotlib import pyplot as plt

image = img.imread("https://i.stack.imgur.com/Ds5Rc.png")

plt.imshow(image)<jupyter_output><empty_output><jupyter_text>Representamos la imagen en una matriz, o mejor dicho, varias matrices correspondientes a la escala de colores en Rojo, Verde y Azul (RGB por sus siglas en inglés). Por lo tanto, una imagen corresponde a 3 matrices $z_i\in Z$, de tamaño $m\times n$.<jupyter_code>print(type(image)) #El objeto devuelto es un arreglo multidimensional MxNxD
print(image.shape) #Funciones de numpy.ndarray, devuelve el tamaño del arreglo.
print(image)<jupyter_output><class 'numpy.ndarray'>
(599, 602, 3)
[[[0.99607843 0.99607843 0.99607843]
  [0.99607843 0.99607843 0.99607843]
  [0.99607843 0.99607843 0.99607843]
  ...
  [0.9647059  0.9647059  0.9647059 ]
  [0.93333334 0.93333334 0.93333334]
  [0.8784314  0.8784314  0.8784314 ]]

 [[0.99607843 0.99607843 0.99607843]
  [0.99607843 0.99607843 0.99607843]
  [0.99607843 0.99607843 0.99607843]
  ...
  [0.972549   0.972549   0.972549  ]
  [0.93333334 0.93333334 0.93333334]
  [0.8784314  0.8784314  0.8784314 ]]

 [[0.99607843 0.99607843 0.99607843]
  [0.99607843 0.99607843 0.99607843]
  [0.99607843 0.99607843 0.99607843]
  ...
  [0.99215686 0.99215686 0.99215686]
  [0.93333334 0.93333334 0.93333334]
  [0.88235295 0.88235295 0.88235295]]

 ...

 [[0.96862745 0.96862745 0.96862745]
  [0.9764706  0.9764706  0.9764706 ]
  [0.99215686 0.99215686 0.99215686]
  ...
  [1.         1.         1.        ]
  [0.9882353  0.9843137  0.9882353 ]
  [0.827451   0.827451   0.827451  ]]

 [[0.96862745 0.96862745 0.96862745][...]<jupyter_text>--- ¿Cuáles son los problemas básicos que deben resolverse en el PP de datos?> En cualquier proceso de Machine Learning, **el PP es el paso en el que los datos se transforman o codifican** para llevarlos a un estado tal que ahora la máquina pueda analizarlos fácilmente. Estos son algunos de los tipos de problemas básicos así como la familia de técnicas de PP a la que pertenecen:* ¿Cómo limpio los datos? ***Limpieza de datos***.* ¿Cómo unifico y escalo los datos? ***Normalización de datos***.* ¿Cómo proporciono datos precisos? ***Transformación de datos***.* ¿Cómo manejo los datos faltantes? ***Imputación de datos perdidos***.* ¿Cómo incorporo y ajusto datos? ***Integración de datos***.* ¿Cómo detecto y manejo el ruido? ***Análisis del ruido***.![](https://docs.google.com/uc?export=download&id=1-Dro_Qk1I63w2OAtjrFXRN2HcXMC07lo)--- a.1. Limpieza de Datos.Involucra operaciones como* **corrección** de datos * **filtrar datos** especificios o incorrectos * **reducir detalles** innecesarios. Es un concepto general que se traslapa con otras técnicas de PP como la imputación de datos faltantes y análisis del ruido (aunque ambas categorías se ven por separado para un análisis más profundo). Otras operaciones son * la **detección de discrepancias** y **datos sucios** (fragmentos de los datos originales que no tienen sentido). Esto típicamente requiere intervención humana ya que es necesaria la comprensión de los datos originales. Ejemplo:https://archive.ics.uci.edu/ml/datasets/Credit+Approval![](https://docs.google.com/uc?export=download&id=1SY3zCno1dL3qukcBjWz8xIa7gkfbqm7D) --><jupyter_code>import pandas as pd
import matplotlib as plt
url = 'https://raw.githubusercontent.com/MauricioRR-Tec/AprendizajeAutomatico/main/Tema_3_Preprocesamiento/data/CreditApproval/creditApproval_dataset.csv'
df = pd.read_csv(url)
df<jupyter_output><empty_output><jupyter_text>Ejercicio:1. Ahora queremos remover (por alguna razón) los registros de la matriz donde la variable A4 == 'u'2. También podriamos querer acotarnos a un rango de valores, por ejemplo para lavariable 'A3' entre 4 y 103. En particular, queremos cambiar el valor de la columna ``class`` de $\{-,+\}$ a $\{-1,1\}$<jupyter_code>#Ahora queremos remover (por alguna razón) los registros de la matriz donde
#la variable A4 == 'u'

lugares_2 = df.A4 != a[0]
copia_df = df[lugares_2]
copia_df



#También podriamos querer acotarnos a un rango de valores, por ejemplo para la
#variable 'A3' entre 4 y 10
#Here your answer
df2 = copia_df[(df.A3 > 4) & (df.A3 < 10)]
df2
#Queremos cambiar el valor de la columna class de {−,+} a {−1,1}
#Here your answer
copia_df3 = df2.replace({"class":{"+":1, "-": -1}})
copia_df3<jupyter_output><empty_output><jupyter_text>--- a.2. Normalización de Datos.La unidad de medida utilizada puede afectar el análisis de datos.>> Por ejemplo: típicamente los datos atmosféricos en México, reflejan una  temperatura acotada entre 8 a 40 °C, mientras que la presión atmosférica esta data entre 950 a 1050 milibar (El milibar (mbar) es una unidad de presión equivalente a una milésima parte del bar, un bar es igual a 1000 (mil) milibares). >> >> >> * ¿Qué variable predomina más? mbar>> * ¿Qué cambio produce un mayor efecto, una diferencia de 5°C de temperatura o 20 mbar de presión? El cambio de presión, ya que existe un rango mayor.La normalización de los datos intenta dar a todos los atributos el mismo peso, expresando cada variable en las mismas unidades de medida y así como una escala en común (determinada). Ejemplo:1. Escalar los valores de las columnas A8 entre -1 y 1.Utilice la siguiente formula:$$x_{new} = 2\cdot \frac{x-\min(x)}{\max(x)-\min(x)} - 1$$en python podemos obtener utilizar las funciones de pandas para realizar este cálculo.<jupyter_code>x_new = 2*((df.A11-df.A11.min())/(df.A11.max()-df.A11.min()))-1
x_new.min()
df.A11
df_scaled = df.copy()
df_scaled['A8'] = x_new
df_scaled.A8<jupyter_output><empty_output><jupyter_text>Ejercicio:1. Escalar los valores de las columnas A3 y A15 entre 0 y 1.Utilice la siguiente formula:$$x_{new} = \frac{x-a}{b-a}$$tal que$$a=\min(x),\ b=\max(x)$$2. Escalar las mismas columnas pero entre dos valores arbitrarios $q$ y $z$, tal que $q<z$.Utilice la siguiente formula:$$x_{qz}= (z-q)\cdot x_{new}+q$$<jupyter_code>#Obtenemos los valores de máx y min
maxA3 = copia_df3.A3.max()
maxA15 = copia_df3.A15.max()
#Escalado
def escalado(x):
  minCol = x.min()
  maxCol = x.max()
  return (x - minCol)/ (maxCol - minCol)
copia_df3.A3 = escalado(copia_df3.A3)
copia_df3.A15 = escalado(copia_df3.A15)
copia_df3
plt.scatter(copia_df3["A3"], copia_df3["class"], alpha= 0.5)
plt.show<jupyter_output><empty_output><jupyter_text>--- a.3. Transformación de DatosEn este paso los datos se **convierten o consolidan** para que el resultado del modelado sea más *eficiente/efectivo*. Entre las técnicas de transformación de datos se encuentra* el **suavizamiento**.    * * **construcción de características**.![](https://docs.google.com/uc?export=download&id=1a4zaszYOY3Rc7YX5Ggo1gBykOz_nwnML)* **agregación o resumen** de datos.* **discretización**.* **generalización**. Sin embargo, la mayoría de estas se pueden considerar como áreas independientes.Las tareas que requieren supervisión humana son las técnicas clásicas de transformación de datos como: * la generación de informes* nuevos atributos que agregan los existentes * generalización de conceptos, especialmente en atributos categóricos    * ej. la sustitución de fechas completas por solo números de año. Ejercicio: One-Hot EncodingOne-Hot Encoding es la transformación de variables nominales/categóricas en númericas. Esta transformación consiste en convertir cada valor $v_i$ de una variable $V$ ($v_i\in V$), en columnas. De tal suerte, que si la variable $V$ tiene tres valores ($|V|=3$), esta será reemplazada por V1, V2 y V3, en donde se pondrá un 1 si $V1 = v_i$, de otra forma 0; se aplica el mismo principio para V2 y V3.![](https://docs.google.com/uc?export=download&id=18CttdKmICOmEvQ82JEJwQbdnxO3myjnU)Por ejemplo, si tenemos ``df.A1=['red', 'red', 'green']``Cada valor de A1 se representara por un vector de 0's y 1's. Esto es ``[1,0],[1,0],[0,1]``. Ahora, en lugar de tener ``df.A1``, tenemos ``df.A1_red,df.A1_ref``.**Aplicar el One-Hot-Encoding a las variables A4 y A5 del conjunto de aprobación de crédito**.<jupyter_code>procesado_df = pd.get_dummies(data=copia_df3, prefix= "_", columns=["A4", "A5"])
procesado_df<jupyter_output><empty_output><jupyter_text>--- a.4. Imputación de datos faltantes.El propósito es llenar las variables que contienen **valores faltantes** (missing values en inglés) con algunos datos intuitivos. En la mayoría de los casos, es mejor agregar una estimación razonable de un valor de datos adecuado que dejarlo en blanco.Tomado de: https://stefvanbuuren.name/fimd/missing-data-pattern.html<jupyter_code>import pandas as pd
import numpy as np

df = pd.read_csv(url)

df<jupyter_output><empty_output><jupyter_text>Insertaremos artificialmente 20% de datos faltantes, codificados como `np.nan`. Para ello utilizamos la función `sample()`, la cual nos permite obtener una muestra de un objeto con respecto a un eje del objeto, por defecto devuelve los renglones en un DataFrame.<jupyter_code>import random
random.seed(3)
df_copy = df.copy()

for col in df_copy.columns:
    df_copy.loc[df_copy.sample(frac=0.2).index, col] = np.nan

df_copy.head(20)
# df_copy.dtypes<jupyter_output><empty_output><jupyter_text>Para valores númericos podemos utilizar la media o mediana, `'mean'` y `'median'` respectivamente.<jupyter_code>from sklearn.impute import SimpleImputer

imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
imp_median = SimpleImputer(missing_values=np.nan, strategy='median')

imp_mean.fit(df_copy.loc[:,['A3','A8']])
imp_median.fit(df_copy.loc[:,['A3','A8']])

# df_copy.loc[:,['A3','A8']] =imp_mean.transform(df_copy.loc[:,['A3','A8']])
df_copy.loc[:,['A3','A8']] =imp_median.transform(df_copy.loc[:,['A3','A8']])
df_copy.head(20)<jupyter_output><empty_output><jupyter_text>Y para valores categoricos podemos utilizar el valor más frecuente, estableciendo la estrategia `'most_frequent'`.<jupyter_code>from sklearn.impute import SimpleImputer

imp_category = SimpleImputer(missing_values=np.nan, strategy='most_frequent')

imp_category.fit(df_copy.loc[:,['A1','A4']])

df_copy.loc[:,['A1','A4']] =imp_category.transform(df_copy.loc[:,['A1','A4']])
df_copy.head(20)<jupyter_output><empty_output><jupyter_text>--- a.5. Integración de Datos.Comprende la fusión de datos de múltiples fuentes de datos. Este proceso debe realizarse con cuidado para evitar redundancias e inconsistencias en el conjunto de datos resultante. Las operaciones típicas logradas dentro de la integración de datos son la * **identificación** y **unificación** de variables y dominios* **análisis de correlación** entre atributos* **identificación de duplicación** y **detección de conflictos** en los valores de datos de diferentes fuentes.Una herramienta básica en este proceso son las tablas pivote o `pivot.table()`.Una tabla pivote se usa para resumir, ordenar, reorganizar, agrupar, contar, datos totales o promedio almacenados en una tabla. Nos permite transformar columnas en filas y filas en columnas. Permite agrupar por cualquier campo (columna) y utilizar cálculos avanzados sobre ellos.[Tabla Pivote de Pandas](https://pandas.pydata.org/docs/reference/api/pandas.pivot_table.html)  EjemploDada la pandemia desencadenada por el COVID19, deseamos entender mejor la  propagación del virus. Los datos por país se pueden consultar en el repositorio de github [Datos Covid 19](https://datahub.io/core/covid-19data). Sin embargo, para nuestro análisis requerimos enfocarnos en los **casos confirmados promedio por país**.Para esto usemos la funcion `pivot.table()`.<jupyter_code>import pandas as pd
import numpy as np
url = 'https://raw.githubusercontent.com/MauricioRR-Tec/AprendizajeAutomatico/main/Tema_3_Preprocesamiento/data/Covid19/covid19WW_2021.csv'
df = pd.read_csv(url)

df1 = df.pivot_table(index=['Date','Country'], 
                    values='Confirmed',
                    aggfunc=np.mean)
df1<jupyter_output><empty_output><jupyter_text>Ejercicio:Dada la pandemia desencadenada por el COVID19, deseamos entender mejor la  propagación del virus. Los datos por país se pueden consultar en el repositorio de github https://datahub.io/core/covid-19data. Sin embargo, para nuestro análisis requerimos enfocarnos en los **casos confirmados acumulados por día y país**.Para esto necesitamos en el eje $y$ (renglones) las fechas, y en el eje $x$ (columnas) los paises. **Realice las acciones de pivoteo necesarias para obtener el DataFrame requerido. La variable ``Date`` debe de ser de tipo fecha. Aseguresé de guardar los resultados en un archivo CSV para su posterior análisis.**<jupyter_code>df.Date = pd.to_datetime(df.Date)
dataframeR = df.pivot_table(index='Date', columns='Country', values='Confirmed',aggfunc= np.sum)
dataframeR<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10990269032627362, 'fraction_numerical': 0.05449341728677733, 'mean_word_length': 5.226300784034213, 'pattern_counts': {'":': 3, '<': 82, '<?xml version=': 0, '>': 101, 'https://': 19, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '18', 'dir': 'jupyter-structured-clean-dedup', 'id': '169747', 'license': 'MIT', 'n_tokens_mistral': 6913, 'n_tokens_neox': 6327, 'n_words': 1891, 'path': '3 Preprocesamiento/01Intro2PPwoAns.ipynb', 'repo_name': 'KevinTMtz/Aprendizaje-Autom-tico-Pr-cticas', 'size': '17557'}