Console

Utiliser la console R ou Python dans LinkR

Introduction

Nous avons vu comment créer un projet en utilisant des plugins pour créer des widgets.

Ces widgets comprennent toujours un onglet pour afficher ou manipuler les données via une interface graphique, et un onglet pour modifier le code à l’origine du résultat affiché.

Modifier le code via l’éditeur des widgets peut permettre d’aller un peu plus loin que ce qui est proposé par l’interface graphique, mais dès lors que l’on veut afficher les données sous une forme différente (un tableau de données plutôt qu’une figure ggplot2 par exemple), nous sommes limités.

Pour cela, il existe deux solutions :

  • Utiliser le plugin Console, qui est un plugin générique permettant d’afficher les données sous le format demandé, par exemple un tableau de données, une figure Plotly ou même une interface web générée avec Shiny
  • Utiliser la page Console, qui est d’accès plus rapide et permet de tester des portions de code facilement avec les données chargées

Plugin Console

Si vous n’avez pas ce plugin, téléchargez le plugin depuis le catalogue de contenus d’InterHop.

Créez un widget avec le plugin Console où vous le souhaitez, dans un onglet sur la page des données individuelles ou des données agrégées.

Inutile de sélectionner des concepts, ce plugin ne les utilise pas.

Une fois le widget créé, il fonctionne de la même façon que les autres widgets, tel que détaillé dans Créer un projet > Créer des onglets et des widgets.

Dans la partie “Paramètres de la figure”, sélectionnez le langage et l’output.

Par exemple, pour le langage R, les outputs suivants sont disponibles :

  • Console : le résultat affiché sera celui qui serait affiché dans la console R
  • UI (HTML) : le résultat sera affiché dans un uiOutput de Shiny
  • Figure : correspond à un figureOutput de Shiny
  • Table : correspond à un tableOutput de Shiny
  • DataTable : correspond à un DT::DTOutput de DT et Shiny
  • RMarkdown : correspond à l’HTML sortant de la conversion du fichier RMarkdown présenté dans la console

Vous pouvez différents fichiers de sauvegardes, qui correspondront à différents scripts.

Ainsi, le plugin Console peut être utilisé par tout ce que les plugins ne peuvent pas (encore !) afficher.

Souvent, répondre à une problématique avec le plugin Console est la première étape de la création d’un plugin.

Voici un exemple de l’utilisation du plugin “Console” pour la création d’un histogramme affichant l’âge des patients du set de données associé au projet.

Voici le code utilisé si vous souhaitez le tester :

d$visit_occurrence %>%
    dplyr::left_join(
        d$person %>% dplyr::select(person_id, birth_datetime),
        by = "person_id"
    ) %>%
    dplyr::collect() %>%
    dplyr::mutate(
        age = round(
            as.numeric(
                difftime(visit_start_datetime, birth_datetime, units = "days")
            ) / 365.25, 1
        )
    ) %>%
    ggplot2::ggplot(ggplot2::aes(x = age)) +
    ggplot2::geom_histogram(binwidth = 5, fill = "#0084D8", color = "white") +
    ggplot2::labs(
        x = "Age (années)",
        y = "Fréquence"
      ) +
    ggplot2::theme_minimal() +
    ggplot2::theme(
        plot.title = ggplot2::element_text(size = 16, face = "bold"),
        axis.title = ggplot2::element_text(size = 14)
    )

Page Console

La page Console est accessible depuis n’importe quelle page de l’application, en cliquant sur l’icône correspondante en haut de l’écran.

De la même façon que pour le plugin Console, vous pouvez choisir le langage de programmation et l’output.

En plus de pouvoir utiliser R et Python, le Shell est accessible ici, permettant par exemple d’afficher les fichiers et dossiers avec ls, ce qui est utile dans le cas d’un container Docker.

Cette console permet également d’aider dans la programmation de LinkR, en rendant les différentes variables de fonctionnement de l’application disponibles. Ces variables sont préfixées par r$.

Par exemple, r$users permet d’afficher la variable contenant les utilisateurs.

L’accès à cette console peut être restreint depuis la page de gestion des utilisateurs.

L’accès aux variables r$... n’est pas disponible depuis le plugin Console.

Que ce soit dans le plugin Console ou sur la page Console, des raccourcis sont disponibles :

  • Ctrl|CMD + Shift + C : commente ou décommente le code sélectionné
  • Ctrl/CMD + Enter : exécute le code sélectionné (exécute tout le code si rien n’est sélectionné)
  • Ctrl/CMD + Shift + Enter : exécute tout le code

Variables des données

L’intérêt principal de cette console, que ce soit via le plugin Console ou via la page Console, réside dans le fait de pouvoir manipuler les tables OMOP depuis un set de données.

