Skip to content

Commit 43f95b8

Browse files
committed
Fix subject_id assignment issue
1 parent 3db32be commit 43f95b8

2 files changed

Lines changed: 57 additions & 6 deletions

File tree

R/Trial.R

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,25 @@ Trial <- R6::R6Class(
210210
# Create snapshots of enrolled subjects from all populations
211211
locked_snapshot_list <- lapply(self$population, function(p) {
212212
keep <- !is.na(p$enrolled)
213-
cbind(
213+
cbind(
214214
p$data[keep, , drop = FALSE],
215215
enroll_time = rep(x=p$enrolled[keep],times=p$n_readouts),
216216
drop_time = rep(x=p$dropped[keep],times=p$n_readouts)
217217
)
218218
})
219219

220-
combined <- do.call(rbind, locked_snapshot_list)
221-
combined$subject_id <- rep(
222-
x=seq_len(as.integer(dim(combined)[1] / p$n_readouts)),
223-
times = p$n_readouts
224-
)
220+
combined <- do.call(rbind, locked_snapshot_list)
221+
offset <- 0L
222+
global_ids <- integer(0)
223+
for (idx in seq_along(self$population)) {
224+
snap <- locked_snapshot_list[[idx]]
225+
if (is.null(snap) || nrow(snap) == 0L) next
226+
nr <- self$population[[idx]]$n_readouts
227+
n_subj <- as.integer(nrow(snap) / nr)
228+
global_ids <- c(global_ids, rep(offset + seq_len(n_subj), each = nr))
229+
offset <- offset + n_subj
230+
}
231+
combined$subject_id <- global_ids
225232

226233
if (is.null(combined) || nrow(combined) == 0L) {
227234
next

tests/testthat/test-Trial.R

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
test_that("Trial run: subject_id globally unique with mixed n_readouts across arms", {
2+
# Arm A: 3 subjects, 1 readout each -> 3 rows
3+
dataA <- data.frame(
4+
id = c(1, 2, 3),
5+
value = c(1, 2, 3),
6+
readout_time = 0
7+
)
8+
popA <- Population$new("A", data = dataA, n_readouts = 1L)
9+
10+
# Arm B: 3 subjects, 2 readouts each -> 6 rows
11+
dataB <- data.frame(
12+
id = c(1, 1, 2, 2, 3, 3),
13+
value = c(4, 4, 5, 5, 6, 6),
14+
readout_time = rep(c(0, 1), 3)
15+
)
16+
popB <- Population$new("B", data = dataB, n_readouts = 2L)
17+
18+
timer <- Timer$new("t")
19+
timer$add_timepoint(time = 1, arm = "A", enroller = 3L, dropper = 0L)
20+
timer$add_timepoint(time = 1, arm = "B", enroller = 3L, dropper = 0L)
21+
22+
trigger_by_calendar(1, timer, analysis = function(df, current_time) df)
23+
24+
trial <- Trial$new(
25+
name = "mixed_readouts",
26+
seed = 1,
27+
timer = timer,
28+
population = list(popA, popB)
29+
)
30+
31+
trial$run()
32+
33+
snap <- trial$locked_data[["time_1"]]
34+
35+
expect_equal(nrow(snap), 9L)
36+
37+
expect_equal(sort(unique(snap$subject_id)), 1:6)
38+
39+
rows_A <- snap[snap$subject_id %in% 1:3, ]
40+
expect_true(all(table(rows_A$subject_id) == 1))
41+
42+
rows_B <- snap[snap$subject_id %in% 4:6, ]
43+
expect_true(all(table(rows_B$subject_id) == 2))
44+
})

0 commit comments

Comments
 (0)