<jupyter_start><jupyter_text>M2.851 &middot; Tipologia y Ciclo de vida de los Datos &middot; M&aacute;ster Universitario en Ciencia de Datos (Data Science) Estudios de Inform&aacute;tica, Multimedia y Telecomunicaci&oacute;n&nbsp;ALUMNA: <NAME> SILVAGITHUB:&nbsp;https://github.com/preyespe/Titanic-Data-Cleaning PAC 2: LIMPIEZA Y VALIDACION DE LOS DATOSEn esta pr&aacute;ctica realizaremos la limpieza y validaci&oacute;n de datos del dataset [TITANIC](https://www.kaggle.com/c/titanic/data) y posteriormente aplicaremos un algoritmo de clasificaci&oacute;n que nos permitir&aacute; predecir la precisi&oacute;n para la sobrevivencia.El contenido a desarrollar es el siguiente:Carga de datosDescripci&oacute;n del datasetIntegraci&oacute;n y selecci&oacute;n de los datos de inter&eacute;s a analizarLimpieza de los datos3.1. Gesti&oacute;n de ceros o elementos vacios3.2.&nbsp;Creación de nuevas variables3.3.&nbsp;Identificaci&oacute;n y tratamiento de valores extremos | Transformación de datosAn&aacute;lisis de los datos 4.1. Selección de los grupos de datos que se quieren analizar/comparar (planificación de los análisis a aplicar). 4.2. Comprobaci&oacute;n de la normalidad y homogeneidad de la varianza 4.3. Aplicaci&oacute;n de pruebas estad&iacute;sticas para comparar los grupos de datosRepresentaci&oacute;n de los resultados a partir de tablas y gr&aacute;ficasConclusiones.  0. Carga de datosLos datos contenidos en el dataset *TITANIC* se han dividido en dos grupos:Un conjunto de entrenamiento (train.csv)Un conjunto de prueba (test.csv)El siguiente c&oacute;digo cargar&aacute; las datos de entrenamiento&nbsp;"train" conteniendo 891 regsitros y otros&nbsp; 418 registros en nuestro conjunto de "test".&nbsp; Podemos comprobar que la carga ha sido correcta, al visualizar los primeros 5 registros del dataset "train".<jupyter_code>import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

# Carga de los datos de entrenamiento y test
train = pd.read_csv('../data/input/train.csv')
test = pd.read_csv('../data/input/test.csv')

