Preface

Мы с вами пытаемся комплексно на протяжении нескольких праздничных недель вырабатывать плоскую социологическую попу и растущие не из неё ручки в процессе применения всех наших навыков (обработки данных в dplyr, рисования, статистических тестов и регрессий и т.д.) к тестовой задачке с более чем одной табличкой и более чем парой строчек задания. //ИЛМ

Внимание! Задание нельзя сделать за день перед сдачей на положительную оценку. Мы рассчитываем, в итоге, на 12 часов работы над ним в течение 2,5 недель минимум.

Description

Этот дейтасет эмулирует реальную работу службы поддержки пользователей игровой компании. Наша задача, как приличных Data Engineers, за несколько итераций использовать наши знания в вытаскивании из сырого массива данных осмысленной информации и представить результаты так, чтобы заказчику, который хочет понять насколько эффективно работает его саппорт – насколько довольны его пользователи, стало ну сразу всё понятно.

Зоны работы, на которые нужно обратить внимание:

Сегодняшняя лабораторная знакомит вас с набором данных и заданием + вы можете успеть обсудить и начать применять интересные вам методы визуализации (и статистические тесты).

В результате первой недели работы отчёт должен содержать пункты Визуализация, Агрегация, Тесты. Если вам хочется влезть дальше, скорее всего, вы недостаточно детально подошли к этим пунктам. При активной работе на лабораторной и задавании вопросов, у вас должно уйти 3-4 часа на эту часть.

В результате второй недели работы мы ждем начала/продолжения статистических тестов/регрессии, работы со временем, (начала работы с тегами). Хорошим результатом 2 недели является переработка того, что что вы сделали в первой. 4-5 часов.

Третья неделя работы – Тэги, (Data Mining), финализация отчёта. 3-5 часов.

Пытайтесь оформлять код внятно, понятно для вас, мы будем его использовать дальше. Например, основные функции могут быть вынесены в script.R и вызываться из rmd-отчета с помощью source("script.R").

Задавайте вопросы. ЗАДАВАЙТЕ, пылесосить вышего бегемотика, ВОПРОСЫ.

Промежуточная сдача результатов составляет вашу текущую оценку за модуль (точнее, 3/4 от неё). Опоздание со сдачей этапа более чем на сутки – “0” за него. В него включаем и то, что мы пробовали, но исключили из окончательной версии – графики, подходы, модельки, не давшие результатов.

Финальный отчёт составляет 3/4 от оценки по контрольной работе за модуль. В нём будет оцениваться итоговый результат и прогресс между этапами (переделка итогового продукта). Это – то что вы показываете заказчику (которому нужен результат, а не стенания по поводу “мы делали до 12 часов”), сюда не включается отбраковка (но, в отличие от заказчика, мы её оцениваем по промежуточным отчётикам).

Мы просим каждого из вас воспринимать это не как казнь египетскую, а как возможность повторить, уточнить, выучить, систематизировать и показать персональный максимум после года прокрастинации, отговорок, самозащитных “ну да, я лох, что с меня взять”.

К делу:

require(plyr)
## Loading required package: plyr
require(dplyr)
## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## 
## The following objects are masked from 'package:plyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize
## 
## The following object is masked from 'package:stats':
## 
##     filter
## 
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
require(ggplot2)
## Loading required package: ggplot2
require(stringr)
## Loading required package: stringr
library(DT) #http://rstudio.github.io/DT/


db <- src_sqlite("/principal/materials/digitalmethods/player-support-data.sqlite3")

# TICKETS

tickets <- collect(tbl(db, "tickets"))

tickets$agent <- as.factor(tickets$agent)
tickets$game <- as.factor(tickets$game)

tickets$created_time <- as.POSIXct(strptime(tickets$created_time, format="%Y-%m-%d %H:%M:%S", tz = ""))

summary(tickets)
##    ticket_id         agent                  game     
##  Min.   :   28   Jane   : 305   Boom Beach    :1294  
##  1st Qu.:23988   Lucy   : 301   Clash of Clans:1269  
##  Median :50371   Susan  : 300   Hay Day       :1271  
##  Mean   :49833   Lisa   : 299   NA's          : 426  
##  3rd Qu.:74926   Peter  : 299                        
##  Max.   :99966   (Other):2573                        
##                  NA's   : 183                        
##   created_time                
##  Min.   :2015-01-01 00:00:05  
##  1st Qu.:2015-01-04 14:53:43  
##  Median :2015-01-07 22:12:48  
##  Mean   :2015-01-07 23:38:43  
##  3rd Qu.:2015-01-11 09:41:28  
##  Max.   :2015-01-14 23:51:07  
## 
datatable(tickets, options = list(iDisplayLength = 5)) #http://rstudio.github.io/DT/

