2 Solución reto día del Hackathon.
En este apartado está descrito cómo nuestro equipo solucionó este reto durante el Hackathon. Se han añadido comentarios para dar más claridad al desarrollo. Aparte de estas notas no hemos añadido nada sustancial al análisis que no fuese incluido durante la competición.
Para ver un análisis hecho con más tiempo y más cercano a lo que nos hubiese gustado hacer puedes pasar directamente al apartado 3 de este notebook.
2.1 Carga de las librerias necesarias.
library(tidyverse)
library(readxl)
library(VIM)
library(GGally)
2.2 Preparación datos “train”.
Los datasets originales de train estaban en formato ‘xls’ y al abrirlos daban un error de formato. No pudimos importarlos en R directamente, ya que nos daba un error con la importación también. Así que los guardamos como ‘csv’ para posteriormente importarlos en R. En este proceso también tuvimos algún problema, así que la importación de los datos nos llevó mucho más tiempo de lo esperado.
Archivos originales “train”:
‘sunlab-faro_meteo_2015.xls’
‘sunlab-faro_meteo_2016.xls’
‘sunlab-faro-pv-2015.xls’
‘sunlab-faro-pv-2016.xls’
Importamos los archivos ya convertidos a formato ‘csv’.
meteo_2015 <- read_csv("./data/hackathon_data/train/sunlab-faro_meteo_2015.csv")
meteo_2016 <- read_csv("./data/hackathon_data/train/sunlab-faro_meteo_2016.csv")
prod_2015 <- read_csv("./data/hackathon_data/train/sunlab-faro-pv-2015.csv")
prod_2016 <- read_csv("./data/hackathon_data/train/sunlab-faro-pv-2016.csv")
Unimos las parejas de archivos de datos de producción y meteorológicos.
meteo_2015_2016 <- bind_rows(meteo_2015, meteo_2016)
prod_2015_2016 <- bind_rows(prod_2015, prod_2016)
# Borramos los archivos originales
rm(meteo_2015)
rm(meteo_2016)
rm(prod_2015)
rm(prod_2016)
Echamos un vistazo a los datos de producción con las funciones ‘summary’ y ‘glimpse’.
summary(prod_2015_2016)
## Datetime A_Vertical - Voltage DC [V]
## Min. :2015-01-01 07:40:00 Min. :10.20
## 1st Qu.:2015-05-28 18:54:30 1st Qu.:26.65
## Median :2015-10-08 17:39:00 Median :27.95
## Mean :2015-12-04 18:29:34 Mean :26.28
## 3rd Qu.:2016-07-19 14:47:30 3rd Qu.:29.10
## Max. :2016-12-29 17:31:00 Max. :35.05
## NA's :13979
## A_Vertical - Current DC [A] A_Vertical - Power DC [W]
## Min. :0.000 Min. : 0.00
## 1st Qu.:0.710 1st Qu.: 15.90
## Median :1.822 Median : 50.94
## Mean :2.252 Mean : 63.56
## 3rd Qu.:3.460 3rd Qu.:100.67
## Max. :8.105 Max. :245.18
## NA's :13979 NA's :13979
## A_Optimal - Voltage DC [V] A_Optimal - Current DC [A]
## Min. :10.10 Min. : 0.000
## 1st Qu.:27.05 1st Qu.: 1.097
## Median :27.90 Median : 3.482
## Mean :27.53 Mean : 3.574
## 3rd Qu.:28.95 3rd Qu.: 5.860
## Max. :35.30 Max. :10.238
## NA's :8342 NA's :8342
## A_Optimal - Power DC [W] A_Horizontal - Voltage DC [V]
## Min. : 0.00 Min. :10.10
## 1st Qu.: 30.74 1st Qu.:26.90
## Median : 99.79 Median :27.70
## Mean :100.48 Mean :26.53
## 3rd Qu.:165.06 3rd Qu.:28.90
## Max. :307.64 Max. :35.35
## NA's :8342 NA's :9039
## A_Horizontal - Current DC [A] A_Horizontal - Power DC [W]
## Min. : 0.000 Min. : 0.00
## 1st Qu.: 1.095 1st Qu.: 27.55
## Median : 2.930 Median : 83.44
## Mean : 3.163 Mean : 87.10
## 3rd Qu.: 5.055 3rd Qu.:140.21
## Max. :10.238 Max. :304.63
## NA's :9039 NA's :9039
## A_Vertical - Temperature [ºC] A_Optimal - Temperature [ºC]
## Min. : 1.80 Min. : 2.0
## 1st Qu.:22.60 1st Qu.:21.5
## Median :30.20 Median :29.0
## Mean :29.21 Mean :28.8
## 3rd Qu.:35.80 3rd Qu.:36.0
## Max. :52.80 Max. :58.6
##
## A_Horizontal - Temperature [ºC] B_Vertical - Voltage DC [V]
## Min. : 1.40 Min. :10.30
## 1st Qu.:20.70 1st Qu.:26.45
## Median :28.30 Median :27.00
## Mean :28.59 Mean :25.48
## 3rd Qu.:36.30 3rd Qu.:27.60
## Max. :64.80 Max. :34.65
## NA's :11201
## B_Vertical - Current DC [A] B_Vertical - Power DC [W]
## Min. :0.000 Min. : 0.00
## 1st Qu.:0.678 1st Qu.: 14.95
## Median :1.847 Median : 49.89
## Mean :2.382 Mean : 64.48
## 3rd Qu.:3.695 3rd Qu.:102.69
## Max. :9.078 Max. :255.99
## NA's :11201 NA's :11201
## B_Optimal - Voltage DC [V] B_Optimal - Current DC [A]
## Min. :10.35 Min. : 0.000
## 1st Qu.:26.70 1st Qu.: 1.083
## Median :27.35 Median : 3.438
## Mean :26.31 Mean : 3.654
## 3rd Qu.:28.00 3rd Qu.: 6.250
## Max. :35.15 Max. :10.238
## NA's :6730 NA's :6730
## B_Optimal - Power DC [W] B_Horizontal - Voltage DC [V]
## Min. : 0.00 Min. :10.65
## 1st Qu.: 27.08 1st Qu.:26.70
## Median : 96.81 Median :27.35
## Mean : 99.69 Mean :26.26
## 3rd Qu.:170.25 3rd Qu.:28.35
## Max. :302.01 Max. :35.10
## NA's :6730 NA's :11902
## B_Horizontal - Current DC [A] B_Horizontal - Power DC [W]
## Min. : 0.000 Min. : 0.00
## 1st Qu.: 1.077 1st Qu.: 25.83
## Median : 2.857 Median : 81.42
## Mean : 3.120 Mean : 85.54
## 3rd Qu.: 4.980 3rd Qu.:139.04
## Max. :10.238 Max. :300.98
## NA's :11902 NA's :11902
## B_Vertical - Temperature [ºC] B_Optimal - Temperature [ºC]
## Min. : 3.20 Min. : 2.30
## 1st Qu.:23.50 1st Qu.:22.50
## Median :30.50 Median :30.90
## Mean :29.53 Mean :30.67
## 3rd Qu.:35.70 3rd Qu.:38.70
## Max. :51.10 Max. :62.00
##
## B_Horizontal - Temperature [ºC]
## Min. : 1.60
## 1st Qu.:21.10
## Median :28.30
## Mean :28.59
## 3rd Qu.:36.10
## Max. :62.10
##
glimpse(prod_2015_2016)
## Observations: 420,507
## Variables: 25
## $ Datetime <dttm> 2015-01-09 12:52:00, 2015-0...
## $ `A_Vertical - Voltage DC [V]` <dbl> 29.35, 29.10, 29.10, 29.35, ...
## $ `A_Vertical - Current DC [A]` <dbl> 6.4125, 6.3975, 6.3325, 6.41...
## $ `A_Vertical - Power DC [W]` <dbl> 188.206875, 186.167250, 184....
## $ `A_Optimal - Voltage DC [V]` <dbl> 28.75, 28.45, 28.45, 28.75, ...
## $ `A_Optimal - Current DC [A]` <dbl> 7.1700, 7.1925, 7.0925, 7.21...
## $ `A_Optimal - Power DC [W]` <dbl> 206.13750, 204.62662, 201.78...
## $ `A_Horizontal - Voltage DC [V]` <dbl> 29.25, 29.50, 29.45, 29.50, ...
## $ `A_Horizontal - Current DC [A]` <dbl> 4.3225, 4.2525, 4.1825, 4.30...
## $ `A_Horizontal - Power DC [W]` <dbl> 126.43313, 125.44875, 123.17...
## $ `A_Vertical - Temperature [ºC]` <dbl> 32.6, 32.4, 33.2, 32.2, 32.8...
## $ `A_Optimal - Temperature [ºC]` <dbl> 28.8, 28.6, 29.4, 28.2, 27.8...
## $ `A_Horizontal - Temperature [ºC]` <dbl> 26.5, 26.1, 26.8, 26.4, 26.1...
## $ `B_Vertical - Voltage DC [V]` <dbl> 27.55, 27.60, 27.40, 27.40, ...
## $ `B_Vertical - Current DC [A]` <dbl> 7.0925, 7.0475, 7.0100, 7.14...
## $ `B_Vertical - Power DC [W]` <dbl> 195.39837, 194.51100, 192.07...
## $ `B_Optimal - Voltage DC [V]` <dbl> 27.85, 28.05, 27.85, 28.05, ...
## $ `B_Optimal - Current DC [A]` <dbl> 7.2225, 7.1125, 7.0450, 7.17...
## $ `B_Optimal - Power DC [W]` <dbl> 201.14663, 199.50563, 196.20...
## $ `B_Horizontal - Voltage DC [V]` <dbl> 29.05, 29.05, 28.75, 28.95, ...
## $ `B_Horizontal - Current DC [A]` <dbl> 4.1775, 4.1275, 4.1125, 4.19...
## $ `B_Horizontal - Power DC [W]` <dbl> 121.356375, 119.903875, 118....
## $ `B_Vertical - Temperature [ºC]` <dbl> 31.2, 31.5, 31.9, 31.7, 32.2...
## $ `B_Optimal - Temperature [ºC]` <dbl> 30.2, 30.0, 30.9, 29.9, 30.7...
## $ `B_Horizontal - Temperature [ºC]` <dbl> 25.3, 24.9, 25.7, 25.1, 25.6...
Y aquí directamente ya decidimos quedarnos directamente con las variables target a predecir ‘A_Optimal - Power DC [W]’ y ‘B_Optimal - Power DC [W]’) más la variable ‘Datetime’ que nos servirá para cruzar esta tabla con la tabla de datos meteorológicos.
prod_2015_2016_final <- prod_2015_2016 %>%
select(Datetime,
'A_Optimal - Power DC [W]',
'B_Optimal - Power DC [W]')
Vemos los principales estadísticos de las variables de la tabla de datos meteorológicos.
summary(meteo_2015_2016)
## Datetime Ambient Temperature [ºC]
## Min. :2015-01-01 00:00:00 Min. :-1.500e+09
## 1st Qu.:2015-05-26 11:06:30 1st Qu.: 1.400e+01
## Median :2015-10-18 23:12:00 Median : 1.800e+01
## Mean :2015-11-27 03:00:27 Mean :-5.358e+03
## 3rd Qu.:2016-05-17 18:32:30 3rd Qu.: 2.300e+01
## Max. :2016-12-31 23:00:00 Max. : 3.800e+01
##
## Global Radiation [W/m2] Diffuse Radiation [W/m2] Ultraviolet [W/m2]
## Min. : 0.7285 Min. : 1.6 Min. : 0.4954
## 1st Qu.: 1.5693 1st Qu.: 1.7 1st Qu.: 0.5106
## Median : 13.0063 Median : 16.5 Median : 1.5008
## Mean : 237.1203 Mean : 68.2 Mean :14.5440
## 3rd Qu.: 452.7272 3rd Qu.:103.7 3rd Qu.:26.0017
## Max. :1421.3282 Max. :720.4 Max. :84.2660
## NA's :399744
## Wind Velocity [m/s] Wind Direction [º] Precipitation [mm]
## Min. :-1.500e+09 Min. : 0.0 Min. :0
## 1st Qu.: 1.000e+00 1st Qu.:123.6 1st Qu.:0
## Median : 2.000e+00 Median :235.8 Median :0
## Mean :-5.375e+03 Mean :212.8 Mean :0
## 3rd Qu.: 3.000e+00 3rd Qu.:296.7 3rd Qu.:0
## Max. : 1.200e+01 Max. :360.0 Max. :2
## NA's :776160
## Atmospheric pressure [hPa] Direct Radiation [W/m2]
## Min. : 999.1 Min. : 1.6
## 1st Qu.:1014.3 1st Qu.: 1.7
## Median :1020.4 Median : 8.6
## Mean :1019.9 Mean : 63.9
## 3rd Qu.:1025.7 3rd Qu.: 91.9
## Max. :1033.8 Max. :790.1
## NA's :776160 NA's :437159
Y decidimos quedarnos únicamente con 4 variables más la variable ‘Datetime’, que nos servirá de referencia para el cruce con la tabla anterior.
meteo_2015_2016_final <- meteo_2015_2016 %>%
select(Datetime,
'Ambient Temperature [ºC]',
'Diffuse Radiation [W/m2]',
'Ultraviolet [W/m2]',
'Global Radiation [W/m2]')
Cruzamos las tablas por Datetime y comprobamos que no se duplican registros, ya que la tabla final tiene el mismo número de registros que la tabla de producción: 420.507.
tabla_final <- prod_2015_2016_final %>%
left_join(meteo_2015_2016_final, by = 'Datetime')
Inspeccionamos las variables.
summary(tabla_final)
## Datetime A_Optimal - Power DC [W]
## Min. :2015-01-01 07:40:00 Min. : 0.00
## 1st Qu.:2015-05-28 18:54:45 1st Qu.: 30.74
## Median :2015-10-08 17:38:30 Median : 99.79
## Mean :2015-12-04 18:28:55 Mean :100.48
## 3rd Qu.:2016-07-19 14:47:15 3rd Qu.:165.06
## Max. :2016-12-29 17:31:00 Max. :307.64
## NA's :8342
## B_Optimal - Power DC [W] Ambient Temperature [ºC]
## Min. : 0.00 Min. :-1.500e+09
## 1st Qu.: 27.08 1st Qu.: 1.700e+01
## Median : 96.81 Median : 2.100e+01
## Mean : 99.69 Mean :-4.093e+03
## 3rd Qu.:170.25 3rd Qu.: 2.600e+01
## Max. :302.01 Max. : 3.800e+01
## NA's :6730 NA's :55918
## Diffuse Radiation [W/m2] Ultraviolet [W/m2] Global Radiation [W/m2]
## Min. : 1.61 Min. : 0.56 Min. : 1.34
## 1st Qu.: 60.12 1st Qu.: 9.75 1st Qu.: 155.74
## Median : 99.84 Median :24.27 Median : 426.75
## Mean :127.92 Mean :27.30 Mean : 452.57
## 3rd Qu.:159.23 3rd Qu.:43.45 3rd Qu.: 727.82
## Max. :720.35 Max. :84.27 Max. :1421.33
## NA's :194998 NA's :55918 NA's :55918
Aquí vemos que la variable Ambient Temperature [ºC]
tiene como dato mínimo un posible error. Así que filtramos esta variable para corregirlo.
tabla_final <- tabla_final %>%
filter(`Ambient Temperature [ºC]` > -100)
Comprobamos que hemos resuelto el problema.
summary(tabla_final$`Ambient Temperature [ºC]`)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 3.167 16.900 21.483 21.432 26.100 38.300
Y exportamos el archivo final en formato csv para cargarlo en la herramienta de modelización BigML.
write_csv(tabla_final, "meteo_prod_2015_2016.csv")
2.3 Preparación datos “test”.
Importaciones
test_prod_2017 <- read_csv("./data/hackathon_data/test/test-sunlab-pv-2017.csv")
test_meteo_2017 <- read_csv("./data/hackathon_data/test/test-sunlab-meteo-2017.csv")
Cruzamos las tablas por Datetime
tabla_final_test <- test_prod_2017 %>%
left_join(test_meteo_2017, by = "Datetime") %>%
select(`A_Optimal - Power DC [W]`,
`Global Radiation [W/m2]`,
`Ultraviolet [W/m2]`)
Exportamos el archivo final en formato csv para cargarlo en la herramienta de modelización BigML.
write_csv(tabla_final_test, "test_meteo_prod_2017.csv")
2.4 Modelo base panel A
Una vez creadas y exportadas la tablas para crear los modelos en BigML y mientras se ejecutan los modelos en esa plataforma creamos un modelo base (o de partida) en R para el tipo de panel A.
Creamos un modelo con una regresión lineal para predecir los valores de Power DC [W] en función de dos únicas variables Global Radiation [W/m2]
y Ultraviolet [W/m2]
# Eliminamos los registros del panel tipo B y eliminamos también los registros con NAs
tabla_final_A <- tabla_final %>%
select(-`B_Optimal - Power DC [W]`) %>%
na.omit()
# Y creamos el modelo
modelo_A_1=lm(`A_Optimal - Power DC [W]` ~ `Global Radiation [W/m2]` + `Ultraviolet [W/m2]` , data = tabla_final_A)
Inspeccionamos el modelo creado.
modelo_A_1
##
## Call:
## lm(formula = `A_Optimal - Power DC [W]` ~ `Global Radiation [W/m2]` +
## `Ultraviolet [W/m2]`, data = tabla_final_A)
##
## Coefficients:
## (Intercept) `Global Radiation [W/m2]`
## 4.8996 0.2692
## `Ultraviolet [W/m2]`
## -0.9980
Obtenemos el resumen del mismo.
summary(modelo_A_1)
##
## Call:
## lm(formula = `A_Optimal - Power DC [W]` ~ `Global Radiation [W/m2]` +
## `Ultraviolet [W/m2]`, data = tabla_final_A)
##
## Residuals:
## Min 1Q Median 3Q Max
## -217.181 -18.974 -5.129 13.335 228.712
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.899640 0.115664 42.36 <2e-16 ***
## `Global Radiation [W/m2]` 0.269219 0.001342 200.54 <2e-16 ***
## `Ultraviolet [W/m2]` -0.997964 0.022165 -45.02 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 30.48 on 221113 degrees of freedom
## Multiple R-squared: 0.8266, Adjusted R-squared: 0.8266
## F-statistic: 5.269e+05 on 2 and 221113 DF, p-value: < 2.2e-16
Y obtenemos un modelo base significativo (p-value mucho menor que 0,05) y con un R cuadrado ajustado de 0,83. Bastante bien para empezar.
Extraemos del modelo los valores predecidos y seleccionamos también de la tabla los valores reales para posteriormente obtener los errores y el MAE (Mean Absolute Error).
fitted_values <- modelo_A_1$fitted.values
real_values <- tabla_final_A$`A_Optimal - Power DC [W]`
Obtenemos el MAE para tenerlo como referencia de comparación con los modelos que estamos desarrollando en BigML.
real_values_df <- as.data.frame(real_values)
fitted_values_df <- as.data.frame(fitted_values)
real_vs_fitted <- bind_cols(real_values_df, fitted_values_df)
errors <- real_vs_fitted %>%
mutate(abs_error = abs(fitted_values - real_values))
MAE <- mean(errors$abs_error)
MAE
## [1] 22.53593
El MAE que tendremos como referencia a mejorar es 22,54.
Para hacer la predicción para los 7 primeros días de 2017 seleccionamos de la tabla de test los campos utilizados en el modelo.
tabla_final_test_A <- tabla_final_test %>%
select(`A_Optimal - Power DC [W]`,
`Global Radiation [W/m2]`,
`Ultraviolet [W/m2]`)
Hacemos la prediccion para los paneles A con nuestro modelo.
prediccion_test <- predict(modelo_A_1, tabla_final_test_A)
Y exportamos nuestras predicciones para enviarlas también, junto a las obtenidas con BigML, al jurado del Hackathon.
prediccion_test <- as.data.frame(prediccion_test)
write_csv(prediccion_test, "predicciones_panel_A.csv")
El modelo base para los datos del tipo de panel B no nos dio tiempo a hacerlo.
2.5 Modelización en BigML
Aquí se ven las fuente de datos creadas para este reto. “meteo_prod_2015_2016.csv” es la fuente a partir de los datos procesados en R para el entrenamiento del modelo. Y “test_meteo_prod_2017.csv” es la fuente, también procesada en R, con los datos para hacer la predicción.
Detalle de la fuente con las columnas que dejamos despues de procesar en R.
Aquí se ven los datasets que creamos a partir de las dos fuentes. Se puede ver que creamos un dataset a partir de los datos originales de la fuente “meteo_prod_2015_2016” y sobre él fuimos iterando. Primero lo dividimos en dos datasets, uno para los paneles de tipo A (“meteo_prod_2015_2016_CONDATOS_A”) y otro para los paneles de tipo B (“meteo_prod_2015_2016_CONDATOS_B”). Y luego eliminamos un valor de temperatura que era erroneo y nos descuadraba el resultado. También está el dataset “test_meteo_prod_2017” que creamos a partir de los datos de test para hacer luego la predicción con el modelo.
Detalle de uno de los datasets con los campos que eliminamos para que no influyesen en la predicción.
Detalle de uno de los datasets con los campos que eliminamos para que no influyesen en la predicción.
Regresiones lineales creadas a partir de los datasets, una para cada modelo de panel solar.
Detalle de la grafica de predicción de una de las regresiones en función de la radiación.
Detalle de regresiones para uno de los paneles.
Predicciones batch para cada modelo creadas con el dataset de prueba.
Detalle de una de las predicciones.
Con las prisas y la falta de experiencia con la herramienta BigML no nos dio tiempo tampoco a comprobar la bondad del ajuste y calidad de los modelos generados. Nos dio el tiempo justo para simplemente enviar las predicciones de los primeros modelos que obtuvimos.