# Visualizamos las 5 primeras filas del dataset de entrenamiento
train.head(5)<jupyter_output><empty_output><jupyter_text>1. Descripción del dataset El hundimiento del RMS Titanic es uno de los naufragios m&aacute;s infames de la historia. El 15 de abril de 1912, durante su viaje inaugural, el Titanic se hundi&oacute; despu&eacute;s de colisionar con un iceberg, matando a 1502 de 2224 pasajeros y tripulantes. Esta sensacional tragedia conmocion&oacute; a la comunidad internacional y condujo a mejores regulaciones de seguridad para los buques. Una de las razones por las que el naufragio provoc&oacute; tal p&eacute;rdida de vidas fue que no hab&iacute;a suficientes botes salvavidas para los pasajeros y la tripulaci&oacute;n. Aunque hubo alg&uacute;n elemento de suerte involucrado en sobrevivir al hundimiento, algunos grupos de personas ten&iacute;an m&aacute;s probabilidades de sobrevivir que otros, como las mujeres, los ni&ntilde;os y la clase alta.[KAGGLE]El conjunto de datos objeto de an&aacute;lisis se ha obtenido desde el sitio Kaggle y est&aacute; constituido por 12 caracter&iacute;sticas (columnas) que presentan 1309 pasajeros (filas o registros).&nbsp; A su vez, este dataset se encuentra dividido en dos subdatasets, el primero para entrenamiento, llamado "train" con 891 pasajeros y el segundo para pruebas, llamado "test" con 481 pasajeros.Entre los campos de este conjunto de datos, encontramos los siguientes:Nro. ItemVariableDescripci&oacute;n1PassengerIdPassenger ID2SurvivedSurvived (0 = No; 1 = Yes)3PclassPassenger Class (1 = 1st; 2 = 2nd; 3 = 3rd)4NameName5SexSex6AgeAge7SibspNumber of Siblings/Spouses Aboard8ParchNumber of Parents/Children Aboard9TicketTicket Number10FareTarifa del pasaje11CabinNro. de Cabina12EmbarkedPort of Embarkation (C = Cherbourg; Q = Queenstown; S = Southampton)Existen adem&aacute;s, las siguientes consideraciones especiales:Pclass es un proxy para el estado socio-econ&oacute;mico (SES, o socio-economic status) 1st Alto; 2nd Medio; 3er BajoLa edad (Age) est&aacute; en a&ntilde;os; Fraccional si la edad es menor que 1. Si la edad es estimada, esta se encuentra en la forma xx.5Con respecto a las variables de relaci&oacute;n familiar (es decir, sibsp y parch) algunas relaciones fueron ignoradas.Las siguientes son las definiciones usadas para sibsp y parch:- Sibling (Hermanos): hermano, hermana, hermanastro o hermanastra de un pasajero a bordo del Titanic.- Spouse (C&oacute;nyuge): Esposo o esposa del pasajero a bordo del Titanic (enamorados y novios ignorados).- Parent (Padre): madre o padre de pasajero a bordo del Titanic.Es importante este dataset, porque analizando la importancia de sus atributos o factores, podemos predecir cu&aacute;les de ellos fueron determinantes para que algunas personas sobrevivan.<jupyter_code># Se muestra el total de los datos, asi como la cantidad de registros para entrenar y probar
total_df = [train, test]
print("Nro. Registros para entrenar: ", train.shape)
print("Nro. Registros para prueba: ", test.shape)
print("Total de DataFrames para analizar: ", len(total_df))<jupyter_output>Nro. Registros para entrenar:  (891, 12)
Nro. Registros para prueba:  (418, 11)
Total de DataFrames para analizar:  2<jupyter_text>2. Integración y selección de los datos de interés a analizarAl analizar los datos disponibles, se han identificando cuales atributos pueden ser relevantes y que otros pueden descartarse. Las consideraciones que se han tenido en cuenta son las siguientes:Si nuestra meta es lograr predecir la supervivencia de los pasajeros, nuestro atributo clave ser&aacute; &ldquo;Survived&rdquo;.Deberemos separar las etiquetas de los datos.Los atributos pclass, sexo y embarcado son variables que poseen diferentes niveles, por lo tanto, son variables categ&oacute;ricas que deber&aacute;n convertirse a numericas.Las variables num&eacute;ricas, se mantendrán como tal.El nombre del pasajero es una variable de texto, y no ser&aacute; una variable &uacute;til para predecir la supervivencia, por tanto se debera eliminar.De esta manera, de los 12 atributos que originalmente nos proporciona el dataset, podremos prescindir de los siguientes:PassengerIdNameTicketCabin<jupyter_code># Eliminamos los atributos de poco relevancia para nuestro análisis
del_atributos = ['PassengerId', 'Name', 'Ticket', 'Cabin']
#total_datos = total_datos.drop(del_atributos, axis = 1)
train = train.drop(del_atributos, axis = 1)
test  = test.drop(del_atributos, axis = 1)
# Nuevo numero de atributos de nuestro dataset
#print("Nro. Total datos/Atributos: ", total_datos.shape)
print("Nro. Registros para entrenar/Atributos: ", train.shape)
print("Nro. Registros para prueba/Atributos (no incluido el atributo 'Survived'): ", test.shape)<jupyter_output>Nro. Registros para entrenar/Atributos:  (891, 8)
Nro. Registros para prueba/Atributos (no incluido el atributo 'Survived'):  (418, 7)<jupyter_text>3. Limpieza de los datos 3.1. Gestión de ceros o elementos vacios: Dado que nuestro dataset es peque&ntilde;o, no deber&iacute;amos optar por eliminar todas las observaciones (filas) o variables (columnas) que contengan valores faltantes.La estrategia utilizada es la de reemplazar los valores faltantes por valores razonables segun la distribuci&oacute;n de los datos.&nbsp; Asi, por ejemplo, utilizaremos la media, la mediana o el modo para reemplazar los valores faltantes. Tambien se utiliza medios graficos a fin de visualizar el impacto de ciertos atributos sobre los valores faltantes.En Python, conocemos la cantidad de valores null o NaN con las siguientes funciones pd.isna() o pd.isnull().<jupyter_code># Verificamos los atributos que contienen valores desconocidos o faltantes
print("Ceros o vacios encontrados: ")
#total_datos.isna().sum()
train.isna().sum()
train.isnull().sum()<jupyter_output><empty_output><jupyter_text>Como podemos observar, existen datos faltantes pas los atributos Age, Fare y&nbsp;Embarked.&nbsp; En Survived, los faltantes corresponden al grupo de datos de "test", que por obvias razones no se contemplan, por ser la variable objetivo, es decir, la que debemos predecir para dicho dataset.Que datos asignamos a cada una de estas tres variables? La estrategia es la siguiente:Age: Existen 263 pasajeros que no tienen registrada su edad.&nbsp; Para asignarles una, se tomar&aacute; el resultado de calcular numeros aleatorios obtenidos a partir de la suma y diferencia entre la media (mean) y desviacion estandar (std) de las edades de los pasajeros.Fare: Existe s&oacute;lo 1 pasajero que no cuenta con la tarifa de su ticket.Embarked: Existen 2 pasajeros que no tienen el dato de puerto de embarque.A continuaci&oacute;n se implementa cada uno de ellos.  a) Datos vacios en el atributo Edad (Age)<jupyter_code># Verificamos cuantos datos faltantes en el atributo Age hay en dataset train
len(train['Age'][np.isnan(train['Age'])])
# Verificamos cuantos datos faltantes en el atributo Age hay en dataset test
len(test['Age'][np.isnan(test['Age'])])<jupyter_output><empty_output><jupyter_text>Antes de aplicar las nuevos valores de edad generadas aleatoriamente a partir de la media y desviacion estandar del total de edades en cada conjunto de datos, visualizaremos mediante un histograma las edades del dataset original vs las edades en el dataset temporal actualizado.<jupyter_code># Para los dos datasets temporales, train1 y test1, llenamos los datos Age que contienen valores NaN 
# con los valores de edad aleatoriamente generados a partir de la media de las edadade y su std