# TAGS

tags <- collect(tbl(db, "tags"))
tags$tag_type <- ifelse(str_detect(tags$tag, "[A-Z]{2}"), "lang", "desc")

lang_tags <- filter(tags, tag_type=='lang')
desc_tags <- filter(tags, tag_type=="desc")

summary(tags)
##    ticket_id         tag              tag_type        
##  Min.   :   28   Length:6578        Length:6578       
##  1st Qu.:23580   Class :character   Class :character  
##  Median :49304   Mode  :character   Mode  :character  
##  Mean   :49502                                        
##  3rd Qu.:74607                                        
##  Max.   :99966
datatable(tags, options = list(iDisplayLength = 5))

# AUDITS

audits <- collect(tbl(db, "audits"))
audits$updated_time <- as.POSIXct(strptime(audits$updated_time, format="%Y-%m-%d %H:%M:%S", tz = ""))

summary(audits)
##    ticket_id        status          previous_status   
##  Min.   :   28   Length:5269        Length:5269       
##  1st Qu.:23980   Class :character   Class :character  
##  Median :49938   Mode  :character   Mode  :character  
##  Mean   :49651                                        
##  3rd Qu.:74820                                        
##  Max.   :99966                                        
##   updated_time                
##  Min.   :2015-01-01 02:44:59  
##  1st Qu.:2015-01-05 13:53:32  
##  Median :2015-01-08 19:22:15  
##  Mean   :2015-01-08 17:38:55  
##  3rd Qu.:2015-01-11 23:32:11  
##  Max.   :2015-01-14 23:58:44
datatable(audits, options = list(iDisplayLength = 5))

Joins

# inner_join
# return all rows from x where there are matching values in y, and all columns from x and y. If there are multiple matches between x and y, all combination of the matches are returned.

tickets_with_tags <- inner_join(tickets, tags, by="ticket_id")

# left_join
# return all rows from x, and all columns from x and y. Rows in x with no match in y will have NA values in the new columns. If there are multiple matches between x and y, all combinations of the matches are returned.

tickets_and_their_tags <- left_join(tickets, tags, by="ticket_id")
twt_sum <- tickets_with_tags %>% 
  group_by(tag_type, agent) %>% 
  summarise(tags_count=n())
ggplot(twt_sum) + geom_boxplot(aes(x=tag_type, y=tags_count))

tat_sum <- tickets_and_their_tags %>% 
  group_by(tag_type, agent) %>% 
  summarise(tags_count=n())
ggplot(tat_sum) + geom_boxplot(aes(x=tag_type, y=tags_count))

ru_games <- tickets_with_tags %>%
  filter(created_time>='2015-01-01', created_time<'2015-01-08') %>%  
  filter(tag=="RU") %>%
  group_by(agent, game) %>%
  summarise(tickets_count=n())

ggplot(ru_games) + geom_boxplot(aes(x=game, y=tickets_count))

ru_games_for_test <- ru_games %>% filter(game %in% c("Clash of Clans", "Hay Day"))
ru_games_for_test$game <- factor(as.character(ru_games_for_test$game))

t.test(tickets_count ~ game, data= ru_games_for_test)
## 
##  Welch Two Sample t-test
## 
## data:  tickets_count by game
## t = 0.3873, df = 25.801, p-value = 0.7017
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -0.8177019  1.1971890
## sample estimates:
## mean in group Clash of Clans        mean in group Hay Day 
##                     2.923077                     2.733333
ggplot(tickets) + 
  geom_bar(aes(x=created_time, fill=game)) + 
  scale_fill_brewer(palette = "Accent")
## stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.

ggplot(tickets) + 
  geom_bar(aes(x=created_time, fill=agent)) + 
  scale_fill_brewer(palette = "Paired")
## stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Paired is 12
## Returning the palette you asked for with that many colors
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Paired is 12
## Returning the palette you asked for with that many colors

ggplot(tickets) + 
  geom_bar(aes(x=agent, fill=game)) + 
  scale_fill_brewer(palette = "Accent")

ggplot(audits) + 
  geom_bar(aes(x=updated_time, fill=status)) + 
  scale_fill_brewer(palette = "Set1")
## stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this.

ggplot(audits) + 
  geom_bar(aes(x=status, fill=previous_status)) + 
  scale_fill_brewer(palette = "Set1")