Skip to content
Snippets Groups Projects
Commit fca1eea3 authored by Thomas  OBADIA's avatar Thomas OBADIA :speech_balloon:
Browse files

Add QC checks for Symptoms and Vital Signs

parent cf783462
No related branches found
No related tags found
No related merge requests found
...@@ -148,6 +148,37 @@ DAT_QC_SAFETY_OF_STUDY_DRUGS <- dat_interventional_m0_raw %>% ...@@ -148,6 +148,37 @@ DAT_QC_SAFETY_OF_STUDY_DRUGS <- dat_interventional_m0_raw %>%
) )
## Data subset for assessment of symptoms and vital signs
# All rows are preserved, but further filtering will happen when calculating
# the QC flags to retain only entries for participants who were properly
# enrolled in the study.
DAT_QC_SYMPTOMS_VITAL_SIGNS <- dat_interventional_m0_raw %>%
filter(redcap_event_name %in% c("Intervention D1 (M0) (Arm 1: Intervention)",
"Intervention D4 (M0) (Arm 1: Intervention)",
"Intervention D7 (M0) (Arm 1: Intervention)",
"2",
"3",
"4")) %>%
select(record_id,
redcap_event_name, redcap_repeat_instrument, redcap_repeat_instance,
country, clusterid, hid, subjid, uniqueid,
symp_yn,
symp_fever, symp_headache, symp_muspain, symp_abdopain, symp_poorappetite,
symp_nausea, symp_vomit, symp_diarrhoea, symp_darkurine, symp_rash,
symp_itch, symp_dizzy, symp_shortbreath,
symp_other_01, symp_other_01_det,
symp_other_02, symp_other_02_det,
vs_weight,
vs_temp_m, vs_temp_e, vs_temp,
vs_hb_m, vs_hb_e, vs_hb,
vs_urine_hillmen
)
...@@ -476,8 +507,8 @@ QC_DEMOGRAPHICS <- DAT_QC_DEMOGRAPHICS %>% ...@@ -476,8 +507,8 @@ QC_DEMOGRAPHICS <- DAT_QC_DEMOGRAPHICS %>%
### NOTE: The subset of participants enrolled, and therefore expected to have ### NOTE: The subset of participants enrolled, and therefore expected to have
### filled the instrument, is achieved by starting from the list of ### filled the instrument, is achieved by starting from the list of
### participants in DAT_QC_DEMOGRAPHICS, subsequently left-joined onto ### participants in DAT_QC_DEMOGRAPHICS, subsequently left-joined onto
### DAT_QC_SCREENING_ELIGIBILITY_CONSENT (to recover 'enroldat'). ### DAT_QC_SCREENING_ELIGIBILITY_CONSENT (to recover 'enroldat'), then
### then restricted to non-missing 'uniqueid'. ### restricted to non-missing 'uniqueid'.
### This explicitly does NOT discard rows with mismatches in the double ### This explicitly does NOT discard rows with mismatches in the double
### entry process for 'uniqueid' and 'uniqueid2'. ### entry process for 'uniqueid' and 'uniqueid2'.
...@@ -1025,7 +1056,93 @@ QC_SAFETY_OF_STUDY_DRUGES <- DAT_QC_SAFETY_OF_STUDY_DRUGS %>% ...@@ -1025,7 +1056,93 @@ QC_SAFETY_OF_STUDY_DRUGES <- DAT_QC_SAFETY_OF_STUDY_DRUGS %>%
##################################################################### ######################################################################
### SYMPTOMS & VITAL SIGNS
######################################################################
### The Symptos & Vital Signs instrument is administered at every
### scheduled visit (D1, D4, D7) with content varying slight across visits.
### Its aim is to detect signs of severe disease and possible onset of
### haemolytic events.
## Table with QC queries
QC_SYMPTOMS_VITAL_SIGNS <- DAT_QC_SYMPTOMS_VITAL_SIGNS %>%
filter(!is.na(uniqueid)) %>%
rowwise %>%
mutate(
# Presence or absence of any relevant symptoms to report is missing
QC_GENERAL_REPORTING_OF_SYMPTOMS_IS_MISSING = case_when(is.na(symp_yn) ~ TRUE,
!is.na(symp_yn) ~ FALSE,
.default = NA),
# Investigator reported symptoms were to be documented but none were
# reported afterward
QC_SPECIFIC_REPORTING_OF_SYMPTOMS_IS_MISSING = case_when(symp_yn %in% REDCAP_LABELS_RADIO_YES & if_all(c(matches("^symp_[^yo]"), symp_other_01), is.na) ~ TRUE,
symp_yn %in% REDCAP_LABELS_RADIO_YES & if_any(c(matches("^symp_[^yo]"), symp_other_01), ~!is.na(.x)) ~ FALSE,
.default = NA),
# Investigator reported symptoms were to be documented but some specific
# symptom assessement is missing
QC_SPECIFIC_REPORTING_OF_SYMPTOMS_IS_INCOMPLETE = case_when(symp_yn %in% REDCAP_LABELS_RADIO_YES & (if_any(c(matches("^symp_[^yo]"), symp_other_01), is.na) |
symp_other_01 != "Absent" & is.na(symp_other_02)) ~ TRUE,
symp_yn %in% REDCAP_LABELS_RADIO_YES & if_all(c(matches("^symp_[^yo]"), symp_other_01), ~!is.na(.x)) & ((symp_other_01 != "Absent" & !is.na(symp_other_02)) |
(symp_other_01 == "Absent" & is.na(symp_other_02))) ~ FALSE,
.default = NA),
# Weight is missing (collected only at D1)
QC_WEIGHT_IS_MISSING = case_when(redcap_event_name %in% c("Intervention D1 (M0) (Arm 1: Intervention)", "2") & is.na(vs_weight) ~ TRUE,
redcap_event_name %in% c("Intervention D1 (M0) (Arm 1: Intervention)", "2") & !is.na(vs_weight) ~ FALSE,
.default = NA),
# Weight is out of bounds (collected only at D1)
QC_WEIGHT_IS_OUT_OF_BOUNDS = case_when(redcap_event_name %in% c("Intervention D1 (M0) (Arm 1: Intervention)", "2") & (vs_weight < VS_WEIGHT_THR_LO | vs_weight > VS_WEIGHT_THR_HI) ~ TRUE,
redcap_event_name %in% c("Intervention D1 (M0) (Arm 1: Intervention)", "2") & vs_weight >= VS_WEIGHT_THR_LO & vs_weight <= VS_WEIGHT_THR_HI ~ FALSE,
.default = NA),
# Temperature is missing
QC_TEMPERATURE_IS_MISSING = case_when((country %in% REDCAP_LABELS_RADIO_COUNTRY_E & is.na(vs_temp_e)) |
(country %in% REDCAP_LABELS_RADIO_COUNTRY_M & is.na(vs_temp_m)) |
is.na(vs_temp) ~ TRUE,
(country %in% REDCAP_LABELS_RADIO_COUNTRY_E & !is.na(vs_temp_e)) |
(country %in% REDCAP_LABELS_RADIO_COUNTRY_M & !is.na(vs_temp_m)) |
!is.na(vs_temp) ~ FALSE,
.default = NA),
# Temperature is out of bounds
QC_TEMPERATURE_IS_OUT_OF_BOUNDS = case_when(vs_temp < VS_TEMP_THR_LO | vs_temp > VS_TEMP_THR_HI ~ TRUE,
vs_temp >= VS_TEMP_THR_LO & vs_temp <= VS_TEMP_THR_HI ~ FALSE,
.default = NA),
# Haemoglobin level is missing
# (collected at D4 and D7; D1 value is propagated in vs_hb_eli)
QC_HB_LEVEL_IS_MISSING = case_when(redcap_event_name %in% c("Intervention D4 (M0) (Arm 1: Intervention)", "Intervention D7 (M0) (Arm 1: Intervention)", "3", "4") & ((country %in% REDCAP_LABELS_RADIO_COUNTRY_E & is.na(vs_hb_e)) |
(country %in% REDCAP_LABELS_RADIO_COUNTRY_M & is.na(vs_hb_m)) |
is.na(vs_hb)) ~ TRUE,
redcap_event_name %in% c("Intervention D1 (M0) (Arm 1: Intervention)", "2") & is.na(vs_hb) ~ TRUE,
redcap_event_name %in% c("Intervention D4 (M0) (Arm 1: Intervention)", "Intervention D7 (M0) (Arm 1: Intervention)", "3", "4") & ((country %in% REDCAP_LABELS_RADIO_COUNTRY_E & !is.na(vs_hb_e)) |
(country %in% REDCAP_LABELS_RADIO_COUNTRY_M & !is.na(vs_hb_m)) |
!is.na(vs_hb)) ~ FALSE,
redcap_event_name %in% c("Intervention D1 (M0) (Arm 1: Intervention)", "2") & !is.na(vs_hb) ~ FALSE,
.default = NA),
# Haemoglobin level is out of bounds
# (collected at D4 and D7; D1 value is propagated in vs_hb_eli)
QC_HB_LEVEL_IS_OUT_OF_BOUNDS = case_when(vs_hb < VS_HB_THR_LO | vs_hb > VS_HB_THR_HI ~ TRUE,
vs_hb >= VS_HB_THR_LO & vs_hb <= VS_HB_THR_HI ~ FALSE,
.default = NA),
# Urine Hillmen scale is missing (only collected at D7)
QC_URINE_HILLMEN_SCALE_IS_OUT_OF_BOUNDS = case_when(redcap_event_name %in% c("Intervention D7 (M0) (Arm 1: Intervention)", "4") & is.na(vs_urine_hillmen) ~ TRUE,
redcap_event_name %in% c("Intervention D7 (M0) (Arm 1: Intervention)", "4") & !is.na(vs_urine_hillmen) ~ FALSE,
.default = NA)
) %>%
ungroup
######################################################################
### WRITE QC DATA TO OUTPUT DIRECTORY ### WRITE QC DATA TO OUTPUT DIRECTORY
###################################################################### ######################################################################
## Name of output files ## Name of output files
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment