Creo que este es el post que más me emociona escribir desde que tengo blog y desde que empecé en el mundo de la data. Y es que es el primer post donde les voy a compartir lo que he aprendido, a codear un poquito, a graficar otro poco y a usar comandos. Creo que es importante aclarar que estoy en un proceso de aprendizaje y si tienes alguna recomendación, tip para hacer mejor código, recursos donde pueda aprender mucho más, estaría muy agradecida con quien sea que quiera hacerlo. Aquí vamos.

El hundimiento del Titanic es uno de los naufragios más infames de la historia, El 15 de abril de 1912, durante su viaje inaugural, el ampliamente considerado “insumergible” RMS Titanic se hundió después de chocar con un iceberg. Desafortunadamente, no había suficientes botes salvavidas para todos a bordo, lo que resultó en la muerte de 1502 de 2224 pasajeros y tripulantes.

Si bien hubo algún elemento de suerte involucrado en la supervivencia, parece que algunos grupos de personas tenían más probabilidades de sobrevivir que otros.

Aquí, vamos a intentar visualizar data, predecir probabilidades de supervivencia, y a practicar lo que hemos aprendido

Para desarrollar este reto vamos a necesitar: 

  • Un poco de Python
  • Instalar las librerías pertinentes en Conda o miniconda (si no sabes como instalar, te dejo este post con comandos básicos en conda)
  • Jupyter Notebooks, lo super cool de usar jupyter es que permite integrar la programación con visualización. Así que tienes como un todo en uno
  • Pandas, librería en python para el análisis y manipulación de datos.
  • MatPlotLib, librería en python para gráficas en 2D
  • Seaborn, librería que facilita la visualización y proceso de generación de gráficos
  • Dataset de Titanic 

Te deje todo los links que necesitas para lograr este reto. 

  1. Lo primero es importar librerías a nuestro notebook con el lenguaje correcto
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

2. Importar el dataset correspondiente. 
Carguemos en un pandas dataframe nuestra base de datos

df = pd.read_csv('DS_Clase_05_titanic.csv')

3. Visualicemos de forma general la data que tenemos 

df.head(5)

Aquí podemos visualizar que columnas podemos encontrar en nuestro dataset, visualizar datos como por ejemplo que la columna Age contiene valores flotantes. 

4. ¿Tengo manera de saber cuántos registros(filas) tengo? ¡Claro que sí!

print(df.shape)
(891, 12)

Es decir, tiene 891 entradas y 14 features o variables.

5. Puedes notar que cuando pre-visualizas los datos, la columna Cabin tiene algunos valores en NaN, éste valor se traduce en python como un None y en humano como un valor nulo. Sería súper útil saber que registros por columna tienen datos valores nulos y en un sólo método puedes obtener esa cuenta.

print(df.count)

Otra forma de saber la cuenta de valores nulos, es contarlos por columna, ya que con el data.count() lo que estoy obteniendo en realidad es la cuenta de datos no-nulos y esto sale de iterar sobre una lista de columnas y preguntando a cada uno por el método isnull() y obteniendo la suma con sum()

col_names = df.columns.tolist()
for column in col_names:
print ("valores nulos en <{0}>: {1}".format(column, df[column].isnull().sum))

6. Ahora visualicemos solo las columnas 

df.columns
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
dtype='object')

7. Digamos que queremos visualizar una columna en especial, quiero ver solo los nombres de ciertos pasajeros ¿Cómo lo hacemos?

columna = df['Name'] 
columna.head()
0                              Braund, Mr. Owen Harris
1 Cumings, Mrs. John Bradley (Florence Briggs Th...
2 Heikkinen, Miss. Laina
3 Futrelle, Mrs. Jacques Heath (Lily May Peel)
4 Allen, Mr. William Henry
Name: Name, dtype: object

Ahora intentemos inspeccionar un poco nuestros datos: 

Podemos obtener información de los principales indicadores estadísticos sobre nuestro dataset en una sola línea 

df.describe

Puedes ver que para Fare, el mínimo valor es 0 ¿Eso quiere decir que hubo personas que viajaron gratis?

df.info()
# columnas númericas y columnas de texto
df.dtypes == float
df.dtypes == int
df.dtypes == object
num = (df.dtypes == float) | (df.dtypes == int)
num
num.index
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
dtype='object')

