Cadre R chez IMPACT Initiatives

Yann Say

06/12/2024

Contents

  1. Raisons
  2. Cadre R
  3. En pratique

Raisons

Raisons

  • ~ 30 pays: Beaucoup d’équipes et de projets
  • 80% des scripts de nettoyage et 50% des analyses utilisent des fonctions personnelles

Cadre R chez IMPACT

Cadre R

Cadre d’analyse modulaire à 2 dimensions:

  • une dimension verticale qui se concentre sur le contenu d’une étape
  • une dimension horizontale qui se concentre sur le résultat d’une étape

Cadre R chez IMPACT

  • 4 étapes
  • 4 verbes
  • 2 adjectifs

4 étapes

  • Nettoyage : Toute manipulation pour passer des données brutes aux données propres
  • Composition : Toute manipulation avant l’analyse, par ex. ajout d’indicateurs, combiner deux bases de données (avant et après une distribution). Les indicateurs sont créés avant l’analyse, et non avec l’analyse.
  • Analyse : Toute manipulation concernant uniquement l’analyse. L’analyse s’arrête à la table des résultats. La table de résultat est format long : statistique + clé d’analyse.
  • Présentation : Toute manipulation pour formater la table des résultats.

4 verbes

  • Ajouter (add_*): Une fonction qui ajoute une variable (colonne) au jeu de données. Par exemple, pour ajouter la durée d’une enquête, pour ajouter la catégorie de score de consommation alimentaire, etc.
  • Vérifier (check_*): Une fonction qui va signaler certaines valeurs (par exemple, valeurs autres à recoder, valeurs aberrantes, etc.). Un check_* renverra une liste : le jeu de données vérifié et le journal de nettoyage.

  • Créer (create_*): Une fonction qui créé, transforme quelque chose, par exemple créer un journal de nettoyage avec des actions à faire, créer une table de résultats d’analyse, créer un produit pour une présentation.
  • Revoir (review_*): Une fonction qui examinera un objet en le comparant à des standards ou à un autre objet et signalera les différences, par exemple en examinant le nettoyage en comparant le jeu de données brut, le jeu de données propre et le journal de nettoyage, l’analyse le comparant à une autre analyse.

2 adjectifs

  • « pipeable » : Chaque étape, chaque famille de fonctions (verbes) peuvent être utilisée une après l’autre. Cela permet à l’utilisateur.ice de pouvoir adapter chaque étape avec les fonctions spécifiques à son contexte.
  • Indépendant : A chaque étape, le cadre définit l’entrée et la sortie, le “comment” est libre, chaque utilisateur.ice peut donc choisir l’outil qu’il/elle préfère.

4 packages

  • cleaningtools
  • addindicators
  • analysistools
  • presentresults


https://github.com/impact-initiatives/

Nettoyage

check_

my_log1 <- my_raw_dataset %>% 
  check_outliers(uuid_column = "X_uuid")


typeof(my_log1)
[1] "list"


my_log1 %>% 
  names()
[1] "checked_dataset"    "potential_outliers"

my_log1$potential_outliers %>% 
  head()
# A tibble: 6 × 4
  uuid                                 issue                  question old_value
  <chr>                                <chr>                  <chr>        <dbl>