pd.options.mode.chained_assignment = None  # deshabilitamos el default='warn'
train1 = train
test1 = test
total_df_test = [train1, test1]

for cadaDataset in total_df_test:
    
    tot_edad_null = len(cadaDataset['Age'][np.isnan(cadaDataset['Age'])])
    edad_avg 	  = cadaDataset['Age'].mean()
    edad_std 	  = cadaDataset['Age'].std()  
    
    # lista de edades que reemplazaran a las edades faltantes por cada dataset
    lista_random_de_edades = np.random.randint(edad_avg - edad_std, 
                                               edad_avg + edad_std, 
                                               size=tot_edad_null)
    
    cadaDataset['Age'][np.isnan(cadaDataset['Age'])] = lista_random_de_edades
    cadaDataset['Age'] = cadaDataset['Age'].astype(int)
# Verificar si hay ceros o vacios
print("Ceros o vacios encontrados en atributo Age del Datasets de prueba: ")
train1.isna().sum()<jupyter_output>Ceros o vacios encontrados en atributo Age del Datasets de prueba:<jupyter_text>Se constata que no existen datos faltantes en el atributo Age, y para asegurar la calidad de los datos de edad generados, visualizamos mediante un histograma, las edades en el dataset original y en el de prueba.<jupyter_code># Visualizamos el histograma para el atributo edad en el dataset original y en el de prueba
# actualizado que no contiene valores vacios en Age
fig = plt.figure()
ax = fig.add_subplot(111)
train['Age'].plot(kind='hist', ax=ax, label="Age en train")
train1['Age'].plot(kind='hist', ax=ax, color='red', label="Age en train1")
plt.title('Age - Datos originales vs Datos Vacios Modificados')
plt.xlabel('Age')
plt.legend()<jupyter_output><empty_output><jupyter_text>Como se visualiza que los nuevos datos para atributo Age son razonables, procederemos a actualizar dichos datos en el dataset original.<jupyter_code>for cadaDataset in total_df:
    
    tot_edad_null = len(cadaDataset['Age'][np.isnan(cadaDataset['Age'])])
    edad_avg 	  = cadaDataset['Age'].mean()
    edad_std 	  = cadaDataset['Age'].std()  
    
    # lista de edades que reemplazaran a las edades faltantes por cada dataset
    lista_random_de_edades = np.random.randint(edad_avg - edad_std, 
                                               edad_avg + edad_std, 
                                               size=tot_edad_null)
    
    cadaDataset['Age'][np.isnan(cadaDataset['Age'])] = lista_random_de_edades
    cadaDataset['Age'] = cadaDataset['Age'].astype(int)
# Verificamos cuantos datos faltantes en el atributo Age hay en dataset train
len(train['Age'][np.isnan(train['Age'])])
# Verificamos cuantos datos faltantes en el atributo Age hay en dataset test
len(test['Age'][np.isnan(test['Age'])])<jupyter_output><empty_output><jupyter_text>b) Datos vacios en el atributo Tarifa (Fare) Existe un pasajero que no posee la tarifa de su ticket.&nbsp; Determinaremos quien es el pasajero y de acuerdo a sus caracterirticas reemplazaremos ese valor con uno razonable.<jupyter_code># Identificamos al pasajero con el la tarifa de su ticket faltante
idx = test.index[test['Fare'].isna()]
test.loc[idx]<jupyter_output><empty_output><jupyter_text>El pasajero se encuentra en la clase 3 (Pclass=3) y se embarc&oacute; en&nbsp;Southampton (Embarked='S'), por tanto, le corresponderia una tarifa 'mediana' correspondiente a tercera clase y embarcando en&nbsp;Southampton.&nbsp; La actualización la hacemos con el siguiente c&oacute;digo:<jupyter_code># Obtenemos la mediana de la tarifa, solo para aquellos pasajeros que pertenecian a tercera clase, 
# y embarcaron en Southampton 

new_fare = test['Fare'].where(cond=((test['Pclass']== 3) & (test['Embarked']=='S'))).median()
new_fare
# Actualizamos el valor de la tarifa 'Fare' al pasajero que la tiene con valor NaN
# df.at[df.index[152], 'ColName'] = valor
test.at[test.index[idx],'Fare'] = new_fare<jupyter_output><empty_output><jupyter_text>Comprobamos ahora que ya no existen valores vacios en los datasets y que el unico valor vacio enel atributo 'Fare' fue correctamente actualizado:<jupyter_code># Verificamos si hay datos faltantes en el atributo Fare en dataset test
test.isna().sum()<jupyter_output><empty_output><jupyter_text>c) Datos vacios en el atributo Puerto de Embarque (Embarked) Debemos inferir el puerto de embarque de los dos pasajeros a partir de la tarifa de su ticket.<jupyter_code># Ubicamos a los pasajeros que no poseen un puerto de embarque
sin_embarque = np.where(train["Embarked"].isnull() == True)
sin_embarque
# Vemos los datos de los pasajeros sin puerto de embarque, coincide que ambos pertenecen a 1ra Clase
# y pagaron una tarifa de $80
# idx = test.index[test['Fare'].isna()]
train.loc[sin_embarque].head()<jupyter_output><empty_output><jupyter_text>Analizaremos que tienen en comun los pasajeros que si embarcaron, pertenecen a 1ra clase y pagaron una tarifa por su ticket.<jupyter_code>con_embarque = np.where((train["Embarked"].isnull() == False) & (train['Pclass'] == 1))
train.loc[con_embarque].head(10)
# Mostramos la tarifa promedio pagada por Puerto de Embarque, cuando la Clase es 1 = Primera clase
train[['Embarked', 'Pclass', 'Fare']].where(
    (train["Embarked"].isnull() == False) & 
    (train['Pclass'] == 1)).groupby(['Embarked'], as_index=False).mean()<jupyter_output><empty_output><jupyter_text>Se puede observar que los pasajeros que pertenecen a 1ra. Clase, pagaron por su Ticket de Embarque, tarifas promedio comprendidas en estos rangos de precios:De 70 a 90 si embarcaron en "S"De 91 a 105 si embarcaron en "Q"Más de 105 si embarcaron en "C"Nuestros pasajeros que pagaron entonces una tarifa de $80 les corresponde entonces el puerto de embarque S (Southampton).<jupyter_code># Actualizamos el valor del embarque 'Embarked' a los pasajeros que lo tiene con valor NaN
# df.at[df.index[152], 'ColName'] = valor
train.at[train.index[sin_embarque],'Embarked'] = 'S'

