Для анализа были взяты предварительно обработанные данные из трех источников: СберИндекс, ДомКлик и Росстат, представленные в открытом доступе и отображающие распределение социоэкономических показателей по регионам России. Итоговый объединенный датафрейм, взятый для анализа, включает 15 показателей (Итоговая таблица.xlsx):
Задачи исследования:
На основании сравнительного анализа социально-экономических показателей выбрать наиболее перспективные регионы для открытия филиалов банка TrustUs
# Подгружаем библиотеки:
library(tidyverse)
## Warning in Sys.timezone(): unable to identify current timezone '!0@0B>2 ':
## please set environment variable 'TZ'
library(readxl)
library(psych)
library(lmtest)
library(sandwich)
library(pROC)
library(stargazer)
# Загружаем данные:
dat <- read_xlsx("Итоговая таблица.xlsx")
dat$`Число активных абонентов беспроводного доступа к сети` <- as.numeric(dat$`Число активных абонентов беспроводного доступа к сети`)
dat$Месяц <- factor(dat$Месяц, ordered = TRUE,
levels = c("Январь", "Февраль", "Март",
"Апрель", "Май", "Июнь", "Июль",
"Август", "Сентябрь", "Октябрь",
"Ноябрь", "Декабрь"))
dat$Квартал <- factor(dat$Квартал,
levels = c("Квартал 1", "Квартал 2", "Квартал 3", "Квартал 4"))
dat$`Всего одобренных заявок` <- factor(dat$`Всего одобренных заявок`,
ordered = TRUE,
levels = c("100 - 500",
"500 - 1 000",
"1 000 - 5 000",
"5 000 - 10 000",
"> 10 000"))
dat$`Всего ипотечных сделок` <- factor(dat$`Всего ипотечных сделок`,
ordered = TRUE,
levels = c("10 - 50",
"50 - 100",
"100 - 500",
"500 - 1 000",
"> 1 000"))
# Выведем описательные статистики для показателей СберИндекс:
dat %>%
select(`Индекс потребительской активности` : `Количество внутренних туристов`) %>%
describe()
## vars n mean sd median trimmed mad
## Индекс потребительской активности 1 912 65.51 8.80 67.00 66.20 7.41
## Доля безналичных платежей 2 912 52.33 7.67 53.25 53.22 5.86
## Количество внутренних туристов 3 912 -7.46 28.25 -4.54 -6.96 28.50
## min max range skew kurtosis se
## Индекс потребительской активности 34.00 88.00 54.00 -0.73 0.61 0.29
## Доля безналичных платежей 16.00 66.10 50.10 -1.85 5.19 0.25
## Количество внутренних туристов -85.47 86.14 171.61 -0.09 -0.18 0.94
Можно отметить, что три исследуемых показателя (Индекс потребительской активности, доля безналичных платежей, количество внутренних туристов) имеют высокий размах, т.е. значительную разницу между минимальными и максимальными значениями показателей. Вместе с этим, имеются небольшие различия между медианными и средними значениями, что может говорить о наличии нетипичных значений. Значения skew во всех трех случаях < 0, что говорит о скошенности распределения влево.
Стоит отметить отрицательные значения медианы и среднего количества внутренних туристов, что может быть связано с противоэпидемическим режимом в 2020 г. И действительно, если посмотреть данные, отрицательные значения по большинству регионов появляются в апреле 2020 г, когда в полной мере были развернуты антиковидные ограничения.
## Построим график, отображающий динамику средних значений данных показателей по месяцам:
dat_mean <- dat %>%
drop_na %>%
group_by(Месяц) %>%
summarise(`Индекс потребительской активности` = mean(`Индекс потребительской активности`),
`Доля безналичных платежей` = mean(`Доля безналичных платежей`),
`Количество внутренних туристов` = mean(`Количество внутренних туристов`))
dat_mean <- pivot_longer(data = dat_mean, cols = 2:4, names_to = "Индекс", values_to = "Значение")
dat_mean %>%
ggplot(aes(x = Месяц, y = Значение, group = Индекс, color = Индекс)) +
geom_line(size = 0.8) +
geom_point(size = 1.2) +
labs(title = "Динамика средних показателей СберИндекс в 2020 году",
x = "Месяц",
y = "Среднее значение по России") +
scale_colour_manual(values = c("tomato", "steelblue", "palegreen3")) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
panel.background = element_rect(fill = "white", colour = "grey50"),
panel.grid.major = element_line(color = "grey95"),
panel.grid.minor = element_line(color = "grey98"))
Графики динамики также отражают падение индекса потребительской активности и количества внутренних туристов весной 2020 г. При этом не уменьшилась доля безналичных платежей, что тоже кажется логичным.
dat_long <- dat %>%
drop_na %>%
select(1:6) %>%
pivot_longer(cols = 4:6,names_to = "Индекс", values_to = "Значение")
dat_long %>%
ggplot(aes(y = Значение, group = Индекс, fill = Индекс)) +
geom_boxplot(color = "gray30",
outlier.fill = "coral",
outlier.shape = 21,
outlier.size = 1.8) +
scale_fill_manual(values = c("lavender", "lightpink", "steelblue")) +
facet_wrap(facets = ~Месяц) +
scale_y_continuous(breaks = c(-50, -25, 0, 25, 50, 75)) +
coord_cartesian(ylim = c(-80, 85)) +
labs(title = "Разброс значений показателей СберИндекс по месяцам") +
theme(axis.ticks.x = element_blank(),
axis.text.x = element_blank(),
panel.background = element_rect(fill = "grey99"),
panel.grid.major = element_line(color = "grey95"),
panel.grid.minor = element_line(color = "grey97"),
strip.background = element_rect(color = "grey70", fill = "grey95"))
Графики с усами также позволяют отследить динамику по месяцам для выбранных показателей, а также отображают большое количество нетипичных значений, которые следует изучить подробнее.
# Поиск нетипичных значений:
dat_clean <- dat %>%
drop_na()
get_outliers <- function(x){
iqr <- IQR(x)
q1 <- quantile(x, 0.25)
q3 <- quantile(x, 0.75)
lower_b <- q1 - 1.5 * iqr
upper_b <- q3 + 1.5 * iqr
extra <- x[x < lower_b | x > upper_b]
return(extra)
}
consume_out <- dat[dat$`Индекс потребительской активности` %in% get_outliers(dat_clean$`Индекс потребительской активности`), 1:4]
cashless_out <- dat[dat$`Доля безналичных платежей` %in% get_outliers(dat_clean$`Доля безналичных платежей`), c(1:3, 5)]
voyage_out <- dat[dat$`Количество внутренних туристов` %in% get_outliers(dat_clean$`Количество внутренних туристов`), c(1:3, 6)]
dat_out <- full_join(consume_out, cashless_out)
dat_out <- full_join(dat_out, voyage_out)
dat_out <- dat_out %>%
pivot_longer(cols = `Индекс потребительской активности` : `Количество внутренних туристов`, names_to = "Индекс", values_to = "Значение")
dat_out <- dat_out %>%
drop_na()
Рассмотрим, каким месяцам соответствует наибольшее количество нетипичных значений:
# Визуализируем нетипичные значения:
dat_out %>%
ggplot(aes(x = Месяц, fill = Индекс)) +
geom_bar(color = "grey20") +
labs(title = "Распределение выбросов по месяцам",
x = "Месяц",
y = "Количество") +
scale_fill_manual(values = c("wheat", "lightpink2", "slategray3")) +
theme(axis.text.x = element_text(angle = 90),
panel.background = element_rect(fill = "grey99"),
panel.grid.major = element_line(color = "grey95"),
panel.grid.minor = element_line(color = "grey97"))
Нетипичные значения в показателе “Доля безналичных платежей” равномерно распределены и встречаются в каждом месяце. Соответственно, это сможет быть связано не с периодом, а с определенными регионами. Нетипичные значения количества внутренних туристов встречаются в феврале, марте, августе и октябре. Вероятно, внутренний туризм в период с апреля по август был затруднен вследствие ограничений. Выбросы в показателе “Индекс потребительской активности” встречаются в четырех месяцах и с максимумом в апреле, что тоже укладывается в предположение о влиянии ограничений, связанных с пандемией COVID-19.
# По регионам:
dat_out %>%
ggplot(aes(x = Регион, fill = Индекс)) +
geom_bar(color = "grey20") +
labs(title = "Распределение выбросов по регионам",
x = "Регион",
y = "Количество") +
scale_fill_manual(values = c("wheat", "lightpink2", "slategray3")) +
theme(axis.text.x = element_text(angle = 90),
panel.background = element_rect(fill = "grey99"),
panel.grid.major = element_line(color = "grey95"),
panel.grid.minor = element_line(color = "grey97"))
Если посмотреть на распределение нетипичных значений по регионам, можно заметить, что выбросы среди значений индекса потребительской активности распределены равномерно, за исключением трех регионов. Так как нетипичные значения в апреле по этому показателю ниже граничного значения (q1 - 1.5 * IQR), то, вероятно, потребительская активность в этих регионах пострадала наиболее сильно. Нетипичные значения доли безналичных платежей соответствуют четырем регионам: Кабардино-Балкарской Республике, Республике Дагестан, республике Карачаево-Черкессии, Республике Северной Осетии-Алании. Так как нетипично низкие значения этого показателя распределены равномерно по месяцам, можно предположить, что в этих регионах традиционно более распространены платежи наличными.
# Находим топ-30 регионов по индексу потребительской активности:
top_consume <- dat %>%
drop_na %>%
group_by(Регион) %>%
summarise(mean_consume = mean(`Индекс потребительской активности`)) %>%
arrange(desc(mean_consume)) %>%
slice_head(n = 30)
# Находим топ-30 регионов по доле безналичных платежей:
top_cashless <- dat %>%
drop_na %>%
group_by(Регион) %>%
summarise(mean_cashless = mean(`Доля безналичных платежей`)) %>%
arrange(desc(mean_cashless)) %>%
slice_head(n = 30)
# Находим регионы, общие для обоих датафреймов:
top_both <- inner_join(top_consume, top_cashless, by = "Регион")
top_both
## # A tibble: 15 × 3
## Регион mean_consume mean_cashless
## <chr> <dbl> <dbl>
## 1 Калининградская область 74.8 58.9
## 2 Воронежская область 73.4 54.5
## 3 Тюменская область 73.2 60.0
## 4 Хабаровский край 71 57.7
## 5 Кировская область 70.3 57.7
## 6 Иркутская область 68.5 56.6
## 7 Свердловская область 68.1 57.3
## 8 Самарская область 67.7 54.9
## 9 Москва 67.7 57.1
## 10 Нижегородская область 67.6 55.7
## 11 Республика Башкортостан 67.4 55.1
## 12 Камчатский край 67.3 60.4
## 13 Кемеровская область 66.5 55.3
## 14 Томская область 66.5 59.0
## 15 Удмуртская Республика 66.4 57.4
# Выберем в основном датафрейме только регионы, попавшие в топ:
top_both <- dat[dat$Регион %in% top_both$Регион, ]
# Среди полученных регионов оставим только те, в которых индекс внутреннего туризма принимал значения выше 0 не менее чем в течение 5 месяцев:
top_both <- top_both %>%
mutate(tourindex = ifelse(`Количество внутренних туристов` > 0, 1, 0), .after = `Количество внутренних туристов`)
top_tour <- top_both %>%
group_by(Регион) %>%
summarise(tour_sum = sum(tourindex)) %>%
filter(tour_sum >= 5)
Выберем регионы, лидирующие по всем трем показателям:
# Выберем из основного датафрейма регионы, лидирующие по всем трем показателями:
top <- dat[dat$Регион %in% top_tour$Регион, ]
unique(top$Регион)
## [1] "Воронежская область" "Калининградская область"
## [3] "Камчатский край" "Кировская область"
## [5] "Нижегородская область" "Самарская область"
Рассмотрим, в какие месяцы наблюдаются максимальные значения исследуемых нами показателей:
## Построим график, отображающий динамику значений исследуемых показателей по месяцам :
top_long <- top %>%
select(1:6)
top_long <- pivot_longer(data = top_long, cols = 4:6, names_to = "Индекс", values_to = "Значение")
top_long %>%
ggplot(aes(x = Месяц, y = Значение, group = Индекс, color = Индекс)) +
geom_line(size = 0.8) +
geom_point(size = 1.2) +
labs(title = "Динамика показателей СберИндекс наиболее перспективных регионов \n в 2020 году",
x = "Месяц",
y = "Значение") +
scale_colour_manual(values = c("tomato", "steelblue", "palegreen3")) +
facet_wrap(facets = ~`Регион`) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
panel.background = element_rect(fill = "white", colour = "grey50"),
panel.grid.major = element_line(color = "grey95"),
panel.grid.minor = element_line(color = "grey98"))
Таким образом, наиболее перспективными для открытия филиалов банка являются следующие регионы (для каждого региона указан период, в котором наблюдались максимальные значения исследуемых показателей):
# График обобщенных показателей по всем выбранным регионам:
top %>%
group_by(Месяц) %>%
summarise(`Индекс потребительской активности` = mean(`Индекс потребительской активности`),
`Доля безналичных платежей` = mean(`Доля безналичных платежей`),
`Количество внутренних туристов` = mean(`Количество внутренних туристов`)) %>%
pivot_longer(cols = 2:4, names_to = "Индекс", values_to = "Значение") %>%
ggplot(aes(x = Месяц, y = Значение, group = Индекс, color = Индекс)) +
geom_line(size = 0.8) +
geom_point(size = 1.2) +
labs(title = "Динамика средних значений показателей СберИндекс \n выбранных регионов в 2020 году",
x = "Месяц",
y = "Значение") +
scale_colour_manual(values = c("tomato", "steelblue", "palegreen3")) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
panel.background = element_rect(fill = "white", colour = "grey50"),
panel.grid.major = element_line(color = "grey95"),
panel.grid.minor = element_line(color = "grey98"))
Обобщая для всех регионов, месяцы, в которых показатели были максимальными:
Проверим наличие связи между двумя показателями: Доля безналичных платежей и Количество внутренних туристов. Для этого построим график и вычислим коэффициент корреляции Пирсона.
top %>%
ggplot(aes(x = `Доля безналичных платежей`, y = `Количество внутренних туристов`)) +
geom_point(size = 3, shape = 21, color = "grey30", fill = "steelblue", alpha = 0.6) +
labs(title = "Характер связи между двумя показателями") +
theme_minimal()
На графике отсутствует заметная связь, между выбранными показателями.
# Коэффициент корреляции Пирсона:
cor.test(top$`Доля безналичных платежей`, top$`Количество внутренних туристов`)
##
## Pearson's product-moment correlation
##
## data: top$`Доля безналичных платежей` and top$`Количество внутренних туристов`
## t = 0.045248, df = 70, p-value = 0.964
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## -0.2265443 0.2367800
## sample estimates:
## cor
## 0.005408091
Значение p-value значительно превышает 0.05, поэтому на 5%-ном уровне значимости мы не можем отвергнуть нулевую гипотезу о независимости двух показателей. Другими словами, мы не можем говорить о наличии статистически значимой связи между долей безналичных платежей и количеством внутренних туристов.
Таким образом, мы не нашли оснований считать верным предположение о том, что в регионах, которые более активно посещаются туристами, доля безналичных платежей выше.
Проверим наличие связи между общим количеством одобренных заявок на кредит и числом ипотечных сделок:
cor.test(as.numeric(top$`Всего одобренных заявок`), as.numeric(top$`Всего ипотечных сделок`), method = "kendall")
##
## Kendall's rank correlation tau
##
## data: as.numeric(top$`Всего одобренных заявок`) and as.numeric(top$`Всего ипотечных сделок`)
## z = 6.6059, p-value = 3.952e-11
## alternative hypothesis: true tau is not equal to 0
## sample estimates:
## tau
## 0.7130607
Мы получили значение p-value меньшее 0.05 - можно отвергнуть нулевую гипотезу о равенстве нулю коэффициента корреляции между двумя исследуемыми показателями. Другими словами, на 5%-ном уровне значимости можно говорить о наличии сильной положительной связи между общим количеством одобренных заявок на кредит и числом ипотечных сделок.
# Вычислим коэффициент корреляции Пирсона для доли безналичных платежей и количеством заявок на кредиты онлайн:
cor.test(top$`Доля безналичных платежей`, top$`Доля онлайн-заявок`, method = "pearson")
##
## Pearson's product-moment correlation
##
## data: top$`Доля безналичных платежей` and top$`Доля онлайн-заявок`
## t = 2.0461, df = 70, p-value = 0.04451
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.006224355 0.444743383
## sample estimates:
## cor
## 0.2375504
При расчете коэффициента корреляции Пирсона выявлена статистически значимая положительная слабая связь на уровне значимости 5% (p-value < 0.05).
Таким образом, анализ взаимосвязей позволил сделать следующие выводы:
# Введем новый столбец Сезон:
top <- top %>%
mutate(Сезон = as.factor(case_when(top$Месяц %in% c("Декабрь", "Январь", "Февраль") ~ "Зима",
top$Месяц %in% c("Март", "Апрель", "Май") ~ "Весна",
top$Месяц %in% c("Июнь", "Июль", "Август") ~
"Лето",
top$Месяц %in% c("Сентябрь", "Октябрь", "Ноябрь") ~ "Осень")), .after = `Квартал`)
# Посторим график распределени ипотечных сделок по сезонам:
top %>%
ggplot(aes(x = `Сезон`, fill = `Всего ипотечных сделок`)) +
geom_bar() +
labs(title = "Распределение количества ипотечных сделок \n по сезонам",
x = "Сезон",
y = "Количество") +
scale_fill_manual(values = c("palegreen3", "wheat", "lightpink", "steelblue")) +
theme_minimal()
График показывает, что больше всего сделок ипотечных сделок жители исследуемых регионов совершают в осенние месяцы.
# Боксплот доля онлайн-заявок на кредиты ~ сезон:
top %>%
ggplot(aes(x = `Сезон`, y = `Доля онлайн-заявок`, fill = Сезон)) +
geom_boxplot() +
labs(title = "Количество онлайн-заявок в разное время года",
x = "Сезон",
y = "Количество") +
scale_fill_manual(values = c("lightpink", "steelblue", "palegreen3", "coral")) +
stat_summary(fun.y = "mean", size = 0.3, shape = 21, color = "black", stroke = 0.5, alpha = 0.8) +
theme_minimal()
# Из боксплотов не очень понятно, особенно если отдельно проставить средние значения, влияет ли существенно время год на количество онлайн-заявок. Нужно проверить, используя статистический критерий. Так как у нас есть факторная переменная Сезон, разбивающая наблюдения на четрые выборки, для сравнения средних получившихся выборок будем использовать критерий Краскела-Уоллиса:
kruskal.test(top$`Доля онлайн-заявок` ~ top$Сезон)
##
## Kruskal-Wallis rank sum test
##
## data: top$`Доля онлайн-заявок` by top$Сезон
## Kruskal-Wallis chi-squared = 4.7869, df = 3, p-value = 0.1881
p-value > 0.05, поэтому мы не можем отвергнуть нулевую гипотезу о равенстве средних в каждой выборке и принять альтернативную гипотезу о том, что по крайней мере в одной выборке результаты отличаются. Таким образом, на 5%-ном уровне значимости у нас нет оснований считать, что доля онлайн-сделок на вторичное жильё зависит от времени года.
Проверим, различается ли доля заявок на вторичное жилья в разное время года:
# Боксплот доля ипотечных сделок на вторичное жилье ~ сезон:
top %>%
ggplot(aes(x = `Сезон`, y = `Доля сделок, вторичка`, fill = Сезон)) +
geom_boxplot(outlier.fill = "coral",
outlier.shape = 21,
outlier.size = 1.8) +
labs(title = "Количество ипотечных сделок на вторичное жилье \n в разное время года",
x = "Сезон",
y = "Доля сделок - вторичка") +
scale_fill_manual(values = c("lightpink", "steelblue", "palegreen3", "coral")) +
stat_summary(fun.y = "mean", size = 0.3, shape = 21, color = "black", stroke = 0.5, alpha = 0.8) +
theme_minimal()
График показывает, что доля сделок на вторичное жилье, совершенных
весной, летом и осенью, примерно одинаково. В то же время летом оно
определенно ниже. Попробуем проверить формально с помощью
статистического критерия.
# Так как критерий Краскела-Уоллиса применяется для тестирования гипотезы о равенстве средних, предварительно удалим нетипичные значения:
sec_out <- top %>%
filter(Сезон == "Весна") %>%
select(`Доля сделок, вторичка`) %>%
pull()
iqr <- IQR(sec_out)
q1 <- quantile(sec_out, 0.25)
q3 <- quantile(sec_out, 0.75)
lower_b <- q1 - 1.5 * iqr
upper_b <- q3 + 1.5 * iqr
sec_out[sec_out < lower_b | sec_out > upper_b]
## [1] 0.46
# Есть одно нетипично низкое значение. Попробуем исключить его перед тестированием гипотезы
top_clean <- top %>%
filter(`Доля сделок, вторичка` != 0.46)
# Оказалось, что удаленное значение совсем незначительно влияет на резльтат, В любом случае, p-value на порядок меньше 0.05:
kruskal.test(top$`Доля сделок, вторичка` ~ top$Сезон)
##
## Kruskal-Wallis rank sum test
##
## data: top$`Доля сделок, вторичка` by top$Сезон
## Kruskal-Wallis chi-squared = 14.122, df = 3, p-value = 0.002743
kruskal.test(top_clean$`Доля сделок, вторичка` ~ top_clean$Сезон)
##
## Kruskal-Wallis rank sum test
##
## data: top_clean$`Доля сделок, вторичка` by top_clean$Сезон
## Kruskal-Wallis chi-squared = 16.254, df = 3, p-value = 0.001006
Да, действительно, в случае ипотеки на вторичное жилье влияние времен года существенно: значение p-value < 0.05, поэтому мы можем отвергнуть нулевую гипотезу о равенстве средних значений в выборках и утверждать, что на уровне значимости 5% доля ипотечных сделок, совершенных по крайней мере в одном из сезонов, статистически отличается от остальных.
Обобщая вышесказанное, можно отметить, что количество ипотечных сделок неодинаково в разное время года. Больше всего сделок заключается в осенние месяцы. При этом не обнаружено статистически значимых различий между средними значениями количества онлайн-заявок на ипотеку в разное время года. В то же время имеет место влияние времени года на долю заявок на вторичное жилье Полученные данные могут быть полезны, например, при планировании рекламы и акций ипотечных продуктов в разные месяцы.
Построение регрессионных моделей может помочь нам более детально понять влияние различных факторов на потребительскую активность и долю безналичных платежей, а также на предпочтение населения пользоваться онлайн-услугами банка и оформлять ипотеку.
Построим линейную модель, описывающую зависимость потребительской активности от средней заработной платы в регионе, числа активных абонентов беспроводного наземного фиксированного доступа к сети Интернет, уровня безработицы населения и времени года:
lmod <- lm(data = top, formula = `Индекс потребительской активности` ~ `Среднемесячная заработная плата` + `Число активных абонентов беспроводного доступа к сети` + `Уровень безработицы населения` + `Сезон`)
summary(lmod)
##
## Call:
## lm(formula = `Индекс потребительской активности` ~
## `Среднемесячная заработная плата` +
## `Число активных абонентов беспроводного доступа к сети` +
## `Уровень безработицы населения` +
## Сезон, data = top)
##
## Residuals:
## Min 1Q Median 3Q Max
## -16.3064 -2.7598 -0.3264 2.8794 15.8226
##
## Coefficients:
## Estimate Std. Error
## (Intercept) 5.606e+01 6.905e+00
## `Среднемесячная заработная плата` -1.847e-05 5.712e-05
## `Число активных абонентов беспроводного доступа к сети` 4.891e-04 4.892e-04
## `Уровень безработицы населения` 8.516e-01 1.008e+00
## СезонЗима 9.749e+00 2.262e+00
## СезонЛето 1.480e+01 2.293e+00
## СезонОсень 1.457e+01 2.307e+00
## t value Pr(>|t|)
## (Intercept) 8.118 1.80e-11 ***
## `Среднемесячная заработная плата` -0.323 0.747
## `Число активных абонентов беспроводного доступа к сети` 1.000 0.321
## `Уровень безработицы населения` 0.845 0.401
## СезонЗима 4.309 5.66e-05 ***
## СезонЛето 6.454 1.58e-08 ***
## СезонОсень 6.316 2.76e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 6.74 on 65 degrees of freedom
## Multiple R-squared: 0.4969, Adjusted R-squared: 0.4505
## F-statistic: 10.7 on 6 and 65 DF, p-value: 3.045e-08
Для этой модели статистически значимыми на любом разумном уровне значимости являются только коэффициенты при показателях, связанных с временами года. Иными словами, в разное время года потребительская активность достоверно различается. Базовой категорией в нашем случая является весна, поэтому коэффициенты напротив других сезонов показывают различие относительно весеннего периода. Интерпретировать результат можно следующим образом (при предположении, что другие условия не изменяются):
Следует обратить внимание на R-квадрат полученной модели. Значение R-squared = 0.4969 говорит о том, что наша модель объясняет примерно 50% дисперсии зависимой переменной, а значит, имеет среднюю предсказательную силу.
Построим модель, описывающую влияние среднемесячной заработной платы, числа активных пользователей беспроводного интернета, уровня безработицы и времени года на долю безналичных платежей:
lmod2 <- lm(data = top, formula = `Доля безналичных платежей` ~ `Среднемесячная заработная плата` + `Число активных абонентов беспроводного доступа к сети` + `Уровень безработицы населения` + `Сезон`)
summary(lmod2)
##
## Call:
## lm(formula = `Доля безналичных платежей` ~
## `Среднемесячная заработная плата` +
## `Число активных абонентов беспроводного доступа к сети` +
## `Уровень безработицы населения` +
## Сезон, data = top)
##
## Residuals:
## Min 1Q Median 3Q Max
## -3.6203 -1.2485 -0.2735 1.1891 3.5084
##
## Coefficients:
## Estimate Std. Error
## (Intercept) 4.856e+01 1.774e+00
## `Среднемесячная заработная плата` 8.194e-05 1.467e-05
## `Число активных абонентов беспроводного доступа к сети` -3.714e-04 1.257e-04
## `Уровень безработицы населения` 1.134e+00 2.590e-01
## СезонЗима 6.025e-01 5.811e-01
## СезонЛето -8.082e-01 5.889e-01
## СезонОсень 1.388e+00 5.927e-01
## t value Pr(>|t|)
## (Intercept) 27.378 < 2e-16 ***
## `Среднемесячная заработная плата` 5.585 4.94e-07 ***
## `Число активных абонентов беспроводного доступа к сети` -2.956 0.00434 **
## `Уровень безработицы населения` 4.377 4.46e-05 ***
## СезонЗима 1.037 0.30370
## СезонЛето -1.372 0.17467
## СезонОсень 2.341 0.02231 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 1.731 on 65 degrees of freedom
## Multiple R-squared: 0.6188, Adjusted R-squared: 0.5837
## F-statistic: 17.59 on 6 and 65 DF, p-value: 5.579e-12
В этом случае коэффициенты при количественных показателях, а также коэффициент при показателе Сезон-Осень, получились статистически значимыми на уровне значимости 5%. Проинтерпретируем влияние каждого фактора на зависимую переменную (при прочих равных условиях):
R-квадрат полученной модели выше, чем у предыдущей, и равен 0.6188. Это означает, что она может объяснять примерно 62% дисперсии зависимой переменной и обладает средней прогностической мощностью.
# Добавим в датафрейм столбец, показыващие преобладание количества онлайн-заявок на кредит в офисе банка или онлайн, а также аналогичный столбец, где 1 соответсвует регионам с общим числом ипотечных сделок > 500:
top <- top %>%
mutate(is_online = ifelse(`Доля онлайн-заявок` > `Доля заявок в офисе банка`, 1, 0), .after = `Доля заявок в офисе банка`)
top$is_online <- as.factor(top$is_online)
top <- top %>%
mutate(hyp_love = ifelse(`Всего ипотечных сделок` %in% c("500 - 1 000", "> 1 000"), 1, 0), .after = `Всего ипотечных сделок`)
top$hyp_love <- as.factor(top$hyp_love)
Построим первую регрессионную модель, которая отображает зависимость склонности населения предпочитать онлайн-услуги банка от средней заработной платы в регионе, числа активных абонентов беспроводного наземного фиксированного доступа к сети Интернет и уровня безработицы населения.
# Так как зависимая переменная у нас может принимать только два значения - 0 и 1, с которыми мы для удобства связали склонность выбирать онлайн услуги, будем использовать логистическую регрессионную модель:
logmod <- glm(data = top,
formula = top$is_online ~ `Среднемесячная заработная плата` + `Число активных абонентов беспроводного доступа к сети` + `Уровень безработицы населения` + `Сезон`, family = "binomial")
summary(logmod)
##
## Call:
## glm(formula = top$is_online ~ `Среднемесячная заработная плата` +
## `Число активных абонентов беспроводного доступа к сети` +
## `Уровень безработицы населения` +
## Сезон, family = "binomial", data = top)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -1.83091 -0.55433 -0.24683 -0.00004 1.99553
##
## Coefficients:
## Estimate Std. Error
## (Intercept) -7.228e+00 3.509e+00
## `Среднемесячная заработная плата` 8.659e-05 3.353e-05
## `Число активных абонентов беспроводного доступа к сети` 5.246e-05 2.479e-04
## `Уровень безработицы населения` 5.785e-01 4.626e-01
## СезонЗима -1.600e+00 1.077e+00
## СезонЛето -1.978e+01 2.263e+03
## СезонОсень -7.198e-01 9.172e-01
## z value Pr(>|z|)
## (Intercept) -2.060 0.03943 *
## `Среднемесячная заработная плата` 2.583 0.00981 **
## `Число активных абонентов беспроводного доступа к сети` 0.212 0.83239
## `Уровень безработицы населения` 1.251 0.21108
## СезонЗима -1.486 0.13740
## СезонЛето -0.009 0.99302
## СезонОсень -0.785 0.43255
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 70.935 on 71 degrees of freedom
## Residual deviance: 44.304 on 65 degrees of freedom
## AIC: 58.304
##
## Number of Fisher Scoring iterations: 18
exp(coef(logmod))
## (Intercept)
## 7.262714e-04
## `Среднемесячная заработная плата`
## 1.000087e+00
## `Число активных абонентов беспроводного доступа к сети`
## 1.000052e+00
## `Уровень безработицы населения`
## 1.783306e+00
## СезонЗима
## 2.018236e-01
## СезонЛето
## 2.561146e-09
## СезонОсень
## 4.868326e-01
Выдача R показывает, что статистически значимым на уровне 5% оказался только коэффициент при одном факторе - среднемесячной заработной плате. Однако, его влияние незначительно (при увеличении средней зарплаты на 1 рубль вероятность склонности выбирать онлайн-услуги увеличивается в среднем в 1.000087 раз при прочих равных). Чтобы было более показательно, попробуем изменить столбец Средняя заработная плата таким образом, чтобы значения отображались в тысячах рублей.
top <- top %>%
mutate(`Средняя заработная плата тысячи` = `Среднемесячная заработная плата` / 1000, .after = `Среднемесячная заработная плата`)
# Продублируем модель с новой размерностью и посмотрим, как это повлияет на коэффициенты при показателях:
logmod1000 <- glm(data = top,
formula = top$is_online ~ `Средняя заработная плата тысячи` + `Число активных абонентов беспроводного доступа к сети` + `Уровень безработицы населения` + `Сезон`, family = "binomial")
summary(logmod1000)
##
## Call:
## glm(formula = top$is_online ~ `Средняя заработная плата тысячи` +
## `Число активных абонентов беспроводного доступа к сети` +
## `Уровень безработицы населения` +
## Сезон, family = "binomial", data = top)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -1.83091 -0.55433 -0.24683 -0.00004 1.99553
##
## Coefficients:
## Estimate Std. Error
## (Intercept) -7.228e+00 3.509e+00
## `Средняя заработная плата тысячи` 8.659e-02 3.353e-02
## `Число активных абонентов беспроводного доступа к сети` 5.246e-05 2.479e-04
## `Уровень безработицы населения` 5.785e-01 4.626e-01
## СезонЗима -1.600e+00 1.077e+00
## СезонЛето -1.978e+01 2.263e+03
## СезонОсень -7.198e-01 9.172e-01
## z value Pr(>|z|)
## (Intercept) -2.060 0.03943 *
## `Средняя заработная плата тысячи` 2.583 0.00981 **
## `Число активных абонентов беспроводного доступа к сети` 0.212 0.83239
## `Уровень безработицы населения` 1.251 0.21108
## СезонЗима -1.486 0.13740
## СезонЛето -0.009 0.99302
## СезонОсень -0.785 0.43255
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 70.935 on 71 degrees of freedom
## Residual deviance: 44.304 on 65 degrees of freedom
## AIC: 58.304
##
## Number of Fisher Scoring iterations: 18
exp(coef(logmod1000))
## (Intercept)
## 7.262714e-04
## `Средняя заработная плата тысячи`
## 1.090449e+00
## `Число активных абонентов беспроводного доступа к сети`
## 1.000052e+00
## `Уровень безработицы населения`
## 1.783306e+00
## СезонЗима
## 2.018236e-01
## СезонЛето
## 2.561146e-09
## СезонОсень
## 4.868326e-01
Мы получили вполне ожидаемый результат: статистически значимым остался только коэффициент при показателе среднемесячной заработной платы, при этом сам коэффициент немного поменялся, а его интерпретация стала более наглядной: при увеличении средней заработной платы на 1 тысячу рублей вероятность того, что потребитель предпочтет оформлять заявку на кредит онлайн возрастает в среднем в 1.09 раз при прочих равных условиях.
Построим вторую модель, которая позволит охарактеризовать влияние того же набора показателей на склонность населения оформлять ипотеку.
logmod2 <- glm(data = top,
formula = hyp_love ~ `Средняя заработная плата тысячи` +
`Число активных абонентов беспроводного доступа к сети` +
`Уровень безработицы населения` +
`Сезон`, family = "binomial")
summary(logmod2)
##
## Call:
## glm(formula = hyp_love ~ `Средняя заработная плата тысячи` +
## `Число активных абонентов беспроводного доступа к сети` +
## `Уровень безработицы населения` +
## Сезон, family = "binomial", data = top)
##
## Deviance Residuals:
## Min 1Q Median 3Q Max
## -2.2149 -0.2453 0.2015 0.4761 1.6768
##
## Coefficients:
## Estimate Std. Error
## (Intercept) 2.6584777 2.8820906
## `Средняя заработная плата тысячи` -0.0748965 0.0337003
## `Число активных абонентов беспроводного доступа к сети` 0.0007899 0.0003221
## `Уровень безработицы населения` -0.1322649 0.4184972
## СезонЗима 0.1286347 0.9424217
## СезонЛето 1.0362722 1.0489430
## СезонОсень 2.4828064 1.3588832
## z value Pr(>|z|)
## (Intercept) 0.922 0.3563
## `Средняя заработная плата тысячи` -2.222 0.0263 *
## `Число активных абонентов беспроводного доступа к сети` 2.452 0.0142 *
## `Уровень безработицы населения` -0.316 0.7520
## СезонЗима 0.136 0.8914
## СезонЛето 0.988 0.3232
## СезонОсень 1.827 0.0677 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 88.632 on 71 degrees of freedom
## Residual deviance: 47.110 on 65 degrees of freedom
## AIC: 61.11
##
## Number of Fisher Scoring iterations: 6
exp(coef(logmod2))
## (Intercept)
## 14.2745423
## `Средняя заработная плата тысячи`
## 0.9278395
## `Число активных абонентов беспроводного доступа к сети`
## 1.0007902
## `Уровень безработицы населения`
## 0.8761089
## СезонЗима
## 1.1372746
## СезонЛето
## 2.8186899
## СезонОсень
## 11.9748238
Выдача R показывает, что статистически значимыми на уровне 5% являются показатели Средняя заработная плата и Число активных абонентов беспроводного доступа к сети. При увеличении средней заработной платы на 1 тысячу рублей склонность потребителя оформлять ипотеку увеличивается в 0.93 раза (или уменьшается на 7%), при условии, что значения других показателей не изменяются. Число активных абонентов беспроводного интернета положительно связано с зависимой переменной: при увеличении первого на 1 склонность оформлять ипотеку увеличивается в 1.0008 раз (или ~ в 1.08 раз при увеличении на 100).
Сначала поработаем с моделями множественной линейной регрессии. В предыдущем пункте мы уже оценили R-квадрат полученных моделей, теперь протестируем их более детально: проверим, что выполняется следующий ряд условий: * В модели нет независимых переменных, которые сильно скоррелированы друг с другом (отсутствие мультиколлинеарности); * Остатки в модели распределены случайно, нет выраженной зависимости между остатками модели и независимыми переменными (проблема гетероскедастичности); * В данных нет влиятельных наблюдений, искажающих плоскость, которую описывает уравнение регрессии.
Для этого построим корреляционную матрицу для независимых переменных:
# Вначале преобразуем факторный показатель Сезон:
top <- top %>%
mutate(Season_numeric = as.numeric(Сезон), .after = Сезон)
mltcor <- top %>%
select(`Среднемесячная заработная плата`, `Число активных абонентов беспроводного доступа к сети`, `Уровень безработицы населения`, Season_numeric)
cor(mltcor)
## Среднемесячная заработная плата
## Среднемесячная заработная плата 1.00000000
## Число активных абонентов беспроводного доступа к сети -0.50399291
## Уровень безработицы населения -0.38481489
## Season_numeric -0.01735107
## Число активных абонентов беспроводного доступа к сети
## Среднемесячная заработная плата -0.503992914
## Число активных абонентов беспроводного доступа к сети 1.000000000
## Уровень безработицы населения -0.008317665
## Season_numeric 0.045851236
## Уровень безработицы населения
## Среднемесячная заработная плата -0.384814885
## Число активных абонентов беспроводного доступа к сети -0.008317665
## Уровень безработицы населения 1.000000000
## Season_numeric 0.255818292
## Season_numeric
## Среднемесячная заработная плата -0.01735107
## Число активных абонентов беспроводного доступа к сети 0.04585124
## Уровень безработицы населения 0.25581829
## Season_numeric 1.00000000
Можно отметить корреляцию средней силы между числом активных абонентов беспроводного доступа к сети и среднемесячной заработной платой, а также среднемесячной заработной платой и уровнем безработицы населения. Максимальное значение по модулю коэффициента корреляции = 0.5. На мой взгляд, это допустимое значение, не требующее корректировки модели. Если бы мы встретили значения по модулю выше 0.7-0.8, то это уже могло бы свидетельствовать о возможных проблемах с качеством получаемых оценок. Вторая модель содержит такой же набор независимых переменных, поэтому повторять этот тест для нее мы не будем.
Для каждой модели построим диаграмму рассеивания вида предсказанные значения - остатки:
# Добавим в основной датафрейм предсказанные значения и остатки моделей lmod и lmod2:
top <- top %>%
mutate(lmod_predicted = lmod$fitted.values)
top <- top %>%
mutate(lmod_residuals = lmod$residuals)
top <- top %>%
mutate(lmod2_predicted = lmod2$fitted.values)
top <- top %>%
mutate(lmod2_residuals = lmod2$residuals)
# Построим график для первой модели:
top %>%
ggplot(aes(x = lmod_predicted, y = lmod_residuals)) +
geom_point(color = "steelblue", size = 2) +
geom_hline(yintercept = 0, color = "tomato") +
labs(title = "Диаграмма рассеивания для предсказанных значений и остатков lmod",
x = "Fitted values",
y = "Residuals") +
theme_minimal()
На графике заметна неоднородность разброса остатков: модель чаще ошибается при предсказании низких значений зависимой переменной. Придется пересчитать коэффициенты модели с помощью инструментов, устойчивых к неоднородности дисперсии случайной ошибки:
coeftest(lmod, vcov. = vcovHC(lmod, type = "HC0"))
##
## t test of coefficients:
##
## Estimate Std. Error
## (Intercept) 5.6059e+01 7.2262e+00
## `Среднемесячная заработная плата` -1.8474e-05 4.4399e-05
## `Число активных абонентов беспроводного доступа к сети` 4.8906e-04 4.8575e-04
## `Уровень безработицы населения` 8.5165e-01 1.0268e+00
## СезонЗима 9.7489e+00 2.5113e+00
## СезонЛето 1.4797e+01 2.5264e+00
## СезонОсень 1.4572e+01 2.7000e+00
## t value Pr(>|t|)
## (Intercept) 7.7577 7.864e-11 ***
## `Среднемесячная заработная плата` -0.4161 0.6787122
## `Число активных абонентов беспроводного доступа к сети` 1.0068 0.3177582
## `Уровень безработицы населения` 0.8294 0.4099237
## СезонЗима 3.8821 0.0002448 ***
## СезонЛето 5.8569 1.704e-07 ***
## СезонОсень 5.3971 1.020e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Мы получили немного другие значения стандартных ошибок и p-value, при этом значимые факторы остались прежними, значения коэффициентов тоже (при округлении до сотых) не изменились. Таким образом, интерпретация модели остается прежней.
Для второй модели:
top %>%
ggplot(aes(x = lmod2_predicted, y = lmod2_residuals)) +
geom_point(color = "steelblue", size = 2) +
geom_hline(yintercept = 0, color = "tomato") +
labs(title = "Диаграмма рассеивания для предсказанных значений и остатков lmod2",
x = "Fitted values",
y = "Residuals") +
theme_minimal()
Здесь также присутствует небольшая, менее выраженная, чем в первом случае, неоднородность (график имеет веретеновидную форму). Пересчитаем коэффциенты модели и сравним их с исходными:
coeftest(lmod2, vcov. = vcovHC(lmod2, type = "HC0"))
##
## t test of coefficients:
##
## Estimate Std. Error
## (Intercept) 4.8561e+01 1.4638e+00
## `Среднемесячная заработная плата` 8.1936e-05 1.3099e-05
## `Число активных абонентов беспроводного доступа к сети` -3.7144e-04 1.1263e-04
## `Уровень безработицы населения` 1.1335e+00 2.0000e-01
## СезонЗима 6.0245e-01 5.5513e-01
## СезонЛето -8.0817e-01 4.9594e-01
## СезонОсень 1.3876e+00 5.7528e-01
## t value Pr(>|t|)
## (Intercept) 33.1746 < 2.2e-16 ***
## `Среднемесячная заработная плата` 6.2552 3.507e-08 ***
## `Число активных абонентов беспроводного доступа к сети` -3.2978 0.001583 **
## `Уровень безработицы населения` 5.6676 3.578e-07 ***
## СезонЗима 1.0853 0.281818
## СезонЛето -1.6296 0.108027
## СезонОсень 2.4120 0.018698 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Значимыми остались прежние коэффициенты, сами значения коэффициентов не изменились (при округлении до сотых). Соотвественно, интерпретация регрессионной модели остается прежней.
Для обеих моделей проверим наличие и при необходимости исключим влиятельные наблюдения. К таким относятся наблюдения, которые являются одновременно нетипичными и характеризуются высокой степенью влиятельности. Для этого построим график, отображающий оба этих параметра:
plot(lmod, 5)
Обычно явно влиятельные наблюдения располагаются на этом графике в правом верхнем углу и отделяются красной пунктирной линией. В нашем случае таких наблюдений не выявлено.
Повторим для второй модели:
plot(lmod2, 5)
Во втором случае также не выявлено влиятельных наблюдений.
Таким образом, мы провели ключевые тесты оценки качества и можем сделать вывод о том, что построенные нами линейные модели являются качественными, однако обладают не очень высокой прогностической силой.
Так как полученные нами модели являются логистическими (зависимая переменная может принимать значение 0 либо 1), оценим, насколько точно каждая модель предсказывает положительный и отрицательный исходы. Для этого сравним полученные на предыдущем этапе значения столбцов is_online и hyp_love с предсказанными значениями для каждой модели.
## Вычислим чувствительность и специфичность для первой модели:
top <- top %>%
mutate(is_online_predicted = ifelse(logmod$fitted.values > mean(logmod$fitted.values), 1, 0), .after = is_online)
# Верно предсказанные 0 (True Negative):
TN <- top %>%
filter(is_online == 0, is_online_predicted == 0) %>%
nrow()
# Ложно предсказанные 1 (False Positive):
FP <- top %>%
filter(is_online == 0, is_online_predicted == 1) %>%
nrow()
# Ложно предсказанные 0 (False Negative):
FN <- top %>%
filter(is_online == 1, is_online_predicted == 0) %>%
nrow()
# Верно предсказанные 1 (True Positive):
TP <- top %>%
filter(is_online == 1, is_online_predicted == 1) %>%
nrow()
# Специфичность модели:
specif <- TN / (TN + FP)
# Чувствительность:
sens <- TP / (TP + FN)
# Чувствительность и специфичность полученной модели = 0.785 и 0.793. Другими словами наша модель нашла 78.5% из всех истинно положительных исходов. Также в 79.3% случаев, модель правильно предсказала 0 среди общего числа истинно отрицательных исходов.
Построим ROC-кривую, еще один инструмент, который поможет наглядно отобразить качество исследуемой нами модели.
proc <- roc(top$is_online ~ logmod$fitted.values)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
proc
##
## Call:
## roc.formula(formula = top$is_online ~ logmod$fitted.values)
##
## Data: logmod$fitted.values in 58 controls (top$is_online 0) < 14 cases (top$is_online 1).
## Area under the curve: 0.8793
plot(proc)
text(x = 1, y = 0.9, "AUC = 0.88")
Площадь под ROC-кривой (AUC) модет принимать значения от 0 до 1. Высокие значения AUC, близкие к 1, соотвествуют высокому качеству регрессионной модели. В нашем случае AUC = 0.88, в связи с чем можно говорить о достаточно высокой предсказательной силе модели.
Повторим то же самое для второй модели.
## Вычислим чувствительность и специфичность для второй модели:
top <- top %>%
mutate(hyp_love_predicted = ifelse(logmod2$fitted.values > mean(logmod2$fitted.values), 1, 0), .after = hyp_love)
# Верно предсказанные 0 (True Negative):
TN2 <- top %>%
filter(hyp_love == 0, hyp_love_predicted == 0) %>%
nrow()
# Ложно предсказанные 1 (False Positive):
FP2 <- top %>%
filter(hyp_love == 0, hyp_love_predicted == 1) %>%
nrow()
# Ложно предсказанные 0 (False Negative):
FN2 <- top %>%
filter(hyp_love == 1, hyp_love_predicted == 0) %>%
nrow()
# Верно предсказанные 1 (True Positive):
TP2 <- top %>%
filter(hyp_love == 1, hyp_love_predicted == 1) %>%
nrow()
# Специфичность модели:
specif2 <- TN2 / (TN2 + FP2)
# Чувствительность:
sens2 <- TP2 / (TP2 + FN2)
# Чувствительность и специфичность второй модели logmod2 оказались еще выше = 0.84 и 0.82 соответственно. Интерпретировать эти значения можно следующим образом: в 84% случаев модель правильно угадывает 1 и в 82% случаев правильно предсказывает 0.
ROC-кривая и AUC:
proc2 <- roc(top$hyp_love ~ logmod2$fitted.values)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
proc2
##
## Call:
## roc.formula(formula = top$hyp_love ~ logmod2$fitted.values)
##
## Data: logmod2$fitted.values in 22 controls (top$hyp_love 0) < 50 cases (top$hyp_love 1).
## Area under the curve: 0.9118
plot(proc2)
text(x = 1.05, y = 0.9, "AUC = 0.91")
Значение AUC = 0.91, получилось еще выше, чем у предыдущей модели.
Таким образом, мы провели оценку качества для двух логистических регрессионных моделей двумя способами: рассчитав чувствительность и специфичность, а также значение AUC для ROC-кривой.
Для модели, предсказывающей склонность населения предпочитать онлайн-услуги банка:
Модель, предсказывающая склонность населения оформлять ипотеку:
Вторая модель характеризуется более высокими показателями.
Обобщая полученные результаты, можно сделать вывод о том, что обе модели имеют достаточно хорошую предсказательную мощность.
Библиотека Stargazer позволяет в удобном виде отображать характеристики сразу нескольких регрессионных моделей.
Выведем описание полученных линейных моделей:
stargazer(lmod, lmod2, type = "html", title = "Зависимость потребительской активности от средней заработной платы в регионе, числа активных абонентов беспроводного интернета, уровня безработицы населения и времени года", style = )
| Dependent variable: | ||
Индекс потребительской активности
|
Доля безналичных платежей
|
|
| (1) | (2) | |
Среднемесячная заработная плата
|
-0.00002 | 0.0001*** |
| (0.0001) | (0.00001) | |
Число активных абонентов беспроводного доступа к сети
|
0.0005 | -0.0004*** |
| (0.0005) | (0.0001) | |
Уровень безработицы населения
|
0.852 | 1.134*** |
| (1.008) | (0.259) | |
| СезонЗима | 9.749*** | 0.602 |
| (2.262) | (0.581) | |
| СезонЛето | 14.797*** | -0.808 |
| (2.293) | (0.589) | |
| СезонОсень | 14.572*** | 1.388** |
| (2.307) | (0.593) | |
| Constant | 56.059*** | 48.561*** |
| (6.905) | (1.774) | |
| Observations | 72 | 72 |
| R2 | 0.497 | 0.619 |
| Adjusted R2 | 0.450 | 0.584 |
| Residual Std. Error (df = 65) | 6.740 | 1.731 |
| F Statistic (df = 6; 65) | 10.701*** | 17.589*** |
| Note: | p<0.1; p<0.05; p<0.01 | |
Аналогично для логистических моделей:
stargazer(logmod1000, logmod2, type = "html", title = "Зависимость склонности населения предпочитать онлайн-услуги банка и брать ипотеку от средней заработной платы, числа активных абонентов интернета и уровня безработицы населения")
| Dependent variable: | ||
| is_online | hyp_love | |
| (1) | (2) | |
Средняя заработная плата тысячи
|
0.087*** | -0.075** |
| (0.034) | (0.034) | |
Число активных абонентов беспроводного доступа к сети
|
0.0001 | 0.001** |
| (0.0002) | (0.0003) | |
Уровень безработицы населения
|
0.578 | -0.132 |
| (0.463) | (0.418) | |
| СезонЗима | -1.600 | 0.129 |
| (1.077) | (0.942) | |
| СезонЛето | -19.783 | 1.036 |
| (2,262.531) | (1.049) | |
| СезонОсень | -0.720 | 2.483* |
| (0.917) | (1.359) | |
| Constant | -7.228** | 2.658 |
| (3.509) | (2.882) | |
| Observations | 72 | 72 |
| Log Likelihood | -22.152 | -23.555 |
| Akaike Inf. Crit. | 58.304 | 61.110 |
| Note: | p<0.1; p<0.05; p<0.01 | |