library(rtauargus)
library(dplyr)
4 Poser le secret sur plusieurs tableaux liés
- Analyser les tableaux pour construire une liste de tableaux et une liste de variables de croisement.
- Poser le secret primaire sur chacun des tableaux indépendamment.
- Calculer le nombre de cellules détectées comme à risque dans chacun des tableaux (i.e. le nombre cellules en secret primaire).
- Poser le secret secondaire en utilisant la fonction
tab_multi_manager()
. - Faire une synthèse de la pose du secret dans chaque tableau.
Objectif : savoir protéger un ensemble de tableaux liés en utilisant la fonction tab_multi_manager()
du package rtauargus
.
Ce chapitre a été réalisé avec la version 1.2.0 de rtauargus
et la version 4.2.3 de TauArgus
.
Appliquons les étapes présentées ci-dessus sur quatre tableaux présents nativement dans le package rtauargus
.
data("turnover_act_size")
data("turnover_act_cj")
data("turnover_nuts_size")
data("turnover_nuts_cj")
4.1 Analyser les caractéristiques des tableaux
4.1.1 Détecter liens par les marges
Les tableaux présentés ici ont la structure suivante :
turnover_act_size
: chiffre d’affaires ventilé par activité et taille de l’entrepriseturnover_act_cj
: chiffre d’affaires ventilé par activité et taille de l’entrepriseturnover_nuts_size
: chiffre d’affaires ventilé par nuts et taille de l’entrepriseturnover_nuts_cj
: chiffre d’affaires ventilé par nuts et catégorie juridique de l’entreprise
Ils sont liés par leurs marges:
turnover_act_size
etturnover_act_cj
partagent les marges d’activitéturnover_nuts_size
etturnover_nuts_cj
partagent les marges des nutsturnover_act_size
etturnover_nuts_size
partagent les marges de tailleturnover_act_cj
etturnover_nuts_cj
partagent les marges de catégorie juridique
4.1.2 Réperer les variables hiérarchiques
Les variables ACTIVITY
et NUTS
sont hiérarchiques. Il faut donc constituer les fichiers argus nécessaires.
Les tables de correspondance associées à ces variables sont présents dans le package : activity_corr_table
et nuts23_fr_corr_table
.
data("activity_corr_table")
data("nuts23_fr_corr_table")
On utilise ces tables de correspondance pour construire les fichiers hiérarchiques pour TauArgus.
<- write_hrc2(activity_corr_table,
act_hrc_file file_name = "tauargus_files/hrc/activity.hrc")
<- write_hrc2(nuts23_fr_corr_table,
nuts_hrc_file file_name = "tauargus_files/hrc/nuts23.hrc")
Cette fonction crée les fichiers hiérarchiques .hrc
dans le répertoire indiqué dans l’argument file_name
et retourne le chemin de ce document.
act_hrc_file
[1] "tauargus_files/hrc/activity.hrc"
nuts_hrc_file
[1] "tauargus_files/hrc/nuts23.hrc"
4.1.3 Construire une liste de tableaux et une liste de variables de croisement
Dans le code ci-dessous, nous manipulons les objets list
de R
. Si ce type d’objets ne vous est pas familier, vous pouvez vous reporter à l’annexe 12 qui présente les listes et comment les manipuler.
<- list(
liste_4tabs act_size = turnover_act_size,
act_cj = turnover_act_cj,
nuts_size = turnover_nuts_size,
nuts_cj = turnover_nuts_cj
)
<- purrr::map(
liste_vars_4tabs
liste_4tabs,function(data) colnames(data)[1:2]
)str(liste_vars_4tabs)
List of 4
$ act_size : chr [1:2] "ACTIVITY" "SIZE"
$ act_cj : chr [1:2] "ACTIVITY" "CJ"
$ nuts_size: chr [1:2] "NUTS" "SIZE"
$ nuts_cj : chr [1:2] "NUTS" "CJ"
Avertissement : il faut repérer les codes servant au total et de s’assurer qu’ils sont cohérents pour une même variable apparaissant dans plusieurs tableaux. En effet, deux tableaux partageant la même variable doivent utiliser la même modalité pour renseigner le total. On le vérifie en regardant les données.
any(turnover_act_cj$CJ == "Total")
[1] TRUE
any(turnover_nuts_size$NUTS == "Total")
[1] TRUE
any(turnover_nuts_cj$NUTS == "Total")
[1] TRUE
any(turnover_nuts_cj$CJ == "Total")
[1] TRUE
Ici il n’y a pas de problème puisque toutes les variables en commun ont une même modalité représentant les marges : “Total”.
4.2 Poser le secret primaire sur chacun des tableaux
Les règles de secret appliquées ici correspondent aux règles spécifiques aux statistiques entreprises. Pour en savoir plus sur les différentes règles existantes, reportez-vous à l’annexe 11.
<- liste_4tabs %>%
liste_4tabs ::map(
purrrfunction(df){
%>%
df mutate(
is_secret_freq = N_OBS > 0 & N_OBS < 3,
is_secret_dom = (MAX != 0) & (MAX > TOT*0.85),
is_secret_prim = is_secret_freq | is_secret_dom
)
} )
Ce code est expliqué à l’annexe 12.
4.3 Calculer le nombre de cellules en secret primaire
Avant de passer à l’étape suivante il est important de prendre connaissance de la quantité de secret primaire présent dans les tableaux. En effet, s’il y a beaucoup de secret primaire alors il y aura sans doute beaucoup de secret secondaire et donc vraisemblablement trop de cellules en secret. Dans ce cas-là, il est intéressant pour réduire le secret primaire de changer les tableaux en regroupant des variables ou des modalités.
%>% purrr::walk(function(tab) count(tab, is_secret_prim) %>% print()) liste_4tabs
# A tibble: 2 × 2
is_secret_prim n
<lgl> <int>
1 FALSE 337
2 TRUE 77
# A tibble: 2 × 2
is_secret_prim n
<lgl> <int>
1 FALSE 346
2 TRUE 60
# A tibble: 2 × 2
is_secret_prim n
<lgl> <int>
1 FALSE 388
2 TRUE 72
# A tibble: 2 × 2
is_secret_prim n
<lgl> <int>
1 FALSE 387
2 TRUE 65
4.4 Poser le secret secondaire avec tab_multi_manager()
La fonction tab_multi_manager()
requiert les arguments suivants :
list_tables : liste de tables à protéger
list_explanatory_vars : liste des noms des variables de croisements présentes dans la liste des tables à protéger dans la table;
dir_name : le nom du répertoire qui contiendra tous les fichiers créés, s’il n’existe pas, il sera créé (ex :
dir_name = "my_directory"
).hrc : un vecteur nommé spécifiant le chemin vers le fichier
.hrc
pour chaque variable hiérarchique (ex :c(ACTIVITY = “chemin_vers_fichier/act.hrc”, NUTS = “chemin_vers_fichier/nuts.hrc” )
).alt_hrc : une liste nommée utile pour traiter les hiérarchies non emboîtées. Les noms de la liste sont les noms des tableaux pour lesquelles une autre hiérarchie (non emboîtée en général) doit être utilisée (ex : si T1 et T2 ont une variable explicative, appelée
ACTIVITY
, et la même variable de réponse, mais la variableACTIVITY
n’a pas la même hiérarchie dans les les deux tables). Supposons que les hiérarchies (act1.hrc
etact2.hrc
) ne sont pas emboîtées. Dans ce cas, nous écrivons les deux arguments comme suit :hrc = c(ACTIVITY = "path_to_file/act_1.hrc")
: par défaut, cette hiérarchie sera utilisée pour la variable ACTIVITY.alt_hrc = list(T2 = c(ACTIVITY = "chemin_vers_fichier/act_2.hrc"))
dans la table T2, la hiérarchie alternative sera utilisée.
totcode : le code du total pour chaque variable explicative. Il est recommandé d’utiliser le même code de total pour chaque variable. Si par exemple le code est “Total” pour toutes les variables. La syntaxe suivante est autorisée :
totcode = “Total”
. Sinon, l’input attendu est une liste spécifiant le code total pour chaque variable explicative (ex :totcode = list(ACTIVITY = “Total”, NUTS = “FR”, SIZE = “Ensemble”, CJ = “Total”)
)
Attention : Si les totaux ne sont pas dans la table, ils seront calculés par Tau-Argus, mais ils ne seront pas éligibles pour la suppression primaire. Il est donc nécessaire de les fournir dans la table de départ.
alt_totcode : une liste nommée pour les codes de totaux alternatifs (voir
alt_hrc
pour l’utilisation).value : le nom de colonne de la variable de réponse dans les tableaux, il DOIT être identique pour chaque table (ex :
valeur = “turnover”
). Valeur par défaut :“value”
.freq : le nom de colonne de la variable de fréquence dans les tableaux, il DOIT être le même nom pour chaque tableau (ex :
freq = “frequency”
). Valeur par défaut :“freq”
.secret_var : le nom de la variable booléenne spécifiant le secret primaire dans les tables, il DOIT être le même nom pour chaque table (ex :
secret_var = “is_secret_prim”
). Valeur par défaut :“is_secret_prim”
.
<- tab_multi_manager(
masq_4tabs list_tables = liste_4tabs,
list_explanatory_vars = liste_vars_4tabs,
dir_name = "tauargus_files/4tabs",
hrc = list(ACTIVITY = act_hrc_file, NUTS = nuts_hrc_file),
totcode = "Total",
value = "TOT",
freq = "N_OBS",
secret_var = "is_secret_prim"
)
4.5 Analyser les résultats
Analyser le journal
La fonction tab_multi_manager()
fournit un journal décrivant l’ensemble des itérations réalisées lors du processus de protection. Il s’agit du fichier journal.txt
dans le répertoire mentionné dans dir_name
.
Pour chaque étape, sont indiqués :
- Le tableau sur lequel est posé sur le secret secondaire ;
- Le bilan du secret posé sur ce tableau ;
- Le nombre de cellules communes (c’est-à-dire appartenant à plusieurs tableaux) touchées.
L’ensemble des cellules communes est listé en fin de processus.
Bilan du secret
L’objet retourné par la fonction tab_multi_manager()
est une liste contenant les mêmes tables que la liste placée en input auxquelles sont ajoutés les résultats des différentes étapes de la pose du secret secondaire. Ainsi, la dernière variable de chaque tableau permet de déterminer le statut final de chaque cellule.
Ce code crée une variable statut_final
renvoyant les codes de la norme européenne :
- `A` les cellules en secret primaire à cause de la règle de
fréquence
- `B` les cellules en secret primaire à cause de la règle de
dominance
- `D` les cellules concernées par le secret secondaire
- `V` les cellules non touchées par le secret, c'est-à-dire les
cellules qui pourront être diffusées
<- masq_4tabs %>%
masq_4tabs ::map(
purrrfunction(tab){
%>%
tab rename_with(~"is_secret_final", last_col()) %>%
mutate(
statut_final = case_when(
~ "A",
is_secret_freq ~ "B",
is_secret_dom ~ "D",
is_secret_final TRUE ~ "V"
)
)
}
)str(masq_4tabs)
List of 4
$ act_size :'data.frame': 414 obs. of 14 variables:
..$ ACTIVITY : chr [1:414] "01" "01" "02" "02" ...
..$ SIZE : chr [1:414] "Total" "tr1" "Total" "tr1" ...
..$ N_OBS : int [1:414] 18 18 387 381 6 1 1 4 4 84 ...
..$ TOT : num [1:414] 853 853 43623 35503 8120 ...
..$ MAX : num [1:414] 303 303 6212 6212 4812 ...
..$ is_secret_freq : logi [1:414] FALSE FALSE FALSE FALSE FALSE TRUE ...
..$ is_secret_dom : logi [1:414] FALSE FALSE FALSE FALSE FALSE TRUE ...
..$ is_secret_prim : logi [1:414] FALSE FALSE FALSE FALSE FALSE TRUE ...
..$ is_secret_1 : logi [1:414] FALSE FALSE FALSE FALSE FALSE TRUE ...
..$ is_secret_2 : logi [1:414] FALSE FALSE FALSE FALSE FALSE TRUE ...
..$ is_secret_3 : logi [1:414] FALSE FALSE FALSE FALSE FALSE TRUE ...
..$ is_secret_4 : logi [1:414] FALSE FALSE FALSE FALSE FALSE TRUE ...
..$ is_secret_final: logi [1:414] FALSE FALSE FALSE FALSE FALSE TRUE ...
..$ statut_final : chr [1:414] "V" "V" "V" "V" ...
$ act_cj :'data.frame': 406 obs. of 14 variables:
..$ ACTIVITY : chr [1:406] "01" "01" "01" "02" ...
..$ CJ : chr [1:406] "LL" "SP" "Total" "LL" ...
..$ N_OBS : int [1:406] 9 9 18 240 147 387 1 1 1 3 ...
..$ TOT : num [1:406] 435 418 853 27625 15998 ...
..$ MAX : num [1:406] 263 303 303 6212 672 ...
..$ is_secret_freq : logi [1:406] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_dom : logi [1:406] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_prim : logi [1:406] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_1 : logi [1:406] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_2 : logi [1:406] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_3 : logi [1:406] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_4 : logi [1:406] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_final: logi [1:406] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ statut_final : chr [1:406] "V" "V" "V" "V" ...
$ nuts_size:'data.frame': 460 obs. of 14 variables:
..$ NUTS : chr [1:460] "FR10" "FR10" "FR10" "FR10" ...
..$ SIZE : chr [1:460] "Total" "tr1" "tr2" "tr3" ...
..$ N_OBS : int [1:460] 38462 37329 1096 37 19469 18919 529 21 2725 2649 ...
..$ TOT : num [1:460] 33026385 13774596 7172793 12078996 19217180 ...
..$ MAX : num [1:460] 3084242 1013320 513792 3084242 3084242 ...
..$ is_secret_freq : logi [1:460] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_dom : logi [1:460] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_prim : logi [1:460] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_1 : logi [1:460] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_2 : logi [1:460] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_3 : logi [1:460] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_4 : logi [1:460] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_final: logi [1:460] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ statut_final : chr [1:460] "V" "V" "V" "V" ...
$ nuts_cj :'data.frame': 452 obs. of 14 variables:
..$ NUTS : chr [1:452] "FR10" "FR10" "FR10" "FR10" ...
..$ CJ : chr [1:452] "LL" "PA" "SP" "Total" ...
..$ N_OBS : int [1:452] 28705 1012 8745 38462 15372 983 3114 19469 1598 1 ...
..$ TOT : num [1:452] 24151930 26238 8848217 33026385 13207770 ...
..$ MAX : num [1:452] 1674878 5577 3084242 3084242 1674878 ...
..$ is_secret_freq : logi [1:452] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_dom : logi [1:452] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_prim : logi [1:452] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_1 : logi [1:452] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_2 : logi [1:452] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_3 : logi [1:452] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_4 : logi [1:452] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ is_secret_final: logi [1:452] FALSE FALSE FALSE FALSE FALSE FALSE ...
..$ statut_final : chr [1:452] "V" "V" "V" "V" ...
On peut ainsi dresser notre bilan par tableau :
%>%
masq_4tabs ::imap_dfr(
purrrfunction(tab, nom){
%>%
tab count(statut_final) %>%
mutate(
part = n/sum(n)*100,
table = nom
%>%
) relocate(table)
} )
table statut_final n part
1 act_size A 52 12.560386
2 act_size B 25 6.038647
3 act_size D 83 20.048309
4 act_size V 254 61.352657
5 act_cj A 35 8.620690
6 act_cj B 25 6.157635
7 act_cj D 88 21.674877
8 act_cj V 258 63.546798
9 nuts_size A 55 11.956522
10 nuts_size B 17 3.695652
11 nuts_size D 82 17.826087
12 nuts_size V 306 66.521739
13 nuts_cj A 45 9.955752
14 nuts_cj B 20 4.424779
15 nuts_cj D 101 22.345133
16 nuts_cj V 286 63.274336