hputter / mstate

https://hputter.github.io/mstate/
7 stars 5 forks source link

Minor issue with msprep() when some transitions are only made by one individual #31

Closed edbonneville closed 4 months ago

edbonneville commented 4 months ago

Reported originally here by David Buis, where a fix was also proposed. Will be a simple fix by adding , drop = FALSE to this line.

library(mstate)
#> Warning: package 'mstate' was built under R version 4.3.2
#> Loading required package: survival
#> Warning: package 'survival' was built under R version 4.3.2

# https://stackoverflow.com/questions/77746086/multi-state-analysis-r-using-mstate/77746826?noredirect=1#comment137094839_77746826
example_dat <- cbind.data.frame(
  subject = c(1, 2, 4, 5, 6, 8),
  aki_1_status = c(0, 0, 1, 1, 1, 1),
  aki_1_time = c(90.2, 90.2, 6.1, 2.1, 3.1, 1.1),
  rec_1_status = c(0, 0, 0, 1, 1, 0),
  rec_1_time = c(90.2, 90.2, 90.2, 10.1, 11.1, 90.2),
  aki_2_status = c(0, 0, 0, 0, 1, 0),
  aki_2_time = c(90.2, 90.2, 90.2, 90.2, 31.1, 90.2),
  rec_2_status = c(0, 0, 0, 0, 1, 0),
  rec_2_time = c(90.2, 90.2, 90.2, 90.2, 47.1, 90.2),
  aki_3_status = c(0, 0, 0, 0, 0, 0),
  aki_3_time = c(90.2, 90.2, 90.2, 90.2, 90.2, 90.2),
  rec_3_status = c(0, 0, 0, 0, 0, 0),
  rec_3_time = c(90.2, 90.2, 90.2, 90.2, 90.2, 90.2),
  aki_4_status = c(0, 0, 0, 0, 0, 0),
  aki_4_time = c(90.2, 90.2, 90.2, 90.2, 90.2, 90.2),
  rec_4_status = c(0, 0, 0, 0, 0, 0),
  rec_4_time = c(90.2, 90.2, 90.2, 90.2, 90.2, 90.2),
  death_status = c(0, 0, 1, 0, 0, 1),
  death_time = c(90.2, 90.2, 11.2, 90.2, 90.2, 2.2)
)

tmat <- transMat(
  x = list(c(2, 10), c(3, 10), c(4, 10), c(5, 10), c(6, 10), c(7, 10), c(8, 10), c(9, 10), c(10), c()),
  names = c("start", "aki_1", "rec_1", "aki_2", "rec_2", "aki_3", "rec_3", "aki_4", "rec_4", "death")
)
tmat
#>        to
#> from    start aki_1 rec_1 aki_2 rec_2 aki_3 rec_3 aki_4 rec_4 death
#>   start    NA     1    NA    NA    NA    NA    NA    NA    NA     2
#>   aki_1    NA    NA     3    NA    NA    NA    NA    NA    NA     4
#>   rec_1    NA    NA    NA     5    NA    NA    NA    NA    NA     6
#>   aki_2    NA    NA    NA    NA     7    NA    NA    NA    NA     8
#>   rec_2    NA    NA    NA    NA    NA     9    NA    NA    NA    10
#>   aki_3    NA    NA    NA    NA    NA    NA    11    NA    NA    12
#>   rec_3    NA    NA    NA    NA    NA    NA    NA    13    NA    14
#>   aki_4    NA    NA    NA    NA    NA    NA    NA    NA    15    16
#>   rec_4    NA    NA    NA    NA    NA    NA    NA    NA    NA    17
#>   death    NA    NA    NA    NA    NA    NA    NA    NA    NA    NA

dlong <- msprep(
  time = c(
    NA, 
    "aki_1_time",  "rec_1_time",
    "aki_2_time",  "rec_2_time", 
    "aki_3_time",  "rec_3_time", 
    "aki_4_time",  "rec_4_time", 
    "death_time"
  ),
  status = c(
    NA, 
    "aki_1_status",  "rec_1_status", 
    "aki_2_status",  "rec_2_status", 
    "aki_3_status",  "rec_3_status", 
    "aki_4_status",  "rec_4_status", 
    "death_status"
  ),
  data = example_dat, 
  id = "subject", 
  trans = tmat
)
#> Error in time[, -startings]: incorrect number of dimensions

# No probs here:
example_dat2 <- rbind.data.frame(example_dat, example_dat[5, ])
dlong <- msprep(
  time = c(
    NA, 
    "aki_1_time",  "rec_1_time",
    "aki_2_time",  "rec_2_time", 
    "aki_3_time",  "rec_3_time", 
    "aki_4_time",  "rec_4_time", 
    "death_time"
  ),
  status = c(
    NA, 
    "aki_1_status",  "rec_1_status", 
    "aki_2_status",  "rec_2_status", 
    "aki_3_status",  "rec_3_status", 
    "aki_4_status",  "rec_4_status", 
    "death_status"
  ),
  data = example_dat2, 
  id = "subject", 
  trans = tmat
)

Created on 2024-06-14 with reprex v2.0.2

edbonneville commented 4 months ago

Also reported by Jonas Faartoft Jensen:

Regarding my previous question about the use of the msprep-function from the mstate-package in R for data preparation of cyclic multistate models, I had an idea (inspired by some ideas from my colleagues). The thought was that I could initially construct the model as a unidirectional, irreversible and acyclic multistate model by simply coding reversible states as new states in the model (so e.g. after a state of sickness you could return to being healthy again but coded separately as a state “healthy after first period of sickness” and so on). So – I tried to implement this idea on a hypothetical data only including a few patients; but when I try to use the msprep function it returns an error “Error in time[,-startings]: incorrect number of dimensions”. I tracked down the error through the code documentation of msprep and msprepEngine to almost the last line of msprepEngine where you use the Recall-function in order to create the recursive functionality. And here the error makes sense because the call of time and status tries to subset these variables as if they are matrices, when they in some previous step in fact have been transformed to vectors (because information on other individuals have been removed somewhere in the process). I have looked up this error also through an extensive google-search and found a few other cases with the same problem but without solutions. Do you know of this problem and how to maybe fix it?

edbonneville commented 4 months ago

Fixed, see: 981bdaf