Overview

This page describes the master PKPD analysis datasets used in the majority of the plots on this site. The datasets were simulated from the indirect response model below, using rxode2. Data specifications can be accessed on Datasets. One dataset was created for single ascending dose PK and another dataset for multiple ascending dose PK and PD. Explore the datasets in the tables below, or download from the following links:

The generation code below is shown for reference but is not run when the site is built. The datasets it produces are committed under Data/, and the tables on this page are rendered from those files. See “Regenerating the datasets” at the foot of the page.

Setup

library(dplyr)
library(rxode2)

Dataset Generation

Indirect response system

ode <- "
Concentration = centr/V2;
C3 = peri/V3;
C4 = peri2/V4;
d/dt(depot) = -KA*depot;
d/dt(centr) = KA*depot - (CL+Q+Q2)*Concentration + Q*C3 + Q2*C4;
d/dt(peri) =                    Q*Concentration - Q*C3;
d/dt(peri2) =                   Q2*Concentration - Q2*C4;
d/dt(eff) = Kin*(1+Emax*Concentration/(EC50 + Concentration)) - Kout*(1)*eff;
"

work <- tempfile("Rx_intro-")
mod1 <- rxode2(model = ode, modName = "mod1")

cat(gsub(pattern="\nConcentration",replacement="Concentration",x=gsub(pattern=";\n",replacement=" \n", x = ode)))

Single Ascending Dose PK Dataset

set.seed(12345666)
ndose <- 5
nsub <- 10 # number of subproblems

SEX <- rep(c(rep("Male",ceiling(nsub/2)),rep("Female",floor(nsub/2))),ndose)
WT0 <- (SEX=="Male")*runif(length(SEX),60,110)+(SEX=="Female")*runif(length(SEX),50,100)
VCOV <- (WT0/70)*(1-0.5*(SEX=="Female"))
CLCOV <- (WT0/70)*(1-0.5*(SEX=="Female"))

CL <- 0.02*exp(rnorm(nsub*ndose,0,.4^2))*CLCOV
KA <- 0.5*exp(rnorm(nsub*ndose,0,.4^2))
V2 <- 30*exp(rnorm(nsub*ndose,0,.4^2))*VCOV
DOSE <- sort(rep(c(100,200,400,800,1600),nsub))
theta.all <- 
  cbind(KA=KA, CL=CL, V2=V2,
        Q=10*CLCOV, V3=100*VCOV, V4 = 10000*VCOV, Q2 = 10*CLCOV,
        Kin=0.5, Kout=0.05, EC50 = 1, Emax = 4)

# Set nominal times for sampling schedule
SAMPLING <- c(-0.1,0.1,0.5,1,2,4,8,12,18,23.9,36,47.9,71.9)

DOSING <- c(0)
NT <- data.frame(NT = c(SAMPLING, DOSING), label = c(rep("SAMPLING",length(SAMPLING)),rep("DOSING",length(DOSING))))
NT <- NT[order(NT$NT),]

ev.all <- list()
for(idose in 1:length(DOSE)){
  ev.all[[idose]] <- eventTable(amount.units='mg', time.units='hours')
  # ev.all[[idose]]$add.dosing(dose = DOSE[idose], nbr.doses = 1, dosing.interval = 24)
  # ev.all[[idose]]$add.sampling(c(c(-0.1,0.1,0.5,1,2,4,8,12,18,23.9,36,47.9,71.9)))
  
  # Include some noise in the sampling & dosing schedules
  temp <- NT
  temp$time <- cumsum(c(temp$NT[1] + 0.1*rnorm(1), abs(temp$NT[2:length(temp$NT)]-temp$NT[1:length(temp$NT)-1] + 0.1*rnorm(length(temp$NT)-1))))
  temp$time <- temp$time - temp$time[temp$NT==0] # center at first dose
  
  ev.all[[idose]]$add.dosing(dose = DOSE[idose], start.time = temp$time[temp$label=="DOSING"])
  ev.all[[idose]]$add.sampling(temp$time[temp$label=="SAMPLING"])
  
}

