From bcec64ff89b28d9137531c7df5210a43a32fbe52 Mon Sep 17 00:00:00 2001 From: Cesaire Joris Kuete Fouodo Date: Wed, 17 Jul 2024 14:49:49 +0200 Subject: [PATCH] Add Rmd --- .Rbuildignore | 1 + README.Rmd | 28 ++++ README.md | 197 +++++-------------------- README_files/figure-gfm/pressure-1.png | Bin 0 -> 22985 bytes 4 files changed, 67 insertions(+), 159 deletions(-) create mode 100644 README.Rmd create mode 100644 README_files/figure-gfm/pressure-1.png diff --git a/.Rbuildignore b/.Rbuildignore index f42871e..8938d6b 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -2,3 +2,4 @@ ^\.Rproj\.user$ ^.*test_code* ^\.github$ +^\.README_files* diff --git a/README.Rmd b/README.Rmd new file mode 100644 index 0000000..02ef439 --- /dev/null +++ b/README.Rmd @@ -0,0 +1,28 @@ +--- +title: "fuseMLR" +author: Cesaire J. K. Fouodo +output: + md_document: + variant: gfm + preserve_yaml: true +--- + +```{r setup, include=FALSE} +knitr::opts_chunk$set(echo = TRUE) +``` + + + [![R-CMD-check](https://github.com/imbs-hl/fuseMLR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/imbs-hl/fuseMLR/actions/workflows/R-CMD-check.yaml) + [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) + [![CRAN downloads](http://www.r-pkg.org/badges/version/fuseMLR)](http://cranlogs.r-pkg.org/badges/grand-total/fuseMLR) + [![Stack Overflow](https://img.shields.io/badge/stackoverflow-questions-orange.svg)](https://stackoverflow.com/questions/tagged/fuseMLR) + + +### fuseMLR +Cesaire J. K. Fouodo + +### Introduction +Recent technological advances have enabled the simultaneous targeting of multiple pathways to enhance therapies for complex diseases. This often results in the collection of numerous data entities across various layers of patient groups, posing a challenge for integrating all data into a single analysis. Ideally, patient data will overlap across layers, allowing for early or intermediate integrative techniques. However, these techniques are challenging when patient data does not overlap well. Additionally, the internal structure of each data entity may necessitate specific statistical methods rather than applying the same method across all layers. Late integration modeling addresses this by analyzing each data entity separately to obtain layer-specific results, which are then integrated using meta-analysis. Currently, no R package offers this flexibility. + +We introduce the fuseMLR package for late integration modeling in R. This package allows users to define studies with multiple layers, data entities, and layer-specific machine learning methods. FuseMLR is user-friendly, enabling the training of different models across layers and automatically conducting meta-analysis once layer-specific training is completed. Additionally, fuseMLR allows for variable selection at the layer level and makes predictions for new data entities. + diff --git a/README.md b/README.md index 35da2e4..ffa54e4 100644 --- a/README.md +++ b/README.md @@ -1,171 +1,50 @@ - - [![R-CMD-check](https://github.com/imbs-hl/fuseMLR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/imbs-hl/fuseMLR/actions/workflows/R-CMD-check.yaml) - [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) - [![CRAN downloads](http://www.r-pkg.org/badges/version/fuseMLR)](http://cranlogs.r-pkg.org/badges/grand-total/fuseMLR) - [![Stack Overflow](https://img.shields.io/badge/stackoverflow-questions-orange.svg)](https://stackoverflow.com/questions/tagged/fuseMLR) - - -### fuseMLR -Cesaire J. K. Fouodo - -### Introduction -Recent technological advances have enabled the simultaneous targeting of multiple pathways to enhance therapies for complex diseases. This often results in the collection of numerous data entities across various layers of patient groups, posing a challenge for integrating all data into a single analysis. Ideally, patient data will overlap across layers, allowing for early or intermediate integrative techniques. However, these techniques are challenging when patient data does not overlap well. Additionally, the internal structure of each data entity may necessitate specific statistical methods rather than applying the same method across all layers. Late integration modeling addresses this by analyzing each data entity separately to obtain layer-specific results, which are then integrated using meta-analysis. Currently, no R package offers this flexibility. - -We introduce the fuseMLR package for late integration modeling in R. This package allows users to define studies with multiple layers, data entities, and layer-specific machine learning methods. FuseMLR is user-friendly, enabling the training of different models across layers and automatically conducting meta-analysis once layer-specific training is completed. Additionally, fuseMLR allows for variable selection at the layer level and makes predictions for new data entities. - -### Installation -Installation from Github: -```R -devtools::install_github("imbs-hl/fuseMLR") -``` - -### Usage -For usage in R, see ?fuseMLR in R. Most importantly, see the Examples section. - -The provided example, utilizing simulated data, mirrors a common scenario in multi-omics analysis. It involves data collected from three distinct layers (methylation, gene expression, and protein expression), with disease status serving as the response variable. Initially, the data entities are consolidated into a single object. Subsequently, the learner arguments (such as ```ranger```) and feature selection parameters for each entity are specified. Following model training for both the entity-level models and the meta-learner, predictions can be generated for new datasets. - -### Load data -```R -data("entities") -``` - -### Training - -#### Training study -```R -train_study <- TrainStudy$new(id = "train_study", - ind_col = "IDS", - target = "disease") -``` - -#### Training layers -```R -tl_geneexpr <- TrainLayer$new(id = "geneexpr", train_study = train_study) -tl_proteinexpr <- TrainLayer$new(id = "proteinexpr", train_study = train_study) -tl_methylation <- TrainLayer$new(id = "methylation", train_study = train_study) -tl_meta_layer <- TrainMetaLayer$new(id = "meta_layer", train_study = train_study) -``` - -#### Training data -```R -train_data_geneexpr <- TrainData$new(id = "geneexpr", - train_layer = tl_geneexpr, - data_frame = entities$training$geneexpr) -train_data_proteinexpr <- TrainData$new(id = "proteinexpr", - train_layer = tl_proteinexpr, - data_frame = entities$training$proteinexpr) -train_data_methylation <- TrainData$new(id = "methylation", - train_layer = tl_methylation, - data_frame = entities$training$methylation) +--- +title: "fuseMLR" +author: Cesaire J. K. Fouodo +output: + md_document: + variant: gfm + preserve_yaml: true +--- -# Upset plot of the study -train_study$upset(order.by = "freq") -``` - -#### Variable selection -```R -same_param_varsel <- ParamVarSel$new(id = "ParamVarSel", - param_list = list(num.trees = 1000, mtry = 3)) - -varsel_geneexpr <- VarSel$new(id = "varsel_geneexpr", - package = "Boruta", - varsel_fct = "Boruta", - param = same_param_varsel, - train_layer = tl_geneexpr) - -varsel_proteinexpr <- VarSel$new(id = "varsel_geneexpr", - package = "Boruta", - varsel_fct = "Boruta", - param = same_param_varsel, - train_layer = tl_proteinexpr) - -varsel_methylation <- VarSel$new(id = "varsel_geneexpr", - package = "Boruta", - varsel_fct = "Boruta", - param = same_param_varsel, - train_layer = tl_methylation) - -# Perform variable selection on the entire study -var_sel_res <- train_study$varSelection() -``` - -#### Learner parameters. Same parameter values at each layer. -```R -same_param <- ParamLrner$new(id = "ParamRanger", - param_list = list(probability = TRUE, - mtry = 1), - hyperparam_list = list(num.trees = 1000)) -``` - -#### Learner - -```R -lrner_geneexpr <- Lrner$new(id = "ranger", - package = "ranger", - lrn_fct = "ranger", - param = same_param, - train_layer = tl_geneexpr) -lrner_proteinexpr <- Lrner$new(id = "ranger", - package = "ranger", - lrn_fct = "ranger", - param = same_param, - train_layer = tl_proteinexpr) -lrner_methylation <- Lrner$new(id = "ranger", - package = "ranger", - lrn_fct = "ranger", - param = same_param, - train_layer = tl_methylation) -lrner_meta <- Lrner$new(id = "weighted", - lrn_fct = "weightedMeanLearner", - param = ParamLrner$new(id = "ParamWeighted", - param_list = list(), - hyperparam_list = list()), - train_layer = tl_meta_layer) - -``` - -#### Train the all study using corss-validation. + -```R -trained_study <- train_study$train(resampling_method = "caret::createFolds", - resampling_arg = list(y=train_study$getTargetValues()$disease, - k = 2), - use_var_sel = TRUE) -``` +[![R-CMD-check](https://github.com/imbs-hl/fuseMLR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/imbs-hl/fuseMLR/actions/workflows/R-CMD-check.yaml) +[![Lifecycle: +experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) +[![CRAN +downloads](http://www.r-pkg.org/badges/version/fuseMLR)](http://cranlogs.r-pkg.org/badges/grand-total/fuseMLR) +[![Stack +Overflow](https://img.shields.io/badge/stackoverflow-questions-orange.svg)](https://stackoverflow.com/questions/tagged/fuseMLR) + -### Predicting +## R Markdown -#### Create and predict a new study +This is an R Markdown document. Markdown is a simple formatting syntax +for authoring HTML, PDF, and MS Word documents. For more details on +using R Markdown see . -#### Create a new study +When you click the **Knit** button a document will be generated that +includes both content as well as the output of any embedded R code +chunks within the document. You can embed an R code chunk like this: -```R -new_study <- NewStudy$new(id = "new_study", ind_col = "IDS") +``` r +summary(cars) ``` -```R -# A meta_layer is not required -new_geneexpr <- NewLayer$new(id = "geneexpr", new_study = new_study) -new_proteinexpr <- NewLayer$new(id = "proteinexpr", new_study = new_study) -new_methylation <- NewLayer$new(id = "methylation", new_study = new_study) -``` + ## speed dist + ## Min. : 4.0 Min. : 2.00 + ## 1st Qu.:12.0 1st Qu.: 26.00 + ## Median :15.0 Median : 36.00 + ## Mean :15.4 Mean : 42.98 + ## 3rd Qu.:19.0 3rd Qu.: 56.00 + ## Max. :25.0 Max. :120.00 -#### NewData are mandatory at each layers +## Including Plots -```R -new_data_geneexpr <- NewData$new(id = "geneexpr", - new_layer = new_geneexpr, - data_frame = entities$testing$geneexpr) -new_data_proteinexpr <- NewData$new(id = "proteinexpr", - new_layer = new_proteinexpr, - data_frame = entities$testing$proteinexpr) -new_data_methylation <- NewData$new(id = "methylation", - new_layer = new_methylation, - data_frame = entities$testing$methylation) +You can also embed plots, for example: -``` +![](README_files/figure-gfm/pressure-1.png) -#### Predicting the new study -```R -tmp_red_study <- study$predict(new_study = new_study) -``` +Note that the `echo = FALSE` parameter was added to the code chunk to +prevent printing of the R code that generated the plot. diff --git a/README_files/figure-gfm/pressure-1.png b/README_files/figure-gfm/pressure-1.png new file mode 100644 index 0000000000000000000000000000000000000000..7bc4c8f7db547c559fb01ef2a8848679c60e06a8 GIT binary patch literal 22985 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 literal 0 HcmV?d00001