The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Getting started with the daoh package

David Cumin

Overview

The daoh package calculates Days Alive and Out of Hospital (DAOH) from administrative admission/discharge/mortality records.

The package supports three hospital-time algorithms and three approaches to incorporating death, allowing direct comparison of results under different methodological assumptions.


Core formula

\[\text{DAOH} = \max\!\bigl(0,\; T - H - D\bigr)\]

where \(T\) is the follow-up period (days), \(H\) is total merged hospital time, and \(D\) is dead time, both clipped to \([t_0,\; t_0 + T]\).


Example 1 — Day-stay: the 1-day difference

A patient admitted and discharged on the same calendar date contributes 0 nights (nights algorithm) but 1 day (days algorithm). This is the most common source of disagreement between the two approaches.

ex <- load_example("daystay")
ex$events
#>   patientID  admission  discharge  dod
#> 1      P001 2020-03-10 2020-03-10 <NA>

# Nights: 0 nights in hospital -> DAOH = 30/30 = 100%
calc_daoh(ex$events, ex$index_dates, period = 30, method = "nights")
#>   patientID  indexDate n_episodes dih dd daoh daohPC
#> 1      P001 2020-03-10          1   0  0   30    100

# Days: 1 day in hospital -> DAOH = 29/30 = 96.7%
calc_daoh(ex$events, ex$index_dates, period = 30, method = "days")
#>   patientID  indexDate n_episodes dih dd daoh   daohPC
#> 1      P001 2020-03-10          1   1  0   29 96.66667

For a population with \(N\) merged hospital episodes in the period:

\[H^{\text{days}} - H^{\text{nights}} \approx N_{\text{episodes}}\]

So the expected difference in DAOH (days − nights) equals the mean number of distinct hospital episodes per patient.


Example 2 — Death handling

A patient with four admissions who dies within the 30-day follow-up period.

ex2 <- load_example("death")
ex2$events
#>   patientID  admission  discharge        dod
#> 1      P002 2020-01-01 2020-01-02 2020-01-18
#> 2      P002 2020-01-05 2020-01-07 2020-01-18
#> 3      P002 2020-01-05 2020-01-05 2020-01-18
#> 4      P002 2020-01-09 2020-01-10 2020-01-18

# All seven variants
results <- expand.grid(
  method       = c("nights", "days", "exact"),
  death_method = c("midday", "midnight", "zero"),
  stringsAsFactors = FALSE
)

results$daoh <- mapply(function(m, dm) {
  calc_daoh(ex2$events, ex2$index_dates,
            period = 30, method = m, death_method = dm)$daoh
}, results$method, results$death_method)

results$daohPC <- round(100 * results$daoh / 30, 1)
print(results)
#>   method death_method daoh daohPC
#> 1 nights       midday 13.5   45.0
#> 2   days       midday 10.5   35.0
#> 3  exact       midday 13.5   45.0
#> 4 nights     midnight 13.0   43.3
#> 5   days     midnight 10.0   33.3
#> 6  exact     midnight 13.0   43.3
#> 7 nights         zero  0.0    0.0
#> 8   days         zero  0.0    0.0
#> 9  exact         zero  0.0    0.0

Note the wide range of DAOH values (0% to ~40%) depending on the method chosen — underscoring the importance of explicit reporting.


Example 3 — Population-level analysis

pop <- load_example("population")

Compare nights vs days

res_n <- calc_daoh(pop$events, pop$index_dates, period = 90, method = "nights")
res_d <- calc_daoh(pop$events, pop$index_dates, period = 90, method = "days")

# Summary statistics
cat("Nights: median DAOH% =", round(median(res_n$daohPC), 1), "\n")
#> Nights: median DAOH% = 96.7
cat("Days:   median DAOH% =", round(median(res_d$daohPC), 1), "\n")
#> Days:   median DAOH% = 94.4

# Difference ≈ number of episodes per patient
cat("Mean episodes (nights):", round(mean(res_n$n_episodes), 2), "\n")
#> Mean episodes (nights): 1.71
cat("Mean difference in DAOH (nights - days):",
    round(mean(res_n$daoh - res_d$daoh), 3), "days\n")
#> Mean difference in DAOH (nights - days): 1.706 days

Bland-Altman analysis

ba <- bland_altman_daoh(res_n, res_d)
cat(sprintf("Mean difference: %.3f%%\n95%% LoA: %.3f%% to %.3f%%\n",
            ba$mean_diff, ba$loa_lower, ba$loa_upper))
#> Mean difference: 1.896%
#> 95% LoA: 0.085% to 3.706%

plot_daoh_ba(ba, method_a = "Nights", method_b = "Days")

Quartile reclassification

rc <- daoh_reclassify(res_n, res_d, n_groups = 4)
cat(sprintf("%.1f%% of patients change quartile when switching nights → days\n",
            rc$pct_reclassified))
#> 51.6% of patients change quartile when switching nights → days
print(rc$confusion_matrix)
#>    b
#> a     1   2   3
#>   1  91   0   0
#>   2  71  57   0
#>   3   0  82  94
#>   4   0   0 105
plot_daoh_reclassify(rc, method_a = "Nights", method_b = "Days")

Distribution plot

plot_daoh_dist(res_n, title = "DAOH – Nights algorithm, 90-day period")


These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.