x.all.df <- NULL
ID = 0
for(i in 1:length(ev.all)){
  #   for(i in 1:nsub){
  ID = ID + 1
  theta <- theta.all[i,]
  inits <- c(depot = 0, centr = 0, peri = 0, peri2 = 0, eff=theta["Kin"]/theta["Kout"])
  x <- mod1$solve(theta, ev.all[[i]], inits = inits)
  
  x.df <- data.frame(x)
  x.df$NT <- SAMPLING
  
  temp <- data.frame(ev.all[[i]]$get.dosing())
  temp$NT <- DOSING
  
  temp[,setdiff(names(x.df),names(temp))]<- NA
  x.df[,setdiff(names(temp),names(x.df))]<- NA
  x.df <- rbind(x.df,temp)
  
  x.df$ID <- ID
  x.df$DOSE <- DOSE[i]
  x.df$WT0 <- WT0[i]
  x.df$SEX <- SEX[i]
  
  if(is.null(x.all.df)){
    x.all.df <- x.df
  }else{
    x.all.df <- rbind(x.all.df, x.df)
  }
}
x.all.df$DV <- x.all.df$Concentration*(exp(rnorm(length(x.all.df$Concentration),0,0.6^2))) + 
  0.01*rnorm(length(x.all.df$Concentration))
x.all.df$DV[x.all.df$DV<0.05]=0.05
x.all.df$DV[x.all.df$Concentration==0]=NA
x.all.df$BLQ=0
x.all.df$BLQ[x.all.df$DV==0.05]=1

my.data <- x.all.df[!is.na(x.all.df$amt),]
my.data$CMT <- 1
my.data$CMT_label <- "Dosing"

temp <- x.all.df[is.na(x.all.df$amt),]
temp$CMT <- 2
temp$CMT_label <- "PK Concentration"
my.data <- rbind(my.data,temp)

my.data$DV <- signif(my.data$DV,3)
my.data$WT0 <- signif(my.data$WT0,3)
my.data$time <- round(my.data$time,3)

my.data <- my.data[order(my.data$ID,my.data$time, my.data$CMT),]

my.data$DOSE_label <- paste(my.data$DOSE,"mg")
my.data$DOSE_label[my.data$DOSE==0] <- "Placebo"
my.data$DOSE_label <- factor(my.data$DOSE_label,levels = c("Placebo",paste(unique(my.data$DOSE[my.data$DOSE!=0]),"mg")))

Single_Ascending_Dose_Dataset <- my.data[,c("ID","time","NT","amt","DV","CMT","CMT_label","BLQ","evid","WT0","SEX","DOSE","DOSE_label")]
write.csv(Single_Ascending_Dose_Dataset,"../Data/Single_Ascending_Dose_Dataset.csv",row.names = FALSE)

Single_Ascending_Dose_Dataset2 <- Single_Ascending_Dose_Dataset
Single_Ascending_Dose_Dataset2$PROFTIME <- Single_Ascending_Dose_Dataset2$NT
Single_Ascending_Dose_Dataset2$NOMTIME <- Single_Ascending_Dose_Dataset2$NT
Single_Ascending_Dose_Dataset2$YTYPE <- Single_Ascending_Dose_Dataset2$CMT
Single_Ascending_Dose_Dataset2$amt[is.na(Single_Ascending_Dose_Dataset2$amt)] <- 0 
Single_Ascending_Dose_Dataset2 <- Single_Ascending_Dose_Dataset2[!(Single_Ascending_Dose_Dataset2$DOSE_label=="Placebo"&
                                      Single_Ascending_Dose_Dataset2$CMT==2),] 
Single_Ascending_Dose_Dataset2$BLQ[Single_Ascending_Dose_Dataset2$DOSE_label=="Placebo"&
                                       Single_Ascending_Dose_Dataset2$CMT==2] <- 1L
