Introducción

En esta actividad realizaremos el análisis exploratorio y el preproceso del conjunto de datos Titanic (archivo titanic_dataset.xlsx), que contiene información de pasajeros/as del RMS Titanic. El objetivo es preparar los datos para posteriores análisis estadísticos.

1. Fichero de datos

Pregunta: Cargad el fichero titanic_dataset.xlsx, examinad el tipo de datos y verificad la consistencia del identificador único.

# Cargar los datos
titanic <- read_excel("titanic_dataset.xlsx")

# Examinar los tipos de datos iniciales
str(titanic)
## tibble [1,309 × 12] (S3: tbl_df/tbl/data.frame)
##  $ PassengerId: num [1:1309] 1 2 3 4 5 6 7 8 9 10 ...
##  $ Survived   : num [1:1309] 0 1 1 1 0 0 0 0 1 1 ...
##  $ Pclass     : num [1:1309] 3 1 3 1 3 3 1 3 3 2 ...
##  $ Name       : chr [1:1309] "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
##  $ Sex        : chr [1:1309] "male" "female" "female" "female" ...
##  $ Age        : num [1:1309] 22 38 26 35 35 NA 54 2 27 14 ...
##  $ SibSp      : num [1:1309] 1 1 0 1 0 0 0 3 0 1 ...
##  $ Parch      : num [1:1309] 0 0 0 0 0 0 0 1 2 0 ...
##  $ Ticket     : chr [1:1309] "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...
##  $ Fare       : chr [1:1309] "7.25" "71.2833" "7.925" "53.1" ...
##  $ Cabin      : chr [1:1309] NA "C85" NA "C123" ...
##  $ Embarked   : chr [1:1309] "S" "C" "S" "S" ...
# Verificar identificador único
duplicados <- titanic %>% filter(duplicated(PassengerId))

Explicación: Se ha cargado el archivo. Si el número de filas de duplicados es 0, significa que el identificador de pasajero es único, cumpliendo el criterio de normalización. En caso de haber duplicados exactos, se eliminarían con la función distinct().

2. Variables cuantitativas

En este apartado revisamos las variables cuantitativas, corrigiendo formatos y valores perdidos. Los valores perdidos o erróneos se sustituirán por NA.

2.1. Age

Pregunta: La variable Age debe ser de tipo cuantitativa discreta (entero).

titanic <- titanic %>%
  mutate(Age = as.integer(Age))

head(titanic$Age)
## [1] 22 38 26 35 35 NA

2.2 y 2.3. SibSp y Parch

Pregunta: Las variables SibSp y Parch deben ser de tipo numérico.

titanic <- titanic %>%
  mutate(
    SibSp = as.numeric(SibSp),
    Parch = as.numeric(Parch)
  )

2.4. Fare

Pregunta: La variable Fare debe ser de tipo numérico continuo y redondearse a dos decimales.

titanic <- titanic %>%
  mutate(
    Fare = as.numeric(gsub(",", ".", Fare)), # Asegurar punto como separador
    Fare = round(Fare, 2)
  )
head(titanic$Fare)
## [1]  7.25 71.28  7.92 53.10  8.05  8.46

2.5. Family size

Pregunta: Cread una variable FamS (FamilySize) que contenga el total de SibSp y Parch (+1) y mostrad su distribución gráficamente.

titanic <- titanic %>%
  mutate(FamS = SibSp + Parch + 1)

ggplot(titanic, aes(x = FamS)) +
  geom_histogram(binwidth = 1, fill = "steelblue", color = "black") +
  theme_minimal() +
  labs(title = "Distribución del Tamaño Familiar (FamS)", x = "Tamaño Familiar", y = "Frecuencia")

3. Variables categóricas

3.1. Survived

Pregunta: Transformar a Yes/No en lugar de 1/0.

titanic <- titanic %>%
  mutate(Survived = factor(ifelse(Survived == 1, "Yes", "No")))

3.2. Pclass

Pregunta: La variable Pclass debe ser de tipo ordinal.

titanic <- titanic %>%
  mutate(Pclass = factor(Pclass, levels = c(1, 2, 3), ordered = TRUE))

3.3. Sex

Pregunta: Tipo categórico con valores “Female”, “Male”.

titanic <- titanic %>%
  mutate(
    Sex = str_to_title(Sex), # Asegura que empiece en mayúscula
    Sex = factor(Sex, levels = c("Female", "Male"))
  )

3.4. Embarked

Pregunta: Debe contener el nombre completo: Cherbourg (C)/Queenstown (Q)/Southampton (S).

titanic <- titanic %>%
  mutate(Embarked = case_when(
    Embarked == "C" ~ "Cherbourg (C)",
    Embarked == "Q" ~ "Queenstown (Q)",
    Embarked == "S" ~ "Southampton (S)",
    TRUE ~ as.character(Embarked)
  )) %>%
  mutate(Embarked = factor(Embarked))

4. Variables de tipo texto

Pregunta: Variables Name, Ticket y Cabin. Eliminar espacios al inicio y final.

titanic <- titanic %>%
  mutate(across(c(Name, Ticket, Cabin), str_trim))

5. Valores extremos

5.1. Age

Pregunta: Visualizad la distribución de Age. Identificad posibles valores extremos e interpretad.

ggplot(titanic, aes(y = Age)) +
  geom_boxplot(fill = "lightblue") +
  theme_minimal() +
  labs(title = "Boxplot de Edad")

Explicación: Se observan valores por encima de los 65-70 años. En el contexto del Titanic, estos valores son plausibles (pasajeros ancianos), por lo que se consideran extremos biológicamente posibles, no errores. No se sustituyen por NA salvo que hubiese edades negativas o imposibles.

5.2. Tarifa (Fare)

Pregunta: Revisad outliers. Mostrad pasajeros con las 10 tarifas más altas.

ggplot(titanic, aes(y = Fare)) +
  geom_boxplot(fill = "lightgreen") +
  theme_minimal() +
  labs(title = "Boxplot de Tarifas (Fare)")

# 10 tarifas más altas
titanic %>%
  arrange(desc(Fare)) %>%
  select(Name, Pclass, Fare) %>%
  head(10) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover"))
Name Pclass Fare
Ward, Miss. Anna 1 512.33
Cardeza, Mr. Thomas Drake Martinez 1 512.33
Lesurer, Mr. Gustave J 1 512.33
Cardeza, Mrs. James Warburton Martinez (Charlotte Wardle Drake) 1 512.33
Fortune, Mr. Charles Alexander 1 263.00
Fortune, Miss. Mabel Helen 1 263.00
Fortune, Miss. Alice Elizabeth 1 263.00
Fortune, Mr. Mark 1 263.00
Fortune, Miss. Ethel Flora 1 263.00
Fortune, Mrs. Mark (Mary McDougald) 1 263.00

Explicación: Hay valores atípicos muy elevados. Dado que los billetes de primera clase podían ser extremadamente caros y a menudo comprados para familias enteras bajo un mismo billete, no se tratan de errores de digitación, sino de extremos reales.

6. Correlaciones

6.1 y 6.2. Matriz y variables más correlacionadas

Pregunta: Calculad matriz de correlaciones entre variables cuantitativas (incluyendo FamS y Survived numérico) y mostrad las más correlacionadas con supervivencia.

# Preparar datos numéricos
datos_cor <- titanic %>%
  mutate(Survived_num = ifelse(Survived == "Yes", 1, 0)) %>%
  select(Age, SibSp, Parch, Fare, FamS, Survived_num) %>%
  na.omit()

matriz_cor <- cor(datos_cor)
corrplot(matriz_cor, method = "circle", type = "upper")

# Variables más correlacionadas con Survived
cor_surv <- as.data.frame(matriz_cor) %>%
  select(Survived_num) %>%
  arrange(desc(abs(Survived_num)))

cor_surv %>% kable() %>% kable_styling()
Survived_num
Survived_num 1.0000000
Fare 0.2406628
Parch 0.1157049
FamS 0.0741649
Age -0.0519486
SibSp 0.0115932

7. Imputación

Pregunta: Imputad Age usando kNN (VIM), predictores numéricos/ordinales, vecinos = 5.

titanic_imp <- kNN(titanic, variable = "Age", 
                   dist_var = c("Pclass", "SibSp", "Parch", "Fare", "FamS"), 
                   k = 5, imp_var = FALSE)

# Mostrar algunos valores imputados
titanic_imp %>% select(PassengerId, Age) %>% head() %>% kable() %>% kable_styling()
PassengerId Age
1 22
2 38
3 26
4 35
5 35
6 21

8. Tabla resumen

Pregunta: Calculad medidas de tendencia central y dispersión y presentad dos tablas agrupadas por Pclass y Sex. Guardad en titanic_dataset_clean.xlsx.

# Tabla resumen de tendencia central y dispersión agrupada
tabla_resumen <- titanic_imp %>%
  group_by(Pclass, Sex) %>%
  summarise(
    Age_Mean = round(mean(Age, na.rm = TRUE), 2),
    Age_Median = median(Age, na.rm = TRUE),
    Age_SD = round(sd(Age, na.rm = TRUE), 2),
    Age_MAD = mad(Age, na.rm = TRUE),
    Fare_Mean = round(mean(Fare, na.rm = TRUE), 2),
    Fare_Median = median(Fare, na.rm = TRUE),
    Fare_SD = round(sd(Fare, na.rm = TRUE), 2),
    Fare_MAD = mad(Fare, na.rm = TRUE),
    .groups = "drop"
  )

# Mostrar la tabla formateada
tabla_resumen %>% kable() %>% kable_styling()
Pclass Sex Age_Mean Age_Median Age_SD Age_MAD Fare_Mean Fare_Median Fare_SD Fare_MAD
1 Female 36.44 35.5 13.53 17.0499 110.03 82.015 83.29 44.989497
1 Male 41.42 42.0 13.63 11.8608 70.28 49.750 74.10 34.396320
1 NA 54.00 47.0 19.47 11.8608 43.80 52.550 40.15 38.992380
2 Female 28.16 28.0 14.15 10.3782 23.33 23.000 11.25 10.748850
2 Male 32.41 30.0 15.41 11.8608 19.91 13.000 14.78 3.706500
2 NA 32.00 32.0 NA 0.0000 13.00 13.000 NA 0.000000
3 Female 23.89 23.0 12.64 10.3782 15.44 11.130 11.83 5.011188
3 Male 26.58 25.0 11.30 8.1543 12.33 7.900 11.01 0.963690
3 NA 31.00 31.0 10.89 13.3434 20.52 8.660 27.41 0.934038
NA Female 29.50 29.5 21.92 22.9803 7.54 7.535 0.45 0.467019
NA Male 25.00 25.0 NA 0.0000 7.05 7.050 NA 0.000000
# Guardar el fichero preprocesado
write_xlsx(titanic_imp, "titanic_dataset_clean.xlsx")