::p_load(
pacman# importation de données
rio, # chemins d'accès relatifs aux fichiers
here, # nettoyage des données et tableaux
janitor, # travailler avec des dates
lubridate, # fonction age_categories()
epikit, # age pyramids
apyramid, # manipulation et visualisation des données
tidyverse, # colour palettes
RColorBrewer, # fancy tables
formattable, # formatage des tableaux
kableExtra )
25 Suivi des contacts
Cette page présente une analyse descriptive de données de recherche de contacts, en ajoutant quelques considérations et approches clés uniques à ce type de données.
Cette page fait référence à un grand nombre des compétences de base en matière de gestion et de visualisation des données R abordées dans d’autres pages (par exemple, le nettoyage des données, le pivotement, les tableaux, les analyses de séries chronologiques), mais nous mettrons en évidence des exemples spécifiques au suivi des contacts qui ont été utiles pour la prise de décision opérationnelle. Il s’agit par exemple de la visualisation des données de suivi de la recherche de contacts dans le temps ou dans des zones géographiques, ou de la production de tableaux d’indicateurs de performance clés (KPI) propres pour les superviseurs de la recherche de contacts.
Pour la démonstration, nous utiliserons un échantillon de données de suivi des contacts provenant de la plateforme Go.Data. Les principes abordés ici s’appliquent aux données de suivi des contacts provenant d’autres plates-formes. Il se peut que vous deviez simplement suivre différentes étapes de pré-traitement des données en fonction de la structure de vos données.
Vous pouvez en savoir plus sur le projet Go.Data sur le site de documentation Github ou la communauté de pratique.
25.1 Préparation
Chargement de packages
Ce bout de code montre le chargement des packages nécessaires aux analyses. Dans ce manuel, nous mettons l’accent sur p_load()
de pacman, qui installe le package si nécessaire et le charger pour l’utiliser. Vous pouvez aussi charger les packages installés avec library()
de base R. Voir la page sur bases de R pour plus d’informations sur les packages R.
Importation de données
Nous allons importer des jeux de données exemple de contacts, et de leur”suivi”. Ces données ont été récupérées et non imbriquées à partir de l’API Go.Data et stockées dans des fichiers “.rds”.
Vous pouvez télécharger tous les exemples de données pour ce manuel à partir de la page Télécharger le manuel et les données.
Si vous souhaitez télécharger les exemples de données de suivi des contacts spécifiques à cette page, utilisez les trois liens de téléchargement ci-dessous :
Cliquer pour télécharger données sur les investigations des cas (.rds file)
Cliquer pour télécharger les données d’enregistrement de contacts (.rds file)
Cliquer pour télécharger les données de suivi des contacts (.rds file)
Dans leur forme originale dans les fichiers téléchargeables, les données reflètent les données fournies par l’API Go.Data (en savoir plus sur APIs here). À titre d’exemple, nous allons nettoyer les données pour les rendre plus faciles à lire sur cette page. Si vous utilisez une instance Go.Data, vous pouvez consulter les instructions complètes sur la façon de récupérer vos données here.
Ci-dessous, les jeux de données sont importés à l’aide de la fonction import()
du package rio. Voir la page Importation et exportation pour les différentes manières d’importer des données. Nous utilisons here()
pour spécifier le chemin du fichier - vous devez fournir le chemin du fichier spécifique à votre ordinateur. Nous utilisons ensuite select()
pour sélectionner seulement certaines colonnes des données, afin de simplifier pour les besoins de la démonstration.
Données des cas
Ces données sont un tableau des cas, et des informations les concernant.
<- import(here("data", "godata", "cases_clean.rds")) %>%
cases select(case_id, firstName, lastName, gender, age, age_class,
occupation, classification, was_contact, hospitalization_typeid)
Voici les nrow(cases)
cas :
Données sur les contacts
Ces données sont un tableau de tous les contacts et des informations les concernant. Là encore, vous pouvez fournir votre propre chemin de fichier. Après l’importation, nous effectuons quelques étapes préliminaires de nettoyage des données, notamment :
- Définir age_class comme facteur et inverser l’ordre des niveaux pour que les plus jeunes soient les premiers.
- Sélectionner seulement certaines colonnes, en renommant l’une d’entre elles.
- Attribuer artificiellement les lignes dont le 2 niveau d’administration est manquant à “Djembe”, pour améliorer la clarté de certains exemples de visualisation.
<- import(here("data", "godata", "contacts_clean.rds")) %>%
contacts mutate(age_class = forcats::fct_rev(age_class)) %>%
select(contact_id, contact_status, firstName, lastName, gender, age,
age_class, occupation, date_of_reporting, date_of_data_entry,date_of_last_exposure = date_of_last_contact,
%>%
date_of_followup_start, date_of_followup_end, risk_level, was_case, admin_2_name) mutate(admin_2_name = replace_na(admin_2_name, "Djembe"))
Voici les nrow(contacts)
lignes de le contacts
dataframe:
Données de suivi
Ces données sont des enregistrements des interactions de “suivi” avec les contacts. Chaque contact est censé avoir une rencontre chaque jour pendant 14 jours après son exposition.
Nous importons et effectuons quelques étapes de nettoyage. Nous sélectionnons certaines colonnes, et convertissons également une colonne de caractères en toutes les valeurs minuscules.
<- rio::import(here::here("data", "godata", "followups_clean.rds")) %>%
followups select(contact_id, followup_status, followup_number,
%>%
date_of_followup, admin_2_name, admin_1_name) mutate(followup_status = str_to_lower(followup_status))
Voici les 50 premières lignes de la base de données nrow(followups)
-row followups
(chaque ligne est une interaction de suivi, avec le statut du suivi dans la colonne followup_status
) :
Données de relations
Ici, nous importons des données montrant la relation entre les cas et les contacts. Nous sélectionnons certaines colonnes à afficher.
<- rio::import(here::here("data", "godata", "relationships_clean.rds")) %>%
relationships select(source_visualid, source_gender, source_age, date_of_last_contact,
date_of_data_entry, target_visualid, target_gender, target_age, exposure_type)
Vous trouverez ci-dessous les 50 premières lignes du jeu de données relations
, qui enregistre toutes les relations entre les cas et les contacts.
25.2 Analyses descriptives
Vous pouvez utiliser les techniques abordées dans d’autres pages de ce manuel pour effectuer des analyses descriptives de vos cas, de vos contacts et de leurs relations. Vous trouverez ci-dessous quelques exemples
Démographie
Comme le montre la page consacrée aux Pyramides démographiques, vous pouvez visualiser la répartition par âge et par sexe (nous utilisons ici le package apyramide).
Age et sexe des contacts
La pyramide ci-dessous compare la répartition par âge des contacts, par sexe. Notez que les contacts dont l’âge est manquant sont inclus dans leur propre barre en haut. Vous pouvez modifier ce comportement par défaut, mais envisagez alors d’indiquer le nombre de contacts manquants dans une légende.
::age_pyramid(
apyramiddata = contacts, # utiliser la base de données des contacts
age_group = "age_class", # colonne d'âge catégorielle
split_by = "gender") + # genre pour les moitiés de la pyramide
labs(
fill = "Gender", # titre de la légende
title = "Age/Sex Pyramid of COVID-19 contacts")+ # titre du graphique
theme_minimal() # un fond simple
Avec la structure de données Go.Data, le jeu de données relations
contient les âges des cas et des contacts, vous pourriez donc utiliser ce jeu de données et créer une pyramide des âges montrant les différences entre ces deux groupes de personnes. Le tableau de données relations
sera modifié pour transformer les colonnes d’âge numériques en catégories (voir la page Nettoyage des données et fonctions de base). Nous faisons également pivoter le tableau de données pour faciliter le traçage avec ggplot2 (voir Pivoter les données).
<- relationships %>%
relation_age select(source_age, target_age) %>%
transmute( # transmute est comme mutate() mais supprime toutes les autres colonnes non mentionnées
source_age_class = epikit::age_categories(source_age, breakers = seq(0, 80, 5)),
target_age_class = epikit::age_categories(target_age, breakers = seq(0, 80, 5)),
%>%
) pivot_longer(cols = contains("class"), names_to = "category", values_to = "age_class") # pivotement plus long
relation_age
# A tibble: 200 × 2
category age_class
<chr> <fct>
1 source_age_class 80+
2 target_age_class 15-19
3 source_age_class <NA>
4 target_age_class 50-54
5 source_age_class <NA>
6 target_age_class 20-24
7 source_age_class 30-34
8 target_age_class 45-49
9 source_age_class 40-44
10 target_age_class 30-34
# ℹ 190 more rows
Maintenant nous pouvons tracer cet ensemble de données transformées avec age_pyramid()
comme avant, mais en remplaçant gender
par category
(contact, ou cas).
::age_pyramid(
apyramiddata = relation_age, # utiliser un ensemble de données de relations modifiées
age_group = "age_class", # colonne d'âge catégorielle
split_by = "category") + # par cas et contacts
scale_fill_manual(
values = c("orange", "purple"), # pour spécifier les couleurs ET les étiquettes
labels = c("Case", "Contact"))+
labs(
fill = "Legend", # titre de la légende
title = "Pyramides demographiques de cas et contacts de COVID-19")+ # titre du graph
theme_minimal() # fond simple
Nous pouvons également visualiser d’autres caractéristiques telles que la répartition par profession (par exemple, sous la forme d’un diagramme circulaire).
# Clean dataset and get counts by occupation
<- cases %>%
occ_plot_data mutate(occupation = forcats::fct_explicit_na(occupation), # faire des valeurs manquantes NA une catégorie
occupation = forcats::fct_infreq(occupation)) %>% # ordonner les niveaux de facteurs par ordre de fréquence
count(occupation) # obtenir des chiffres par profession
# Make pie chart
ggplot(data = occ_plot_data, mapping = aes(x = "", y = n, fill = occupation))+
geom_bar(width = 1, stat = "identity") +
coord_polar("y", start = 0) +
labs(
fill = "Occupation",
title = "Occupation connue des cas de covid-19")+
theme_minimal() +
theme(axis.line = element_blank(),
axis.title = element_blank(),
axis.text = element_blank())
Contacts par cas
Le nombre de contacts par cas peut être une unité de mesure importante pour évaluer la qualité du dénombrement des contacts et la conformité de la population à la réponse de santé publique.
En fonction de votre structure de données, cela peut être évalué avec un ensemble de données qui contient tous les cas et les contacts. Dans les ensembles de données de Go.Data, les liens entre les cas (“sources”) et les contacts (“cibles”) sont stockés dans le jeu de données relationships
.
Dans cet ensemble de données, chaque ligne est un contact, et le cas source est listé dans la ligne. Aucun contact n’a de relations avec plusieurs affaires. multiples, mais si c’est le cas, vous devrez peut-être en tenir compte avant de faire le graphique (et de les explorer aussi !).
Nous commençons par compter le nombre de lignes (contacts) par cas source. Ceci est enregistré comme un tableau de données.
<- relationships %>%
contacts_per_case count(source_visualid)
contacts_per_case
source_visualid n
1 CASE-2020-0001 13
2 CASE-2020-0002 5
3 CASE-2020-0003 2
4 CASE-2020-0004 4
5 CASE-2020-0005 5
6 CASE-2020-0006 3
7 CASE-2020-0008 3
8 CASE-2020-0009 3
9 CASE-2020-0010 3
10 CASE-2020-0012 3
11 CASE-2020-0013 5
12 CASE-2020-0014 3
13 CASE-2020-0016 3
14 CASE-2020-0018 4
15 CASE-2020-0022 3
16 CASE-2020-0023 4
17 CASE-2020-0030 3
18 CASE-2020-0031 3
19 CASE-2020-0034 4
20 CASE-2020-0036 1
21 CASE-2020-0037 3
22 CASE-2020-0045 3
23 <NA> 17
Nous utilisons geom_histogram()
pour représenter ces données sous forme d’histogramme.
ggplot(data = contacts_per_case)+ # commencer avec le tableau de données créé ci-dessus
geom_histogram(mapping = aes(x = n))+ # afficher l'histogramme du nombre de contacts par cas
scale_y_continuous(expand = c(0,0))+ # supprimer l'espace excédentaire en dessous de 0 sur l'axe des ordonnées
theme_light()+ # simplifier le fond
labs(
title = "Number of contacts per case",
y = "Cases",
x = "Contacts per case"
)
25.3 Suivi de contacts
Les données de recherche des contacts contiennent souvent des données de “suivi”, qui enregistrent les résultats des contrôles quotidiens des symptômes des personnes en quarantaine. L’analyse de ces données permet d’orienter la stratégie de réponse, d’identifier les contacts susceptibles d’être perdus pour le suivi ou de développer la maladie.
Nettoyage de données
Ces données peuvent exister sous différents formats. Elles peuvent exister sous la forme d’une large avec une ligne par contact et une colonne par “jour” de suivi. jour” de suivi. Voir Pivoter les données pour obtenir des descriptions des données “longues” et données “larges” et comment faire pivoter des données plus larges ou plus longues.
Dans notre exemple Go.Data, ces données sont stockées dans le tableau followups
, qui est dans un format “long” avec une ligne par interaction de suivi. Les 50 premières lignes ressemblent à ceci :
ATTENTION: Méfiez-vous des doublons lorsque vous traitez des données de suivi, car il peut y avoir plusieurs suivis erronés le même jour pour un contact donné. Cela peut sembler être une erreur mais reflète la réalité - par exemple, un agent de recherche de contacts pourrait soumettre un formulaire de suivi en début de journée alors qu’il n’a pas pu joindre le contact, et soumettre un second formulaire lorsqu’il a été joint par la suite. La façon dont vous souhaitez traiter les doublons dépend du contexte opérationnel. - veillez simplement à documenter clairement votre approche.
Voyons combien d’instances de lignes “en double” nous avons :
%>%
followups count(contact_id, date_of_followup) %>% # obtenir des jours de suivi uniques
filter(n > 1) # afficher les enregistrements où le nombre est supérieur à 1
contact_id date_of_followup n
1 <NA> 2020-09-03 2
2 <NA> 2020-09-04 2
3 <NA> 2020-09-05 2
Dans notre exemple de données, les seuls enregistrements auxquels cela s’applique sont ceux auxquels il manque un ID ! Nous pouvons les supprimer. Mais, pour les besoins de la démonstration, nous allons montrer les étapes de la déduplication afin qu’il n’y ait qu’un seul encoutrement de suivi par personne et par jour. Voir la page sur déduplication pour plus de détails. Nous supposerons que l’enregistrement de rencontre le plus récent est le bon. Nous profitons également de l’occasion pour nettoyer la colonne followup_number
(le “jour” du suivi qui devrait qui devrait être compris entre 1 et 14).
<- followups %>%
followups_clean
# Enlever les doublons
group_by(contact_id, date_of_followup) %>% # grouper les lignes par jour de suivi
arrange(contact_id, desc(date_of_followup)) %>% # organiser les lignes, par jour de suivi, par date de suivi (le plus récent en haut)
slice_head() %>% # ne conserver que la première ligne par id contact
ungroup() %>%
# Autres nettoyages
mutate(followup_number = replace(followup_number, followup_number > 14, NA)) %>% # nettoyer des données erronées
drop_na(contact_id) # supprimer les id_contact dont les données sont manquantes
Pour chaque rencontre de suivi, nous avons un statut de suivi (tel que si la rencontre a eu lieu et, le cas échéant, si le contact a eu des symptômes ou non). Pour voir toutes les valeurs, nous pouvons exécuter un rapide tabyl()
(de janitor) ou table()
(de base R) (voir Tableaux descriptifs) par followup_status
pour voir la fréquence de chacun des résultats.
Dans cet ensemble de données, “vu_not_ok” signifie “vu avec des symptômes”, et “vu_ok” signifie “vu sans symptômes”.
%>%
followups_clean tabyl(followup_status)
followup_status n percent
missed 10 0.02325581
not_attempted 5 0.01162791
not_performed 319 0.74186047
seen_not_ok 6 0.01395349
seen_ok 90 0.20930233
Graphe dans le temps
Comme les données de dates sont continues, nous utiliserons un histogramme pour les représenter avec date_du_suivi
assigné à l’axe des abscisses. Nous pouvons obtenir un histogramme “empilé” en spécifiant un argument fill =
dans aes()
, que nous assignons à la colonne followup_status
. Par conséquent, vous pouvez définir le titre de la légende en utilisant l’argument fill =
de labs()
.
On constate que les contacts ont été identifiés par vagues (correspondant vraisemblablement aux vagues épidémiques de cas), et que vl’achèvement du suivi ne semble pas s’être amélioré au cours de l’épidémie.
ggplot(data = followups_clean)+
geom_histogram(mapping = aes(x = date_of_followup, fill = followup_status)) +
scale_fill_discrete(drop = FALSE)+ # Afficher tous les niveaux de facteurs (followup_status) dans la légende, même ceux qui ne sont pas utilisés.
theme_classic() +
labs(
x = "",
y = "Number of contacts",
title = "Daily Contact Followup Status",
fill = "Followup Status",
subtitle = str_glue("Data as of {max(followups$date_of_followup, na.rm=T)}")) # sous-titres dynamiques
ATTENTION: Si vous préparez de nombreux graphiques (par exemple pour plusieurs juridictions), vous voudrez que les légendes apparaissent de manière identique, même si les données sont plus ou moins complètes ou composées. Il peut y avoir des graphiques pour lesquels tous les statuts de suivi ne sont pas présents dans les données, mais vous voulez quand même que ces catégories apparaissent dans les légendes. Dans les ggplots (comme ci-dessus), vous pouvez spécifier l’argument drop = FALSE
de la fonction scale_fill_discrete()
. Dans les tableaux, utilisez tabyl()
qui montre les comptes pour tous les niveaux de facteurs, ou si vous utilisez count()
de dplyr ajoutez l’argument .drop = FALSE
pour inclure les comptes pour tous les niveaux de facteurs.
Suivi quotidien individuel
Si votre épidémie est suffisamment petite, vous voudrez peut-être voir chaque contact individuellement et voir son statut au cours de son suivi. Heureusement, cet tableau de données followups
contient déjà une colonne avec le le “numéro” du jour du suivi (1-14). Si cette colonne n’existe pas dans vos données, vous pouvez la créer en calculant la différence entre la date de la dernière rencontre et la date à laquelle le suivi devait commencer pour le contact.
Un mécanisme de visualisation pratique (si le nombre de cas n’est pas trop important) peut être un diagramme de dispersion, réalisé avec geom_tile()
. Voir plus de détails dans la page heat plot.
ggplot(data = followups_clean)+
geom_tile(mapping = aes(x = followup_number, y = contact_id, fill = followup_status),
color = "grey")+ # lignes grises
scale_fill_manual( values = c("yellow", "grey", "orange", "darkred", "darkgreen"))+
theme_minimal()+
scale_x_continuous(breaks = seq(from = 1, to = 14, by = 1))
Analyse par groupe
Ces données de suivi sont peut-être consultées journellement ou hebdomadairement pour la prise de décision opérationnelle. Vous souhaitez peut-être des désagrégations plus significatives par zone géographique ou par équipe de suivi des contacts. Nous pouvons le faire en ajustant les colonnes fournies à group_by()
.
<- followups_clean %>% # commencer par l'ensemble de données de suivi
plot_by_region count(admin_1_name, admin_2_name, followup_status) %>% # obtenir les chiffres par région-statut unique (crée la colonne 'n' avec les chiffres)
# begin ggplot()
ggplot( # commencer le ggplot
mapping = aes(x = reorder(admin_2_name, n), # réorganiser les facteurs administratifs en fonction des valeurs numériques de la colonne 'n'.
y = n, # hauteur de la barre de la colonne 'n'.
fill = followup_status, # colorer les barres empilées en fonction de leur statut
label = n))+ # passer à geom_label()
geom_col()+ # barres empilées, cartographie obtenue au-dessus
geom_text( # ajouter du texte, cartographie obtenue à partir de la version précédente
size = 3,
position = position_stack(vjust = 0.5),
color = "white",
check_overlap = TRUE,
fontface = "bold")+
coord_flip()+
labs(
x = "",
y = "Number of contacts",
title = "Contact Followup Status, by Region",
fill = "Followup Status",
subtitle = str_glue("Data as of {max(followups_clean$date_of_followup, na.rm=T)}")) +
theme_classic()+ # Simplifier le fond
facet_wrap(~admin_1_name, strip.position = "right", scales = "free_y", ncol = 1) # introduire les facettes
plot_by_region
25.4 Tableaux KPI
Il existe un certain nombre d’indicateurs clés de performance ( KPI) qui peuvent être calculés et suivis à différents niveaux de désagrégation et sur différentes périodes de temps afin de contrôler les performances de la recherche de contacts. Une fois que vous maîtrisez les calculs et le format de base du tableau, il est assez facile d’intervertir les différents KPI.
Il existe de nombreuses sources de KPI pour le suivi des contacts, comme celle de ResolveToSaveLives.org. La majeure partie du travail consistera à parcourir votre structure de données et à réfléchir à tous les critères d’inclusion/exclusion. Nous présentons quelques exemples ci-dessous, en utilisant la structure de métadonnées de Go.Data :
Catégorie | Indicateur | Go.Data Numérateur | Go.Data D énominateur |
---|---|---|---|
Indicateur de processus -Rapidité du Suivi de contact | % cas interviewé et isololé dans les 24h du cas rapport | NOMBRE DE case_id OU (da te_of_reporting - da te _of_data_entry ) < 1 jour et (is ol ation_startdate - da te _of_data_entry ) < 1 jour |
NOMBRE DE case_id
|
Indicateur de processus -Rapidité du Suivi de contact | % contacts notifié et mis en quarantaine dans 24h d’ élicitation | NOMBRE DE contact_id OÙ followup_status == “SEEN_NOT_OK” OR “SEEN_OK” ET d ate_of_followup - da te_of_reporting < 1 jour |
NOMBRE DE c ontact_id
|
Indicateur de processus - Complétude des tests | % nouveaux symptômes cas testés et interviewé dans les 3 jours de début de symptôme | NOMBRE DE case_id OÙ (da te_of_reporting - date_of_onset ) < =3 jours |
NOMBRE DE case_id
|
Indicateur de résultat - Globale ment | % nouveaux cas parmi les contacts listés | NOMBRE DE case_id OÙ was_contact == “TRUE” |
NOMBRE DE case_id
|
Nous vous proposons ci-dessous un exemple de création d’un tableau visuel pour afficher le suivi des contacts dans les différentes zones d’administration. À la fin, nous le convertirons en tableau de présentation avec le package formattable (mais vous pouvez utiliser d’autres packages comme flextable - voir Tableaux de présentation).
La manière de créer un tel tableau dépend de la structure de vos données de suivi des contacts. Utilisez la page Tableaux descriptifs pour apprendre à résumer les données à l’aide des fonctions dplyr.
Nous allons créer une table qui sera dynamique et changera au fur et à mesure que les données changeront. Pour rendre les résultats intéressants, nous allons définir une “date de rapport” pour nous permettre de simuler l’exécution du tableau à un certain jour (nous choisissons le 10 juin 2020). Les données sont filtrées à cette date.
# Définissez "Date du rapport" pour simuler l'exécution du rapport avec des données "à partir de" cette date.
<- as.Date("2020-06-10")
report_date
# Créez des données de suivi pour refléter la date du rapport.
<- followups_clean %>%
table_data filter(date_of_followup <= report_date)
Maintenant, sur la base de notre structure de données, nous allons faire ce qui suit :
- Commencez par les données
followups
et résumez-les pour inclure, pour chaque contact unique :
- La date du dernier enregistrement (quel que soit le statut du suivi).
- La date de la dernière suivi où le contact a été “vu”
- le statut du suivi lors de cette dernière suivi (par exemple, avec des symptômes, sans symptômes)
- Joignez ces données aux données des contacts, qui contiennent d’autres informations telles que le statut général du contact, la date de la dernière exposition à un cas, etc. Nous allons également calculer des indicateurs intéressants pour chaque contact, comme le nombre de jours depuis la dernière exposition.
- Nous regroupons les données de contact élargies par région géographique (
admin_2_name
) et calculons des statistiques sommaires par région
- Enfin, nous mettons en forme le tableau pour qu’il soit bien présenté.
Tout d’abord, nous résumons les données de suivi pour obtenir les informations qui nous intéressent :
<- table_data %>%
followup_info group_by(contact_id) %>%
summarise(
date_last_record = max(date_of_followup, na.rm=T),
date_last_seen = max(date_of_followup[followup_status %in% c("seen_ok", "seen_not_ok")], na.rm=T),
status_last_record = followup_status[which(date_of_followup == date_last_record)]) %>%
ungroup()
Voici à quoi ressemblent ces données :
Maintenant, nous allons ajouter ces informations à l’ensemble de données contacts
, et calculer quelques colonnes supplémentaires.
<- followup_info %>%
contacts_info right_join(contacts, by = "contact_id") %>%
mutate(
database_date = max(date_last_record, na.rm=T),
days_since_seen = database_date - date_last_seen,
days_since_exposure = database_date - date_of_last_exposure
)
Voici à quoi ressemblent ces données. Il faut noter la colonne contacts
à droite, et la nouvelle colonne calculée à l’extrême droite.
Ensuite, nous résumons les données sur les contacts par région, afin d’obtenir un tableaux de synthèse des colonnes de statistiques.
<- contacts_info %>%
contacts_table
group_by(`Admin 2` = admin_2_name) %>%
summarise(
`Registered contacts` = n(),
`Active contacts` = sum(contact_status == "UNDER_FOLLOW_UP", na.rm=T),
`In first week` = sum(days_since_exposure < 8, na.rm=T),
`In second week` = sum(days_since_exposure >= 8 & days_since_exposure < 15, na.rm=T),
`Became case` = sum(contact_status == "BECAME_CASE", na.rm=T),
`Lost to follow up` = sum(days_since_seen >= 3, na.rm=T),
`Never seen` = sum(is.na(date_last_seen)),
`Followed up - signs` = sum(status_last_record == "Seen_not_ok" & date_last_record == database_date, na.rm=T),
`Followed up - no signs` = sum(status_last_record == "Seen_ok" & date_last_record == database_date, na.rm=T),
`Not Followed up` = sum(
== "NOT_ATTEMPTED" | status_last_record == "NOT_PERFORMED") &
(status_last_record == database_date, na.rm=T)) %>%
date_last_record
arrange(desc(`Registered contacts`))
Et maintenant, nous appliquons le style des paquets formattable et knitr. y compris une note de pied de page qui indique la date “en date du”.
%>%
contacts_table mutate(
`Admin 2` = formatter("span", style = ~ formattable::style(
color = ifelse(`Admin 2` == NA, "red", "grey"),
font.weight = "bold",font.style = "italic"))(`Admin 2`),
`Followed up - signs`= color_tile("white", "orange")(`Followed up - signs`),
`Followed up - no signs`= color_tile("white", "#A0E2BD")(`Followed up - no signs`),
`Became case`= color_tile("white", "grey")(`Became case`),
`Lost to follow up`= color_tile("white", "grey")(`Lost to follow up`),
`Never seen`= color_tile("white", "red")(`Never seen`),
`Active contacts` = color_tile("white", "#81A4CE")(`Active contacts`)
%>%
) kable("html", escape = F, align =c("l","c","c","c","c","c","c","c","c","c","c")) %>%
kable_styling("hover", full_width = FALSE) %>%
add_header_above(c(" " = 3,
"Of contacts currently under follow up" = 5,
"Status of last visit" = 3)) %>%
::footnote(general = str_glue("Data are current to {format(report_date, '%b %d %Y')}")) kableExtra
Admin 2 | Registered contacts | Active contacts | In first week | In second week | Became case | Lost to follow up | Never seen | Followed up - signs | Followed up - no signs | Not Followed up |
---|---|---|---|---|---|---|---|---|---|---|
Djembe | 59 | 30 | 44 | 0 | 2 | 15 | 22 | 0 | 0 | 0 |
Trumpet | 3 | 1 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Venu | 2 | 0 | 0 | 0 | 2 | 0 | 2 | 0 | 0 | 0 |
Congas | 1 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
Cornet | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 |
Note: | ||||||||||
Data are current to Jun 10 2020 |
25.5 Matrices de transmission
Comme indiqué sur la page Heat plots, vous pouvez créer une matrice de “qui a infecté qui” en utilisant geom_tile()
.
Lorsque de nouveaux contacts sont créés, Go.Data stocke ces informations de liens dans le lien relationships
de l’API ; et nous pouvons voir les 50 premières lignes de cet ensemble de données ci-dessous. Cela signifie que nous pouvons créer un diagramme de chaleur avec relativement peu d’étapes étant donné que chaque contact est déjà joint à son cas source.
Comme nous l’avons fait ci-dessus pour la pyramide des âges comparant les cas et les contacts, nous pouvons sélectionner les quelques variables dont nous avons besoin et créer des colonnes avec des groupes d’âge catégoriques pour les sources (cas) et les cibles (contacts).
<- relationships %>%
heatmap_ages select(source_age, target_age) %>%
mutate( # transmute est comme mutate() mais supprime toutes les autres colonnes
source_age_class = epikit::age_categories(source_age, breakers = seq(0, 80, 5)),
target_age_class = epikit::age_categories(target_age, breakers = seq(0, 80, 5)))
Comme décrit précédemment, nous créons des tableaux croisés ;
<- table(
cross_tab source_cases = heatmap_ages$source_age_class,
target_cases = heatmap_ages$target_age_class)
cross_tab
target_cases
source_cases 0-4 5-9 10-14 15-19 20-24 25-29 30-34 35-39 40-44 45-49 50-54
0-4 0 0 0 0 0 0 0 0 0 1 0
5-9 0 0 1 0 0 0 0 1 0 0 0
10-14 0 0 0 0 0 0 0 0 0 0 0
15-19 0 0 0 0 0 0 0 0 0 0 0
20-24 1 1 0 1 2 0 2 1 0 0 0
25-29 1 2 0 0 0 0 0 0 0 0 0
30-34 0 0 0 0 0 0 0 0 1 1 0
35-39 0 2 0 0 0 0 0 0 0 1 0
40-44 0 0 0 0 1 0 2 1 0 3 1
45-49 1 2 2 0 0 0 3 0 1 0 3
50-54 1 2 1 2 0 0 1 0 0 3 4
55-59 0 1 0 0 1 1 2 0 0 0 0
60-64 0 0 0 0 0 0 0 0 0 0 0
65-69 0 0 0 0 0 0 0 0 0 0 0
70-74 0 0 0 0 0 0 0 0 0 0 0
75-79 0 0 0 0 0 0 0 0 0 0 0
80+ 1 0 0 2 1 0 0 0 1 0 0
target_cases
source_cases 55-59 60-64 65-69 70-74 75-79 80+
0-4 1 0 0 0 0 0
5-9 1 0 0 0 0 0
10-14 0 0 0 0 0 0
15-19 0 0 0 0 0 0
20-24 1 0 0 0 0 1
25-29 0 0 0 0 0 0
30-34 1 0 0 0 0 0
35-39 0 0 0 0 0 0
40-44 1 0 0 0 1 1
45-49 2 1 0 0 0 1
50-54 1 0 1 0 0 1
55-59 0 0 0 0 0 0
60-64 0 0 0 0 0 0
65-69 0 0 0 0 0 0
70-74 0 0 0 0 0 0
75-79 0 0 0 0 0 0
80+ 0 0 0 0 0 0
convertir en format long avec des proportions ;
<- data.frame(prop.table(cross_tab)) long_prop
et créer une carte géographique pour l’âge.
ggplot(data = long_prop)+ # utiliser des données longues, avec des proportions comme Freq
geom_tile( # visualisez-le en tuiles
aes(
x = target_cases, # l'axe des x est l'âge du cas
y = source_cases, # l'axe y est l'âge de l'infecteur
fill = Freq))+ # La couleur de la tuile est la colonne Freq dans les données
scale_fill_gradient( # ajuster la couleur de remplissage des tuiles
low = "blue",
high = "orange")+
theme(axis.text.x = element_text(angle = 90))+
labs( # labels
x = "Target case age",
y = "Source case age",
title = "Who infected whom",
subtitle = "Frequency matrix of transmission events",
fill = "Proportion of all\ntranmsission events" # legend title
)
25.6 Resources
https://github.com/WorldHealthOrganization/godata/tree/master/analytics/r-reporting