Single_Ascending_Dose_Dataset2$evid <- plyr::mapvalues(Single_Ascending_Dose_Dataset2$evid, c(NA,101), c(0,1))
Single_Ascending_Dose_Dataset2$TIMEUNIT <- "Hours"
Single_Ascending_Dose_Dataset2$EVENTU[Single_Ascending_Dose_Dataset2$CMT==1] <- "mg"
Single_Ascending_Dose_Dataset2$EVENTU[Single_Ascending_Dose_Dataset2$CMT==2] <- "ng/mL"

Single_Ascending_Dose_Dataset2 <- Single_Ascending_Dose_Dataset2[,c("ID","time","NOMTIME","TIMEUNIT","amt","DV","CMT",
                                                                        "CMT_label","EVENTU","BLQ","evid","WT0","SEX","DOSE_label",
                                                                        "DOSE")]
names(Single_Ascending_Dose_Dataset2) <- c("ID","TIME","NOMTIME","TIMEUNIT","AMT","LIDV","CMT",
                                             "NAME","EVENTU","CENS","EVID","WEIGHTB","SEX","TRTACT",
                                             "DOSE")

write.csv(Single_Ascending_Dose_Dataset2,"../Data/Single_Ascending_Dose_Dataset2.csv",row.names = FALSE)
DT::datatable(Single_Ascending_Dose_Dataset2, rownames = FALSE, options = list(autoWidth = TRUE, scrollX=TRUE)) 

Multiple Ascending Dose PK & PD Dataset

set.seed(12345666)
ndose <- 6
nsub <- 10 # number of subproblems

SEX <- rep(c(rep("Male",ceiling(nsub/2)),rep("Female",floor(nsub/2))),ndose)
WT0 <- (SEX=="Male")*runif(length(SEX),60,110)+(SEX=="Female")*runif(length(SEX),50,100)
VCOV <- (WT0/70)*(1-0.5*(SEX=="Female"))
CLCOV <- (WT0/70)*(1-0.5*(SEX=="Female"))

CL <- 0.02*exp(rnorm(nsub*ndose,0,.4^2))*CLCOV
KA <- 0.5*exp(rnorm(nsub*ndose,0,.4^2))
V2 <- 30*exp(rnorm(nsub*ndose,0,.4^2))*VCOV

Kin <- 0.1*exp(rnorm(nsub*ndose,0,0.4^2))
DOSE <- sort(rep(c(0,100,200,400,800,1600),nsub))
theta.all <- 
  cbind(KA=KA, CL=CL, V2=V2,
        Q=10*CLCOV, V3=100*VCOV, V4 = 10000*VCOV, Q2 = 10*CLCOV,
        Kin=Kin, Kout=0.01, EC50 = 1, Emax = 2+2*(SEX=="Female"))

# Nominal times for sampling schedule
SAMPLING <- c(c(-24,-0.1,0.1,0.5,1,2,4,8,12,18,23.9),23.9+seq(1,4)*24,
                                 5*24 + c(0.1,0.5,1,2,4,8,12,18,23.9,36,47.9,71.9,95.9))
DOSING <- seq(0,5*24,24)
NT <- data.frame(NT = c(SAMPLING, DOSING), label = c(rep("SAMPLING",length(SAMPLING)),rep("DOSING",length(DOSING))))
NT <- NT[order(NT$NT),]