# Verificamos si hay datos faltantes en el atributo "Embarked" del dataset train
train.isna().sum()<jupyter_output><empty_output><jupyter_text>3.2. Creación de nuevas variables:  A partir del dataset inicial podemos generar algunas variables adicionales interesantes, relacionadas al pasajero, y cuyos datos podrian tomarse en cuenta para el analisis.&nbsp; Estas variables responder&aacute;n a las siguientes preguntas:El pasajero viaja en familia o no?El pasajero es adulto o menor de edad?A continuaci&oacute;, vamos a crear las siguientes variables nuevas:enFamilia: A partir de los atributos&nbsp;Siblings/Spouses o Parents/Children, se podr&aacute; identificar si el pasajero viajaba en famiia o solo.rangoEdad: Nos interesa tambien descubrir si el pasajero era adulto o ni&ntilde;o.<jupyter_code># Creacion de variable enFamilia
train['enFamilia'] = (train['SibSp'] > 0) | (train['Parch'] > 0)
test['enFamilia'] = (test['SibSp'] > 0) | (test['Parch'] > 0)

# Creacion de variable rangoEdad (-1 para cubrir a los niños menores a un año)
train['rangoEdad'] = pd.cut(train['Age'], [-1, 15, 80], labels=['niño', 'adulto'])
test['rangoEdad'] = pd.cut(test['Age'], [-1, 15, 80], labels=['niño', 'adulto'])

train.head()
test.head(5)<jupyter_output><empty_output><jupyter_text>3.3. Identificación y tratamiento de valores extremos | Transformación de datos:  3.3.1. Identificación y tratamiento de valores extremos:  Los valores extremos son valores numericos atipicos (outliers) que se encuentran distantes de los valores "tipicos" que puede tomar una variable.  Analizaremos la variable tarifa del ticket o 'Fare' y mediante un gráfico de cajas podremos observar si existen valores atipicos.<jupyter_code>train.plot(kind="box",figsize=(8,8))<jupyter_output><empty_output><jupyter_text>Observamos en el diagrama anterior que de todas las variables numericas del dataset train, sólo la variable 'Fare' presenta valores atipicos, esto quiere decir, que hay pasajeros que pagaron una tarifa muy superior por el Ticket de Embarque.  Conozcamos quienes y cuantos pasajeros fueron:<jupyter_code>idx = np.where(train["Fare"] == max(train["Fare"]) )
train.loc[idx]<jupyter_output><empty_output><jupyter_text>Son tres los pasajeros que pagaron una tarifa bastante alta por el ticket de embarque. A pesar de eello, no se eliminar&aacute;n estos valores.En el paso siguiente, "Transformaci&oacute;n de Datos", se mostrar&aacute; que al transformar los datos de la tarifa (Fare) por valores en el rango de 0 a 4, este valor extremo dejar&aacute; de serlo. 3.3.2. Transformación de Datos:  Como mencionamos anteriormente, los atributos sexo y embarcado son variables que poseen diferentes niveles de valores, por lo tanto, son variables categ&oacute;ricas que deber&aacute;n convertirse a numericas (pclass lo era pero se elimin&oacute; para efecto de esta pr&aacute;ctica).<jupyter_code># Variables categoricas en el conjunto de datos de train
categoricasX = train.dtypes[train.dtypes == "object"].index
print(categoricasX)

train[categoricasX].describe()
# Variables categoricas en el conjunto de datos de test
categoricasY = test.dtypes[test.dtypes == "object"].index
print(categoricasY)

test[categoricasY].describe()<jupyter_output>Index(['Sex', 'Embarked'], dtype='object')<jupyter_text>Transformación de las atributos Sex , Embarked, enFamilia, rangoEdad<jupyter_code>from sklearn import preprocessing

# Inicializamos el encoder de la etiqueta
label_enc = preprocessing.LabelEncoder()

# Convertimos las variables sexo y embarcado de categoricas a numericas en datasets train y test
train["Sex"] = label_enc.fit_transform(train["Sex"])
train["Embarked"] = label_enc.fit_transform(train["Embarked"])
train["enFamilia"] = label_enc.fit_transform(train["enFamilia"])
train["rangoEdad"] = label_enc.fit_transform(train["rangoEdad"])

test["Sex"] = label_enc.fit_transform(test["Sex"])
test["Embarked"] = label_enc.fit_transform(test["Embarked"])
test["enFamilia"] = label_enc.fit_transform(test["enFamilia"])
test["rangoEdad"] = label_enc.fit_transform(test["rangoEdad"])
train.head(5)
test.head(5)<jupyter_output><empty_output><jupyter_text>La edad (Age) y la tarifa (Fare), siendo atributos numericos, deben transformarse en rangos adecuados para ser analizados con el resto de atributos.Los rangos ser&aacute;n los siguientes:Edad:Age &lt;= 16 a&ntilde;os&nbsp; &nbsp; -&gt; 0Age &gt; 16 y &lt;= 32 -&gt; 1Age &gt; 32 y &lt;= 48 -&gt; 2Age &gt; 48 y &lt;= 64 -&gt; 3Age &gt; 64&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt; 4Tarifa:Fare &lt;= 7.91&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-&gt; 0Fare &gt; 7.91 &lt;= 14.454&nbsp; -&gt; 1Fare &gt;&nbsp;14.454&nbsp; &lt;= 31&nbsp; &nbsp; -&gt; 2Fare &gt; 31&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt; 3<jupyter_code>total_df= [train, test]

for cadaDataset in total_df:
    # Transformamos el atributo Age (edad) en un rango de 0 a 4
    cadaDataset.loc[ cadaDataset['Age'] <= 16, 'Age'] = 0
    cadaDataset.loc[(cadaDataset['Age'] > 16) & (cadaDataset['Age'] <= 32), 'Age'] = 1
    cadaDataset.loc[(cadaDataset['Age'] > 32) & (cadaDataset['Age'] <= 48), 'Age'] = 2
    cadaDataset.loc[(cadaDataset['Age'] > 48) & (cadaDataset['Age'] <= 64), 'Age'] = 3
    cadaDataset.loc[ cadaDataset['Age'] > 64, 'Age'] = 4 
    cadaDataset['Age'] = cadaDataset['Age'].astype(int)

    # Transformamos el atributo Fare (tarifa) en un rango de 0 a 3
    cadaDataset.loc[ cadaDataset['Fare'] <= 7.91, 'Fare'] = 0
    cadaDataset.loc[(cadaDataset['Fare'] > 7.91)   & (cadaDataset['Fare'] <= 14.454), 'Fare'] = 1
    cadaDataset.loc[(cadaDataset['Fare'] > 14.454) & (cadaDataset['Fare'] <= 31), 'Fare']     = 2
    cadaDataset.loc[ cadaDataset['Fare'] > 31, 'Fare'] = 3
    cadaDataset['Fare'] = cadaDataset['Fare'].astype(int)

