library(dtplyr)
library(dplyr)
library(data.table)
library(xgboost)

train = fread('../input/train.csv', 
              select = c('Semana','Producto_ID', 'Cliente_ID', 'Demanda_uni_equil'))
test = fread('../input/test.csv', select = c("Semana",'id','Cliente_ID', 'Producto_ID'))
train = train[Semana > 3]

train$Demanda_uni_equil = log1p(train$Demanda_uni_equil)

#setting it up so we can merge test+train - inspired by  Bohdan Pavlyshenko's lag script:
train$id = 0; test$Demanda_uni_equil = 0; train$tst = 0; test$tst = 1
rec_train = rbind(train[Semana == 9], test) #this is what we will merge with.
rm(test)
gc()

#now compute mean demand + count on train weeks 3 - 8 then join with weeks 9, 10 ,11:
train[Semana <= 8][, .(mean_client_prod = mean(Demanda_uni_equil), 
                          count_client_prod = .N),
                      by = .(Producto_ID, Cliente_ID)] %>% 
    merge(rec_train, all.y = TRUE, by = c("Producto_ID", "Cliente_ID")) -> rec_train


train[Semana <= 8][, .(mean_prod = mean(Demanda_uni_equil),
                          count_prod = .N),
                      by = .(Producto_ID)] %>% 
    merge(rec_train, all.y = TRUE, by = c("Producto_ID")) -> rec_train


train[Semana <= 8][, .(mean_cliente = mean(Demanda_uni_equil),
                          count_cliente = .N),
                      by = .(Cliente_ID)] %>% 
    merge(rec_train, all.y = TRUE, by = c("Cliente_ID")) -> rec_train

rm(train)

#boosting on week 9 of train - around 10 million training examples:
y_train = rec_train$Demanda_uni_equil[rec_train$tst == 0] 

dtrain = xgb.DMatrix(as.matrix(rec_train[tst == 0] %>% select(- Demanda_uni_equil, -id, - tst)),
label = y_train)
model = xgb.train(data = dtrain, nrounds = 25, max_depth = 8, eta = 0.5)

preds = predict(model, as.matrix(rec_train[tst == 1] %>% select(- Demanda_uni_equil, -id, - tst)))
preds = expm1(preds)
preds[preds < 0] = 0
id = rec_train[tst == 1]$id

solution = data.frame(id = as.integer(id), Demanda_uni_equil = preds)
write.csv(solution, "xgboost_mean_preds_1.csv", row.names = FALSE)