ev.all <- list()
for(idose in 1:length(DOSE)){
  ev.all[[idose]] <- eventTable(amount.units='mg', time.units='hours')
  # ev.all[[idose]]$add.dosing(dose = DOSE[idose], nbr.doses = 6, dosing.interval = 24)
  # ev.all[[idose]]$add.sampling(c(c(-24,-0.1,0.1,0.5,1,2,4,8,12,18,23.9),23.9+seq(1,4)*24,
  #                                5*24 + c(0.1,0.5,1,2,4,8,12,18,23.9,36,47.9,71.9,95.9)))
  
  # Include some noise in the sampling & dosing schedules
  temp <- NT
  temp$time <- cumsum(c(temp$NT[1] + 0.1*rnorm(1), abs(temp$NT[2:length(temp$NT)]-temp$NT[1:length(temp$NT)-1] + 0.1*rnorm(length(temp$NT)-1))))
  temp$time <- temp$time - temp$time[temp$NT==0] # center at first dose
  
  if(DOSE[idose] > 0){
      ev.all[[idose]]$add.dosing(dose = DOSE[idose], start.time = temp$time[temp$label=="DOSING"])
  }else{
      ev.all[[idose]]$add.dosing(dose = 1e-12, start.time = temp$time[temp$label=="DOSING"])
  }

  ev.all[[idose]]$add.sampling(temp$time[temp$label=="SAMPLING"])
  
}

x.all.df <- NULL
ID = 0
for(i in 1:length(ev.all)){
  ID = ID + 1
  theta <- theta.all[i,]
  inits <- c(depot = 0, centr = 0, peri = 0, peri2 = 0, eff=theta["Kin"]/theta["Kout"])
  x <- mod1$solve(theta, ev.all[[i]], inits = inits)
  
  x.df <- data.frame(x)
  x.df$NT <- SAMPLING
    
  temp <- data.frame(ev.all[[i]]$get.dosing())
  temp$NT <- DOSING
  temp[,setdiff(names(x.df),names(temp))]<- NA
  x.df[,setdiff(names(temp),names(x.df))]<- NA
  x.df <- rbind(x.df,temp)
  
  x.df$ID <- ID
  x.df$DOSE <- DOSE[i]
  x.df$WT0 <- WT0[i]
  x.df$SEX <- SEX[i]
  
  if(is.null(x.all.df)){
    x.all.df <- x.df
  }else{
    x.all.df <- rbind(x.all.df, x.df)
  }
}
x.all.df$DV <- x.all.df$Concentration*(exp(rnorm(length(x.all.df$Concentration),0,0.6^2))) + 
  0.01*rnorm(length(x.all.df$Concentration))
x.all.df$DV[x.all.df$DV<0.05]=0.05
x.all.df$DV[x.all.df$Concentration==0]=NA
x.all.df$BLQ <- 0
x.all.df$BLQ[x.all.df$DV==0.05] <- 1

temp <- exp(rnorm(length(x.all.df$eff),0,0.4^2))
x.all.df$eff2 <- x.all.df$eff*temp + rnorm(length(x.all.df$eff),0,2) + 10*x.all.df$time/(72 + x.all.df$time)

temp <- runif(length(x.all.df$eff),0,1)
x.all.df$Response <- 0
x.all.df$Response[0.2*x.all.df$time/(72 + x.all.df$time) + exp((x.all.df$eff2-30))/(1+exp((x.all.df$eff2-30))) > temp] <- 1 


x.all.df$Severity <- 3
x.all.df$Severity[0.2*x.all.df$time/(72 + x.all.df$time) + exp((x.all.df$eff2-18))/(1+exp((x.all.df$eff2-18))) > temp] <- 2
x.all.df$Severity[0.2*x.all.df$time/(72 + x.all.df$time) + exp((x.all.df$eff2-28))/(1+exp((x.all.df$eff2-28))) > temp] <- 1
x.all.df$Severity_label <- plyr::mapvalues(x.all.df$Severity,c(1,2,3),c("mild","moderate","severe"))
x.all.df$Severity_label <- factor(x.all.df$Severity_label, levels = unique(x.all.df$Severity_label[order(x.all.df$Severity)]))

x.all.df$Count <- NA
x.all.df$Count[!is.na(x.all.df$eff2)]<-rpois(length(na.omit(x.all.df$eff2)), na.omit(10*( 0.5/(1 + x.all.df$time/24) + 0.5*exp(-((x.all.df$eff2)-28))/(1+exp(-((x.all.df$eff2)-28))))) )


my.data <- x.all.df[!is.na(x.all.df$amt),]
my.data$CMT_label <- "Dosing"
my.data$CMT <- 1

temp <- x.all.df[is.na(x.all.df$amt),]
temp$CMT <- 2
temp$CMT_label <- "PK Concentration"
my.data <- rbind(my.data,temp)

temp <- x.all.df[x.all.df$NT%in%c(-0.1,23.9,(23.9+seq(1,9)*24)),]
temp$DV <- temp$eff2
temp$CMT <- 3
temp$CMT_label <- "PD - Continuous"
my.data <- rbind(my.data,temp)

temp <- x.all.df[x.all.df$NT%in%c(-0.1,23.9,23.9+seq(1,9)*24),]
temp$DV <- temp$Count
temp$CMT <- 4
temp$CMT_label <- "PD - Count"
my.data <- rbind(my.data,temp)

temp <- x.all.df[x.all.df$NT%in%c(-24,23.9,23.9+seq(1,9)*24),]
temp$DV <- temp$Severity
temp$CMT <- 5
temp$CMT_label <- "PD - Ordinal"
my.data <- rbind(my.data,temp)

temp <- x.all.df[x.all.df$NT%in%c(-0.1,23.9,(23.9+seq(1,9)*24)),]
temp$DV <- temp$Response
temp$CMT <- 6
temp$CMT_label <- "PD - Binary"
my.data <- rbind(my.data,temp)


my.data$DV <- signif(my.data$DV,3)
my.data$WT0 <- signif(my.data$WT0,3)
my.data$time <- round(my.data$time,3)

my.data <- my.data[order(my.data$ID,my.data$time, my.data$CMT),]

my.data$DOSE_label <- paste(my.data$DOSE,"mg")
my.data$DOSE_label[my.data$DOSE==0] <- "Placebo"
my.data$DOSE_label <- factor(my.data$DOSE_label,levels = c("Placebo",paste(unique(my.data$DOSE[my.data$DOSE!=0]),"mg")))

my.data$DAY <- floor(my.data$NT/24)+1
my.data$DAY_label <- paste("Day",ceiling(my.data$DAY))
my.data$DAY_label[my.data$DAY<=0]<-"Baseline"
my.data$DAY_label <- factor(my.data$DAY_label,
                            levels = c("Baseline",paste("Day",sort(unique(ceiling(my.data$DAY))))))
my.data$CYCLE <- my.data$DAY
my.data$CYCLE[my.data$CYCLE>6] <- 6


# temp <- my.data[my.data$DAY_label=="Baseline"&my.data$CMT!=2,]
# temp$Severity0 <- temp$Severity
# temp$Response0 <- temp$Response
# temp$Count0 <- temp$Count
# temp$eff20 <- temp$eff2
# 
# cnames <- c("ID","Severity0","Response0","Count0","eff20")
# 
# my.data2 <- merge(my.data, unique(temp[,cnames]),by=c("ID"),all.x=TRUE)


Multiple_Ascending_Dose_Dataset <- my.data[,c("ID","time","NT","amt","DV","CMT","CMT_label","BLQ","evid","WT0","SEX","DOSE_label","DOSE","DAY","DAY_label","Response","Severity","Severity_label","Count","CYCLE")]

write.csv(Multiple_Ascending_Dose_Dataset,"../Data/Multiple_Ascending_Dose_Dataset.csv",row.names = FALSE)

# DT::datatable(Multiple_Ascending_Dose_Dataset[,c("time","NT","ID","CMT","DV","DOSE","DOSE_label","WT0","SEX","DAY","DAY_label","CMT_label")], rownames = FALSE, options = list(autoWidth = TRUE, scrollX=TRUE))