Ahora indiquemos cuantos nulos hay por cada variable (columna)

df.isnull().sum()
PassengerId      0
Survived 0
Pclass 0
Name 0
Sex 0
Age 177
SibSp 0
Parch 0
Ticket 0
Fare 0
Cabin 687
Embarked 2
dtype: int64

Usualmente cuando trabajamos con dataset , queremos hacer algún tipo de estandarización a los valores o darles algún formato en particular. Tomemos como ejemplo la columna Sex, que tiene como únicos valores male y female y se me ocurre querer reemplazarlo por M y F respectivamente. Una vez, invocando habilidades de programación podemos hacerlo con diccionarios y funciones lambda las cuales no siempre son tan fáciles de entender, pero espero que en el ejemplo no sea tan complicado de hacerlo.

#creamos un diccionario con los valores originales y los valores de reemplazo
a = {"male" : "M", "female" : "F"}
#utilizamos un lambda para el reemplazo
df["Sex"] = df["Sex"].apply(lambda x:a[x])
#verifiquemos que el cambio se haya hecho
df["Sex"].head()
.
.
0 M
1 F
2 F
3 F
4 M
Name: Sex, dtype: object

Vamos a ver una forma muy sencilla para acceder a las columnas que nos facilitará el trabajo

df.Sex

Algo también genial de pandas es que podemos hacer agrupaciones o tablas de referencia cruzada

¿Y es posible hacer agrupaciones por varias columnas? ¡Es posible! y súper fácil!

pclass_gender_survival_count_df = df.groupby(["Pclass", "Sex"])["Survived"].sum()
pclass_gender_survival_count_df
.
.
.
Pclass Sex
1 F 91
M 45
2 F 70
M 17
3 F 72
M 47
Name: Survived, dtype: int64

Ahora que hemos mucho código raro, Vamos a visualizar con esos gráficos lindos que nos gustan

Primero vamos a realizar un gráfico donde se puedan observar las relaciones entre variables y sus histogramas

sns.pairplot(df)

Para este ejemplo te recomiendo que corras tu propio código y asi visualices mejor las gráficas y saques tus propias conclusiones

Ahora vamos a responder ciertas preguntas 

¿Cúantas personas sobrevivieron al desastre del Titanic? (Además de Rose)

Lo primero es determinar el tamaño del canvas(área de dibujo) para las gráficas; para el ejemplo agregué el subplot2grid para poder tener los gráficos uno al lado del otro

fig = plt.figure(figsize=(30,10)) #creamos un canva o figura de 30X10 pixeles
#Yo quiero ver un plot al costado del otro
plt.subplot2grid((2,3),(0,0))
df.Survived.value_counts().plot(kind="bar", alpha=0.5)
plt.title("sobrevivieron - cuenta total -")
#hay maneras un poco más amigables de interpretar datos, con porcentajes
plt.subplot2grid((2,3),(0,0))
df.Survived.value_counts(normalize = True).plot(kind="bar", alpha=0.5)
plt.title("sobrevivieron - cuenta total -")
plt.show()

Este código se ve un poco raro, así que me parece pertinente dejarte la imagen del código en mi notebook para que lo visualicen un poco mejor

La gráfica izquierda muestra los sobrevivientes en número mientras que la de la derecha los muestra en porcentajes. Menos del 40% de nuestro dataset sobrevivió. 

Ahora ¿Quiénes sobrevivieron más, los hombres o las mujeres?

Podemos filtrar por sobrevivencia data.Sex[data.Survived == 1]

fig = plt.figure(figsize=(30,10))
df.Sex[df.Survived == 1].value_counts(normalize = True).plot(kind="barh", alpha=0.5)
plt.title("sobrevivientes - Male VS female")
plt.show()

Podemos ver que en nuestro dataset la mayoría de sobrevivientes fueron mujeres

