Introduction to FragiliTidy

FragiliTidy provides fast, tidyverse-friendly implementations of fragility metrics for two-arm clinical trials:

library(FragiliTidy)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tibble)

Dichotomous outcomes

trials <- tribble(
  ~study,    ~ie, ~ce, ~in_, ~cn,
  "Trial A",  10,  20,  100,  100,
  "Trial B",   5,  15,   80,   80,
  "Trial C",  30,  30,  200,  200
)

trials |>
  fragility_index(ie, ce, in_, cn) |>
  revfragility_index(ie, ce, in_, cn)
#> # A tibble: 3 × 7
#>   study      ie    ce   in_    cn fragility_index revfragility_index
#>   <chr>   <dbl> <dbl> <dbl> <dbl>           <dbl>              <dbl>
#> 1 Trial A    10    20   100   100               0                  1
#> 2 Trial B     5    15    80    80               1                  0
#> 3 Trial C    30    30   200   200               0                  8

Continuous outcomes

From raw data

set.seed(1)
x <- rnorm(50, mean = 70, sd = 10)
y <- rnorm(50, mean = 50, sd = 10)
continuous_fragility_index_raw(x, y)
#> [1] 33

From summary statistics

When raw per-patient outcomes are not available, the CFI is estimated by simulating compatible datasets via rejection sampling and averaging the iterative substitution result over n_sim simulations (Caldwell et al., 2021):

continuous_fragility_index_summary(
  mean1 = 70, sd1 = 10, n1 = 100,
  mean2 = 50, sd2 = 10, n2 = 100,
  seed  = 1
)
#> [1] 65.2

Reverse CFI: distance from significance

For non-significant trials, the reverse CFI estimates how many additional participants per arm would have been required to reach significance, given the observed effect size and variance:

reverse_continuous_fragility_index_summary(
  mean1 = 55, sd1 = 10, n1 = 30,
  mean2 = 50, sd2 = 10, n2 = 30,
  seed  = 1
)
#> [1] 7.2

Tidy interface

Both CFI variants integrate into dplyr pipelines:

trials_continuous <- tribble(
  ~study,    ~m1, ~s1, ~k1, ~m2, ~s2, ~k2,
  "Trial X",  70,  10,  50,  50,  10,  50,
  "Trial Y",  60,  15,  40,  55,  15,  40
)

trials_continuous |>
  continuous_fragility_index(m1, s1, k1, m2, s2, k2) |>
  reverse_continuous_fragility_index(m1, s1, k1, m2, s2, k2)
#> # A tibble: 2 × 9
#>   study      m1    s1    k1    m2    s2    k2 continuous_fragility_index
#>   <chr>   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>                      <dbl>
#> 1 Trial X    70    10    50    50    10    50                       29.2
#> 2 Trial Y    60    15    40    55    15    40                        0  
#> # ℹ 1 more variable: reverse_continuous_fragility_index <dbl>

References