Multiple_Ascending_Dose_Dataset2 <- Multiple_Ascending_Dose_Dataset
Multiple_Ascending_Dose_Dataset2$PROFTIME <- Multiple_Ascending_Dose_Dataset2$NT - (Multiple_Ascending_Dose_Dataset2$CYCLE-1)*24
Multiple_Ascending_Dose_Dataset2$NOMTIME <- Multiple_Ascending_Dose_Dataset2$NT
Multiple_Ascending_Dose_Dataset2$YTYPE <- Multiple_Ascending_Dose_Dataset2$CMT
Multiple_Ascending_Dose_Dataset2$amt[is.na(Multiple_Ascending_Dose_Dataset2$amt)] <- 0 
Multiple_Ascending_Dose_Dataset2 <- Multiple_Ascending_Dose_Dataset2[!(Multiple_Ascending_Dose_Dataset2$DOSE_label=="Placebo"&
                                      Multiple_Ascending_Dose_Dataset2$CMT==2),] 
Multiple_Ascending_Dose_Dataset2$BLQ[Multiple_Ascending_Dose_Dataset2$DOSE_label=="Placebo"&
                                       Multiple_Ascending_Dose_Dataset2$CMT==2] <- 1L
Multiple_Ascending_Dose_Dataset2$evid <- plyr::mapvalues(Multiple_Ascending_Dose_Dataset2$evid, c(NA,101), c(0,1))
Multiple_Ascending_Dose_Dataset2$TIMEUNIT <- "Hours"
Multiple_Ascending_Dose_Dataset2$EVENTU[Multiple_Ascending_Dose_Dataset2$CMT==1] <- "mg"
Multiple_Ascending_Dose_Dataset2$EVENTU[Multiple_Ascending_Dose_Dataset2$CMT==2] <- "ng/mL"
Multiple_Ascending_Dose_Dataset2$EVENTU[Multiple_Ascending_Dose_Dataset2$CMT==3] <- "IU/L"
Multiple_Ascending_Dose_Dataset2$EVENTU[Multiple_Ascending_Dose_Dataset2$CMT==4] <- "count"
Multiple_Ascending_Dose_Dataset2$EVENTU[Multiple_Ascending_Dose_Dataset2$CMT==5] <- "severity"
Multiple_Ascending_Dose_Dataset2$EVENTU[Multiple_Ascending_Dose_Dataset2$CMT==6] <- "response"

Multiple_Ascending_Dose_Dataset2 <- Multiple_Ascending_Dose_Dataset2[,c("ID","time","NOMTIME","TIMEUNIT","amt","DV","CMT",
                                                                        "CMT_label","EVENTU","BLQ","evid","WT0","SEX","DOSE_label",
                                                                        "DOSE","DAY","PROFTIME","CYCLE")]
names(Multiple_Ascending_Dose_Dataset2) <- c("ID","TIME","NOMTIME","TIMEUNIT","AMT","LIDV","CMT",
                                             "NAME","EVENTU","CENS","EVID","WEIGHTB","SEX","TRTACT",
                                             "DOSE","PROFDAY","PROFTIME","CYCLE")

write.csv(Multiple_Ascending_Dose_Dataset2,"../Data/Multiple_Ascending_Dose_Dataset2.csv",row.names = FALSE)
DT::datatable(Multiple_Ascending_Dose_Dataset2, rownames = FALSE, options = list(autoWidth = TRUE, scrollX=TRUE) )

Regenerating the datasets

