The vignettes of this package, in reading order:
AnalysisConfigurationlm_imputebuild_contrast_analysis() method on one
small datasetimpute_from_model()The package website https://fgcz.github.io/prolfqua/ has three more articles:
build_contrast_analysis() methods side by side, with
plotsbuild_contrast_analysis()prolfqua covers the steps of a label-free quantification (LFQ) proteomics analysis: quality control, normalization, aggregation of peptides to proteins, modelling, hypothesis testing and sample size estimation (Wolski et al. 2023).
The centre of the package is a factory,
build_contrast_analysis(). It takes the data, a model
formula, the contrasts and a method, and returns a ready
analysis: one model per protein and the requested contrasts.
build_contrast_analysis() is a factory: the method key selects the model, and every model rolls out with the same interface.
The method argument selects the model: linear models
(lm, rlm, rfit), limma and
limma-voom, DEqMS variance moderation, limpa’s detection probability
model, Firth logistic and binomial models of detection, mixed models and
ROPECA on peptide-level data, a hurdle model combining intensity and
detection, and variants that impute groups without observations at the
limit of detection.
Every method returns an object with the same interface:
get_contrasts(), get_Plotter(),
get_missing() and to_wide(). Results of
different methods therefore have the same columns and can be compared or
combined directly.
build_contrast_analysis() takes its data as an
LFQData object. The package works with data in long format,
one row per measured feature (protein, peptide, precursor) and
sample:
AnalysisConfiguration maps the columns of the table to
their roles: the feature hierarchy (protein, peptide, …), the
explanatory factors, the sample and the intensity column.LFQData holds the data together with its configuration.
Its methods return helpers for transformation
(get_Transformer()), aggregation
(get_Aggregator()), summary statistics
(get_Stats()), missing-value summaries
(get_Summariser()) and plots
(get_Plotter()).Install prolfqua from Bioconductor with:
if (!requireNamespace("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
BiocManager::install("prolfqua")The development version is available on GitHub:
We simulate peptide-level intensities for 100 proteins measured in
three groups (A, B and Ctrl).
sim_lfq_data_peptide_config() returns the data together
with a matching AnalysisConfiguration.
library(prolfqua)
istar <- sim_lfq_data_peptide_config(Nprot = 100, seed = 1234)
lfqdata <- LFQData$new(istar$data, istar$config)
lfqdata$factors() |> head()
#> # A tibble: 6 × 3
#> sample sampleName group_
#> <chr> <chr> <chr>
#> 1 A_V1 A_V1 A
#> 2 A_V2 A_V2 A
#> 3 A_V3 A_V3 A
#> 4 A_V4 A_V4 A
#> 5 B_V1 B_V1 B
#> 6 B_V2 B_V2 BWe \(\log_2\) transform the intensities, scale them robustly, and aggregate the peptides to proteins with Tukey’s median polish.
lfqdata <- lfqdata$get_Transformer()$log2()$robscale()$lfq
lfqprot <- lfqdata$get_Aggregator()$aggregate()Distribution of the normalized protein intensities per sample.
We compare groups A and B with the control
group using lm_impute: a linear model per protein with
moderated variances. Proteins whose fit fails because a group has no
observations are refitted with the missing values imputed at the limit
of detection, borrowing the variance from the other proteins.
contrasts <- c(
"A_vs_Ctrl" = "group_A - group_Ctrl",
"B_vs_Ctrl" = "group_B - group_Ctrl"
)
fa <- build_contrast_analysis(lfqprot, "~ group_", contrasts, method = "lm_impute")
res <- fa$get_contrasts()
head(res[, c("protein_Id", "contrast", "diff", "p.value", "FDR")])
#> # A tibble: 6 × 5
#> protein_Id contrast diff p.value FDR
#> <chr> <chr> <dbl> <dbl> <dbl>
#> 1 0EfVhX~3967 A_vs_Ctrl 0.199 0.000123 0.000397
#> 2 0m5WN4~6025 A_vs_Ctrl 0.178 0.0000160 0.0000726
#> 3 0YSKpy~2865 A_vs_Ctrl -0.175 0.00277 0.00554
#> 4 3QLHfm~8938 A_vs_Ctrl 0.214 0.00456 0.00807
#> 5 3QYop0~7543 A_vs_Ctrl -0.221 0.00000298 0.0000179
#> 6 76k03k~7094 A_vs_Ctrl -0.0822 0.00980 0.0156Volcano plot of the two contrasts.
All available methods are listed by list_facades(); the
vignette All modelling methods at a
glance runs each of them on one small dataset.
names(list_facades())
#> [1] "binomial_firth_nested" "binomial_nested" "deqms"
#> [4] "deqms_voom" "firth" "firth_nested"
#> [7] "hurdle_nested" "limma" "limma_impute"
#> [10] "limma_voom" "limma_voom_impute" "limpa"
#> [13] "limpa_nested" "lm" "lm_impute"
#> [16] "lmer_nested" "rfit" "rfit_impute"
#> [19] "rlm" "ropeca_nested"sessionInfo()
#> R version 4.6.2 (2026-10-29)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04.1 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.32.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [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: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] ggplot2_4.0.3 prolfqua_0.99.8 dplyr_1.2.1 BiocStyle_2.41.0
#>
#> loaded via a namespace (and not attached):
#> [1] Rdpack_2.6.6 gridExtra_2.3.1 rlang_1.3.0
#> [4] magrittr_2.0.5 clue_0.3-68 GetoptLong_1.1.1
#> [7] otel_0.3.0 matrixStats_1.5.0 compiler_4.6.2
#> [10] mgcv_1.9-5 png_0.1-9 vctrs_0.7.3
#> [13] pkgconfig_2.0.3 shape_1.4.6.1 crayon_1.5.3
#> [16] fastmap_1.2.0 backports_1.5.1 labeling_0.4.3
#> [19] utf8_1.2.6 promises_1.5.0 rmarkdown_2.32
#> [22] nloptr_2.2.1 UpSetR_1.4.1 purrr_1.2.2
#> [25] xfun_0.62 glmnet_5.2 jomo_2.7-6
#> [28] logistf_1.26.1 cachem_1.1.0 jsonlite_2.0.0
#> [31] progress_1.2.3 later_1.4.8 pan_2.0
#> [34] Rfit_0.27.0 prettyunits_1.2.0 broom_1.0.13
#> [37] parallel_4.6.2 cluster_2.1.8.3 R6_2.6.1
#> [40] bslib_0.12.0 stringi_1.8.9 RColorBrewer_1.1-3
#> [43] limma_3.99.4 boot_1.3-32 rpart_4.1.27
#> [46] numDeriv_2016.8-1.1 jquerylib_0.1.4 Rcpp_1.1.2
#> [49] iterators_1.0.14 knitr_1.52 IRanges_2.47.5
#> [52] httpuv_1.6.17 Matrix_1.7-6 splines_4.6.2
#> [55] nnet_7.3-21 tidyselect_1.2.1 yaml_2.3.12
#> [58] doParallel_1.0.17 codetools_0.2-20 lmerTest_3.2-1
#> [61] lattice_0.23-1 tibble_3.3.1 plyr_1.8.9
#> [64] shiny_1.14.0 withr_3.0.3 S7_0.2.2
#> [67] evaluate_1.0.5 survival_3.8-12 circlize_0.4.18
#> [70] pillar_1.11.1 BiocManager_1.30.27 mice_3.19.0
#> [73] KernSmooth_2.23-27 foreach_1.5.2 stats4_4.6.2
#> [76] reformulas_0.4.4 plotly_4.12.1 generics_0.1.4
#> [79] hms_1.1.4 S4Vectors_0.51.10 scales_1.4.0
#> [82] minqa_1.2.8 xtable_1.8-8 glue_1.8.1
#> [85] maketools_1.3.2 tools_4.6.2 sys_3.4.3
#> [88] data.table_1.18.6.1 lme4_2.1-0 forcats_1.0.1
#> [91] buildtools_1.0.0 grid_4.6.2 limpa_1.5.2
#> [94] tidyr_1.3.2 rbibutils_2.4.1 crosstalk_1.2.2
#> [97] colorspace_2.1-4 nlme_3.1-172 formula.tools_1.7.1
#> [100] cli_3.6.6 viridisLite_0.4.3 ComplexHeatmap_2.29.0
#> [103] gtable_0.3.6 sass_0.4.10 digest_0.6.39
#> [106] operator.tools_1.6.3.1 BiocGenerics_0.59.13 ggrepel_0.9.8
#> [109] rjson_0.2.23 htmlwidgets_1.6.4 farver_2.1.2
#> [112] htmltools_0.5.9 lifecycle_1.0.5 httr_1.4.9
#> [115] mime_0.13 GlobalOptions_0.1.4 mitml_0.4-5
#> [118] statmod_1.5.2 MASS_7.3-66