En este ejemplo quiero mostrar la diferencia de hacer el gráfico (con algunos cambios pequeños ) en seaborn 

sns.countplot(x='Sex', hue='Survived', data=df)
plt.title('Supervivencia desagregada por genero')
plt.show()

¿El tipo de tiquete (clase de cabina) influyó en la supervivencia de los pasajeros?

fig = plt.figure(figsize=(10,5))
#colors ``
df.Pclass[df.Survived == 1].value_counts(normalize = True).plot(kind="barh", alpha=0.5)
plt.title("Sobrevivientes por clase de ticket")
plt.show()
Resulta interesante que quienes tenían un tiquete de clase intermedia tuvieron poca chance de sobrevivir

Ejercicio: ¿Cómo harías este gráfico en seaborn?

Juguemos un poco con las edades

Algo que se podría inferir en relación a edad-economía es que probablemente las personas más jóvenes tenían menos dinero y por ende compraron los tiquetes más baratos.

Ésto lo podemos ver con un gráfica de densidad, otro tipo (kind) de gráfica disponible en matplotlib

fig = plt.figure(figsize=(20,10))
for t_class in [1,2,3]:
df.Age[df.Pclass == t_class].plot(kind="kde")

plt.legend({"primera clase", "segunda clase", "tercera clase"})
plt.show()

¿Qué podemos deducir de la gráfica?

Si vemos la línea azul(tercera clase) vemos que el promedio de edad es cerca de los 20 años y en primera (naranja) el promedio de edad es 40, lo que muestra una relación entre edad-economía

Ahora veamos la distribución de edades separadas por género de los pasajeros del Titanic

edad_hombres = df.Age[df.Sex == 'male']
edad_mujeres = df.Age[df.Sex == 'female']
edad_hombres.hist(bins = np.arange(0,80,5),label = 'Hombres', alpha = 0.5)
edad_mujeres.hist(bins = np.arange(0,80,5),label = 'Mujeres', alpha = 0.5)
plt.title('Distribución de edades separadas por género de los pasajeros del Titanic')
plt.xlabel('Edad')
plt.legend()
plt.show()

Hasta casi los 20 años la diferencia de cantidad entre hombres y mujeres es muy poca. Lo segundo que podemos hacer es separar, dentro de la gente que sobrevivió, el histograma por género. ¿Para qué hacemos eso? Si tenemos evidencia de que las mujeres tenían mayor probabilidad de supervivencia que los hombres, tal vez esta tendencia no sea tan clara en los rangos etarios más bajos. Esto se va a entender mejor una vez que tengamos el gráfico hecho.

edad_survived = df.Age[survived_bool]
edad_survived[df.Sex == 'male'].hist(bins = np.arange(0,80,5),label = 'Hombres', alpha = 0.75)
edad_survived[df.Sex == 'female'].hist(bins = np.arange(0,80,5),label = 'Mujeres', alpha = 0.5)
plt.title('Distribución de edades dentro de las personas que sobrevivieron separadas por género')
plt.xlabel('Edad')
plt.legend()
plt.show()

Notar que en todos los rangos de edad sobrevivieron más mujeres que hombres, excepto en los dos primeros, donde sobrevivieron más niños que niñas.

Ahora observemos la Distribución de pasajeros por clases de forma un poco diferente

sns.countplot(x="Pclass", data=df)
plt.show()

Conclusiones: 

  1. Las mujeres tenían una mayor probabilidad de supervivencia. ¿Por qué? Porque si bien entre los pasajeros había más hombres que mujeres, dentro de los que sobrevivieron hay más mujeres que hombres, con una diferencia que parece ser significativa.
  2. Los bebes y niños tenían una probabilidad de supervivencia más grande que el resto de los grupos etarios. Acá la cosa se complicó un poco, pero repasemos qué nos lleva a concluir eso:
  3. En todos los rangos de edades la cantidad de gente que sobrevivió es menor que la que no, salvo en el rango 0–12. Esto no se debe a que en ese rango de edades haya habido una mayoría de mujeres.
  4. Es el único rango de edades donde sobrevivieron más hombres que mujeres.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *