
Extract PCA component summaries
Source:R/ExtractPCAComponentSummary.R
ExtractPCAComponentSummary.RdExtract variables contributing to each PCA component based on an absolute loading threshold. Returns both a tidy long-format table and compact summary tables suitable for reporting.
Usage
ExtractPCAComponentSummary(
PCAObject,
loading_threshold = 0.4,
top_n = NULL,
use_labels = TRUE,
html_format = TRUE
)Arguments
- PCAObject
Output object from CreatePCAObject().
- loading_threshold
Minimum absolute loading required for inclusion. Default is 0.4.
- top_n
Optional maximum number of contributors per component. If NULL, all contributors above threshold are retained.
- use_labels
Logical indicating whether variable labels should be used when available. Default TRUE.
- html_format
Logical indicating whether negative contributors should be formatted using red HTML text. Default TRUE.
Value
A list containing:
- LongTable
A tidy tibble with one row per contributor.
- SummaryTable
A compact tibble with one row per component and comma-separated contributor summaries.
- SummaryTableLines
A compact tibble with one row per component and line-separated contributor summaries.
- FormattedSummaryTable
A formatted gt table with comma-separated contributors.
- FormattedSummaryTableLines
A formatted gt table with line-separated contributors.
Details
Negative contributors can optionally be formatted in red HTML text for improved readability in HTML tables.
Use this after CreatePCAObject(), at the point where the components exist
but do not yet mean anything. PCA hands back axes named PC1, PC2, PC3
each a weighted combination of every input variable - and the analysis cannot be written up until those names are replaced by something interpretable.
The full loadings matrix is the wrong tool for that job: with 40 variables
and 8 components it is 320 numbers, most of them near zero and irrelevant.
This function keeps only the loadings whose absolute value clears
loading_threshold (0.4 by default), which are the variables actually
driving each component, and reports them per component, sorted by strength.
Reading down the retained variables is what tells you that PC1 is "an
inflammatory axis" or that PC2 separates volume from thickness.
The sign matters as much as the magnitude. A component with some variables
loading positively and others negatively is a contrast - it scores the
balance between two sets of measures rather than their overall level - and
html_format = TRUE prints the negative contributors in red so that
structure is visible at a glance instead of having to be hunted for in a
column of numbers.
Once a component has a name, that name is what belongs on the axis of every downstream plot and in every table of PCA scores.
Choosing a threshold
loading_threshold trades completeness against readability. Raise it
(0.5-0.6) when a component retains so many variables that no theme is
visible; lower it (0.3) when a component comes back nearly empty, which
usually means its variance is spread thinly across many measures rather
than concentrated in a few. top_n caps the list per component instead,
which is the better control when what you want is a compact table for a
manuscript rather than a different scientific claim.
See also
CreatePCAObject() to fit the PCA, CreatePCATable() for the
variance-explained table, and ProjectPCA() to score new data on the
components once they have been interpreted.
Examples
# \donttest{
data(SampleData)
data(SampleVariableTypes)
df_Labelled <- RevalueData(SampleData, SampleVariableTypes)$RevaluedData
vars_Biomarkers <- c(
"AXL", "Adiponectin", "Alpha_1_Antitrypsin", "Alpha_2_Macroglobulin",
"Apolipoprotein_A1", "Apolipoprotein_B", "C_Reactive_Protein",
"Cortisol", "Cystatin_C", "Ferritin", "Insulin", "Leptin", "p_tau"
)
# Thirteen correlated biomarkers reduced to a handful of components
pca_obj <- CreatePCAObject(
data = df_Labelled,
VarsToReduce = vars_Biomarkers
)
# At this point the components are called RC1, RC2, RC3
summary_obj <- ExtractPCAComponentSummary(pca_obj)
# One row per component, listing only the variables that drive it
summary_obj$FormattedSummaryTableLines
Component
Top Contributors
# The same information, one contributor per row
htmltools::browsable(htmltools::HTML(as.character(
FreezeTableHeader(
dplyr::mutate(
summary_obj$LongTable,
dplyr::across(dplyr::where(is.numeric), \(x) round(x, 3))
),
height = "320px", full_width = TRUE
)
)))
Variable
PlotLabel
Component
Loading
AbsLoading
Direction
Label
Rank
p_tau
Phosphorylated tau protein
RC1
0.857
0.857
Positive
Phosphorylated tau protein
1
AXL
AXL receptor tyrosine kinase
RC1
0.848
0.848
Positive
AXL receptor tyrosine kinase
2
Cystatin_C
Cystatin C
RC1
0.839
0.839
Positive
Cystatin C
3
Ferritin
Ferritin
RC1
0.664
0.664
Positive
Ferritin
4
Alpha_2_Macroglobulin
Alpha-2-macroglobulin
RC1
0.528
0.528
Positive
Alpha-2-macroglobulin
5
Apolipoprotein_B
Apolipoprotein B
RC2
0.843
0.843
Positive
Apolipoprotein B
1
Alpha_2_Macroglobulin
Alpha-2-macroglobulin
RC2
0.685
0.685
Positive
Alpha-2-macroglobulin
2
Leptin
Leptin
RC3
0.974
0.974
Positive
Leptin
1
Cortisol
Cortisol
RC4
0.986
0.986
Positive
Cortisol
1
Insulin
Insulin
RC5
0.853
0.853
Positive
Insulin
1
Apolipoprotein_A1
Apolipoprotein A-1
RC5
0.616
0.616
Positive
Apolipoprotein A-1
2
Alpha_1_Antitrypsin
Alpha-1-antitrypsin
RC6
0.907
0.907
Positive
Alpha-1-antitrypsin
1
Apolipoprotein_A1
Apolipoprotein A-1
RC6
0.422
0.422
Positive
Apolipoprotein A-1
2
C_Reactive_Protein
C-reactive protein
RC7
0.918
0.918
Positive
C-reactive protein
1
Adiponectin
Adiponectin
RC8
0.866
0.866
Positive
Adiponectin
1
Apolipoprotein_A1
Apolipoprotein A-1
RC8
0.436
0.436
Positive
Apolipoprotein A-1
2
# A stricter threshold
ExtractPCAComponentSummary(pca_obj, loading_threshold = 0.6)$SummaryTable
#> # A tibble: 8 × 2
#> Component Contributors
#> <chr> <chr>
#> 1 RC1 Phosphorylated tau protein, AXL receptor tyrosine kinase, Cystatin …
#> 2 RC2 Apolipoprotein B, Alpha-2-macroglobulin
#> 3 RC3 Leptin
#> 4 RC4 Cortisol
#> 5 RC5 Insulin, Apolipoprotein A-1
#> 6 RC6 Alpha-1-antitrypsin
#> 7 RC7 C-reactive protein
#> 8 RC8 Adiponectin
# Capping the list per component instead
ExtractPCAComponentSummary(pca_obj, top_n = 3)$SummaryTable
#> # A tibble: 8 × 2
#> Component Contributors
#> <chr> <chr>
#> 1 RC1 Phosphorylated tau protein, AXL receptor tyrosine kinase, Cystatin C
#> 2 RC2 Apolipoprotein B, Alpha-2-macroglobulin
#> 3 RC3 Leptin
#> 4 RC4 Cortisol
#> 5 RC5 Insulin, Apolipoprotein A-1
#> 6 RC6 Alpha-1-antitrypsin, Apolipoprotein A-1
#> 7 RC7 C-reactive protein
#> 8 RC8 Adiponectin, Apolipoprotein A-1
# }