train.head(5)
test.head(5)<jupyter_output><empty_output><jupyter_text>Junto con los atributos originales seleccionados, las nuevas variables creadas enFamilia y rangoEdad se utilizar&aacute;n en el proceso de an&aacute;lisis de datos siguiente.  Generación de archivo de datos limpio<jupyter_code>train.to_csv("train_clean.csv", index=False)
test.to_csv("test_clean.csv", index=False)<jupyter_output><empty_output><jupyter_text>4. Análisis de los datos 4.1. Selección de los grupos de datos que se quieren analizar/comparar (planificación de los análisis a aplicar)  A continuaci&oacute;n, se seleccionan los grupos dentro de nuestro conjunto de datos que pueden resultar interesantes para analizar y/o comparar. Compararemos basicamente cada una de las variables de nuestro conjunto de datos con la variable objetivo "Survived", porque nos interesa conocer que tan relacionadas están, ello conllevará a definir si tiene o no un gran impacto.  Análisis de datos individuales  1. Clase del pasajero vs Supervivencia<jupyter_code>print (train[['Pclass', 'Survived']].groupby(['Pclass'], as_index=False).mean())<jupyter_output>Pclass  Survived
0       1  0.629630
1       2  0.472826
2       3  0.242363<jupyter_text>- Se observa que los pasajeros perteneciente a la Primera Clase (Pclass = 1) fueron los que mayormente sobrevivieron.  2. Sexo del pasajero vs Supervivencia<jupyter_code>print (train[["Sex", "Survived"]].groupby(['Sex'], as_index=False).mean())<jupyter_output>Sex  Survived
0    0  0.742038
1    1  0.188908<jupyter_text>- Se observa que los pasajeros de sexo femenino (Sex = 0) fueron los que mayormente sobrevivieron.  3. Pasajero viajaba solo o en Familia vs Supervivencia<jupyter_code>print (train[['enFamilia', 'Survived']].groupby(['enFamilia'], as_index=False).mean())<jupyter_output>enFamilia  Survived
0          0  0.303538
1          1  0.505650<jupyter_text>- Se observa que los pasajeros que viajaban solos (enFamilia = 1) fueron los que mayormente sobrevivieron.  4. Puerto de Embarque vs Supervivencia<jupyter_code>print (train[['Embarked', 'Survived']].groupby(['Embarked'], as_index=False).mean())<jupyter_output>Embarked  Survived
0         0  0.553571
1         1  0.389610
2         2  0.339009<jupyter_text>Recordemos que Embarked es:= 0 -&gt; "C" &oacute;&nbsp;Cherburgo= 1&nbsp;-&gt; "Q" &oacute;&nbsp;Queenstown= 2 -&gt; "S" &oacute; Southampton- Se observa que los pasajeros que embarcaron en "C"&nbsp; (Embarked = 0) fueron los que mayormente sobrevivieron.  5. Tarifa del ticket vs Supervivencia Recordemos que los rangos de Tarifa para los tickets de embarque que se han contemplado son los siguientes:Tarifa:Fare &lt;= 7.91&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;-&gt; 0Fare &gt; 7.91 &lt;= 14.454&nbsp; -&gt; 1Fare &gt;&nbsp;14.454&nbsp; &lt;= 31&nbsp; &nbsp; -&gt; 2Fare &gt; 31&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt; 3<jupyter_code>print (train[['Fare', 'Survived']].groupby(['Fare'], as_index=False).mean())<jupyter_output>Fare  Survived
0     0  0.197309
1     1  0.308756
2     2  0.445415
3     3  0.581081<jupyter_text>- Se observa que los pasajeros que pagaron una mayor tarifa por su ticket de embarque (Fare = 2 y 3) fueron los que mayormente sobrevivieron.  6. Edad del Pasajero vs Supervivencia Recordemos que los rangos de edad de los pasajeros que se han contemplado son los siguientes:Edad:Age &lt;= 16 a&ntilde;os&nbsp; &nbsp; -&gt; 0Age &gt; 16 y &lt;= 32 -&gt; 1Age &gt; 32 y &lt;= 48 -&gt; 2Age &gt; 48 y &lt;= 64 -&gt; 3Age &gt; 64&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -&gt; 4<jupyter_code>print (train[['Age', 'Survived']].groupby(['Age'], as_index=False).mean())<jupyter_output>Age  Survived
0    0  0.540541
1    1  0.357143
2    2  0.360902
3    3  0.434783
4    4  0.090909<jupyter_text>- Se observa que los pasajeros que por edad sobrevivieron, fueron los ni&ntilde;os mayores menores de 16 a&ntilde;os y los adultos entre 49 y 64 a&ntilde;os (Fare = 0 y 3) fueron los que mayormente sobrevivieron.  Análisis de datos agrupados  1. Agrupamiento: Clase, Sexo y rango de Edad Nos interesa comparar la tasa de supervivencia con las siguientes tres variables:ClaseSexoRango de edad<jupyter_code>conjunto_datos = pd.concat(
    [train.groupby(['Pclass', 'Sex', 'rangoEdad'])['Survived'].mean(),
     train.groupby(['Pclass', 'Sex', 'rangoEdad'])['Survived'].count()],
    axis=1)
