Introduction:

Research Question: How do passengers class, sex, age, and fare affect the probability of survival on the titanic

My protect is focused on using the logistic regression to examine if sex, age, class, and fare are related to the probability of survival. The data set I will be using contains 891 observations and 12 variables. In the data set each observation represents one passenger on the titanic. The variables contain the passengers name, survival, sex, cabin, ticket information, family members aboard, class, port of embarkation, age, Fare, Porch. I will only be using five of these variables. Since we only have two possible outcomes for survival, logistic regression is the best choice for my analysis. The data set is from the data set link in our blackboard classroom. It is fount in the GitHub free repository (Titanic.csv). https://github.com/awesomedata/awesome-public-datasets/blob/master/Datasets/titanic.csv.zip

library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.2.1     ✔ readr     2.2.0
## ✔ forcats   1.0.1     ✔ stringr   1.6.0
## ✔ ggplot2   4.0.3     ✔ tibble    3.3.1
## ✔ lubridate 1.9.5     ✔ tidyr     1.3.2
## ✔ purrr     1.2.2     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
titanic <- read_csv("titanic.csv")
## Rows: 891 Columns: 12
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): Name, Sex, Ticket, Cabin, Embarked
## dbl (7): PassengerId, Survived, Pclass, Age, SibSp, Parch, Fare
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
dim(titanic)
## [1] 891  12
head(Titanic)
## , , Age = Child, Survived = No
## 
##       Sex
## Class  Male Female
##   1st     0      0
##   2nd     0      0
##   3rd    35     17
##   Crew    0      0
## 
## , , Age = Adult, Survived = No
## 
##       Sex
## Class  Male Female
##   1st   118      4
##   2nd   154     13
##   3rd   387     89
##   Crew  670      3
## 
## , , Age = Child, Survived = Yes
## 
##       Sex
## Class  Male Female
##   1st     5      1
##   2nd    11     13
##   3rd    13     14
##   Crew    0      0
## 
## , , Age = Adult, Survived = Yes
## 
##       Sex
## Class  Male Female
##   1st    57    140
##   2nd    14     80
##   3rd    75     76
##   Crew  192     20

Data Analysis:

Since my Analysis focuses on survival, class, age, sex, and fare I will clean the Date to focus on these variables. To clean the data removing the missing observations in the age variable since it is on of the predictors I will use. I will explore the data to take a look at the distribution of the variables and the relationship between passenger characteristics and survival. Since I will not need all 12 variables, I will create a separate data set called titanic_clean. It will only contain the variables I will be needing in this project. I will also create two plots to see the relationships between survival, sex, and class. This is to help me understand the data more before creating the model.

colSums(is.na(titanic))
## PassengerId    Survived      Pclass        Name         Sex         Age 
##           0           0           0           0           0         177 
##       SibSp       Parch      Ticket        Fare       Cabin    Embarked 
##           0           0           0           0         687           2
library(dplyr)

titanic_clean <- titanic |>
  
  select(Survived, Pclass, Sex, Age, Fare) |>
  
  filter(!is.na(Age))
summary(titanic_clean)
##     Survived          Pclass             Sex           Age       
##  Min.   :0.0000   Min.   :1.000   Length   :714   Min.   : 0.42  
##  1st Qu.:0.0000   1st Qu.:1.000   N.unique :  2   1st Qu.:20.12  
##  Median :0.0000   Median :2.000   N.blank  :  0   Median :28.00  
##  Mean   :0.4062   Mean   :2.237   Min.nchar:  4   Mean   :29.70  
##  3rd Qu.:1.0000   3rd Qu.:3.000   Max.nchar:  6   3rd Qu.:38.00  
##  Max.   :1.0000   Max.   :3.000                   Max.   :80.00  
##       Fare       
##  Min.   :  0.00  
##  1st Qu.:  8.05  
##  Median : 15.74  
##  Mean   : 34.69  
##  3rd Qu.: 33.38  
##  Max.   :512.33
dim(titanic_clean)
## [1] 714   5
ggplot(
  titanic_clean, aes(
  x = Sex, 
  fill = factor(Survived))) +
  geom_bar() +
  labs(
  title = "Survival by Sex",
  x = "Sex",
  fill = "Survived"
  )

ggplot(
  titanic_clean, aes(
  x = factor(Pclass), 
  fill = factor(Survived))) +
  geom_bar() +
  labs(
  title = "Survival by Passenger Class", x = "Passenger Class",
  fill = "Survived"
  )

Regression Analysis:

For my final model I will perform my a logistic regression analysis to see the relationship between passengers charecteristics and survival. To perform my regression model I will use the glm(family = binomial). The predictors in my model are sex, age, fare, and class. I chose these because they provide information about the passengers and can help examine factors associated with survival. After removing the missing observations of a age the model is based on 714 observations. The results of my regression analysis show that class, sex, and age were statistically significant predictors of survival while fare was not significant. Compared with first class passengers, second class passengers had an odds ration of 0.279 approximately 72.1% lower oddss of survival. Third class passengers had and odds ratio of 0.079, so they had approximately 92.1% lower odds of survival compared with first class. The odds ratio for male passengers was 0.081, this means males had approximately 91.9% lower odds of survival than females. Age has an odds ratio of 0.964, meaning that each additional year of age was associated with close to a 3.6% decrease in odds of survival. Fare was not statistically significant because the odds ratio for fare was 1.001 and its p-value was 0.817 this shows that there was not enough evidence to associate fare with passengers survival.