Pour charger des données, vous pouvez :

  • soit les charger depuis la page “Set de données”, en sélectionnant un set, puis en allant dans l’onglet “Code” et en cliquant sur “Exécuter le code”
  • soit en chargeant un projet associé à un set de données

Une fois les données chargées, elles deviennent accessibles via les variables préfixées par d$ (d pour data).

Toutes les tables OMOP sont disponibles via ces variables.

Comme vous pouvez le voir ici, toutes les tables sont chargées en lazy (d’où les points d’interrogations à la place du nombre de lignes du dataframe), ce qui signifie qu’elles ne sont pas chargées en mémoire.

Ceci permet d’économiser des ressources, de filtrer les donneés avant de les charger en mémoire, avec dplyr::collect().

Dans l’exemple suivant, nous filtrons les données de la table Measurement pour le patient 13589912, avant de collecter les données en mémoire.

Les tables disponibles dans d$ sont les tables complètes, comprenant toutes les données du set de données chargé.

Des sous-ensembles de ces données existent, en fonction des éléments sélectionnés :

  • d$data_subset : comprend tous les tables des patients du subset sélectionné
  • d$data_person : comprend les données du patient sélectionné
  • d$data_visit_detail : comprend les données du séjour sélectionné

Chacune de ces variables comprendra les tables OMOP, sous la forme d$data_person$measurement par exemple, sauf pour les tables pour lesquelles cela n’aurait pas de sens (il n’existe pas de table d$data_person$person, étant donné que la table d$person recense les patients).

Par exemple, si dans le projet actuellement ouvert, j’ai sélectionné le même patient que précédemment (13589912), j’obtiendrai avec d$data_person$measurement les mêmes données que précédemment, lorsque j’ai filtré la variable globale d$measurement sur ce patient.

Pour obtenir les éléments sélectionnés, je peux utiliser les variables préfixées par m$ :

  • m$selected_subset : subset actuellement sélectionné
  • m$selected_person : patient sélectionné
  • m$selected_visit_detail : séjour sélectionné

Les concepts des terminologies OMOP sont disponibles dans la variable d$concept.

Vous pouvez utiliser la fonction join_concepts pour faciliter les jointures entre les variables.

d$measurement %>%
    dplyr::filter(person_id == 13589912) %>%
    join_concepts(d$concept, c(
        "measurement", "measurement_type",
        "operator", "unit"
    )) %>%
    dplyr::select(
        person_id,
        measurement_concept_id, measurement_concept_name,
        value_as_number, unit_concept_name
    ) %>%
    dplyr::collect()

Vous pouvez retrouver les requêtes OMOP usuelles dans ce tutoriel.

Requêtes SQL

Par souci d’interopérabilité, il est nécessaire de pouvoir requêter les tables OMOP en SQL.

Lorsque vous importez des données dans LinkR, il s’agit toujours d’une connexion à une base de donnnées.

En effet, soit vous utilisez la valeur “db” pour l’argument data_source, dans ce cas vous renseignez l’objet con qui est directement l’objet de connexion à la base de données OMOP, soit vous utilisez la valeur “disk” pour l’argument data_source, et à ce moment-là, que vos données soient au format Parquet ou CSV, elles sont chargées en créant une base de données DuckDB.

Ainsi, dès que des données sont chargées dans LinkR, un objet de connexion d$con est créé, vous permettant de requêter vos données en SQL.

Ce code vous permet donc d’afficher toutes les données de la table patient :

DBI::dbGetQuery(d$con, "SELECT * FROM person") %>% tibble::as_tibble()

Vous pouvez également utiliser les requêtes SQL du tutoriel requêtes OMOP usuelles.

Cette requête, extraite de ce tutoriel, vous permet d’obtenir l’âge des patients :

sql <- "
    SELECT 
        v.visit_occurrence_id,
        v.person_id,
        ROUND(
            EXTRACT(EPOCH FROM (
                CAST(v.visit_start_datetime AS TIMESTAMP) - 
                CAST(p.birth_datetime AS TIMESTAMP)
            )) / (365.25 * 86400), 
            1
        ) AS age
    FROM 
        visit_occurrence v
    LEFT JOIN 
        (SELECT person_id, birth_datetime FROM person) p
    ON 
        v.person_id = p.person_id;
"

DBI::dbGetQuery(d$con, sql) %>% tibble::as_tibble()

Jointure avec la table CONCEPT

Il n'est actuellement pas possible de réaliser des jointures en SQL, les concepts se trouvant dans une base de données différente de celle des données.
Ceci sera résolu dès que possible, en ajoutant une table CONCEPT à la base de données chargée, contenant uniquement les concepts utilisés par le set de données chargé (#135).

Dernière modification 05.01.2025: Update EN console doc (#11) (9b5b2ed)