1 b5b1d37a-e27a-4c35-a0f5-2cde9d6dfd06 outlier (normal distr… age_res…        86
2 956b5ed0-5a62-41b7-aec3-af93fbc5b494 outlier (normal distr… age_res…        84
3 97ad6294-30c6-454e-a0b3-42126415b767 outlier (log distribu… age_res…        18
4 e005e719-57c4-44a3-ac2f-5d6d1ff68831 outlier (log distribu… age_res…        18
5 c9aaa542-118f-4e42-93de-fb0916572541 outlier (normal distr… num_hh_…        19
6 48e8896b-d1be-4600-8839-2d8b994ebcfb outlier (normal distr… num_hh_…        19

pipe-able

more_logs <- my_raw_dataset %>% 
  check_duplicate(uuid_column = "X_uuid") %>% 
  check_soft_duplicates(uuid_column = "X_uuid", kobo_survey = my_kobo_survey, sm_separator = ".") %>%
  check_outliers(uuid_column = "X_uuid") %>%
  check_value(uuid_column = "X_uuid") 


names(more_logs)
[1] "checked_dataset"    "duplicate_log"      "soft_duplicate_log"
[4] "potential_outliers" "flaged_value"      

more_logs$potential_outliers %>% 
  head()
# A tibble: 6 × 4
  uuid                                 issue                  question old_value
  <chr>                                <chr>                  <chr>        <dbl>
1 b5b1d37a-e27a-4c35-a0f5-2cde9d6dfd06 outlier (normal distr… age_res…        86
2 956b5ed0-5a62-41b7-aec3-af93fbc5b494 outlier (normal distr… age_res…        84
3 97ad6294-30c6-454e-a0b3-42126415b767 outlier (log distribu… age_res…        18
4 e005e719-57c4-44a3-ac2f-5d6d1ff68831 outlier (log distribu… age_res…        18
5 c9aaa542-118f-4e42-93de-fb0916572541 outlier (normal distr… num_hh_…        19
6 48e8896b-d1be-4600-8839-2d8b994ebcfb outlier (normal distr… num_hh_…        19
more_logs$duplicate_log %>% 
  head()
# A tibble: 0 × 4
# ℹ 4 variables: uuid <chr>, old_value <chr>, question <chr>, issue <glue>

create

my_combined_log <- create_combined_log(more_logs)
List of element to combine- checked_dataset, duplicate_log, soft_duplicate_log, potential_outliers, flaged_value


names(my_combined_log)
[1] "checked_dataset" "cleaning_log"   

my_combined_log$cleaning_log %>% 
  head()
# A tibble: 6 × 7
  uuid              old_value question issue change_type new_value check_binding
  <chr>             <chr>     <chr>    <chr> <chr>       <chr>     <chr>        
1 b5b1d37a-e27a-4c… 86        age_res… outl… <NA>        <NA>      age_responde…
2 956b5ed0-5a62-41… 84        age_res… outl… <NA>        <NA>      age_responde…
3 97ad6294-30c6-45… 18        age_res… outl… <NA>        <NA>      age_responde…
4 e005e719-57c4-44… 18        age_res… outl… <NA>        <NA>      age_responde…
5 c9aaa542-118f-4e… 19        num_hh_… outl… <NA>        <NA>      num_hh_membe…
6 48e8896b-d1be-46… 19        num_hh_… outl… <NA>        <NA>      num_hh_membe…


create_xlsx_cleaning_log(my_combined_log,
                         kobo_survey = my_kobo_survey,
                         kobo_choices = my_kobo_choice,
                         use_dropdown = T,
                         sm_dropdown_type = "logical",
                         output_path =  "outputs/02 - example - cleaning-log-with-kobo.xlsx")

create

my_filled_log <- readxl::read_excel("my_filled_log.xlsx", sheet = 2)

my_clean_data <- create_clean_data(raw_dataset = my_raw_dataset,
                                   raw_data_uuid_column = "X_uuid",
                                   cleaning_log = my_filled_log, 
                                   cleaning_log_uuid_column = "uuid",
                                   cleaning_log_question_column = "question",
                                   cleaning_log_new_value_column = "new_value",
                                   cleaning_log_change_type_column = "change_type")

review

review_of_cleaning <- review_cleaning(raw_dataset = my_raw_dataset,
                    raw_dataset_uuid_column = "X_uuid", 
                    clean_dataset = my_clean_data2$data_with_fix_concat,
                    clean_dataset_uuid_column = "X_uuid",
                    cleaning_log = my_filled_log_no_deletion, 
                    cleaning_log_uuid_column = "uuid",
                    cleaning_log_question_column = "question",
                    cleaning_log_new_value_column = "new_value",
                    cleaning_log_change_type_column = "change_type", 
                    cleaning_log_old_value_column = "old_value", 
                    deletion_log = my_deletion_log, 
                    deletion_log_uuid_column = "uuid"
                    )

Composition

add

my_data_with_indicators <- my_data %>%
  add_fcs(
  cutoffs = "normal",
  fsl_fcs_cereal = "fs_fcs_cereals_grains_roots_tubers",
  fsl_fcs_legumes = "fs_fcs_beans_nuts",
  fsl_fcs_veg = "fs_fcs_vegetables_leaves",
  fsl_fcs_fruit = "fs_fcs_fruit",
  fsl_fcs_meat = "fs_fcs_meat_fish_eggs",
  fsl_fcs_dairy = "fs_fcs_dairy",
  fsl_fcs_sugar = "fs_fcs_sugar",
  fsl_fcs_oil = "fs_fcs_oil_fat_butter"
  ) %>%
  add_hhs(
  )

my_data_with_indicators[, tail(names(my_data_with_indicators), 14)] %>%
  head()
  fsl_fcs_score fsl_fcs_cat fs_hhs_nofood_yn_recoded fs_hhs_nofood_freq_recoded
1          48.5  Acceptable                        0                          0
2          50.5  Acceptable                        1                          1
3          46.5  Acceptable                        0                          0
4          42.5  Acceptable                        0                          0
5          55.5  Acceptable                        0                          0
6          37.5  Acceptable                        1                          1
  fs_hhs_sleephungry_yn_recoded fs_hhs_sleephungry_freq_recoded
1                             0                               0
2                             0                               0
3                             1                               2
4                             0                               1
5                             0                               1
6                             0                               2
  fs_hhs_daynoteating_yn_recoded fs_hhs_daynoteating_freq_recoded hhs_comp1
1                              0                                0         0
2                              0                                1         1
3                              1                                0         0
4                              1                                0         0
5                              1                                0         0
6                              1                                2         1
  hhs_comp2 hhs_comp3 hhs_score hhs_cat_ipc      hhs_cat
1         0         0         0        None No or Little
2         0         0         1      Little No or Little
3         2         0         2    Moderate     Moderate
4         0         0         0        None No or Little
5         0         0         0        None No or Little
6         0         2         3    Moderate     Moderate

Analyse

create

my_design <- srvyr::as_survey_design(my_data_with_indicators, strata = "admin1")

my_analysis <- create_analysis(my_design, sm_separator = "/")

Entrée pour create_analysis est un object survey_design de survey/srvyr

my_analysis$results_table %>%
  select(stat, analysis_key) %>%
  head()
# A tibble: 6 × 2
   stat analysis_key                                                            
  <dbl> <chr>                                                                   
1 0.258 prop_select_one @/@ fcs_cat %/% low @/@ location %/% locationA -/- popu…
2 0.323 prop_select_one @/@ fcs_cat %/% medium @/@ location %/% locationA -/- p…
3 0.419 prop_select_one @/@ fcs_cat %/% high @/@ location %/% locationA -/- pop…
4 0.25  prop_select_one @/@ fcs_cat %/% low @/@ location %/% locationA -/- popu…
5 0.375 prop_select_one @/@ fcs_cat %/% medium @/@ location %/% locationA -/- p…
6 0.375 prop_select_one @/@ fcs_cat %/% high @/@ location %/% locationA -/- pop…

Produits

create

library(presentresults)
my_analysis$results_table %>% 
  create_table_group_x_variable() %>% 
  create_xlsx_group_x_variable(file_path = "outputs/04 - example - group_x_variable.xlsx", overwrite = T)

my_results_table %>% 
  create_table_variable_x_group() %>%
  create_xlsx_variable_x_group(file_path = "outputs/05 - example - variable_x_group.xlsx", overwrite = T)

Merci


yann.say@impact-initiatives.org

www.impact-initiatives.org