выполнил: Григорий Михолап
дата: 18/01/2016
Задание:
Есть данные по уровням match-3 игры: сложность, отток пользователь, количество покупок. Проанализировать, как связаны между собой сложность уровней и отток на этих уровнях. Сложность определяется как количество попыток до победы на уровне, отток – процент людей, которые не перешли на следующий уровень относительно всех тех, кто начал первый уровень. Проверить, есть ли связь между количеством покупок на уровнях и этими показателями. Данные представлены в файле “Data.xls” на вкладке «Сложность уровней».
Выводы кратко:
Между Покупками и Сложностью существует положительная связь, т.е. рост одной переменной сопровождается ростом другой. Динамика этого роста зависит от уровня игры. Например, на нижних уровнях небольшие изменения сложности приводят к большему росту числа покупок, на более высоких уровнях рост покупок не так резко реагирует на рост сложности
Также отток совместно со сложностью влияют на покупки. Влияние оттока на покупки имеет более сложный характер - при невысокой сложности влияние оттока на покупки по абсолютной величине невелико, но может быть как положительным так и отрицательным. При сложности более 2 пунктов влияние положительно.
обнаружена интересная зависимость связывающая уровни и среднее количество покупок на уровне, которая показывает, резкий рост среднего числа покупок ближе к концу игры.
Замечание по поводу программного кода: Программный код, который используется в отчете, в т.ч. и некоторые операции (такие как загрузка и подготовка данных для анализа) не были включены в отчет, при необходимости все эти данные вы можете найти по ссылке
При загрузке данных я переименовал столбцы и наша таблица теперь выглядит так
## level slozn ottok pokupki
## 1 1 1.00 0.00 38
## 2 2 1.00 15.83 17
## 3 3 1.00 9.93 15
## 4 4 1.01 5.44 12
## 5 5 1.17 4.06 8
## 6 6 1.42 3.38 18
При анализе нам понадобится факторная версия переменной level
, мы разобъем переменную level
на 3 уровня [ 1, 35) [35, 68) [68,100] и сохраним в новой переменной level3
## level slozn ottok pokupki level3
## 1 1 1.00 0.00 38 [ 1, 35)
## 2 2 1.00 15.83 17 [ 1, 35)
## 3 3 1.00 9.93 15 [ 1, 35)
## 4 4 1.01 5.44 12 [ 1, 35)
## 5 5 1.17 4.06 8 [ 1, 35)
## 6 6 1.42 3.38 18 [ 1, 35)
Посмотрим есть ли в нашей таблице пропущенные значения
## level slozn ottok pokupki level3
## 0 0 0 0 0
Пропущенных значений нет
посмотрим на квантили значений наших переменных
## slozn ottok pokupki level3
## Min. : 1.000 Min. : 0.0000 Min. : 1.00 [ 1, 35):34
## 1st Qu.: 1.567 1st Qu.: 0.0300 1st Qu.: 11.75 [35, 68):33
## Median : 2.245 Median : 0.1200 Median : 23.00 [68,100]:33
## Mean : 3.426 Mean : 0.9986 Mean : 29.19
## 3rd Qu.: 4.473 3rd Qu.: 0.6400 3rd Qu.: 42.00
## Max. :13.220 Max. :15.8300 Max. :105.00
Параметр level3
факторный, остальные параметры - числовые, распределения несимметричные, но явных выбросов нет.
Вспоминая, что наша задача найти зависимости между переменными Отток, Покупки и Сложность для начала посмотрим на попарные корреляции между нашими переменными.
Анализ данного графика показывает, что между покупками и сложностью существует достаточно сильная линейная связь (коэффициент корреляции 0.58
). Есть слабая корреляция в парах Уровень-сложность и Уровень-Отток, оставшиеся пары значений практически не коррелируют. Например, увеличение сложности практически не влияет на отток (!) и количество покупок тоже не связано с оттоком - это выглядит несколько неожиданно.
Рассмотрим более детально связь между количеством покупок и сложностью уровня. В качестве дополнительного предиктора можно добавить в модель уровень игры, который показывает небольшую корреляцию со сложностью.
мы видим что зависимость между покупками и сложностью похожа на линейную, также расскраска графика по группам переменной level3
подсказывает, что в модель можно попробовать включить и взаимодействие переменных slozn:level3
.
Переменных у нас немного и мы можем попробовать построить несколько моделей с различными комбинациями. Построим 4 модели: 1. со всеми переменными, 2. с переменными level3
и slozn
, 3. только с переменной slozn
и 4. с переменными slozn
и ottok
. И сравним эти модели с помощью информационного критерия Акаике (который реализован в R
с помощью функции AIC
)
fit1 <- lm(pokupki~., data = df[,-c(1)]) #1. со всеми переменными
fit2 <- lm(pokupki~slozn, data = df) # 2. только с переменной `slozn`
fit3 <- lm(pokupki~level3:slozn, data = df) # 3. с переменной `level3` и `slozn`
fit4 <- lm(pokupki~slozn*ottok, data=df)
AIC(fit1,fit2,fit3,fit4)
## df AIC
## fit1 6 828.4315
## fit2 3 832.0135
## fit3 5 820.5404
## fit4 5 824.4357
Предпочтение нужно отдавать моделям с меньшими значениями AIC, в нашем случае наилучшей будет модель fit3
с переменными level3
и slozn
. Поэтому остановимся на данной модели, т.к. она к тому же достаточно простая и легко интерпретируется.
Замечание: также модель fit3
имеет минимальную сумму квадратов ошибок и максимальный показатель Adjusted R-squared среди рассмотренных моделей, что также свидетельстует в ее пользу.
Замечание2: ниже мы также более подробно рассмотрим 2-ю по рейтингу модель fit4
, она к тому же содержит интересующий нас предиктор ottok
.
Диагностика модели
проверим нашу линейную модель на соответствие основным требованиям
1.1 нормальность остатков (тест Шапиро-Вилка)
##
## Shapiro-Wilk normality test
##
## data: fit3$residuals
## W = 0.89808, p-value = 1.149e-06
Требование НЕ выполнено! Тест показал, что остатки не распределены нормально
1.2 визуальная оценка нормальности остатков (QQ-plot)
визуальная оценка подсказывает, что такое отклонение от нормального распределения можно исправить степенным преобразованием зависимой переменной (об этом ниже)
2. независимость остатков (тест Дарбина-Уотсона)
## lag Autocorrelation D-W Statistic p-value
## 1 -0.03558285 2.04064 0.998
## Alternative hypothesis: rho != 0
Требование выполнено! Т.к. p.value>0.05, то остатки независимы
3. тест на гомоскедастичность остатков
## Non-constant Variance Score Test
## Variance formula: ~ fitted.values
## Chisquare = 2.983176 Df = 1 p = 0.08413405
Требование выполнено! Т.к. p.value>=0.05, то дисперсия остатков равномерна (т.е. гомоскедастичность выполняется)
Подгонка модели
Для того, чтобы привести остатки к нормальному распределению, можно воспользоваться степенным преобразованием зависимой переменной. Функция powerTransform
рекомендует нужную степень.
## bcPower Transformation to Normality
##
## Est.Power Std.Err. Wald Lower Bound Wald Upper Bound
## df$pokupki 0.2829 0.0942 0.0982 0.4676
##
## Likelihood ratio tests about transformation parameters
## LRT df pval
## LR test, lambda = (0) 9.884543 1 1.666729e-03
## LR test, lambda = (1) 46.261255 1 1.034905e-11
Как видим, рекомендуется извлечь кубический корень из зависимой переменной. Попробуем перестроить нашу модель
fit3up <- lm(I(pokupki^(1/3))~level3:slozn, data = df)
и проверить заново все тесты
Тест | Результат исходный | Результат после преобразования |
---|---|---|
Нормальность остатков | 0 (NO) |
0.3112 (YES) |
Независимость остатков | 0.998 (YES) |
0.328 (YES) |
Гомоскедастичность остатков | 0.0841 (YES) |
0.2326 (YES) |
Т.о. мы видим, что наша модель удовлетворяет всем необходимым требованиям.
Посмотрим на основные параметры построенной модели
## Residual standard error: 0.5553 on 96 degrees of freedom
## Multiple R-squared: 0.5712 Adjusted R-squared: 0.5578
## F-statistic: 42.62 on 3 and 96 DF, p-value: < 2.22e-16
Estimate | Std. Error | t value | Pr(>|t|) | |
---|---|---|---|---|
(Intercept) | 1.9317 | 0.1024 | 18.87 | 0.0000 |
level3[ 1, 35):slozn | 0.4442 | 0.0644 | 6.90 | 0.0000 |
level3[35, 68):slozn | 0.2484 | 0.0284 | 8.75 | 0.0000 |
level3[68,100]:slozn | 0.2175 | 0.0215 | 10.13 | 0.0000 |
Коэффициент Adjusted R-squared = 0.56
говорит о том, что наша модель объясняет 56% вариативности зависимой переменной pokupki
что достаточно хороший показатель.
Все коэффициенты статистически значимы. Аналитически данную зависимость можно записать формулой pokupki^(1/3) = 1.93 + F(level)*slozn + Err
, где F
- функция от уровня, заданная таблицей:
Level | [ 1, 35) | [35, 68) | [68,100] |
---|---|---|---|
F(level) | 0.44 | 0.25 | 0.22 |
а Err
- нормально распределенная по закону N(0,0.55) случайная величина. Err
- ошибка модели, которая неизбежно возникает, т.к. не все факторы влияющие на зависимую переменную учтены в модели. По сути в нашей модели мы учли только сложность и уровень. Другие факторы из имеющихся у нас, модель улучшить не смогли.
Визуализация результатов
т.е. мы видим, что наша линейная модель для каждого из 3-х уровней содержит отдельную аппроксимирующую прямую. И на начальных уровнях (красный цвет) это прямая растет более резко, чем на последующих уровнях, это значит, что увеличение сложности на 1 дает больший прирост покупок на начальных уровнях.
Замечание: при построении модели в зависимости целей построения модели, можно пренебречь некоторыми требованиями диагностики модели. В нашем случаем мы могли бы остановиться на модели без степенного преобразования, это бы дало нам более простую и интерпретируемую модель.
Рассмотрим более подробно построенную нами выше модель fit4=pokupki~slozn*ottok
fit4 <- lm(pokupki~slozn*ottok, data=df)
Диагностика модели (сделанная по той же схеме, как и для предыдущей модели) показала, что необходимо степенное преобразование зависимой переменной. Обновим модель:
fit4up <- lm(I(pokupki^(1/3))~slozn*ottok, data=df)
Для такой модели все указанные выше тесты выполняются. Посмотрим теперь на параметры модели
## Residual standard error: 0.5689 on 96 degrees of freedom
## Multiple R-squared: 0.5499 Adjusted R-squared: 0.5358
## F-statistic: 39.1 on 3 and 96 DF, p-value: < 2.22e-16
Estimate | Std. Error | t value | Pr(>|t|) | |
---|---|---|---|---|
(Intercept) | 2.1248 | 0.0993 | 21.39 | 0.0000 |
slozn | 0.1917 | 0.0213 | 8.98 | 0.0000 |
ottok | -0.1523 | 0.0543 | -2.81 | 0.0061 |
slozn:ottok | 0.1305 | 0.0411 | 3.18 | 0.0020 |
Коэффициент Adjusted R-squared = 0.54
говорит о том, что наша модель объясняет 54% вариативности зависимой переменной pokupki
что достаточно хороший показатель.
Все коэффициенты статистически значимы. Аналитически данную зависимость можно записать формулой pokupki^(1/3) = 2.12 + 0.19*slozn - 0.15*ottok + 0.13*slozn*ottok + Err
, где Err
- нормально распределенная по закону N(0,0.56) случайная величина.
Мы видим, что при невысокой сложности (около 1 пункта) влияние оттока на покупки по абсолютной величине невелико, оно может быть как положительным так и отрицательным. При сложности более 2 пунктов влияние положительно.
Предварительный анализ показал, что отток не коррелирует ни со сложностью, ни с покупками, посмотрим как отток зависит от уровня игры
Мы видим, что отток после 25-го уровня очень близок к нулю. Среднее значение оттока на уровнях 25-100 равно 0.2771053%. Такие низкие значения оттока с увеличеним уровня игры мы имеем из-за методики расчета оттока - “отток – процент людей, которые не перешли на следующий уровень относительно всех тех, кто начал первый уровень”.
Давайте посмотрим на локальный отток на каждом уровне, т.е. процент людей, которые не перешли на следующий уровень относительно всех тех, кто начал данный уровень“. Возможно данная переменная будет коррелировать с другими переменным.
Локальный отток ottok2
рассчитывается следующим образом
df$ottok2 <- df$ottok
s <- df$ottok[1]
df$ottok2[1] <- df$ottok[1]
for (i in 2:100) {
df$ottok2[i] <- df$ottok[i]/(100-s)
s <- s + df$ottok[i]
}
Проверим коррелирует ли локальный отток с нашими переменными Сложность, Покупки и Уровень соответственно
## [1] 0.02603304
## [1] 0.0811148
## [1] 0.0592195
как видим, связи не наблюдается, мои ожидания о корреляции новой переменной с другими не оправдались.
Замечание: Но все-таки польза от введения новой переменной есть - обнаружились уровни, на которых локальный отток выше 30%, т.е. с данных уровней ушли треть дошедших до него игроков. Это следующию уровни:
## [1] 59 61 85
При этом сложность заданий на этих уровнях не выше средней, что же явилось причиной столь высокого оттока? Стоит внимательней проанализировать поведение пользователей на этих уровнях, возможно в интерфейсе игры на этих уровнях есть проблемы с юзабилити или вовсе какие-то баги.
Среднее число покупок на уровне рассчитывается следующим фрагментом кода и сохраняется в новый столбец pokupkiAver
. Данный показатель характеризует средние объемы покупок одного пользователя.
s <- 0
for (i in 1:100) {
df$pokupkiAver[i] <- df$pokupki[i]/(100-s)
s <- s + df$ottok[i]
}
Предварительный анализ (не включенный в отчет) распределения и коррелиции для переменной pokupkiAver
показал, что среднее число покупок на уровне достаточно сильно коррелирует с уровнем - это можно проанализировать подробнее
построим линейную модель, описывающую данную зависимость учитывая ступенчатый характер зависимости в качестве предикторов возьмем level
и level3
. Также на диаграмме выше видны в правом верхнем углу подозрительно большие значения, с помощью теста Бонферони найдем выбросы и удалим их при построении модели (я выбросил четыре значения - строки 97,98,87,92)
tt <- outlierTest(fit) # ищем выбросы - 92
fit <- lm(pokupkiAver~level*level3, data = df[-c(97,98,87,92),])
## Residual standard error: 21.28 on 90 degrees of freedom
## Multiple R-squared: 0.8025 Adjusted R-squared: 0.7915
## F-statistic: 73.13 on 5 and 90 DF, p-value: < 2.22e-16
Estimate | Std. Error | t value | Pr(>|t|) | |
---|---|---|---|---|
(Intercept) | -0.0833 | 7.4635 | -0.01 | 0.9911 |
level | 0.0564 | 0.3720 | 0.15 | 0.8798 |
level3[35, 68) | -13.6284 | 21.5207 | -0.63 | 0.5282 |
level3[68,100] | -279.6709 | 36.1654 | -7.73 | 0.0000 |
level:level3[35, 68) | 0.3115 | 0.5383 | 0.58 | 0.5643 |
level:level3[68,100] | 4.2847 | 0.5650 | 7.58 | 0.0000 |
Мы получили достаточно точную модель Adjusted R-squared = 0,79
связывающую уровни level
и среднее количество покупок на уровне pokupkiAver
. Аналитически эту зависимость можно записать формулой pokupkiAver = -280 + 4.3*level
где level>=68
. Т.о. начиная примерно с 68-го уровня, каждый игрок переходя на следующий уровень делает на 4 покупки больше, чем сделал на предыдущем уровне. Вообще данная зависимость интересна таким резким ростом покупок в конце игры, возможно это объясняется тем, что в конце игры остаются только самые вовлеченные игроки, которые твердо решили дойти до конца невзирая на затраты.
1. Сложность связана с количеством покупок следующей формулой
pokupki^(1/3) = 1.93 + F(level)*slozn + Err
, где F
- функция от уровня, заданная таблицей:
Level | [ 1, 35) | [35, 68) | [68,100] |
---|---|---|---|
F(level) | 0.44 | 0.25 | 0.22 |
а Err
- нормально распределенная по закону N(0,0.55) случайная величина.
2. Также найдена достаточно сильная и устойчивая зависимость между 3 переменными интереса - Покупками, Оттоком и Сложностью, данная зависимость выглядит так: pokupki^(1/3) = 2.12 + 0.19*slozn - 0.15*ottok + 0.13*slozn*ottok + Err
, где Err
- нормально распределенная по закону N(0,0.56) случайная величина.
3. Также обнаружена интересная зависимость связывающая уровни level
и среднее количество покупок на уровне pokupkiAver
.
pokupkiAver = -280 + 4.3*level
где level>=68