Сегодня мы работаем с набором данных “Титаник”. Это данные реальных людей, которые путешествовали на “Титанике”, некоторая информация о них, а так же выжили они или нет в результате крушения. Мы загрузим данные, исследуем их, попытаемся предсказать какие переменные влияют на шансы выжить.
Мы возьмем эти данные из специального модуля.
install.packages('titanic')
С остальными библиотеками мы уже знакомы, загрузим все.
library('dplyr')
library('titanic')
library('ggplot2')
library('psych')
Загрузим данные. В библиотеке данные разбиты на две подвыборки, потому что он часто используется для машинного обучения. Мы будем работать с titanic_train.
data("titanic_train")
head(titanic_train)
## PassengerId Survived Pclass
## 1 1 0 3
## 2 2 1 1
## 3 3 1 3
## 4 4 1 1
## 5 5 0 3
## 6 6 0 3
## Name Sex Age SibSp
## 1 Braund, Mr. Owen Harris male 22 1
## 2 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female 38 1
## 3 Heikkinen, Miss. Laina female 26 0
## 4 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1
## 5 Allen, Mr. William Henry male 35 0
## 6 Moran, Mr. James male NA 0
## Parch Ticket Fare Cabin Embarked
## 1 0 A/5 21171 7.2500 S
## 2 0 PC 17599 71.2833 C85 C
## 3 0 STON/O2. 3101282 7.9250 S
## 4 0 113803 53.1000 C123 S
## 5 0 373450 8.0500 S
## 6 0 330877 8.4583 Q
Посмотрим на переменные. По описанию переменных и данным в них, опишите их тип (количественные, категориальные, порядковые, бинарные).
?titanic_train
## starting httpd help server ... done
str(titanic_train)
## 'data.frame': 891 obs. of 12 variables:
## $ PassengerId: int 1 2 3 4 5 6 7 8 9 10 ...
## $ Survived : int 0 1 1 1 0 0 0 0 1 1 ...
## $ Pclass : int 3 1 3 1 3 3 1 3 3 2 ...
## $ Name : chr "Braund, Mr. Owen Harris" "Cumings, Mrs. John Bradley (Florence Briggs Thayer)" "Heikkinen, Miss. Laina" "Futrelle, Mrs. Jacques Heath (Lily May Peel)" ...
## $ Sex : chr "male" "female" "female" "female" ...
## $ Age : num 22 38 26 35 35 NA 54 2 27 14 ...
## $ SibSp : int 1 1 0 1 0 0 0 3 0 1 ...
## $ Parch : int 0 0 0 0 0 0 0 1 2 0 ...
## $ Ticket : chr "A/5 21171" "PC 17599" "STON/O2. 3101282" "113803" ...
## $ Fare : num 7.25 71.28 7.92 53.1 8.05 ...
## $ Cabin : chr "" "C85" "" "C123" ...
## $ Embarked : chr "S" "C" "S" "S" ...
Сегодня мы попробуем построить самые простые гипотезы и протестировать их. Мы будем пытаться предсказать переменную Survived (выжил пассажир или нет в результате крушения).
Впервую очередь мы хотим посмотреть, как наша зависимая переменная (та, которую мы хотим предсказать) распределена в наборе данных.
table(titanic_train$Survived)
##
## 0 1
## 549 342
Мы даже можем посмотреть на эти данные как на части целого (proportion.)
prop.table(table(titanic_train$Survived))
##
## 0 1
## 0.6161616 0.3838384
Давайте построим график.
ggplot(titanic_train, aes(x = Survived)) +
geom_bar()
В социальных науках мы стараемся строить гипотезы, основываясь на теории и информации о зависимостях в данных. Самые лучшие предсказательные модели для “Титаника” строят люди, которые проводят расследования вплоть до того, на какой палубле размещались каюты с определенными номерами и как это влияет на шансы выжить.
Если вдруг вы помните, то на “Титанике” оперировали правилом “первыми - женщины и дети”. Давайте посмотрим, как эти переменные связаны с нашей зависимой.
titanic_train$Sex <- as.factor(titanic_train$Sex)
summary(titanic_train$Sex)
## female male
## 314 577
Какой самый простой способ посмотреть на то, как пол связан с зависимой переменной?
prop.table(table(titanic_train$Sex, titanic_train$Survived))
##
## 0 1
## female 0.09090909 0.26150393
## male 0.52525253 0.12233446
Такой вариант, к сожалению, не очень информативен, потому что дает нам пропорцию в КАЖДОЙ ячейке нашей таблицы 2x2, а нам нужна разбивка по рядам. Сделать это можно так:
# если мы заменим 1 на 2, то получим proportion table по колонкам
prop.table(table(titanic_train$Sex, titanic_train$Survived), 1)
##
## 0 1
## female 0.2579618 0.7420382
## male 0.8110919 0.1889081
Давайте посмотрим на распределение на графике.
ggplot(subset(titanic_train, Survived == 0), aes(x = Sex)) +
geom_bar()
ggplot(subset(titanic_train, Survived == 1), aes(x = Sex)) +
geom_bar(aes(fill = Sex))
И правда, видим, что действительно есть обратная зависимость между полом и шансом выжить. Давайте сформулируем первую гипотезу: Тот факт, что пассажир женского пола, повышает его шансы выжить при крушении
Перед тем как перейти ко второй половине теории “первыми - женщины и дети” давайте подумаем, не можем ли мы в наших данных выделить дополнительный признак, на основе которого тоже можно будет делать предсказания/работать с другими переменными.
Да, мы видим, что в каждом имени у нас “зашит” титул, из которого мы тоже можем вычленить некоторую информацию (возраст, статусность, принадлежность к аристократии).
Подумайте, по какому признаку мы могли вычленить титул в отдельную переменную.
titanic_train$Name[1]
## [1] "Braund, Mr. Owen Harris"
Можем воспользоваться функцией strsplit, которая разбивает строковую переменную на части.
# в параметре split в квадратных скобках указываем знаки, по которым хотим разбить
strsplit(titanic_train$Name[1], split = '[,.]')
## [[1]]
## [1] "Braund" " Mr" " Owen Harris"
Убедимся, что вся эта история возвращает нам контэйнер [[1]] с несколькими элементами внутри.
strsplit(titanic_train$Name[1], split = '[,.]')[[1]][2]
## [1] " Mr"
Отлично! Давайте создадим новую переменную Title и применим эту функцию ко всем рядам внтури c помощью функции sapply. Она работает как цикл for - проходит по всем рядам и применяет заданную функцию. в аргументе FUN мы задаем, какую функцию мы хотим использовать. Если это не встроенная функция, то пишем ее сами по синтаксису циклов.
titanic_train$Title <- sapply(titanic_train$Name, FUN=function(x) {strsplit(x, split='[,.]')[[1]][2]})
table(titanic_train$Title)
##
## Capt Col Don Dr Jonkheer
## 1 2 1 7 1
## Lady Major Master Miss Mlle
## 1 2 40 182 2
## Mme Mr Mrs Ms Rev
## 1 517 125 1 6
## Sir the Countess
## 1 1
Еще, если посмотрит выше на нашего ‘Mr’, то увидим, что в титуле был пробел. Давайте удалим все затесавшиеся пробелы в начале и конце строк, иначе нам потом будет сложно фильтровать. Функция sub находит заданные символы (пробелы " “) и заменяет их на отсуттвие символов (”“) в нашем случае.
titanic_train$Title <- sub(' ', '', titanic_train$Title)
Теперь давайте подумаем о наших титулах с точки зрения предсказательной важности. У нас есть достаточно редкие категории, которые встречаются один или всего несколько раз. Нужно ли их сохранять? Нужно ли укрупнить категории? Нет точного ответа, сколько категорий - хорошо. Но лучше ориентироваться не больше, чем на 5-6 категорий, по которым равномерно распределены наши наблюдения. Пока давайте избавимся от совсем избыточных категорий.
Какие встречаются совсем редко?
‘Capt’, ‘Don’, ‘Major’, ‘Sir’ встречаются редко и все они вцелом значат, что носитель титула - крупный землевладелец. ‘Dona’, ‘Lady’, ‘the Countess’, ‘Jonkheer’ - то же самое, но для женщин. Давайте объединим этим категории. Mme и Mlle (madame и mademoiselle) - титулы французской аристократии, давайте их тоже объединим. Для фильтрации наших векторов воспользуемся %in% - благодаря этому оператору R сравнивает значение в нужном ряду нужной колонке с рядом значений в векторе и, если условие выполняется, присваивает новое значение переменной (похоже по принципу на конструкцию if else).
titanic_train$Title[titanic_train$Title %in% c('Capt', 'Don', 'Major', 'Sir')] <- 'Sir'
titanic_train$Title[titanic_train$Title %in% c('Lady', 'the Countess', 'Jonkheer')] <- 'Lady'
titanic_train$Title[titanic_train$Title %in% c('Mlle', 'Mme')] <- 'Mlle'
table(titanic_train$Title)
##
## Col Dr Lady Master Miss Mlle Mr Mrs Ms Rev
## 2 7 3 40 182 3 517 125 1 6
## Sir
## 5
Пока оставим так, потому что в основном будем использовать эти титулы для заполнения пропусков в переменной возраст. Преобразуем в категориальную переменную.
titanic_train$Title <- as.factor(titanic_train$Title)
Хорошо, кажется теория с “первыми - женщины и дети” наполовину подтвердилась. Давайте разбираться с возрастом. Это у нас количественная переменная, можем посмотреть ее дискриптивные статитистики.
summary(titanic_train$Age)
## Min. 1st Qu. Median Mean 3rd Qu. Max. NA's
## 0.42 20.12 28.00 29.70 38.00 80.00 177
Ого! 177 пропущенных значений. Давайте подумаем, что с этим можно сделать? Какие стратегии вы предложите? (Хорошие статьи по стратегиям работы с пропущенными значениями: https://r-analytics.blogspot.com/2017/01/blog-post.html#.XAV41WgzZRY https://medium.com/coinmonks/dealing-with-missing-data-using-r-3ae428da2d17)
Выше мы выделили новый признак. Давайте посмотрим связан ли титул с возрастом.
ggplot(titanic_train, aes(x = Title, y = Age)) +
geom_boxplot()
## Warning: Removed 177 rows containing non-finite values (stat_boxplot).
Видим, что медианы групп разнятся. Давайте попробуем заполнить пропущенные значения на основании медианы для каждого титула (т.е. будем смотреть титул пассажира, возраст которого мы не знаем, и подставлять ему значения медианы его или ее группы).
Посмотрим, как остутствующие значения распределены по группам.
table(subset(titanic_train, is.na(Age))$Title)
##
## Col Dr Lady Master Miss Mlle Mr Mrs Ms Rev
## 0 1 0 4 36 0 119 17 0 0
## Sir
## 0
Посмотрим медианный возраст для каждой группы.
median_Age <- summarize(group_by(titanic_train, Title), median_Age = median(Age, na.rm = TRUE))
median_Age
## # A tibble: 11 x 2
## Title median_Age
## <fct> <dbl>
## 1 Col 58
## 2 Dr 46.5
## 3 Lady 38
## 4 Master 3.5
## 5 Miss 21
## 6 Mlle 24
## 7 Mr 30
## 8 Mrs 35
## 9 Ms 28
## 10 Rev 46.5
## 11 Sir 49
Заполним пропуски с помощью пайплайнов и функции ifelse. Подумайте над структурой такого запроса. Совет - сначала создадим новую колонку, чтобы случайно не перезаписать оригинальную переменную кодом с ошибкой.
titanic_train <-
titanic_train %>%
group_by(Title) %>%
mutate(Copy_Age = ifelse(is.na(Age), median(Age, na.rm = TRUE), Age))
Давайте посмотрим на наши NA и сверимся, что функция сработала верно.
subset(titanic_train, is.na(Age))
## # A tibble: 177 x 14
## # Groups: Title [5]
## PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare
## <int> <int> <int> <chr> <fct> <dbl> <int> <int> <chr> <dbl>
## 1 6 0 3 Mora~ male NA 0 0 330877 8.46
## 2 18 1 2 Will~ male NA 0 0 244373 13
## 3 20 1 3 Mass~ fema~ NA 0 0 2649 7.22
## 4 27 0 3 Emir~ male NA 0 0 2631 7.22
## 5 29 1 3 "O'D~ fema~ NA 0 0 330959 7.88
## 6 30 0 3 Todo~ male NA 0 0 349216 7.90
## 7 32 1 1 Spen~ fema~ NA 1 0 PC 17~ 147.
## 8 33 1 3 Glyn~ fema~ NA 0 0 335677 7.75
## 9 37 1 3 Mame~ male NA 0 0 2677 7.23
## 10 43 0 3 Krae~ male NA 0 0 349253 7.90
## # ... with 167 more rows, and 4 more variables: Cabin <chr>,
## # Embarked <chr>, Title <fct>, Copy_Age <dbl>
Выглядит хорошо! Давайте перезапишем оригинальную колонку возраст.
titanic_train$Age <- titanic_train$Copy_Age
И наконец-то посмотрим распределение выживших по возрасту.
ggplot(titanic_train, aes(x = Age, group = Survived)) +
geom_density(aes(fill = Survived), alpha =0.5)
Распределения накладываются друг на друга, но мы видим, что по ощущения больше маленьких детей выжило, чем нет (смещение влево). Давайте попробуем ввести дополнительную бинарную переменную Child.
titanic_train$Child <- 0
titanic_train$Child[titanic_train$Age < 18] <- 1
Теперь, когда у нас есть переменные и для возраста, и для пола, давайте посмотрит аггрегированные статистики о влиянии этих переменных на выживание.
View(titanic_train)
aggregate(Survived ~ Child + Sex, data=titanic_train, FUN=sum)
## Child Sex Survived
## 1 0 female 195
## 2 1 female 38
## 3 0 male 84
## 4 1 male 25
Но эта история нам мало, что говорит, потому что это только значения для тех, кто выжил. Для того, чтобы делать выводы нам нужна пропорция.
aggregate(Survived ~ Child + Sex, data=titanic_train, FUN= function(x) {sum(x)/length(x)})
## Child Sex Survived
## 1 0 female 0.7528958
## 2 1 female 0.6909091
## 3 0 male 0.1631068
## 4 1 male 0.4032258
Влияет ли тот факт, что пассажир младше 18 лет на то, выживет он или нет, по вашему мнению?
18 лет мы выбрали достаточно арбитрарно (как и многие другие вещи в статистике). Давайте предположим, что детей опеределяли не юридически, а на “глаз”. Давайте перекодируем переменную Child, на этот раз будем считать детьми всех младше 12.
titanic_train$Child <- 0
titanic_train$Child[titanic_train$Age < 12] <- 1
aggregate(Survived ~ Child + Sex, data=titanic_train, FUN= function(x) {sum(x)/length(x)})
## Child Sex Survived
## 1 0 female 0.7588652
## 2 1 female 0.5937500
## 3 0 male 0.1620112
## 4 1 male 0.5500000
Стало ли лучше? Давайте экспериментальным путем ще раз уменьшим возраст “детей”.
titanic_train$Child <- 0
titanic_train$Child[titanic_train$Age < 10] <- 1
aggregate(Survived ~ Child + Sex, data=titanic_train, FUN= function(x) {sum(x)/length(x)})
## Child Sex Survived
## 1 0 female 0.7535211
## 2 1 female 0.6333333
## 3 0 male 0.1626617
## 4 1 male 0.5833333
Эффект для мужчин становится все более выраженными. Для женщин пропорция примерно одинаковая. Давайте сформулируем гипотезу. Пассажиры мужского пола выживали чаще, если это дети.
С женщинами и детьми разобрались. Теперь давайте смотреть, что у нас за история с ценой на проезд и классом, в котором путешествовал пассажир?
summary(titanic_train$Fare)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.00 7.91 14.45 32.20 31.00 512.33
Не переживайте из-за минимального значения 0 - здесь это не пропуски, а специальные билеты (например, для членов команды или их семей).
Класс у нас переменная категориальная. Давайте посмотрим, как они соотносятся между собой.
ggplot(titanic_train, aes(x = as.factor(Pclass), y = Fare)) +
geom_boxplot()
Ого, выбросы сильно портят картину. Давайте посмотрим распределения без них.
ggplot(titanic_train, aes(x = as.factor(Pclass), y = Fare)) +
geom_boxplot(outlier.shape = NA) +
scale_y_continuous(limits = c(0, 150))
## Warning: Removed 29 rows containing non-finite values (stat_boxplot).
Подтверждает ли предположение, что цена сильно зависит от класса? Какую переменную лучше использовать? Ваши версии.
Давайте попробуем сделать из переменной Fare категориальную и грубо разобьем ее на четыре группы, которые примерно будут соответсвовать нашим классам, но и отражать разброс внутри них.
titanic_train$Fare2 <- '30+'
titanic_train$Fare2[titanic_train$Fare < 30 & titanic_train$Fare >= 20] <- '20-30'
titanic_train$Fare2[titanic_train$Fare < 20 & titanic_train$Fare >= 10] <- '10-20'
titanic_train$Fare2[titanic_train$Fare < 10] <- '<10'
Теперь давайте посмотрим, как цена билета и класс каюты влияют на “выживаемость”.
ggplot(titanic_train, aes(x = Fare2, group = Survived)) +
geom_bar(aes(fill = Survived)) +
facet_wrap(~Pclass)
Какие выводы можете сделать? В приницие все, как и ожидалось. Самая большая пропорпция выживших людей - в первом классе с самыми дорогими билетами, во втором классе пропорции примерно 50/50 во всех категориях, в третьем классе интересно, что люди с билетами за 10-20 долларов выживали в пропорции чаще, чем люди с другими билетами (в том числе и дороже). Возможно, это как-то связано с расположением кают в каждой ценовой категории. Мы с вами не настраиваем сейчас модель так тонко, поэтому просто примем решение использовать для предсказания только одну перменную из класса и цены за проезд.
Сформулируем гипотезу: Чем выше класс путешествующего пассажира, тем больше вероятности, что он выживет.
Последний признак, с которым мы будем работать - размер семьи. У нас есть признаки SpSib и ParCh, которые показывают сколько горизонтальных и вертикальных родственников было у пассажира на борту.
Пока мы не начали работать, какие у вас есть идеи? Как размер семьи может быть свзязан с шансами на выживание?
Давайте создадим новую переменную, которая бы определяла размер семьи пассажира. Достаточно ли их просто сложить для этого?
titanic_train$FamilySize <- titanic_train$SibSp + titanic_train$Parch + 1
table(titanic_train$FamilySize)
##
## 1 2 3 4 5 6 7 8 11
## 537 161 102 29 15 22 12 6 7
Давайте посмотрим, как размер семьи влияет на шансы выжить. Так же, наверное. мы захотим укрупнить наши категории.
ggplot(titanic_train, aes(x=FamilySize,group=Survived)) +
geom_bar(aes(fill=Survived))
видим, что, чем больше семья, тем меньше людей спасалось. Возможно, размер семьи в данном случае прокси для класса (аристократические семьи все-таки были меньше по размеру) или если уж из семьи кому-то не хватало места на лодке, то оставались все. Давайте попробуем укрупнить наши категории. Оставим одиночек, семьи маленького размера (2-4 человека) и большие семьи.
titanic_train$FamilySize[titanic_train$FamilySize == 1] <- 'Alone'
titanic_train$FamilySize[titanic_train$FamilySize %in% c(2,3,4)] <- 'Small'
titanic_train$FamilySize[titanic_train$FamilySize %in% c(5,6,7,8,11)] <- 'Big'
titanic_train$FamilySize <- as.factor(titanic_train$FamilySize)
Давайте еще раз построим график.
ggplot(titanic_train, aes(x=FamilySize, group = Survived)) +
geom_bar(aes(fill=Survived))
Ого, кажется, что у членов маленьких семей было больше шансов спастись. Давайте сформулируем.
У членов семей маленького размера больше шансов спастись, чем у одиночек и семей большого размера
Выше мы сформулировали несколько гипотез. Давайте попробуем их проверить. Сначала мы воспользуемся непараметрическим тестом хи-квадрат. http://kineziolog.su/content/proverka-gipotez-kriteriem-khi-kvadrat-pirsona Такой тест дает нам понимание, существенно ли отличаются значения в наших таблицах (например, выжившие мужчины и женщины).
Потом мы попробуем протестировать наши гипотезы тестом Стьюдента, чтобы понять, статистически ли значимо отличаются между собой средние наших выборок, сформулированных в гипотезе (например, мальчики выживают чаще, чем взрослые мужчины). http://www.machinelearning.ru/wiki/index.php?title=%D0%9A%D1%80%D0%B8%D1%82%D0%B5%D1%80%D0%B8%D0%B9_%D0%A1%D1%82%D1%8C%D1%8E%D0%B4%D0%B5%D0%BD%D1%82%D0%B0
Затем попробуем построить логистическую регрессию, в которую в качестве независимых переменных передадим те признаки, которые по нашему мнению влияют на шансы выжить. https://habr.com/company/io/blog/265007/
install.packages("gmodels")
library(gmodels)
Хи-квадрат может быть использован для категориальных переменных. Давайте вернемся к нашей первой гипотезе про том, что у женщин больше шансов выжить.
Когда мы формлируем гипотезу, мы всегда хотим опровергнуть гипотезу нулевую: о том, что изменений нет/фактор не влияет. H0: пол пассажира не влияет на шансы выжить
Теперь, когда мы импортировали модуль для анализа данных gmodels, мы можем построить более наглядную кросс-таблицу (но по сути это то же, что мы делали вначале.)
CrossTable(titanic_train$Survived,titanic_train$Sex)
##
##
## Cell Contents
## |-------------------------|
## | N |
## | Chi-square contribution |
## | N / Row Total |
## | N / Col Total |
## | N / Table Total |
## |-------------------------|
##
##
## Total Observations in Table: 891
##
##
## | titanic_train$Sex
## titanic_train$Survived | female | male | Row Total |
## -----------------------|-----------|-----------|-----------|
## 0 | 81 | 468 | 549 |
## | 65.386 | 35.583 | |
## | 0.148 | 0.852 | 0.616 |
## | 0.258 | 0.811 | |
## | 0.091 | 0.525 | |
## -----------------------|-----------|-----------|-----------|
## 1 | 233 | 109 | 342 |
## | 104.962 | 57.120 | |
## | 0.681 | 0.319 | 0.384 |
## | 0.742 | 0.189 | |
## | 0.262 | 0.122 | |
## -----------------------|-----------|-----------|-----------|
## Column Total | 314 | 577 | 891 |
## | 0.352 | 0.648 | |
## -----------------------|-----------|-----------|-----------|
##
##
options(scipen = 999) # отключаем научную запись малых чисел.
chisq.test(table(titanic_train$Survived,titanic_train$Sex))
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table(titanic_train$Survived, titanic_train$Sex)
## X-squared = 260.72, df = 1, p-value < 0.00000000000000022
Чтобы опровергнуть или принять гипотезу, мы в первую очередь смотрим на p-значение. Оно нам говорит, является ли статистика с таким значением, которое мы получили нормальным для распределения или попадает в ту его часть, где находится очень маленькое количество значений. В частности, когда мы отвергаем нулевую гипотезу при p-value < 0.05, мы фактически говорим, что мы отвергаем нулевую гипотезу с вероятностью 5%, что мы ошиблись.
Отвергаем ли мы нулевую гипотезу?
https://ru.wikipedia.org/wiki/P-%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5
Сформулируйте нулевые гипотезы и проверьте критерием хи-квадрата выживают ли мальчики чаще, чем мужчины, а девочки чаще, чем взрослые женщины.
H0: Для пассажиров мужского пола возраст не влияет на шансы выжить. H0: Для пассажиров женского пола возраст не влияет на шансы выжить.
titanic_men <- subset(titanic_train, Sex == 'male')
table(titanic_men$Survived, titanic_men$Child)
##
## 0 1
## 0 453 15
## 1 88 21
chisq.test(table(titanic_men$Survived, titanic_men$Child))
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table(titanic_men$Survived, titanic_men$Child)
## X-squared = 36.287, df = 1, p-value = 0.000000001703
titanic_women <- subset(titanic_train, Sex == "female")
table(titanic_women$Survived, titanic_women$Child)
##
## 0 1
## 0 70 11
## 1 214 19
chisq.test(table(titanic_women$Survived, titanic_women$Child))
##
## Pearson's Chi-squared test with Yates' continuity correction
##
## data: table(titanic_women$Survived, titanic_women$Child)
## X-squared = 1.4679, df = 1, p-value = 0.2257
Можем ли мы отвергнуть нулевые гипотезы?
Упражнение: проверьте гипотезы о влиянии размера семьи и класс пассажира на выживание
Для критериястьюдента нам нужна количественная переменная. Нам нужно построить распределение этой переменной для двух групп и понять, является ли статистически значимым различие их средних.
Давайте проверим нулевую гипотезу, что возраст не влияет на шансы на спасение, отдельно у мужчин и у женщин.
t.test(Age~Survived,data = titanic_women)
##
## Welch Two Sample t-test
##
## data: Age by Survived
## t = -2.3118, df = 149.49, p-value = 0.02216
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## -6.9744559 -0.5462351
## sample estimates:
## mean in group 0 mean in group 1
## 24.71605 28.47639
t.test(Age~Survived,data = titanic_men)
##
## Welch Two Sample t-test
##
## data: Age by Survived
## t = 2.4821, df = 141.94, p-value = 0.01423
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
## 0.8096098 7.1444575
## sample estimates:
## mean in group 0 mean in group 1
## 31.16667 27.18963
Проинтерпретируйте результаты.
А теперь давайте попробуем построить модель логистической регрессии, которая будет нам предсказывать выжили пассажиры или нет и передадим в нее в качестве переменных Sex, FamilySize, Pclass, Child.
titanic_log <- glm(formula = Survived ~ Sex + FamilySize + Pclass + Child, family = binomial, data = titanic_train)
summary(titanic_log)
##
## Call:
## glm(formula = Survived ~ Sex + FamilySize + Pclass + Child, family = binomial,
## data = titanic_train)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -3.1884 -0.6675 -0.4220 0.6151 2.3426
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 3.50194 0.34859 10.046 < 0.0000000000000002 ***
## Sexmale -2.91911 0.20824 -14.018 < 0.0000000000000002 ***
## FamilySizeBig -2.82588 0.49446 -5.715 0.00000001097 ***
## FamilySizeSmall 0.03802 0.20693 0.184 0.854
## Pclass -0.98549 0.11431 -8.621 < 0.0000000000000002 ***
## Child 2.52222 0.43404 5.811 0.00000000621 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1186.66 on 890 degrees of freedom
## Residual deviance: 755.15 on 885 degrees of freedom
## AIC: 767.15
##
## Number of Fisher Scoring iterations: 5
Интерпретируем результаты модели: Переменные (или уровни факторов) имеющие самые маленькие p-значения большего всего связаны с зависимой переменной. Коэффицент переменной (estimate) говорим нам, позитивная или негативная это связть. Например, дети умеют шансы выжить в 2.5 раза выше, чем другие пассажиры.
Проинтерпретируйте результаы.