我认为以下满足您的要求。它的工作原理是从 27 周的正态分布中获取样本的累积总和,并将其转换为 0 到 100 之间的逻辑尺度(这样就不会违反最大/最小分数)。它使用replicate 为 309 名参与者执行此操作。然后,它通过选择随机参与者和随机一周来模拟 30% 的辍学,之后他们的测量值都是NA。它还为其他参与者增加了一些随机缺失的周数。结果被转换成长格式以便于分析。
library(tidyverse)
set.seed(1)
# Generate correlated scores for 309 people over 27 visits
df <- setNames(cbind(data.frame(ID = 1:309, t(replicate(309, {
x <- cumsum(rnorm(27, 0.05, 0.1))
round(100 * exp(x)/(1 + exp(x)))
})))), c('ID', paste0('Visit_', 1:27)))
# Model dropouts at 30% rate
dropout <- sample(c(TRUE, FALSE), 309, TRUE, prob = c(0.7, 0.3))
df[cbind(which(!dropout), sample(2:28, sum(!dropout), TRUE))] <- NA
df <- as.data.frame(t(apply(df, 1, function(x) ifelse(is.na(cumsum(x)), NA,x))))
# Add random missing visits
df[cbind(sample(309, 100, TRUE), sample(2:28, 100, TRUE))] <- NA
df <- pivot_longer(df, -ID, names_to = 'Week', values_to = 'Score') %>%
mutate(Week = 2 * (as.numeric(gsub('\D+', '', Week)) - 1))
我们的数据框现在看起来像这样:
head(df)
#> # A tibble: 6 x 3
#> ID Week Score
#> <dbl> <dbl> <dbl>
#> 1 1 0 50
#> 2 1 2 51
#> 3 1 4 51
#> 4 1 6 56
#> 5 1 8 58
#> 6 1 10 57
我们可以看到分数随时间向上漂移(因为我们在创建分数时在 rnorm 上设置了一个小的正 mu。
lm(Score ~ Week, data = df)
#>
#> Call:
#> lm(formula = Score ~ Week, data = df)
#>
#> Coefficients:
#> (Intercept) Week
#> 52.2392 0.5102
我们可以绘制并查看分数的整体形状及其分布:
ggplot(df, aes(Week, Score, group = ID)) + geom_line(alpha = 0.1)
创建于 2023-01-31 reprex v2.0.2