The code on this page is not evaluated during a normal site build, for two reasons. It needs rxode2, which requires C and Fortran compilers and is not needed by any other page. And it writes to Data/*.csv — the committed datasets that every other page on this site reads — so running it as part of a build would let the site quietly regenerate its own inputs.

The datasets are therefore treated as source: generated deliberately, checked, and committed. To regenerate them:

Rscript -e 'pak::pak("rxode2")'
cd Rmarkdown
XGX_REGENERATE_DATA=true Rscript -e 'rmarkdown::render("PKPD_Datasets.Rmd")'

Review the diff to Data/ before committing: the code is seeded, but the results still depend on the R version and on the ODE solver, so the numbers can move. This page previously used RxODE, which was archived from CRAN on 2022-10-10; the migration to rxode2 has not been run end to end, so expect to verify the output the first time.

R Session Info

sessionInfo()
## R version 4.6.1 (2026-06-24)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.4 LTS
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
## LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
## 
## locale:
##  [1] LC_CTYPE=C.UTF-8       LC_NUMERIC=C           LC_TIME=C.UTF-8       
##  [4] LC_COLLATE=C.UTF-8     LC_MONETARY=C.UTF-8    LC_MESSAGES=C.UTF-8   
##  [7] LC_PAPER=C.UTF-8       LC_NAME=C              LC_ADDRESS=C          
## [10] LC_TELEPHONE=C         LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C   
## 
## time zone: UTC
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] survminer_0.5.2 ggpubr_1.0.0    survival_3.8-6  knitr_1.51     
##  [5] broom_1.0.13    caTools_1.18.4  GGally_2.4.0    DT_0.34.0      
##  [9] lubridate_1.9.5 forcats_1.0.1   stringr_1.6.0   purrr_1.2.2    
## [13] readr_2.2.0     tibble_3.3.1    tidyverse_2.0.0 xgxr_1.1.6     
## [17] zoo_1.9-0       gridExtra_2.3.1 tidyr_1.3.2     dplyr_1.2.1    
## [21] ggplot2_4.0.3  
## 
## loaded via a namespace (and not attached):
##  [1] bitops_1.1-0       gld_2.6.8          readxl_1.5.0       rlang_1.3.0       
##  [5] magrittr_2.0.5     otel_0.2.0         e1071_1.7-17       compiler_4.6.1    
##  [9] png_0.1-9          vctrs_0.7.3        pkgconfig_2.0.3    fastmap_1.2.0     
## [13] backports_1.5.1    labeling_0.4.3     pander_0.6.6       rmarkdown_2.31    
## [17] markdown_2.0       tzdb_0.5.0         haven_2.5.5        visdat_0.6.0      
## [21] UpSetR_1.4.1       xfun_0.60          cachem_1.1.0       litedown_0.10     
## [25] jsonlite_2.0.0     Deriv_4.3.0        cluster_2.1.8.2    DescTools_0.99.60 
## [29] R6_2.6.1           bslib_0.12.0       stringi_1.8.9      RColorBrewer_1.1-3
## [33] car_3.1-5          boot_1.3-32        rpart_4.1.27       jquerylib_0.1.4   
## [37] cellranger_1.1.0   Rcpp_1.1.2         assertthat_0.2.1   base64enc_0.1-6   
## [41] splines_4.6.1      Matrix_1.7-5       nnet_7.3-20        timechange_0.4.0  
## [45] tidyselect_1.2.1   abind_1.4-8        rstudioapi_0.19.0  yaml_2.3.12       
## [49] minpack.lm_1.2-4   lattice_0.22-9     plyr_1.8.9         withr_3.0.3       
## [53] S7_0.2.2           evaluate_1.0.5     foreign_0.8-91     ggstats_0.13.0    
## [57] proxy_0.4-29       pillar_1.11.1      carData_3.0-6      corrplot_0.95     
## [61] checkmate_2.3.4    generics_0.1.4     RCurl_1.98-1.19    hms_1.1.4         
## [65] commonmark_2.0.0   scales_1.4.0       rootSolve_1.8.2.4  class_7.3-23      
## [69] glue_1.8.1         Hmisc_5.2-6        lmom_3.3           tools_4.6.1       
## [73] data.table_1.18.4  ggsignif_0.6.4     Exact_3.3          fs_2.1.0          
## [77] mvtnorm_1.4-2      grid_4.6.1         crosstalk_1.2.2    colorspace_2.1-3  
## [81] htmlTable_2.5.0    Formula_1.2-6      naniar_1.1.0       cli_3.6.6         
## [85] expm_1.0-0         binom_1.1-2        gtable_0.3.6       rstatix_1.1.0     
## [89] sass_0.4.10        digest_0.6.39      htmlwidgets_1.6.4  farver_2.1.2      
## [93] htmltools_0.5.9    lifecycle_1.0.5    httr_1.4.8         MASS_7.3-65