The early_warning_biomarker
function is designed to detect unexpected changes in biomarker values for individual patients based on clinical chemistry data. It will flag cases where patients' biomarker results deviate from defined thresholds or exhibit significant changes within a specified time window.
early_warning_biomarker(
df,
testcode = NULL,
...,
column_date = NULL,
column_patientid = NULL,
column_testcode = NULL,
column_testresult = NULL,
threshold_min = NULL,
threshold_max = NULL,
window_days = NULL,
max_delta_absolute = NULL,
max_delta_relative = NULL,
direction = "any"
)
A data frame containing clinical chemistry data with columns for patient ID, date, test code, and test result.
Value of the column containing test codes to filter on.
Filter arguments, e.g. testcode == "eGFR"
Name of the column to use for dates. If left blank, the first date column will be used.
Name of the column to use for patient IDs. If left blank, the first column resembling "patient|patid"
will be used.
Name of the column containing test codes.
Name of the column containing test results.
Minimum threshold for biomarkers.
Maximum threshold for biomarkers.
Number of days for the time window to check for changes.
Maximum allowable absolute change in biomarkers.
Maximum allowable relative change in biomarkers.
Direction of change to check ("up", "down", or "any").
A list with the following components:
flags
: A list of flags per patient, containing data frames for each patient with details on dates, test codes, test results, and flagging criteria. The structure of each data frame includes the following columns:
patient
: Patient identifier.
date
: Date of the biomarker measurement.
testcode
: Code of the biomarker test.
testresult
: Biomarker test result.
delta_absolute
: Absolute change in biomarker values.
delta_relative
: Relative change in biomarker values.
threshold_min_flag
: A logical flag indicating if the threshold minimum is exceeded.
threshold_max_flag
: A logical flag indicating if the threshold maximum is exceeded.
delta_absolute_flag
: A logical flag indicating if the absolute change exceeds the threshold.
delta_relative_flag
: A logical flag indicating if the relative change exceeds the threshold.
details
: A data frame containing all patient details and calculated flags, regardless of whether they meet the flagging criteria. The data frame includes the same columns as the individual patient data frames.
This whole function, including the documentation, was written by ChatGPT 3.5 in October 2023. Only minor changes were applied manually.
This function is particularly useful in early detection of anomalous biomarker results, which can be indicative of health issues or treatment response. By providing detailed flags, it allows healthcare professionals and researchers to take timely action, conduct further investigations, or make informed clinical decisions.
The output of this function can be utilised for:
Generating patient-specific reports for healthcare providers.
Identifying trends and patterns in biomarker changes for research purposes.
Enhancing patient care by enabling proactive interventions when necessary.
Supporting data-driven clinical epidemiology studies and research.
The format()
function allows you to format the results of the early_warning_biomarker()
function for better readability and analysis. It organises the flag information into a structured data frame for easier inspection.
data <- data.frame(date = Sys.Date() + 1:10,
patient = "test",
value = c(10,12,14,15,13,21,22,19,14,12))
check <- data |> early_warning_biomarker(window_days = 6, max_delta_absolute = 10)
#> Using column 'date' for dates
#> Using column 'patient' for patient IDs
#> Using column 'value' for test results
check
#> A total of 1 patients with a total of 2 flags.
#>
#> # A tibble: 1 × 6
#> patient total_flags flag_threshold_min flag_threshold_max flag_delta_absolute
#> <chr> <int> <int> <int> <int>
#> 1 test 2 0 0 2
#> # ℹ 1 more variable: flag_delta_relative <int>
unlist(check)
#> flags.test.patient1 flags.test.patient2
#> "test" "test"
#> flags.test.date1 flags.test.date2
#> "20038" "20039"
#> flags.test.testcode1 flags.test.testcode2
#> NA NA
#> flags.test.testresult1 flags.test.testresult2
#> "21" "22"
#> flags.test.delta_absolute1 flags.test.delta_absolute2
#> "8" "1"
#> flags.test.delta_relative1 flags.test.delta_relative2
#> "0.615384615384615" "0.0476190476190476"
#> flags.test.threshold_min_flag1 flags.test.threshold_min_flag2
#> "FALSE" "FALSE"
#> flags.test.threshold_max_flag1 flags.test.threshold_max_flag2
#> "FALSE" "FALSE"
#> flags.test.delta_absolute_flag1 flags.test.delta_absolute_flag2
#> "TRUE" "TRUE"
#> flags.test.delta_relative_flag1 flags.test.delta_relative_flag2
#> "FALSE" "FALSE"
#> flags.test.sum_delta_absolute1 flags.test.sum_delta_absolute2
#> "11" "12"
#> flags.test.cumulative_days1 flags.test.cumulative_days2
#> "5" "6"
#> details.patient1 details.patient2
#> "test" "test"
#> details.patient3 details.patient4
#> "test" "test"
#> details.patient5 details.patient6
#> "test" "test"
#> details.patient7 details.patient8
#> "test" "test"
#> details.patient9 details.patient10
#> "test" "test"
#> details.date1 details.date2
#> "20033" "20034"
#> details.date3 details.date4
#> "20035" "20036"
#> details.date5 details.date6
#> "20037" "20038"
#> details.date7 details.date8
#> "20039" "20040"
#> details.date9 details.date10
#> "20041" "20042"
#> details.testcode1 details.testcode2
#> NA NA
#> details.testcode3 details.testcode4
#> NA NA
#> details.testcode5 details.testcode6
#> NA NA
#> details.testcode7 details.testcode8
#> NA NA
#> details.testcode9 details.testcode10
#> NA NA
#> details.testresult1 details.testresult2
#> "10" "12"
#> details.testresult3 details.testresult4
#> "14" "15"
#> details.testresult5 details.testresult6
#> "13" "21"
#> details.testresult7 details.testresult8
#> "22" "19"
#> details.testresult9 details.testresult10
#> "14" "12"
#> details.delta_absolute1 details.delta_absolute2
#> "0" "2"
#> details.delta_absolute3 details.delta_absolute4
#> "2" "1"
#> details.delta_absolute5 details.delta_absolute6
#> "-2" "8"
#> details.delta_absolute7 details.delta_absolute8
#> "1" "-3"
#> details.delta_absolute9 details.delta_absolute10
#> "-5" "-2"
#> details.delta_relative1 details.delta_relative2
#> "0" "0.2"
#> details.delta_relative3 details.delta_relative4
#> "0.166666666666667" "0.0714285714285714"
#> details.delta_relative5 details.delta_relative6
#> "-0.133333333333333" "0.615384615384615"
#> details.delta_relative7 details.delta_relative8
#> "0.0476190476190476" "-0.136363636363636"
#> details.delta_relative9 details.delta_relative10
#> "-0.263157894736842" "-0.142857142857143"
#> details.threshold_min_flag1 details.threshold_min_flag2
#> "FALSE" "FALSE"
#> details.threshold_min_flag3 details.threshold_min_flag4
#> "FALSE" "FALSE"
#> details.threshold_min_flag5 details.threshold_min_flag6
#> "FALSE" "FALSE"
#> details.threshold_min_flag7 details.threshold_min_flag8
#> "FALSE" "FALSE"
#> details.threshold_min_flag9 details.threshold_min_flag10
#> "FALSE" "FALSE"
#> details.threshold_max_flag1 details.threshold_max_flag2
#> "FALSE" "FALSE"
#> details.threshold_max_flag3 details.threshold_max_flag4
#> "FALSE" "FALSE"
#> details.threshold_max_flag5 details.threshold_max_flag6
#> "FALSE" "FALSE"
#> details.threshold_max_flag7 details.threshold_max_flag8
#> "FALSE" "FALSE"
#> details.threshold_max_flag9 details.threshold_max_flag10
#> "FALSE" "FALSE"
#> details.delta_absolute_flag1 details.delta_absolute_flag2
#> "FALSE" "FALSE"
#> details.delta_absolute_flag3 details.delta_absolute_flag4
#> "FALSE" "FALSE"
#> details.delta_absolute_flag5 details.delta_absolute_flag6
#> "FALSE" "TRUE"
#> details.delta_absolute_flag7 details.delta_absolute_flag8
#> "TRUE" "FALSE"
#> details.delta_absolute_flag9 details.delta_absolute_flag10
#> "FALSE" "FALSE"
#> details.delta_relative_flag1 details.delta_relative_flag2
#> "FALSE" "FALSE"
#> details.delta_relative_flag3 details.delta_relative_flag4
#> "FALSE" "FALSE"
#> details.delta_relative_flag5 details.delta_relative_flag6
#> "FALSE" "FALSE"
#> details.delta_relative_flag7 details.delta_relative_flag8
#> "FALSE" "FALSE"
#> details.delta_relative_flag9 details.delta_relative_flag10
#> "FALSE" "FALSE"
#> details.sum_delta_absolute1 details.sum_delta_absolute2
#> "0" "2"
#> details.sum_delta_absolute3 details.sum_delta_absolute4
#> "4" "5"
#> details.sum_delta_absolute5 details.sum_delta_absolute6
#> "3" "11"
#> details.sum_delta_absolute7 details.sum_delta_absolute8
#> "12" "9"
#> details.sum_delta_absolute9 details.sum_delta_absolute10
#> "4" "2"
#> details.cumulative_days1 details.cumulative_days2
#> "0" "1"
#> details.cumulative_days3 details.cumulative_days4
#> "2" "3"
#> details.cumulative_days5 details.cumulative_days6
#> "4" "5"
#> details.cumulative_days7 details.cumulative_days8
#> "6" "7"
#> details.cumulative_days9 details.cumulative_days10
#> "8" "9"
#> details.any_flag1 details.any_flag2
#> "FALSE" "FALSE"
#> details.any_flag3 details.any_flag4
#> "FALSE" "FALSE"
#> details.any_flag5 details.any_flag6
#> "FALSE" "TRUE"
#> details.any_flag7 details.any_flag8
#> "TRUE" "FALSE"
#> details.any_flag9 details.any_flag10
#> "FALSE" "FALSE"