Le package contient un ensemble de fonctions pour vérifier et corriger des données entsoe.
L’objectif du package est de permettre la création d’un jeu de données complet pour deux années de données et pour plusieurs pays.
Les données peuvent être manquantes ou imparfaites. Il s’agit de permettre :
- l’identification des problèmes,
- leur reporting afin de permettre leur correction par l’entsoe,
- leur correction si la donnée n’a pu être corrigée par l’entsoe.
La procédure est pour l’instant implémentée pour les données de consommation.
On va charger l’ensemble des données archivées sur archive.org à l’URL suivante : https://archive.org/details/RTE_load
Le zip à charger est le suivant: https://archive.org/download/RTE_load/load.zip.
load_dir <- file.path(tempdir(), "load_files" )
load_zip <- file.path(tempdir(), "load.zip" )
local_zip <- "/Users/davidgohel/Documents/consulting/RTE/load_20180115.zip"
if( file.exists(local_zip))
file.copy(local_zip, load_zip, overwrite = TRUE )
#> [1] TRUE
if( !file.exists(load_zip) )
download.file(url = "https://archive.org/download/RTE_load/load.zip",
destfile = load_zip )
if( dir.exists(load_dir) )
unlink(load_dir, recursive = TRUE, force = TRUE)
utils::unzip(load_zip, exdir = load_dir )
Les données sont disponibles dans le répertoire /var/folders/51/6jygptvs3bb4njv0t6x7br900000gn/T//RtmpKjomya/load_files. Celui ci contient les fichiers suivants :
csv_files <- list.files(load_dir, full.names = TRUE, pattern = "\\.csv$")
csv_infos <- file.info(csv_files)[, c(1, 3) ]
row.names(csv_infos) <- NULL
csv_infos$file <- basename(csv_files)
kable(csv_infos)
size | mode | file |
---|---|---|
4818387 | 644 | 2014_12_ActualTotalLoad.csv |
11754929 | 644 | 2015_1_ActualTotalLoad.csv |
11875895 | 644 | 2015_10_ActualTotalLoad.csv |
11310965 | 644 | 2015_11_ActualTotalLoad.csv |
11781789 | 644 | 2015_12_ActualTotalLoad.csv |
10726713 | 644 | 2015_2_ActualTotalLoad.csv |
11787017 | 644 | 2015_3_ActualTotalLoad.csv |
11697487 | 644 | 2015_4_ActualTotalLoad.csv |
12126637 | 644 | 2015_5_ActualTotalLoad.csv |
11542277 | 644 | 2015_6_ActualTotalLoad.csv |
11876256 | 644 | 2015_7_ActualTotalLoad.csv |
11475976 | 644 | 2015_8_ActualTotalLoad.csv |
11391554 | 644 | 2015_9_ActualTotalLoad.csv |
11419260 | 644 | 2016_1_ActualTotalLoad.csv |
11875625 | 644 | 2016_10_ActualTotalLoad.csv |
11451870 | 644 | 2016_11_ActualTotalLoad.csv |
11912513 | 644 | 2016_12_ActualTotalLoad.csv |
10715373 | 644 | 2016_2_ActualTotalLoad.csv |
11896459 | 644 | 2016_3_ActualTotalLoad.csv |
11049881 | 644 | 2016_4_ActualTotalLoad.csv |
11394632 | 644 | 2016_5_ActualTotalLoad.csv |
11051677 | 644 | 2016_6_ActualTotalLoad.csv |
11618280 | 644 | 2016_7_ActualTotalLoad.csv |
11567961 | 644 | 2016_8_ActualTotalLoad.csv |
11135435 | 644 | 2016_9_ActualTotalLoad.csv |
11781347 | 644 | 2017_1_ActualTotalLoad.csv |
12206677 | 644 | 2017_10_ActualTotalLoad.csv |
11575500 | 644 | 2017_11_ActualTotalLoad.csv |
11797364 | 644 | 2017_12_ActualTotalLoad.csv |
10570762 | 644 | 2017_2_ActualTotalLoad.csv |
11948418 | 644 | 2017_3_ActualTotalLoad.csv |
11574925 | 644 | 2017_4_ActualTotalLoad.csv |
11943294 | 644 | 2017_5_ActualTotalLoad.csv |
11596317 | 644 | 2017_6_ActualTotalLoad.csv |
11715569 | 644 | 2017_7_ActualTotalLoad.csv |
11458478 | 644 | 2017_8_ActualTotalLoad.csv |
11212775 | 644 | 2017_9_ActualTotalLoad.csv |
3153704 | 644 | 2018_1_ActualTotalLoad.csv |
Avant de dégager une série de consommation par pays
library(antaDraft)
load_data <- anta_load(data_dir = load_dir )
L’opération va ajouter autant de colonnes qu’il y a de tests exprimés
dans le fichier config/load/raw_validate.yml
.
Ce fichier décrit les règles de validation de chaque ligne de donnée.
rules: - expr: observed==TRUE name: IS_OBS - expr: is.finite(TotalLoadValue) name: IS_FINITE - expr: sign(TotalLoadValue)>0.001 name: IS_POS
load_data <- augment_validation(load_data)
head(load_data)
#> DateTime MapCode AreaTypeCode country AreaName TotalLoadValue
#> 1 2014-12-01 AT CTA AUSTRIA <NA> NA
#> 2 2014-12-01 AT CTY AUSTRIA <NA> NA
#> 3 2014-12-01 BE BZN BELGIUM Elia BZ 9100.34
#> 4 2014-12-01 BE CTA BELGIUM Elia CA 9100.34
#> 5 2014-12-01 BE CTY BELGIUM Belgium 9100.34
#> 6 2014-12-01 CH BZN SWITZERLAND <NA> NA
#> observed IS_OBS IS_FINITE IS_POS
#> 1 FALSE FALSE TRUE TRUE
#> 2 FALSE FALSE TRUE TRUE
#> 3 TRUE TRUE TRUE TRUE
#> 4 TRUE TRUE TRUE TRUE
#> 5 TRUE TRUE TRUE TRUE
#> 6 FALSE FALSE TRUE TRUE
On va produire les données agrégées avec la fonction
aggregate_with_rules
. Les règles sont exprimées dans le fichier
config/global/atc_per_country.yml
.
FRANCE: CTY: - FR CTA: - FR BZN: - FR BELGIUM: CTY: - BE CTA: - BE BZN: - BE SWITZERLAND: CTY: - CH CTA: - CH BZN: - CH SPAIN: CTY: - ES CTA: - ES BZN: - ES NETHERLANDS: CTY: - NL CTA: - NL BZN: - NL PORTUGAL: CTY: - PT CTA: - PT BZN: - PT ITALY: CTY: - IT CTA: - IT BZN: - IT_CNOR - IT_CSUD - IT_North - IT_SARD - IT_SICI - IT_SUD GERMANY: CTY: - DE CTA: - DE_TenneT_GER - DE_TransnetBW - DE_Amprion - DE_50HzT BZN: - DE_AT_LU - "!CTY|AUSTRIA" - "!CTY|LUXEMBOURG" AUSTRIA: CTY: - AT CTA: - AT BZN: - DE_AT_LU - "!CTY|GERMANY" - "!CTY|LUXEMBOURG" UK: CTY: - GB - "!CTA|NORTH_IRELAND" CTA: - GB BZN: - GB IRELAND: CTY: - IE CTA: - IE BZN: - IE_SEM - "!CTA|NORTH_IRELAND" NORTH_IRELAND: CTY: - NIE CTA: - NIE BZN: - IE_SEM - "!CTY|IRELAND" LUXEMBOURG: CTY: - LU CTA: - LU BZN: - DE_AT_LU - "!CTY|GERMANY" - "!CTY|AUSTRIA"
La fonction prend des données de load comme argument, c’est à dire
obtenue avec la fonction anta_load()
.
aggregated_db <- agg_data(load_data)
Ces données peuvent être représentées graphiquement avec la fonction
plot
(voire ?plot_agg
).
plot_agg(aggregated_db, subset = aggregated_db$country %in% "SWITZERLAND")
Comme pour les données brutes, l’opération va ajouter autant de colonnes
qu’il y a de tests exprimés dans le fichier agg_validate.yml
.
rules: - expr: is.finite(CTY) name: CTY_NA - expr: is.finite(CTA) name: CTA_NA - expr: is.finite(BZN) name: BZN_NA - expr: CTY > 0.001 name: CTY_IS_POS - expr: CTA > 0.001 name: CTA_IS_POS - expr: BZN > 0.001 name: BZN_IS_POS - expr: abs(CTY-CTA) < 1 name: CTY_CTA_EQUAL - expr: abs(CTY-BZN) < 1 name: CTY_BZN_EQUAL - expr: abs(CTA-BZN) < 1 name: CTA_BZN_EQUAL - expr: abs(1 - (CTY / CTA) ) < .05 name: CTY_CTA_DIFF_LT_05 - expr: abs(1 - (CTY / BZN) ) < .05 name: CTY_BZN_DIFF_LT_05 - expr: abs(1 - (CTA / BZN) ) < .05 name: CTA_BZN_DIFF_LT_05 - expr: abs(1 - (CTY / CTA) ) < .1 name: CTY_CTA_DIFF_LT_10 - expr: abs(1 - (CTY / BZN) ) < .1 name: CTY_BZN_DIFF_LT_10 - expr: abs(1 - (CTA / BZN) ) < .1 name: CTA_BZN_DIFF_LT_10 - expr: (is.na(data.table::shift(CTY)) | sign(CTY) < 1 | (abs(CTY - data.table::shift(CTY)) / CTY) < .3 ) & ( is.na(data.table::shift(CTY)) | sign(CTY) < 1 | (abs(data.table::shift(CTY) - CTY) / data.table::shift(CTY)) < .3 ) name: CTY_LAG_LT_30 - expr: ( is.na(data.table::shift(CTA)) | sign(CTA) < 1 | (abs(CTA - data.table::shift(CTA)) / CTA) < .3 ) & ( is.na(data.table::shift(CTA)) | sign(CTA) < 1 | (abs(data.table::shift(CTA) - CTA) / data.table::shift(CTA)) < .3 ) name: CTA_LAG_LT_30 - expr: ( is.na(data.table::shift(BZN)) | sign(BZN) < 1 | (abs(BZN - data.table::shift(BZN)) / BZN) < .3 ) & (is.na(data.table::shift(BZN)) | sign(BZN) < 1 | (abs(data.table::shift(BZN) - BZN) / data.table::shift(BZN)) < .3 ) name: BZN_LAG_LT_30
aggregated_db <- augment_validation(aggregated_db)
Ces données peuvent être représentées graphiquement avec la fonction
plot
(voire ?plot.controled
).
plot(aggregated_db, subset = aggregated_db$country %in% "SWITZERLAND")
aggregated_db <- data_correct_with_rules(aggregated_db)
aggregated_db <- augment_process_summary(aggregated_db)
library(dplyr)
library(tidyr)
aggregated_db %>%
group_by_at(c( "country", "summary") ) %>%
tally() %>%
spread(summary, n) %>%
kable()
country | corrected | invalid | original |
---|---|---|---|
AUSTRIA | 13989 | 13044 | 218 |
BELGIUM | 9 | 22724 | 4518 |
FRANCE | 1 | 26985 | 265 |
GERMANY | 14012 | 1211 | 12028 |
IRELAND | 9 | 27242 | NA |
ITALY | 24 | 25440 | 1787 |
LUXEMBOURG | 13854 | 13351 | 46 |
NETHERLANDS | 28 | 27223 | NA |
NORTH_IRELAND | 21310 | 5941 | NA |
PORTUGAL | 1047 | 24418 | 1786 |
SPAIN | 767 | 26484 | NA |
SWITZERLAND | 49 | 27165 | 37 |
UK | 1 | 27162 | 88 |
Il faut dans un premier temps enrichir la base de données avec des
variables potentiellement explicatives. On utilise la fonction
as_learning_db
.
dat <- as_learning_db(aggregated_db )
head(dat)
#> country DateTime BZN CTA CTY rule_0003_BZN rule_0002_CTY
#> 1 AUSTRIA 2014-12-01 00:00:00 0 0 0 FALSE FALSE
#> 2 AUSTRIA 2014-12-01 01:00:00 0 0 0 FALSE FALSE
#> 3 AUSTRIA 2014-12-01 02:00:00 0 0 0 FALSE FALSE
#> 4 AUSTRIA 2014-12-01 03:00:00 0 0 0 FALSE FALSE
#> 5 AUSTRIA 2014-12-01 04:00:00 0 0 0 FALSE FALSE
#> 6 AUSTRIA 2014-12-01 05:00:00 0 0 0 FALSE FALSE
#> rule_0001_CTA CTY_NA CTA_NA BZN_NA CTY_IS_POS CTA_IS_POS BZN_IS_POS
#> 1 FALSE TRUE TRUE TRUE FALSE FALSE FALSE
#> 2 FALSE TRUE TRUE TRUE FALSE FALSE FALSE
#> 3 FALSE TRUE TRUE TRUE FALSE FALSE FALSE
#> 4 FALSE TRUE TRUE TRUE FALSE FALSE FALSE
#> 5 FALSE TRUE TRUE TRUE FALSE FALSE FALSE
#> 6 FALSE TRUE TRUE TRUE FALSE FALSE FALSE
#> CTY_CTA_EQUAL CTY_BZN_EQUAL CTA_BZN_EQUAL CTY_CTA_DIFF_LT_05
#> 1 TRUE TRUE TRUE TRUE
#> 2 TRUE TRUE TRUE TRUE
#> 3 TRUE TRUE TRUE TRUE
#> 4 TRUE TRUE TRUE TRUE
#> 5 TRUE TRUE TRUE TRUE
#> 6 TRUE TRUE TRUE TRUE
#> CTY_BZN_DIFF_LT_05 CTA_BZN_DIFF_LT_05 CTY_CTA_DIFF_LT_10
#> 1 TRUE TRUE TRUE
#> 2 TRUE TRUE TRUE
#> 3 TRUE TRUE TRUE
#> 4 TRUE TRUE TRUE
#> 5 TRUE TRUE TRUE
#> 6 TRUE TRUE TRUE
#> CTY_BZN_DIFF_LT_10 CTA_BZN_DIFF_LT_10 CTY_LAG_LT_30 CTA_LAG_LT_30
#> 1 TRUE TRUE TRUE TRUE
#> 2 TRUE TRUE TRUE TRUE
#> 3 TRUE TRUE TRUE TRUE
#> 4 TRUE TRUE TRUE TRUE
#> 5 TRUE TRUE TRUE TRUE
#> 6 TRUE TRUE TRUE TRUE
#> BZN_LAG_LT_30 summary is_off likely_off year.iso week.iso hour.iso
#> 1 TRUE invalid FALSE FALSE 2014 49 0
#> 2 TRUE invalid FALSE FALSE 2014 49 1
#> 3 TRUE invalid FALSE FALSE 2014 49 2
#> 4 TRUE invalid FALSE FALSE 2014 49 3
#> 5 TRUE invalid FALSE FALSE 2014 49 4
#> 6 TRUE invalid FALSE FALSE 2014 49 5
#> day.iso light_time HOUR_SHIFT_CTY_PLUS_1 HOUR_SHIFT_CTY_MINUS_1
#> 1 2 524 NA NA
#> 2 2 524 NA NA
#> 3 2 524 NA NA
#> 4 2 524 NA NA
#> 5 2 524 NA NA
#> 6 2 524 NA NA
#> DAILY_MIN_CTY_PLUS_1 DAILY_AVG_CTY_PLUS_1 DAILY_MAX_CTY_PLUS_1
#> 1 NA NA NA
#> 2 NA NA NA
#> 3 NA NA NA
#> 4 NA NA NA
#> 5 NA NA NA
#> 6 NA NA NA
#> DAILY_MIN_CTY_MINUS_1 DAILY_AVG_CTY_MINUS_1 DAILY_MAX_CTY_MINUS_1
#> 1 6306 7581.317 8661.2
#> 2 6306 7581.317 8661.2
#> 3 6306 7581.317 8661.2
#> 4 6306 7581.317 8661.2
#> 5 6306 7581.317 8661.2
#> 6 6306 7581.317 8661.2
On peut alors créer deux modèles, un dépandant des mesures suivantes et un dépendant des mesures précédentes.
On utilisera pour cela la fonction define_model_rf
. Celle-ci
sauvegarde les modèles dans un répertoire local à la machine.
repertoire_model <- tempfile()
dir.create(repertoire_model, showWarnings = FALSE, recursive = TRUE)
Création du modèle backward:
x_vars <- c(
"year.iso", "week.iso", "hour.iso", "day.iso", "light_time",
"is_off", "likely_off",
"DAILY_MIN_CTY_MINUS_1", "DAILY_AVG_CTY_MINUS_1", "DAILY_MAX_CTY_MINUS_1",
"HOUR_SHIFT_CTY_MINUS_1")
dat <- define_model_rf(
data = dat, x_vars = x_vars, y_var = "CTY",
save_model_dir = repertoire_model, id = "BACKWARD" )
Création du modèle forward:
x_vars <- c(
"year.iso", "week.iso", "hour.iso", "day.iso", "light_time",
"is_off", "likely_off",
"DAILY_MIN_CTY_PLUS_1", "DAILY_AVG_CTY_PLUS_1", "DAILY_MAX_CTY_PLUS_1",
"HOUR_SHIFT_CTY_PLUS_1")
dat <- define_model_rf(
data = dat, x_vars = x_vars, y_var = "CTY",
save_model_dir = repertoire_model, id = "FORWARD" )
Maintenant qu’on a deux modèles, on peut les utiliser en boucle pour remplacer les valeurs invalides par des valeurs prévues par les modèles.
for(i in 1:12 ){
dat <- impute_with_model(dat, id = "FORWARD")
dat <- impute_with_model(dat, id = "BACKWARD")
dat <- update_learning_db(dat)
}
library(dplyr)
library(tidyr)
dat %>%
group_by_at(c( "country", "summary") ) %>%
tally() %>%
spread(summary, n) %>%
kable()