prolfqua 0.99.8
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.
Figure 1: 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:
BiocManager::install("fgcz/prolfqua")
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 B
We \(\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()
lfqprot$get_Plotter()$intensity_distribution_density()
Figure 2: 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 0YSKpy~2865 A_vs_Ctrl -0.175 0.00277 0.00554
#> 3 0m5WN4~6025 A_vs_Ctrl 0.178 0.0000160 0.0000726
#> 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.0156
fa$get_Plotter()$volcano()$FDR
Figure 3: Volcano 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.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.5 LTS
#>
#> Matrix products: default
#> BLAS: /home/biocbuild/bbs-3.24-bioc/R/lib/libRblas.so
#> LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0 LAPACK version 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] 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] RColorBrewer_1.1-3 jsonlite_2.0.0 shape_1.4.6.1
#> [4] magrittr_2.0.5 TH.data_1.1-5 estimability_2.0.0
#> [7] jomo_2.7-6 magick_2.9.1 farver_2.1.2
#> [10] logistf_1.26.1 nloptr_2.2.1 rmarkdown_2.32
#> [13] GlobalOptions_0.1.4 vctrs_0.7.3 Cairo_1.7-0
#> [16] minqa_1.2.8 tinytex_0.61 htmltools_0.5.9
#> [19] forcats_1.0.1 progress_1.2.3 broom_1.0.13
#> [22] mitml_0.4-5 sass_0.4.10 KernSmooth_2.23-27
#> [25] bslib_0.12.0 htmlwidgets_1.6.4 plyr_1.8.9
#> [28] sandwich_3.1-3 emmeans_2.0.4 plotly_4.12.1
#> [31] zoo_1.9-1 cachem_1.1.0 mime_0.13
#> [34] lifecycle_1.0.5 iterators_1.0.14 pkgconfig_2.0.3
#> [37] Matrix_1.7-6 R6_2.6.1 fastmap_1.2.0
#> [40] rbibutils_2.4.1 shiny_1.14.0 clue_0.3-68
#> [43] digest_0.6.39 numDeriv_2016.8-1.1 colorspace_2.1-4
#> [46] S4Vectors_0.51.10 crosstalk_1.2.2 labeling_0.4.3
#> [49] httr_1.4.9 mgcv_1.9-5 compiler_4.6.1
#> [52] withr_3.0.3 doParallel_1.0.17 S7_0.2.2
#> [55] backports_1.5.1 UpSetR_1.4.1 pan_2.0
#> [58] MASS_7.3-66 rjson_0.2.23 tools_4.6.1
#> [61] otel_0.2.0 httpuv_1.6.17 nnet_7.3-21
#> [64] glue_1.8.1 nlme_3.1-172 promises_1.5.0
#> [67] grid_4.6.1 cluster_2.1.8.3 generics_0.1.4
#> [70] operator.tools_1.6.3.1 gtable_0.3.6 formula.tools_1.7.1
#> [73] tidyr_1.3.2 data.table_1.18.6.1 hms_1.1.4
#> [76] utf8_1.2.6 BiocGenerics_0.59.12 ggrepel_0.9.8
#> [79] foreach_1.5.2 pillar_1.11.1 limma_3.99.4
#> [82] later_1.4.8 circlize_0.4.18 splines_4.6.1
#> [85] lattice_0.23-1 survival_3.8-12 tidyselect_1.2.1
#> [88] ComplexHeatmap_2.29.0 knitr_1.52 reformulas_0.4.4
#> [91] gridExtra_2.3.1 bookdown_0.48 IRanges_2.47.5
#> [94] stats4_4.6.1 xfun_0.62 statmod_1.5.2
#> [97] matrixStats_1.5.0 stringi_1.8.9 yaml_2.3.12
#> [100] boot_1.3-32 evaluate_1.0.5 codetools_0.2-20
#> [103] Rfit_0.27.0 tibble_3.3.1 BiocManager_1.30.27
#> [106] cli_3.6.6 rpart_4.1.27 xtable_1.8-8
#> [109] Rdpack_2.6.6 jquerylib_0.1.4 dichromat_2.0-1
#> [112] Rcpp_1.1.2 coda_0.19-4.1 png_0.1-9
#> [115] parallel_4.6.1 prettyunits_1.2.0 lme4_2.1-0
#> [118] glmnet_5.2 viridisLite_0.4.3 limpa_1.5.2
#> [121] mvtnorm_1.4-2 lmerTest_3.2-1 scales_1.4.0
#> [124] purrr_1.2.2 crayon_1.5.3 GetoptLong_1.1.1
#> [127] rlang_1.3.0 multcomp_1.4-32 mice_3.19.0