1 Modelo base.
1.1 Datos.
1.2 Importación de tablas de datos
# Carga de librerías
library(tidyverse)
library(data.table)
library(lubridate)
library(GGally)
library(gridExtra)
library(knitr)
# Librerías para el modelado
library(caret)
library(ranger)
Importo todas las tablas con la información de producción y meteorología. Los datos meteorológicos los separo en dos datasets, el primero del año 2014 al 2017 para el entrenamiento y validación del modelo y el segundo con los datos de 2018 para tomar como datos de entrada para la predicción final.
meteo_files <- list.files(path = "data", pattern = "sunlab-faro-meteo")
data_chr <- rep("data/", length(meteo_files))
meteo_files <- paste0(data_chr,meteo_files)
meteo_data <- meteo_files %>% map_df(~fread(.)) %>% as_tibble()
meteo_data_14_17 <- meteo_data %>% filter(year(Datetime) < 2018) %>% as_tibble()
meteo_data_18 <- meteo_data %>% filter(year(Datetime) == 2018) %>% as_tibble()
production_files <- list.files(path = "data", pattern = "sunlab-faro-pv")
data_chr <- rep("data/", length(production_files))
production_files <- paste0(data_chr,production_files)
production_data <- production_files %>% map_df(~fread(.)) %>% as_tibble()
Necesitamos un modelo que prediga la producción del módulo solar B en su orientación óptima. Así que en principio sólo nos tenemos que quedar con la variable B_Optimal - Power DC [W]
del dataset “production_data” (también nos quedamos con la variable “Datetime”, que nos permitirá cruzar esta tabla con la que contiene los datos meteorológicos).
production_data_optimal_b <- production_data %>% select(Datetime, `B_Optimal - Power DC [W]`)
Echamos un vistazo a las variables meteorológicas.
summary(meteo_data_14_17)
## Datetime Ambient Temperature [ºC] Global Radiation [W/m2]
## Length:1886655 Min. :-1.500e+09 Min. : 0.7285
## Class :character 1st Qu.: 1.400e+01 1st Qu.: 1.5651
## Mode :character Median : 1.800e+01 Median : 10.1154
## Mean :-7.137e+03 Mean : 231.2153
## 3rd Qu.: 2.300e+01 3rd Qu.: 437.6787
## Max. : 3.800e+01 Max. :1484.3798
##
## Diffuse Radiation [W/m2] Ultraviolet [W/m2] Wind Velocity [m/s]
## Min. : 1.6 Min. : 0.4954 Min. :-1.500e+09
## 1st Qu.: 1.7 1st Qu.: 0.5106 1st Qu.: 1.000e+00
## Median : 9.9 Median : 1.2513 Median : 2.000e+00
## Mean : 64.7 Mean :14.1992 Mean :-7.153e+03
## 3rd Qu.: 98.0 3rd Qu.:25.1983 3rd Qu.: 3.000e+00
## Max. :776.6 Max. :85.5154 Max. : 1.500e+01
## NA's :399744
## Wind Direction [º] Precipitation [mm] Atmospheric pressure [hPa]
## Min. : 0.0 Min. :0 Min. :-1.500e+09
## 1st Qu.:124.2 1st Qu.:0 1st Qu.: 1.013e+03
## Median :237.5 Median :0 Median : 1.016e+03
## Mean :214.2 Mean :0 Mean :-4.106e+03
## 3rd Qu.:298.3 3rd Qu.:0 3rd Qu.: 1.020e+03
## Max. :360.0 Max. :2 Max. : 1.036e+03
## NA's :1301023 NA's :1301023
## Direct Radiation [W/m2]
## Min. : 1.6
## 1st Qu.: 1.7
## Median : 8.6
## Mean : 63.9
## 3rd Qu.: 91.9
## Max. :790.1
## NA's :1486911
summary(meteo_data_18)
## Datetime Ambient Temperature [ºC] Global Radiation [W/m2]
## Length:10079 Min. : 5.100 Min. : 0.9146
## Class :character 1st Qu.: 9.117 1st Qu.: 1.5885
## Mode :character Median :11.583 Median : 2.2009
## Mean :11.764 Mean :106.7527
## 3rd Qu.:14.500 3rd Qu.:144.7449
## Max. :19.200 Max. :718.0579
##
## Diffuse Radiation [W/m2] Ultraviolet [W/m2] Wind Velocity [m/s]
## Min. : 1.597 Min. : 0.4973 Min. :0.000
## 1st Qu.: 1.659 1st Qu.: 0.5087 1st Qu.:1.683
## Median : 2.063 Median : 0.5153 Median :2.450
## Mean : 35.135 Mean : 6.2665 Mean :2.497
## 3rd Qu.: 59.762 3rd Qu.: 9.4911 3rd Qu.:3.167
## Max. :368.154 Max. :35.2159 Max. :7.917
##
## Wind Direction [º] Precipitation [mm] Atmospheric pressure [hPa]
## Min. : 0.0 Min. :0.00e+00 Min. :1000
## 1st Qu.:270.6 1st Qu.:0.00e+00 1st Qu.:1003
## Median :311.2 Median :0.00e+00 Median :1029
## Mean :277.9 Mean :9.92e-05 Mean :1020
## 3rd Qu.:323.2 3rd Qu.:0.00e+00 3rd Qu.:1032
## Max. :359.8 Max. :1.00e+00 Max. :1035
##
## Direct Radiation [W/m2]
## Min. : NA
## 1st Qu.: NA
## Median : NA
## Mean :NaN
## 3rd Qu.: NA
## Max. : NA
## NA's :10079
Y para este modelo cortamos por lo sano y nos quedamos sólo con las variables que no presentan valores nulos en los datos de entrenamiento.
meteo_data_14_17_global_rad <- meteo_data_14_17 %>% select(Datetime,
`Global Radiation [W/m2]`,
`Ambient Temperature [ºC]`,
`Ultraviolet [W/m2]`,
`Wind Velocity [m/s]`,
`Wind Direction [º]`)
1.3 Modelo base
Cruzamos ambos datasets con la ayuda de la variable Datetime. Nos aseguramos de que no haya ningún valor nulo y renombramos las variables.
data <- left_join(production_data_optimal_b, meteo_data_14_17_global_rad, by = "Datetime") %>% na.omit()
data <- data %>% rename(global_radiation = `Global Radiation [W/m2]`,
power = `B_Optimal - Power DC [W]`,
temp = `Ambient Temperature [ºC]`,
wind_vel = `Wind Velocity [m/s]`,
wind_dir = `Wind Direction [º]`,
ultra_vi = `Ultraviolet [W/m2]`)
Echamos un vistazo gráficamente a la relación entre la energía producida y la radiación solar (sólo utilizamos una parte reducida de los datos para que “pinte” el gráfico rápidamente). Y como es de esperar la relación es clara y positiva.
set.seed <- 42
sample_data <- sample_n(data, 10000)
ggplot(data = sample_data, aes(x = global_radiation, y = power)) +
geom_point()
Y pasamos a generar el modelo y a evaluarlo.
data <- data %>% select(-Datetime)
set.seed(42)
trainIndex <- createDataPartition(data$power, p = .9,
list = FALSE,
times = 1)
train_data <- data[trainIndex,]
validation_data <- data[-trainIndex,]
X_validation_data <- validation_data %>% select(-power)
y_validation_data <- validation_data %>% select(power)
# Generamos un modelo con un random forest de solo 100 árboles con el paquete Ranger. Utilizamos los valores por defecto de todos sus parámetros.
rf_mod <- ranger(power ~ .,
data = train_data,
num.trees = 100,
seed = 42)
# Generamos una predicción con el modelo generado con los datos de validación
prediction <- predict(rf_mod, X_validation_data)
y_validation_data <- c(y_validation_data$power)
prediction <- c(prediction$predictions)
# Y lo evaluamos obteniendo el MAE y el R cuadrado.
MAE <- MAE(y_validation_data, prediction)
MAE
r_squared <- R2(prediction,y_validation_data)
r_squared
Con este modelo obtenemos un MAE de 15,92 y un R cuadrado de 0,87
[1] 15.92131 [1] 0.8684656
Utilizamos el modelo resultante para generar mi primera predicción.
# Generamos el dataset para la predicción
pred_data <- meteo_data_18 %>% rename(global_radiation = `Global Radiation [W/m2]`,
temp = `Ambient Temperature [ºC]`,
wind_vel = `Wind Velocity [m/s]`,
wind_dir = `Wind Direction [º]`,
ultra_vi = `Ultraviolet [W/m2]`) %>%
arrange(Datetime) %>%
select(global_radiation, temp, wind_vel, wind_dir, ultra_vi)
prediction <- predict(rf_mod, pred_data)
predictions <- prediction$predictions %>%
as.data.frame()
colnames(predictions) <- "B_Optimal - Power DC [W]"
Datetime <- meteo_data_18 %>% select(Datetime) %>% arrange(Datetime)
submission_01 <- bind_cols(Datetime, predictions)
write_csv(submission_01, "submission_01.csv")
En el primer envío me devolvió un error. El problema es que no hay que enviar las predicciones para todos los registros disponibles de 2018, sino únicamente los que trae el template. Así que generamos de nuevo el csv, pero esta vez cruzandolo con el archivo “Solar_Template.csv”.
template <- read_delim("data/Solar_Template.csv", delim = ";") %>% select(Datetime)
submission_01 <- read_csv("submission_01.csv")
submission_02 <- template %>% left_join(submission_01, by = "Datetime")
write_csv(submission_02, "submission_02.csv")
These are the results from my base model for this challenge. I used for this model the features with less number of NAs: Global Radiation [W/m2]
, Ambient Temperature [ºC]
, Ultraviolet [W/m2]
, Wind Velocity [m/s]
and Wind Direction [º]
)
I applied a random forest of just 100 trees to the data. I used the ranger package on R.
rf_mod <- ranger(power ~ .,
data = train_data,
num.trees = 100,
splitrule = “variance”,
min.node.size = 5,
seed = 42)