conjunto_datos.columns = ['Sobrevivieron', 'Num']
conjunto_datos<jupyter_output><empty_output><jupyter_text>Se observa en general, que en las tres clases sobrevivieron m&aacute;s mujeres y ni&ntilde;os que adultos hombres.  2. Agrupamiento: Sexo y Tarifa Habrá sido importante esta relacion? Revisemos la tarifa promedio pagada por cada sexo (0: mujer, 1:hombre):<jupyter_code>tarifa_por_sexo = train.groupby('Sex')['Fare'].mean()
tarifa_por_sexo<jupyter_output><empty_output><jupyter_text>Se puede observar que las mujeres pagaron una tarifa superior por su ticket de embarque que los hombres.  3. Agrupamiento: Clase, Sexo y Tarifa Hemos observado que las mujeres pagaron por su ticket de embarque más que los hombres, pero a continuaci&oacute;n veremos si la clase del ticket fue ifluyente para que sea asi.<jupyter_code>tarifa_por_clase_sexo = train.groupby(['Pclass', 'Sex'])['Fare'].mean()
tarifa_por_clase_sexo<jupyter_output><empty_output><jupyter_text>-Se observa que independiente de la clase, las mujeres pagaron una tarifa superior a los hombres. 4.2. Comprobación de la normalidad y homogeneidad de la varianza<jupyter_code>import scipy
resultado_anderson = scipy.stats.anderson(train)
print(resultado_anderson)<jupyter_output><empty_output><jupyter_text>Para verificar que los valores que toman nuestras variables cuantitativas dentro de nuestro conjunto de datos "train" provienen de una poblaci&oacute;n distribuida normalmente, reealizaremos la prueba de normalidad de Anderson-Darling.La salida de esta prueba de normalidad es comprobar que para cada ensayo, se obtiene un valor (p-valor) superior al valor pre-fijado de 0,05.&nbsp; De cumplirse esta condici&oacute;n, se concluiria que nuestras variables tienen una distribuci&oacute;n normal. 4.3. Aplicación de pruebas estadísticas para comparar los grupos de datos  A continuaci&oacute;n vamos a generar &nbsp;un gr&aacute;fico de correlaci&oacute;n de las caracter&iacute;sticas para ver c&oacute;mo se relaciona una caracter&iacute;stica con la siguiente. Para hacerlo, utilizaremos el paquete gráfico llamado Seaborn que nos permite trazar mapas de calor de la siguiente manera:<jupyter_code>import seaborn as sns

mapacolor = plt.cm.RdBu
plt.figure(figsize=(14,12))
plt.title('Correlación de las variables - Pearson', y=1.05, size=15)
sns.heatmap(train.astype(float).corr(),linewidths=0.1,vmax=1.0, 
            square=True, cmap=mapacolor, linecolor='white', annot=True)<jupyter_output><empty_output><jupyter_text>El gr&aacute;fico anterior, de Correlaci&oacute;n de Pearson, nos permite visualizar que no hay demasiadas caracter&iacute;sticas fuertemente correlacionadas entre s&iacute;. Esto es bueno desde el punto de vista que las variables de nuestro conjunto de datos (de train) no poseen mucha informaci&oacute;n redundante o poco relevante, sino datos unicos, entonces ser&aacute; un buen conjunto de entrenamiento para ser usado posteriormente en modelos de machine learning.  5. Representación de los resultados a partir de tablas y gráficas A continuación se visualiza graficamente los resultados obtenidos a partir del analisis individual y grupal de las variables anteriormente evaluadas.  1. Gráfico de Agrupamiento: Clase, Sexo y rango de Edad<jupyter_code>g = sns.factorplot(
    x='rangoEdad', 
    y='Survived', 
    col='Pclass',
    row='Sex',
    data=train,
    margin_titles=True, 
    kind="bar", 
    ci=None)<jupyter_output><empty_output><jupyter_text>Efectivamente, en las tres clases sobrevivieron m&aacute;s mujeres y ni&ntilde;os que adultos hombres.  2. Gráfico de Agrupamiento: Sexo y Tarifa Revisemos la tarifa promedio pagada por cada sexo:<jupyter_code>ax = tarifa_por_sexo.plot.bar(title='Tarifa Promedio y Sexo')
ax.set_ylabel('Tarifa Promedio')<jupyter_output><empty_output><jupyter_text>Efectivamente, se grafica que los pasajeros del sexo femenio (Sex = 0) pagaron una tarifa mayor que la de los hombres. El por que escapa al an&aacute;lisis de esta pr&aacute;ctica.  3. Gráfico de Agrupamiento: Clase, Sexo y Tarifa<jupyter_code>ax = tarifa_por_clase_sexo.plot.bar(figsize=(16,4), title='Tarifa Promedio por Clase y Sexo')
ax.set_ylabel('Tarifa Promedio')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09672240802675586, 'fraction_numerical': 0.0188628762541806, 'mean_word_length': 5.5471863367637395, 'pattern_counts': {'":': 0, '<': 139, '<?xml version=': 0, '>': 143, 'https://': 2, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '35', 'dir': 'jupyter-structured-clean-dedup', 'id': '661487', 'license': 'MIT', 'n_tokens_mistral': 10916, 'n_tokens_neox': 10491, 'n_words': 3378, 'path': 'code/preyespe_M2.851_20172-TITANIC.ipynb', 'repo_name': 'preyespe/Titanic-Data-Cleaning', 'size': '29908'}