Pourquoi ?
Cette vignette a pour but d’expliciter l’usage d’impactR
et la manière dont il est possible de l’utiliser dans le cadre d’un
suivi de collecte de données et du nettoyage. Commençons par charger le
package.
# Si vous n'avez pas encore installé le package
# devtools::install_github("impactR)
library(impactR)
Ci-dessus, on peut charger des données exemple collectées.
# Load dataset in environment
data(data)
# Show the first lines and types of airports' tibble
data <- data |> tibble::as_tibble()
data
## Warning in as.POSIXlt.POSIXct(x, tz): unable to identify current timezone 'H':
## please set environment variable 'TZ'
## # A tibble: 30 × 52
## uuid cluster weights start end
## <chr> <chr> <dbl> <dttm> <dttm>
## 1 x1 wendou_1 0.8 2021-10-18 09:08:24 2021-10-18 10:01:35
## 2 x2 wendou_1 0.8 2021-10-20 09:14:47 2021-10-20 10:05:23
## 3 x3 wendou_2 0.8 2021-10-20 10:11:14 2021-10-20 11:00:07
## 4 x4 wendou_2 0.8 2021-10-18 09:08:24 2021-10-20 12:02:57
## 5 x5 wendou_1 0.8 2021-10-20 10:11:14 2021-10-20 15:02:31
## 6 x6 wendou_2 0.8 2021-10-20 14:14:36 2021-10-20 16:04:35
## 7 x7 wendou_1 0.8 2021-10-20 15:09:11 2021-10-20 10:26:34
## 8 x8 wendou_1 0.8 2021-10-20 09:44:15 2021-10-20 11:12:48
## 9 x9 gnarala_1 1.2 2021-10-20 11:12:05 2021-10-21 11:12:48
## 10 x10 gnarala_2 1.2 2021-10-20 14:14:36 2021-10-22 11:12:48
## # … with 20 more rows, and 47 more variables: today <dttm>, deviceid <chr>,
## # i_enum_id <dbl>, i_enum_genre <chr>, i_admin2 <chr>, i_ville <chr>,
## # i_secteur <chr>, i_info_secteur <chr>, i_zad <chr>, i_zad_1 <chr>,
## # i_consensus <chr>, i_consensus_note <chr>, i_enquete_age <dbl>,
## # i_enquete_genre <chr>, i_statut <chr>, i_note_statut <lgl>,
## # i_statut_1 <chr>, c_note <lgl>, c_chef_menage <chr>,
## # c_n_chef_menage_genre <chr>, c_n_chef_menage_age <dbl>, …
La plupart des fonctions de impactR
sont écrites en
supposant que les données fournies peuvent être converties en tibble,
puisqu’elles utilisent largement le tidyverse.
Supposons que nous ayons une feuille ‘survey’ composée comme suit :
## # A tibble: 44 × 12
## type name label hint requi…¹ choic…² calcu…³ relev…⁴ const…⁵ const…⁶
## <chr> <chr> <chr> <lgl> <lgl> <chr> <chr> <chr> <chr> <chr>
## 1 start start NA NA NA NA NA NA NA NA
## 2 end end NA NA NA NA NA NA NA NA
## 3 today today NA NA NA NA NA NA NA NA
## 4 deviceid devi… NA NA NA NA NA NA NA NA
## 5 select_one… i_en… Code… NA TRUE NA NA NA NA NA
## 6 select_one… i_en… Sexe… NA TRUE NA NA NA NA NA
## 7 hidden i_ad… Quel… NA FALSE NA NA NA NA NA
## 8 hidden i_vi… Quel… NA FALSE NA NA NA NA NA
## 9 select_one… i_se… Quel… NA TRUE NA NA NA NA NA
## 10 calculate i_in… NA NA TRUE NA jr:cho… NA NA NA
## # … with 34 more rows, 2 more variables: given_name <lgl>, default <chr>, and
## # abbreviated variable names ¹required, ²choice_filter, ³calculation,
## # ⁴relevant, ⁵constraint, ⁶constraint_message
La première chose à faire avec l’objet ‘survey’, car il sera utilisé ailleurs : il faut séparer en deux la colonne ‘type’.
# Miseà part l'argument 'col_to_split' (la colonne à séparer), les autres paramètres sont les paramètres par défaut
survey <- survey |>
split_survey(
col_to_split = "type",
into = c("type", "list_name"),
sep = " ",
fill = "right")
survey
## # A tibble: 44 × 13
## type list_n…¹ name label hint requi…² choic…³ calcu…⁴ relev…⁵ const…⁶
## <chr> <chr> <chr> <chr> <lgl> <lgl> <chr> <chr> <chr> <chr>
## 1 start NA start NA NA NA NA NA NA NA
## 2 end NA end NA NA NA NA NA NA NA
## 3 today NA today NA NA NA NA NA NA NA
## 4 deviceid NA devi… NA NA NA NA NA NA NA
## 5 select_one l_enum_… i_en… Code… NA TRUE NA NA NA NA
## 6 select_one l_genre i_en… Sexe… NA TRUE NA NA NA NA
## 7 hidden NA i_ad… Quel… NA FALSE NA NA NA NA
## 8 hidden NA i_vi… Quel… NA FALSE NA NA NA NA
## 9 select_one l_secte… i_se… Quel… NA TRUE NA NA NA NA
## 10 calculate NA i_in… NA NA TRUE NA jr:cho… NA NA
## # … with 34 more rows, 3 more variables: constraint_message <chr>,
## # given_name <lgl>, default <chr>, and abbreviated variable names ¹list_name,
## # ²required, ³choice_filter, ⁴calculation, ⁵relevant, ⁶constraint
Contrôle de la qualité des données
Journal de nettoyage des valeurs aberrantes
Afin de pouvoir obtenir les valeurs dites aberrantes (pour les
variables numériques), vous pouvez utiliser la fonction
make_log_outlier
qui permet d’obtenir deux types de valeurs
aberrantes : l’écart par rapport à la moyenne en utilisant la fonction
outliers_sd
et l’écart interquartile en utilisant la
fonction outliers_iqr
.
# Utilitaire pour obtenir toutes les variables numériques
#numeric_cols(data) # Obtenir toutes les colonnes numériques : cela inclut par exemple les identifiants numériques des énumérateurs ou les points GPS.
#numeric_cols(data, survey) # Obtenir toutes les colonnes numériques en utilisant la feuille 'survey' de l'outil Kobo (uniquement les calculate, integer, etc.)
# Valeurs aberrantes interquartle (règle des 1,5 fois par défaut)
#outliers_iqr(data, col = i_enquete_age,times = 1.5, id_col = uuid) # La colonne d'identifiant 'id_col' est habituellement "uuid" avec Kobo
# Valeurs aberrantes à la moyenne
#outliers_sd(data, i_enquete_age, times = 3, id_col = uuid)
# Fabriquer le journal de nettoyage entier pour toutes les variables numériques (en prenant en compte l'outil Kobo)
log_outliers <- make_log_outlier(data, survey, id_col = uuid, today, i_enum_id, i_zad)
log_outliers
## # A tibble: 2 × 16
## id_check today i_enu…¹ i_zad uuid quest…² quest…³ why feedb…⁴
## <chr> <dttm> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 outlier 2021-10-18 00:00:00 8 wend… x1 c_n_ch… Quel e… Outl… Fill in
## 2 outlier 2021-10-20 00:00:00 3 wend… x2 c_n_ch… Quel e… Outl… Fill in
## # … with 7 more variables: action <chr>, old_value <dbl>, new_value <chr>,
## # type <chr>, other_parent_question <chr>, other_new_value <chr>,
## # checkdate <chr>, and abbreviated variable names ¹i_enum_id, ²question_name,
## # ³question_label, ⁴feedback
Journal de nettoyage des “autres”
Cette fonction nécessite que la question Kobo avec la réponse “autre” soit définie comme “variable” pour la question parent et “autre_variable” pour la question parent. “autre_” peut être différent selon les outils et est défini dans la question suivante par l’argument “autre”, qui est la chaîne de caractères de chaque début de variable autre codée dans Kobo. Dans l’exemple qui suit, il s’agit de “autre_”.
# Obtenir les autres
other_cols <- other_cols(data, "autre_", id_col = uuid)
other_cols
## # A tibble: 4 × 4
## uuid question_name old_value other_parent_quest…¹
## <chr> <chr> <chr> <chr>
## 1 x5 autre_h_3_type_latrine Aussi latrines communales h_3_type_latrine
## 2 x7 autre_r_besoin_assistance Un métier r_besoin_assistance
## 3 x15 autre_r_besoin_assistance Electricité r_besoin_assistance
## 4 x22 autre_h_3_type_latrine Trou ouvert h_3_type_latrine
## # … with abbreviated variable name ¹other_parent_question
# Obtenir les autres parents
other_parent_cols(data, other_cols, "autre_", id_col = uuid)
## # A tibble: 4 × 3
## uuid other_parent_question other_old_value
## <chr> <chr> <chr>
## 1 x15 r_besoin_assistance abri_bna secal autre
## 2 x22 h_3_type_latrine latrine_prive autre
## 3 x5 h_3_type_latrine latrine_prive_partage autre
## 4 x7 r_besoin_assistance abri_bna secal autre
# Fabriquer le journal de nettoyage des "autres"
log_others <- make_log_other(data, survey, "autre_", uuid, today, i_enum_id, i_zad)
log_others
## # A tibble: 4 × 17
## id_check today i_enu…¹ i_zad uuid quest…² quest…³ why feedb…⁴
## <chr> <dttm> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 autre_ 2021-10-20 00:00:00 3 wend… x5 autre_… Lesque… Othe… Fill in
## 2 autre_ 2021-10-20 00:00:00 12 wend… x7 autre_… De que… Othe… Fill in
## 3 autre_ 2021-10-20 00:00:00 3 gnar… x15 autre_… De que… Othe… Fill in
## 4 autre_ 2021-10-20 00:00:00 5 gnar… x22 autre_… Lesque… Othe… Fill in
## # … with 8 more variables: action <chr>, old_value <chr>, new_value <chr>,
## # type <chr>, other_parent_question <chr>, other_old_value <chr>,
## # other_new_value <chr>, checkdate <chr>, and abbreviated variable names
## # ¹i_enum_id, ²question_name, ³question_label, ⁴feedback
Journal de nettoyage basé sur une liste de vérifications
Il suffit d’avoir produit en amont un fichier Excel de vérification logique, qu’il est par ailleurs possible de modifier au cours de la collecte.
## # A tibble: 5 × 7
## id_check question_name why logic…¹ new_v…² action type
## <chr> <chr> <chr> <chr> <lgl> <chr> <chr>
## 1 id1 i_consensus Pas de consentement p… "i_con… NA remove char…
## 2 id2 survey_duration Durée d'enquête de mo… "surve… NA urgen… doub…
## 3 id3 survey_duration Durée d'enquête de pl… "surve… NA check doub…
## 4 id4 survey_duration Durée d'enquête de pl… "surve… NA urgen… doub…
## 5 id5 c_chef_menage_age Le ou la cheffe de mé… "c_che… NA check doub…
## # … with abbreviated variable names ¹logical_test, ²new_value
Le tableur excel de vérifications doit suivre quelques règles pour
pouvoir être lu par les fonctions d’impactR [ajouter la liste]. Par
exemple, il est nécessaire que toutes les variables présentes dans les
tests logiques (colonne ‘logical_test’ du tableau de vérifications)
existent aussi dans les données, objet data
. Pour cela, on
peut utiliser la fonction check_check_list
, qui vise à
valider ou non un tableur de vérifications logiques [note : elle n’est
pas encore robuste, mais elle permet déjà de faire un certain nombre de
contrôles].
Par exemple, ci-dessous la colonne survey_duration
n’existe pas dans les données data
. Pourtant, il y a des
vérifications logiques qui la prennent en compte dans le tableur de
vérifications logiques check_list
. Si on lance la commande
suivante, on obtiendrait une erreur :
check_check_list(check_list, data)
# following column/s from `question_name` is/are missing in `.tbl`: survey_duration, survey_duration, survey_duration
On va donc jouter la colonne de durée d’enquête à l’aide de la
fonction survey_duration
. On en profite pour assi ajouter
la différence de temps entre deux enquêtes par enquêteur.rice :
data <- data |>
survey_duration(start, end, new_colname = "survey_duration") #|>
# NOT RUN!
# survey_difftime(start, end, new_colname = "survey_difftime", i_enum_id)
data$survey_duration
## [1] 53 51 49 3055 291 110 -283 89 1441 2698 1204 2969 1481 5884 1558
## [16] 2942 4444 2942 1258 2644 1529 2881 1258 2644 1529 2921 1529 5884 1502 2698
On peut vérifier de nouveau le tableur de vérifications logiques :
check_check_list(check_list, data)
## [1] TRUE
Cette fois-ci, c’est bon, la fonction donne TRUE
, on
peut donc procéder avec la production du log de nettoyage.
log_check_list <- make_log_from_check_list(data, survey, check_list, uuid, today, i_enum_id, i_zad)
log_check_list
## # A tibble: 57 × 17
## id_ch…¹ today i_enu…² i_zad uuid quest…³ quest…⁴ why feedb…⁵
## <chr> <dttm> <dbl> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 id2 2021-10-20 00:00:00 12 wend… x7 survey… "" Duré… Verifi…
## 2 id3 2021-10-18 00:00:00 8 wend… x1 survey… "" Duré… Verifi…
## 3 id3 2021-10-20 00:00:00 3 wend… x2 survey… "" Duré… Verifi…
## 4 id3 2021-10-20 00:00:00 3 wend… x3 survey… "" Duré… Verifi…
## 5 id3 2021-10-20 00:00:00 3 wend… x4 survey… "" Duré… Verifi…
## 6 id3 2021-10-20 00:00:00 3 wend… x5 survey… "" Duré… Verifi…
## 7 id3 2021-10-20 00:00:00 3 wend… x6 survey… "" Duré… Verifi…
## 8 id3 2021-10-20 00:00:00 12 wend… x8 survey… "" Duré… Verifi…
## 9 id3 2021-10-20 00:00:00 1 gnar… x9 survey… "" Duré… Verifi…
## 10 id3 2021-10-20 00:00:00 5 gnar… x10 survey… "" Duré… Verifi…
## # … with 47 more rows, 8 more variables: action <chr>, old_value <chr>,
## # new_value <lgl>, type <chr>, other_parent_question <chr>,
## # other_old_value <chr>, other_new_value <chr>, checkdate <chr>, and
## # abbreviated variable names ¹id_check, ²i_enum_id, ³question_name,
## # ⁴question_label, ⁵feedback
Journal de nettoyage complet et exportation
Pour terminer, il nous suffit de combiner tous ces journaux de nettoyage en un seul. On peut ensuite l’exporter en fichier excel.
log <- list(log_outliers, log_check_list, log_others) |>
purrr::map(~ .x |> dplyr::mutate(dplyr::across(.fns = as.character))) |>
dplyr::bind_rows() |>
readr::type_convert()
Il est aussi possible d’utiliser la fonction
make_all_logs
qui combine ces trois fonctions et ne sort
qu’un unique journal de nettoyage.
log <- make_all_logs(data, survey, check_list, "autre_", uuid, today, i_enum_id, i_zad)
log
## # A tibble: 63 × 17
## id_check today i_enum…¹ i_zad uuid quest…² quest…³ why feedb…⁴ action
## <chr> <date> <dbl> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 id2 2021-10-20 12 wend… x7 survey… NA Duré… Verifi… urgen…
## 2 id3 2021-10-18 8 wend… x1 survey… NA Duré… Verifi… check
## 3 id3 2021-10-20 3 wend… x2 survey… NA Duré… Verifi… check
## 4 id3 2021-10-20 3 wend… x3 survey… NA Duré… Verifi… check
## 5 id3 2021-10-20 3 wend… x4 survey… NA Duré… Verifi… check
## 6 id3 2021-10-20 3 wend… x5 survey… NA Duré… Verifi… check
## 7 id3 2021-10-20 3 wend… x6 survey… NA Duré… Verifi… check
## 8 id3 2021-10-20 12 wend… x8 survey… NA Duré… Verifi… check
## 9 id3 2021-10-20 1 gnar… x9 survey… NA Duré… Verifi… check
## 10 id3 2021-10-20 5 gnar… x10 survey… NA Duré… Verifi… check
## # … with 53 more rows, 7 more variables: old_value <chr>, new_value <chr>,
## # type <chr>, other_parent_question <chr>, other_old_value <chr>,
## # other_new_value <lgl>, checkdate <chr>, and abbreviated variable names
## # ¹i_enum_id, ²question_name, ³question_label, ⁴feedback
Enfin, il existe plusieurs manière d’exporter. Ici on donne l’exemple
avec le package writexl
:
# Not run! La plus simple
# writexl::write_xlsx(log, "output/log.xlsx)
# On peut y ajouter la date du jour pour permettre le suivi
# writexl::write_xlsx(log, paste0("output/log_", Sys.Date(), ".xlsx))