model <- glm(
  Survived ~ factor(Pclass) + Sex + Age + Fare,
  data = titanic_clean,
  family = binomial
)

summary(model)
## 
## Call:
## glm(formula = Survived ~ factor(Pclass) + Sex + Age + Fare, family = binomial, 
##     data = titanic_clean)
## 
## Coefficients:
##                   Estimate Std. Error z value Pr(>|z|)    
## (Intercept)      3.7225052  0.4645113   8.014 1.11e-15 ***
## factor(Pclass)2 -1.2765903  0.3126370  -4.083 4.44e-05 ***
## factor(Pclass)3 -2.5415762  0.3277677  -7.754 8.89e-15 ***
## Sexmale         -2.5185052  0.2082017 -12.096  < 2e-16 ***
## Age             -0.0367302  0.0077325  -4.750 2.03e-06 ***
## Fare             0.0005226  0.0022579   0.231    0.817    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 964.52  on 713  degrees of freedom
## Residual deviance: 647.23  on 708  degrees of freedom
## AIC: 659.23
## 
## Number of Fisher Scoring iterations: 5
exp(coef(model))
##     (Intercept) factor(Pclass)2 factor(Pclass)3         Sexmale             Age 
##     41.36790090      0.27898693      0.07874218      0.08057997      0.96393620 
##            Fare 
##      1.00052269
confint(model)
## Waiting for profiling to be done...
##                        2.5 %       97.5 %
## (Intercept)      2.829632469  4.654812846
## factor(Pclass)2 -1.896680560 -0.668915245
## factor(Pclass)3 -3.195813717 -1.907866245
## Sexmale         -2.935909527 -2.118633355
## Age             -0.052183279 -0.021826170
## Fare            -0.003872481  0.005255922
exp(confint(model))
## Waiting for profiling to be done...
##                       2.5 %      97.5 %
## (Intercept)     16.93923399 105.0895502
## factor(Pclass)2  0.15006593   0.5122640
## factor(Pclass)3  0.04093320   0.1483967
## Sexmale          0.05308242   0.1201958
## Age              0.94915489   0.9784103
## Fare             0.99613501   1.0052698

Diagnostic:

Since I used the logistic regression to do my model, it was evaluated using a confusion matrix, accuracy sensitivity, specificity, and a ROC curve. I sued a probability threshold of 0.50 to classify each passenger as predicted to survive or predicted not to survive. The confusion matrix compares the survival outcomes with outcome predicted by my model.The model had an accuracy of 0.79, meaning that approximately 79% of the passengers were classified correctly. The sensitivity was 0.72, this measures how well the model identifies passengers did survive. The specificity was 0.84 this measures how well the model identified the passengers who did not survive. The graph had an AUC of 0.85 since it is close to 1 it indicates better classification performance.

probability <- predict(model, type = "response")

head(probability)
##          1          2          3          4          5          6 
## 0.10509514 0.91404126 0.55726903 0.92162960 0.06793029 0.32031425
predicted <- ifelse(probability >= 0.5, 1, 0)

head(predicted)
## 1 2 3 4 5 6 
## 0 1 1 1 0 0
confusion <- table(
  Actual = titanic_clean$Survived,
  Predicted = predicted
)

confusion
##       Predicted
## Actual   0   1
##      0 357  67
##      1  81 209
accuracy <- sum(diag(confusion)) / sum(confusion)

sensitivity <- confusion[2,2] / sum(confusion[2,])

specificity <- confusion[1,1] / sum(confusion[1,])

accuracy
## [1] 0.7927171
sensitivity
## [1] 0.7206897
specificity
## [1] 0.8419811
library(pROC)
## Type 'citation("pROC")' for a citation.
## 
## Attaching package: 'pROC'
## The following objects are masked from 'package:stats':
## 
##     cov, smooth, var
roc_curve <- roc(
  titanic_clean$Survived,
  probability
)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
plot(
  roc_curve,
  main = "ROC Curve for Titanic Survival Model"
)

auc(roc_curve)
## Area under the curve: 0.8522

Conclusion:

My project was created to show how passenger class, sex, age, and fare were associated with the probability of survival on the Titanic. I used a logistic regression model was because survival was a binary outcome. The results showed that passenger class, sex, and age were statistically significant predictors of survival, while fare was not statistically significant. Compared with first-class passengers, second-class passengers had approximately 72.1% lower odds of survival, while third-class passengers had approximately 92.1% lower odds of survival. Male passengers had approximately 91.9% lower odds of survival than female passengers. In addition, each one-year increase in age was associated with approximately a 3.6% decrease in the odds of survival.

The model diagnostics provide additional information about how well the model predicted survival. The confusion matrix, accuracy, sensitivity, specificity, and AUC were used to evaluate the model’s classification performance. a. One limitation is that some factors that may have influenced survival were not included in the model. Future research could include additional variables or examine interactions between passenger characteristics.

References:

Awesome Public Datasets. (n.d.). Titanic dataset. GitHub. https://github.com/awesomedata/awesome-public-datasets/tree/master/Datasets

R Core Team. (2026). R: A language and environment for statistical computing. R Foundation for Statistical Computing.