This vignette is the third chapter in the “Pathway Significance
Testing with pathwayPCA
” workflow, providing a detailed
perspective to the Creating
Data Objects section of the Quickstart Guide. This vignette builds
on the material covered in the “Import
and Tidy Data” vignette. This guide will outline the major steps
needed to create a data object for analysis with the
pathwayPCA
package. These objects are called
Omics
-class objects.
Before we move on, we will outline our steps. After reading this vignette, you should be able to
Omics
object
class.Omics
objects.First, load the pathwayPCA
package and the tidyverse
package
suite.
Because this is the third chapter in the workflow, we assume that
pathwayCollection
object.If you are unsure about any of the three points above (or you don’t know what these mean), please review the Import and Tidy Data vignette first. It isn’t very long, but it will help you set up your data in the right way. If your data is not in the proper form, the steps in this vignette may be very difficult.
For the purpose of example, we will load some “toy” data: a combined
assay / phenotype data frame and a pathwayCollection
list.
These objects already fit the three criteria above. This tidy data set
has 656 gene expression measurements (columns) on 250 colon cancer
patients (rows).
data("colonSurv_df")
colonSurv_df
#> # A tibble: 250 × 659
#> sampleID OS_time OS_event JUN SOS2 PAK3 RAF1 PRKCB BTC SHC1 PRKCA
#> <chr> <dbl> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 subj1 64.9 0 9.29 5.48 8.21 8.03 5.49 6.65 8.26 8.94
#> 2 subj2 59.8 0 9.13 6.35 8.33 7.94 6.26 7.02 8.39 9.61
#> 3 subj3 62.4 0 9.37 5.67 7.82 7.74 6.05 7.52 8.69 8.40
#> 4 subj4 54.5 0 10.6 4.94 8.79 7.64 5.37 6.87 7.81 9.80
#> 5 subj5 46.3 1 8.70 5.60 8.75 8.05 6.07 6.49 8.45 8.21
#> 6 subj6 55.9 0 9.78 5.36 7.56 8.07 5.90 6.39 8.87 8.22
#> 7 subj7 58.0 0 9.22 5.05 8.20 7.80 5.55 6.86 8.28 8.97
#> 8 subj8 54.0 0 10.3 5.33 7.82 7.89 6.27 6.25 8.66 9.71
#> 9 subj9 0.427 1 10.8 5.07 7.63 7.69 5.48 7.57 8.36 9.69
#> 10 subj10 41.4 0 9.52 5.50 7.48 7.53 5.71 7.33 8.54 8.14
#> # ℹ 240 more rows
#> # ℹ 648 more variables: ELK1 <dbl>, NRG1 <dbl>, PAK2 <dbl>, MTOR <dbl>,
#> # PAK4 <dbl>, MAP2K4 <dbl>, EIF4EBP1 <dbl>, BAD <dbl>, PRKCG <dbl>,
#> # NRG3 <dbl>, …
Notice that the assay and survival response information have already been merged, so we have two additional columns (for Overall Survival Time and its corresponding death indicator). We also have a small collection of 15 pathways which correspond to our example colon cancer assay.
data("colon_pathwayCollection")
colon_pathwayCollection
#> Object with Class(es) 'pathwayCollection', 'list' [package 'pathwayPCA'] with 2 elements:
#> $ pathways:List of 15
#> $ TERMS : chr [1:15] "KEGG_PENTOSE_PHOSPHATE_PATHWAY" ...
str(colon_pathwayCollection$pathways, list.len = 10)
#> List of 15
#> $ pathway3 : chr [1:27] "RPE" "RPIA" "PGM2" "PGLS" ...
#> $ pathway60 : chr [1:64] "RPE65" "CYP3A5" "UGT2B28" "CYP4A11" ...
#> $ pathway87 : chr [1:87] "JUN" "SOS2" "PAK3" "RAF1" ...
#> $ pathway120 : chr [1:89] "HLA-DOA" "HLA-DOB" "KLRC3" "KLRD1" ...
#> $ pathway176 : chr [1:54] "CASP9" "SOS2" "E2F1" "PRKCB" ...
#> $ pathway177 : chr [1:30] "HLA-DRB4" "HLA-DRB5" "HLA-DOA" "HLA-DOB" ...
#> $ pathway187 : chr [1:16] "IKBKG" "CHUK" "EP300" "RELA" ...
#> $ pathway266 : chr [1:11] "PRF1" "DFFA" "DFFB" "HMGB2" ...
#> $ pathway390 : chr [1:29] "JUN" "BAG4" "CASP8" "MAPK8" ...
#> $ pathway413 : chr [1:23] "PLD1" "RAF1" "EPHB2" "VAV1" ...
#> [list output truncated]
The pathway collection and tidy assay (with matched phenotype
information) are all the information we need to create an
Omics
-class data object.
Omics
-Class Objects DefinedNow that we have our data loaded, we can create an analysis object
for the pathwayPCA
package.
In this package, all primary input data will be in an
Omics
data object. There are three classes of
Omics*
objects, but one function (CreateOmics
)
creates all of them. Each class contains a tidy assay and
pathwayCollection
list. The classes differ in the type of
response information they can hold. The classes, and their responses,
are
OmicsSurv
—a data object for survival information, which
includes event time (the time of last follow-up with a subject) and
event indicator (did the subject die, or was the observation
right-censored).OmicsReg
—a data object for continuous responses
(usually a linear regression response).OmicsCateg
—a data object for categorical responses, the
dependent variable of a generalized linear model. Currently, we only
support binary classification (through logistic regression).OmicsPathway
—a data object with no response. This is
the “parent” class for the other three Omics
classes.R
Take a quick look back at the structure of our
colonSurv_df
object. We have a table data frame with the
first two columns as subject response information and the rest as an
expression design matrix. Look at the types of the columns of this data
frame (the <dbl>
and <int>
tags
directly under the column names): these tags tell us that the columns
contain “double / numeric” (dbl
) and “integer”
(int
) information. The other tags we could potentially see
here are <chr>
(character), <lgl>
(logical), or <fct>
(factor). These tags are
important because they identify which “class” of data is in each
column.
Here are some examples of how to change data between types. We inspect the first 10 entries of each object.
# Original integer column
head(colonSurv_df$OS_event, 10)
#> [1] 0 0 0 0 1 0 0 0 1 0
# Integer to Character
head(as.character(colonSurv_df$OS_event), 10)
#> [1] "0" "0" "0" "0" "1" "0" "0" "0" "1" "0"
# Integer to Logical
head(as.logical(colonSurv_df$OS_event), 10)
#> [1] FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE
# Integer to Factor
head(as.factor(colonSurv_df$OS_event), 10)
#> [1] 0 0 0 0 1 0 0 0 1 0
#> Levels: 0 1
The CreateOmics
function puts the response information
into specific classes:
numeric
(time) and
logical
(death indicator) vectors.numeric
or
integer
vector.factor
vector.These restrictions are on purpose: the internal data creation
functions in the pathwayPCA
package have very specific
requirements about the types of data they take as inputs. This ensures
the integrity of your data analysis.
Omics
ObjectsAll new Omics
objects are created with the
CreateOmics
function. You should use this function to
create Omics
-class objects for survival, regression, or
categorical responses. This CreateOmics
function
internally calls on a specific creation function for each
response type:
CreateOmicsSurv()
function
creates an Omics
object with class OmicsSurv
.
This object will contain:
eventTime
: a numeric
vector of event
times.eventObserved
: a logical
vector of death
(or other event) indicators. This format precludes the option of
recurrent-event survival analysis.assayData_df
: a tidy data.frame
or
tibble
of assay data. Rows are observations or subjects;
the columns are -Omics measures (e.g. transcriptome). The column names
must match a subset of the genes provided in the pathways list
(in the pathwayCollection
object).pathwayCollection
: a list
of pathway
information, as returned by the read_gmt
function (see the
Import
and Tidy Data vignette for more details). The names of the genes in
these pathways must match a subset of the genes recorded in the
assay data frame (in the assayData_df
object).CreateOmicsReg()
function
creates an Omics
object with class OmicsReg
.
This object will contain:
response
: a numeric
vector of the
response.assayData_df
: a tidy data.frame
or
tibble
of assay data, as described above.pathwayCollection
: a list
of pathway
information, as described above.CreateOmicsCateg()
function creates an Omics
object with class
OmicsCateg
. In future versions, this function will be able
to take in \(n\)-ary responses and
ordered categorical responses, but we only support binary responses for
now. This object will contain:
response
: a factor
vector of the
response.assayData_df
: a tidy data.frame
or
tibble
of assay data, as described above.pathwayCollection
: a list
of pathway
information, as described above.In order to create example Omics
-class objects, we will
consider the overall patient survival time (and corresponding censoring
indicator) as our survival response, the event time as our regression
response, and event indicator as our binary classification response.
Omics
Data ObjectNow we are prepared to create our first survival Omics
object for later analysis with either AES-PCA or Supervised PCA. Recall
that the colonSurv_df
data frame has the survival time in
the first column, the event indicator in the second column, and the
assay expression data in the subsequent columns. Therefore, the four
arguments to the CreateOmics
function will be:
assayData_df
: this will be only the expression
columns of the colonSurv_df
data frame (i.e. all but
the first two columns). In R
, we can remove the first two
columns of the colonSurv_df
data frame by negative
subsetting: colonSurv_df[, -(1:2)]
.pathwayCollection_ls
: this will be the
colon_pathwayCollection
list object. Recall that you can
import a .gmt
file into a pathwayCollection
object via the read_gmt
function, or create a
pathwayCollection
list object by hand with the
CreatePathwayCollection
function.response
: this will be the first two columns of the
colonSurv_df
data frame. The survival time stored in the
OS_time
column and the event indicator stored in the
OS_event
column.respType
: this will be the word "survival"
or an abbreviation of it.Also, when you create an Omics*
-class object, the
CreateOmics()
function prints helpful diagnostic messages
about the overlap between the features in the supplied assay data and
those in the pathway collection.
colon_OmicsSurv <- CreateOmics(
assayData_df = colonSurv_df[, -(2:3)],
pathwayCollection_ls = colon_pathwayCollection,
response = colonSurv_df[, 1:3],
respType = "surv"
)
#>
#> ====== Creating object of class OmicsSurv =======
#> The input pathway database included 676 unique features.
#> The input assay dataset included 656 features.
#> Only pathways with at least 3 or more features included in the assay dataset are
#> tested (specified by minPathSize parameter). There are 15 pathways which meet
#> this criterion.
#> Because pathwayPCA is a self-contained test (PMID: 17303618), only features in
#> both assay data and pathway database are considered for analysis. There are 615
#> such features shared by the input assay and pathway database.
The last three sentences inform you of how strong the overlap is between the genes measured in your data and the genes selected in your pathway collection. This messages tells us that 9% of the 676 total genes included in all pathways were not measured in the assay; zero pathways were removed from the pathways list for having too few genes after gene trimming; and the genes in the pathways list call for 93.8% of the 656 genes measured in the assay. The last number is the most important: it measures how well your pathway collection overlaps with the genes measured in your assay. This number should be as close to 100% as possible. These diagnostic messages depend on the overlap between the pathway collection and the assay, so these messages are response agnostic.
In order to view a summary of the contents of the
colon_OmicsSurv
object, you need simply to print it to the
R
console.
colon_OmicsSurv
#> Formal class 'OmicsSurv' [package "pathwayPCA"] with 6 slots
#> ..@ eventTime : num [1:250] 64.9 59.8 62.4 54.5 46.3 ...
#> ..@ eventObserved : logi [1:250] FALSE FALSE FALSE FALSE TRUE FALSE ...
#> ..@ assayData_df : tibble [250 × 656] (S3: tbl_df/tbl/data.frame)
#> ..@ sampleIDs_char : chr [1:250] "subj1" "subj2" "subj3" "subj4" ...
#> ..@ pathwayCollection :List of 3
#> .. ..- attr(*, "class")= chr [1:2] "pathwayCollection" "list"
#> ..@ trimPathwayCollection:List of 4
#> .. ..- attr(*, "class")= chr [1:2] "pathwayCollection" "list"
Also notice that the CreateOmics()
function stores a
“cleaned” copy of the pathway collection. The object creation functions
within the pathwayPCA
package subset the feature data frame
by the genes in each pathway. Therefore, if we have genes in the
pathways that are not recorded in the data frame, then we will
necessarily create missing (NA
) predictors. To circumvent
this issue, we check if each gene in each pathway is recorded in the
data frame, and remove from each pathway the genes for which the assay
does not have recorded expression levels. However, if we remove genes
from pathways which do not have recorded levels in the predictor data
frame, we could theoretically remove all the genes from a given pathway.
Thus, we also check to make sure that each pathway in the given pathways
list still has some minimum number of genes present (defaulting to three
or more) after we have removed genes without corresponding expression
levels.
The IntersectOmicsPwyCollct()
function performs these
two actions simultaneously, and this function is called and executed
automatically within the object creation step. This function removes the
unrecorded genes from each pathway, trims the pathways that have fewer
than the minimum number of genes allowed, and returns a “trimmed”
pathway collection. If there are any pathways removed by this execution,
the pathways
list within the
trimPathwayCollection
object within the Omics
object will have a character vector of the pathways removed stored as
the "missingPaths"
attribute. Access this attribute with
the attr()
function.
Omics
Data
ObjectsWe create regression- and categorical-type Omics
data
objects identically to survival-type Omics
objects. We will
use the survival time as our toy regression response and the death
indicator as the toy classification response.
colon_OmicsReg <- CreateOmics(
assayData_df = colonSurv_df[, -(2:3)],
pathwayCollection_ls = colon_pathwayCollection,
response = colonSurv_df[, 1:2],
respType = "reg"
)
#>
#> ====== Creating object of class OmicsReg =======
#> The input pathway database included 676 unique features.
#> The input assay dataset included 656 features.
#> Only pathways with at least 3 or more features included in the assay dataset are
#> tested (specified by minPathSize parameter). There are 15 pathways which meet
#> this criterion.
#> Because pathwayPCA is a self-contained test (PMID: 17303618), only features in
#> both assay data and pathway database are considered for analysis. There are 615
#> such features shared by the input assay and pathway database.
colon_OmicsReg
#> Formal class 'OmicsReg' [package "pathwayPCA"] with 5 slots
#> ..@ response : num [1:250] 64.9 59.8 62.4 54.5 46.3 ...
#> ..@ assayData_df : tibble [250 × 656] (S3: tbl_df/tbl/data.frame)
#> ..@ sampleIDs_char : chr [1:250] "subj1" "subj2" "subj3" "subj4" ...
#> ..@ pathwayCollection :List of 3
#> .. ..- attr(*, "class")= chr [1:2] "pathwayCollection" "list"
#> ..@ trimPathwayCollection:List of 4
#> .. ..- attr(*, "class")= chr [1:2] "pathwayCollection" "list"
colon_OmicsCateg <- CreateOmics(
assayData_df = colonSurv_df[, -(2:3)],
pathwayCollection_ls = colon_pathwayCollection,
response = colonSurv_df[, c(1, 3)],
respType = "categ"
)
#>
#> ====== Creating object of class OmicsCateg =======
#> The input pathway database included 676 unique features.
#> The input assay dataset included 656 features.
#> Only pathways with at least 3 or more features included in the assay dataset are
#> tested (specified by minPathSize parameter). There are 15 pathways which meet
#> this criterion.
#> Because pathwayPCA is a self-contained test (PMID: 17303618), only features in
#> both assay data and pathway database are considered for analysis. There are 615
#> such features shared by the input assay and pathway database.
colon_OmicsCateg
#> Formal class 'OmicsCateg' [package "pathwayPCA"] with 5 slots
#> ..@ response : Factor w/ 2 levels "0","1": 1 1 1 1 2 1 1 1 2 1 ...
#> ..@ assayData_df : tibble [250 × 656] (S3: tbl_df/tbl/data.frame)
#> ..@ sampleIDs_char : chr [1:250] "subj1" "subj2" "subj3" "subj4" ...
#> ..@ pathwayCollection :List of 3
#> .. ..- attr(*, "class")= chr [1:2] "pathwayCollection" "list"
#> ..@ trimPathwayCollection:List of 4
#> .. ..- attr(*, "class")= chr [1:2] "pathwayCollection" "list"
Omics
-Class ObjectsIn order to access or edit a specific component of an
Omics
object, we need to use specific accessor
functions. These functions are named with the component they access.
The get*
functions access the part of the data object
you specify. You can save these objects to their own variables, or
simply print them to the screen for inspection. Here we print the assay
data frame contained in the colon_OmicsSurv
object to the
screen:
getAssay(colon_OmicsSurv)
#> # A tibble: 250 × 656
#> JUN SOS2 PAK3 RAF1 PRKCB BTC SHC1 PRKCA ELK1 NRG1
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 -0.880 0.367 1.30 0.480 -0.867 -0.790 -0.284 0.0104 1.04 0.670
#> 2 -1.11 2.15 1.62 0.165 0.547 -0.261 -0.000491 1.18 1.49 1.30
#> 3 -0.752 0.764 0.330 -0.541 0.164 0.452 0.691 -0.950 0.667 0.128
#> 4 1.03 -0.751 2.75 -0.878 -1.09 -0.481 -1.34 1.52 2.23 3.65
#> 5 -1.73 0.613 2.66 0.550 0.197 -1.02 0.156 -1.29 1.68 -2.15
#> 6 -0.162 0.126 -0.324 0.627 -0.106 -1.17 1.11 -1.27 0.964 1.79
#> 7 -0.980 -0.520 1.28 -0.343 -0.762 -0.489 -0.257 0.0518 1.21 -0.312
#> 8 0.616 0.0633 0.343 -0.0195 0.578 -1.37 0.638 1.37 1.05 -0.703
#> 9 1.35 -0.467 -0.149 -0.718 -0.898 0.527 -0.0604 1.32 -1.00 -0.266
#> 10 -0.538 0.413 -0.503 -1.27 -0.466 0.178 0.345 -1.40 -0.378 0.0623
#> # ℹ 240 more rows
#> # ℹ 646 more variables: PAK2 <dbl>, MTOR <dbl>, PAK4 <dbl>, MAP2K4 <dbl>,
#> # EIF4EBP1 <dbl>, BAD <dbl>, PRKCG <dbl>, NRG3 <dbl>, MAPK9 <dbl>,
#> # ERBB4 <dbl>, …
This function is rather simple: it shows us what object is stored in
the assayData_df
slot of the colon_OmicsSurv
data object. As we should expect, we see all the columns of the
colonSurv_df
data frame except for the first two (the
survival time and event indicator).
If we needed to edit the assay data frame in the
colon_OmicsSurv
object, we can use the “replacement” syntax
of the getAssay
function. These are the “set” functions,
and they use the getSLOT(object) <- value
syntax. For
example, if we wanted to remove all of the genes except for the first
ten from the assay data, we can replace this assay data with a subset of
the the original colonSurv_df
data frame. The
SLOT
shorthand name is Assay
, and the
replacement value is the first ten gene expression columns (in columns 3
through 12) of the colonSurv_df
data frame:
colonSurv_df[, (3:12)]
.
Now, when we inspect the colon_OmicsSurv
data object, we
see only ten variables measured in the assayData_df
slot,
instead of our original 656.
colon_OmicsSurv
#> Formal class 'OmicsSurv' [package "pathwayPCA"] with 6 slots
#> ..@ eventTime : num [1:250] 64.9 59.8 62.4 54.5 46.3 ...
#> ..@ eventObserved : logi [1:250] FALSE FALSE FALSE FALSE TRUE FALSE ...
#> ..@ assayData_df : tibble [250 × 10] (S3: tbl_df/tbl/data.frame)
#> ..@ sampleIDs_char : chr [1:250] "subj1" "subj2" "subj3" "subj4" ...
#> ..@ pathwayCollection :List of 3
#> .. ..- attr(*, "class")= chr [1:2] "pathwayCollection" "list"
#> ..@ trimPathwayCollection:List of 4
#> .. ..- attr(*, "class")= chr [1:2] "pathwayCollection" "list"
Before we move on, we should resest the data in the
assayData_df
slot to the full data by
Here is a table listing each of the “get” and “set” methods for the
Omics
class, and which sub-classes they can access or
modify.
Command | Omics Sub-class |
Function |
---|---|---|
getAssay(object) |
All | Extract the assayData_df data frame stored in
object . |
getAssay(object) <- value |
All | Set assayData_df stored in object to
value . |
getSampleIDs(object) |
All | Extract the sampleIDs_char vector stored in
object . |
getSampleIDs(object) <- value |
All | Set sampleIDs_char stored in object to
value . |
getPathwayCollection(object) |
All | Extract the pathwayCollection list stored in
object . |
getPathwayCollection(object) <- value |
All | Set pathwayCollection stored in object to
value . |
getEventTime(object) |
Surv |
Extract the eventTime_num vector stored in
object . |
getEventTime(object) <- value |
Surv |
Set eventTime_num stored in object to
value . |
getEvent(object) |
Surv |
Extract the eventObserved_lgl vector stored in
object . |
getEvent(object) <- value |
Surv |
Set eventObserved_lgl stored in object to
value . |
getResponse(object) |
Reg or Categ |
Extract the response vector stored in
object . |
getResponse(object) <- value |
Reg or Categ |
Set response stored in object to
value . |
The response
vector accessed or edited with the
getResponse
method depends on if the object
supplied is a “regression” Omics
-class object or a
“categorical” one. For regression Omics
objects,
getResponse(object)
and
getResponse(object) <- value
get and set, respectively,
the response_num
slot. However, for categorical
Omics
objects, getResponse(object)
and
getResponse(object) <- value
get and set, respectively,
the response_fact
slot. This is because regression objects
contain numeric
response vectors while categorical objects
contain factor
response vectors.
pathwayCollection
ListAs we mentioned in the Importing
with the read_gmt
Function subsection of the previous
vignette, the pathwayCollection
object will be modified
upon Omics
-object creation. Before, this list only had two
elements, pathways
and TERMS
(we skipped
importing the “description” field). Now, it has a third element:
setsize
—the number of genes contained in each pathway.
getPathwayCollection(colon_OmicsSurv)
#> Object with Class(es) 'pathwayCollection', 'list' [package 'pathwayPCA'] with 3 elements:
#> $ pathways:List of 15
#> $ TERMS : Named chr [1:15] "KEGG_PENTOSE_PHOSPHATE_PATHWAY" ...
#> $ setsize : Named int [1:15] 27 64 ...
We now summarize our steps so far. We have
Omics
class and three sub-classes:
survival, regression, and categorical (and the “parent” class).Omics
object for the three sub-classes.Now we are prepared to analyze our created data objects with either AES-PCA or Supervised PCA. Please read vignette chapter 4 next: Test Pathway Significance.
Here is the R session information for this vignette:
sessionInfo()
#> R Under development (unstable) (2024-10-21 r87258)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.1 LTS
#>
#> Matrix products: default
#> BLAS: /home/biocbuild/bbs-3.21-bioc/R/lib/libRblas.so
#> LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_GB LC_COLLATE=C
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: America/New_York
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats4 parallel stats graphics grDevices utils datasets
#> [8] methods base
#>
#> other attached packages:
#> [1] SummarizedExperiment_1.37.0 Biobase_2.67.0
#> [3] GenomicRanges_1.59.0 GenomeInfoDb_1.43.0
#> [5] IRanges_2.41.0 S4Vectors_0.45.0
#> [7] BiocGenerics_0.53.0 MatrixGenerics_1.19.0
#> [9] matrixStats_1.4.1 survminer_0.4.9
#> [11] ggpubr_0.6.0 survival_3.7-0
#> [13] pathwayPCA_1.23.0 lubridate_1.9.3
#> [15] forcats_1.0.0 stringr_1.5.1
#> [17] dplyr_1.1.4 purrr_1.0.2
#> [19] readr_2.1.5 tidyr_1.3.1
#> [21] tibble_3.2.1 ggplot2_3.5.1
#> [23] tidyverse_2.0.0
#>
#> loaded via a namespace (and not attached):
#> [1] tidyselect_1.2.1 farver_2.1.2 fastmap_1.2.0
#> [4] digest_0.6.37 timechange_0.3.0 lifecycle_1.0.4
#> [7] magrittr_2.0.3 compiler_4.5.0 rlang_1.1.4
#> [10] sass_0.4.9 tools_4.5.0 utf8_1.2.4
#> [13] yaml_2.3.10 data.table_1.16.2 knitr_1.48
#> [16] ggsignif_0.6.4 S4Arrays_1.7.0 labeling_0.4.3
#> [19] bit_4.5.0 DelayedArray_0.33.0 abind_1.4-8
#> [22] withr_3.0.2 grid_4.5.0 fansi_1.0.6
#> [25] lars_1.3 xtable_1.8-4 colorspace_2.1-1
#> [28] scales_1.3.0 cli_3.6.3 rmarkdown_2.28
#> [31] crayon_1.5.3 generics_0.1.3 km.ci_0.5-6
#> [34] httr_1.4.7 tzdb_0.4.0 cachem_1.1.0
#> [37] zlibbioc_1.53.0 splines_4.5.0 XVector_0.47.0
#> [40] survMisc_0.5.6 vctrs_0.6.5 Matrix_1.7-1
#> [43] jsonlite_1.8.9 carData_3.0-5 car_3.1-3
#> [46] hms_1.1.3 bit64_4.5.2 rstatix_0.7.2
#> [49] archive_1.1.9 Formula_1.2-5 jquerylib_0.1.4
#> [52] glue_1.8.0 stringi_1.8.4 gtable_0.3.6
#> [55] UCSC.utils_1.3.0 munsell_0.5.1 pillar_1.9.0
#> [58] htmltools_0.5.8.1 GenomeInfoDbData_1.2.13 R6_2.5.1
#> [61] KMsurv_0.1-5 vroom_1.6.5 evaluate_1.0.1
#> [64] lattice_0.22-6 highr_0.11 backports_1.5.0
#> [67] broom_1.0.7 bslib_0.8.0 SparseArray_1.7.0
#> [70] gridExtra_2.3 nlme_3.1-166 mgcv_1.9-1
#> [73] xfun_0.48 zoo_1.8-12 pkgconfig_2.0.3