Affichages de sortie Shiny : fonctions render et emplacements Output en R

Associez le bon render() à son Output(), câblez-le par outputId, et placez graphiques, texte, tableaux et interface dynamique sur la page.

Programming
Shiny

Chaque sortie Shiny est une paire : un render() dans le server qui construit le résultat et un Output() dans le ui qui l’affiche. Cette référence couvre renderPlot/plotOutput, renderText et renderPrint, renderTable et DT, renderImage, et renderUI — pour chacun le code, ce qu’il affiche, et quand l’utiliser — plus le contrat outputId qui relie les deux moitiés.

Date de publication

28 juin 2026

Modifié

7 juillet 2026

AstucePoints clés
  • Chaque sortie est une paire : un render*() dans le server construit le résultat, un *Output() dans le ui l’affiche, et un outputId partagé les relie.
  • Les deux moitiés doivent être de la même famille : renderPlot s’associe à plotOutput, renderTable à tableOutput, renderText à textOutput — mélangez les familles et vous obtenez un vide ou une erreur.
  • Le contrat, c’est output$<id> : un *Output("id") dans le ui est rempli par output$id <- renderX(...) dans le server. Même id des deux côtés.
  • Choisissez le render selon ce que vous affichez : un graphique → renderPlot ; une chaîne sur une ligne → renderText ; une sortie de type console comme summary()renderPrint ; un tableau statique → renderTable ; un tableau triable/cherchable → DT::renderDataTable ; des contrôles construits côté server → renderUI.
  • Les sorties sont réactives : placez un input$<id> à l’intérieur d’un render*() et il se redessine automatiquement chaque fois que cette entrée change — aucun code d’événement.

Introduction

Les entrées collectent ce que veut l’utilisateur ; les sorties lui montrent le résultat. Chaque graphique, tableau et ligne de texte dans une application Shiny est une sortie — et chacune comporte deux moitiés : une fonction render*() dans le server qui construit le contenu, et un emplacement *Output() dans le ui qui l’affiche.

C’est la référence à laquelle vous revenez. Chaque type de sortie que vous utiliserez est ici, groupé par ce qu’il affiche, et pour chacun vous obtenez trois choses : le code des deux moitiés, ce qu’il met sur la page, et quand l’utiliser. Vous avez déjà rencontré les entrées dans contrôles d’entrée — lues avec input$<id>. Les sorties sont l’image miroir : écrites avec output$<id>, et construites par un render*() qui correspond à l’emplacement.

NoteCopiez n’importe quel bloc et exécutez-le en local

Le code de cette page n’est pas exécuté ici — une application Shiny a besoin d’une session R active, elle ne peut donc pas tourner dans une page web statique. Copiez n’importe quel bloc dans un fichier app.R et exécutez-le en local avec shiny::runApp() (ou cliquez sur Run App dans RStudio). Chaque exemple montre les deux moitiés d’une sortie : déposez l’*Output() dans un ui fluidPage() et le output$<id> <- renderX(...) correspondant dans le server.

Le contrat outputId

Avant le catalogue, la règle unique qui relie toutes les sorties. Un *Output("id") dans le ui réserve un emplacement sur la page ; le server le remplit en affectant un render*() correspondant à output$id. La chaîne est la connexion — et les deux fonctions doivent être de la même famille.

# ui — reserve a plot-shaped spot called "dist"
plotOutput("dist")

# server — fill that spot with a plot
output$dist <- renderPlot({
  hist(faithful$waiting)
})

L’id "dist" dans plotOutput("dist") et output$dist dans le server sont le lien — exactement le miroir du côté entrée, où sliderInput("bins", …) se lit comme input$bins. L’id doit être unique dans toute l’application et être un nom R valide (lettres, chiffres, _, . — pas d’espaces, pas de tirets).

Deux règles en découlent, et ce sont elles qui causent la plupart des bugs « rien ne s’affiche » :

  • Les familles doivent correspondre. plotOutput est rempli par renderPlot, tableOutput par renderTable, textOutput par renderText. Un plotOutput("x") rempli avec renderText n’affiche rien.
  • Les sorties sont réactives. Référencez un input$<id> à l’intérieur du corps du render*() et Shiny réexécute cette sortie chaque fois que l’entrée change — vous n’écrivez jamais de gestionnaire de mise à jour. Voir programmation réactive pour comprendre le fonctionnement de ce graphe.

Graphiques

Pour les figures — base R ou ggplot2. renderPlot() exécute votre code de tracé et plotOutput() affiche le résultat sous forme d’image. C’est la pièce maîtresse de la plupart des applications de données.

# ui
plotOutput("scatter")

# server — any base-R or ggplot2 code that draws a plot
output$scatter <- renderPlot({
  plot(mtcars$wt, mtcars$mpg, xlab = "Weight", ylab = "MPG")
})

Cela fonctionne de la même façon avec ggplot2 — renvoyez l’objet graphique et Shiny le dessine.

output$gg <- renderPlot({
  library(ggplot2)
  ggplot(mtcars, aes(wt, mpg)) +
    geom_point() +
    theme_minimal()
})

Dimensionnez la figure du côté ui avec plotOutput("scatter", height = "400px", width = "100%"), et rendez-la réactive en lisant une entrée à l’intérieur du corps — geom_histogram(bins = input$bins) se redessine à mesure que le curseur bouge. Utilisez renderPlot/plotOutput pour tout graphique R statique ; pour un graphique pleinement interactif (zoom, survol) vous recourrez à un widget comme plotly (renderPlotly/plotlyOutput), qui suit exactement la même règle d’association.

Texte

Pour afficher une chaîne calculée. Il y a deux sorties texte, et celle que vous choisissez dépend de la nature du résultat : une phrase ou une sortie de console.

renderText() avec textOutput() affiche une chaîne calculée unique, rendue comme du texte de page ordinaire. Utilisez-le pour un court message, un effectif, une étiquette — tout ce que vous construiriez avec paste().

# ui
textOutput("msg")

# server
output$msg <- renderText({
  paste("The dataset has", nrow(mtcars), "rows.")
})

renderPrint() avec verbatimTextOutput() capture tout ce qui s’afficherait dans la console R — dans un bloc préformaté à largeur fixe. Utilisez-le quand la valeur est une sortie de console, pas une phrase : un summary() de modèle, un str(), un début de data frame, tout ce dont la mise en forme compte.

# ui
verbatimTextOutput("model")

# server
output$model <- renderPrint({
  summary(lm(mpg ~ wt, data = mtcars))   # multi-line console output, kept as-is
})

La règle empirique : renderText pour une chaîne que vous assemblez (il affiche la valeur) ; renderPrint pour une sortie de console que vous voulez préserver (il affiche ce que la console afficherait). Un summary() dans renderText se réduit à une ligne inutile ; dans renderPrint il conserve sa forme.

Tableaux

Pour des données tabulaires. Comme pour le texte, il y a deux voies — un simple tableau statique, ou un tableau pleinement interactif.

renderTable() avec tableOutput() rend un data frame sous forme de tableau HTML simple — pas de tri, pas de recherche, pas de pagination. Utilisez-le pour des résultats petits et fixes : un résumé, quelques lignes, une table de correspondance.

# ui
tableOutput("head")

# server
output$head <- renderTable({
  head(mtcars, 5)
}, striped = TRUE, hover = TRUE)

DT::renderDataTable() avec DT::DTOutput() rend un tableau interactif — colonnes triables, une barre de recherche, et la pagination — à partir du package DT. Préférez-le dès que le tableau dépasse quelques lignes, ou que l’utilisateur voudra trier, filtrer ou parcourir les données par pages.

# ui
DT::DTOutput("table")

# server
output$table <- DT::renderDataTable({
  mtcars
}, options = list(pageLength = 10))

Lequel préférer : recourez à renderTable pour un petit affichage en lecture seule où l’interactivité serait du bruit ; recourez à DT::renderDataTable dès que le jeu de données est assez grand pour que l’utilisateur ait besoin de chercher, trier ou paginer pour s’y retrouver. DT défile et pagine côté client, il reste donc réactif là où un renderTable de 1 000 lignes serait un mur de HTML inutilisable.

Images

renderImage() avec imageOutput() affiche un fichier image — un logo, une figure enregistrée, une image externe — plutôt qu’un graphique dessiné au moment du rendu. La fonction de rendu renvoie une list décrivant l’image : au minimum src (le chemin du fichier), plus optionnellement contentType, width, height et alt.

# ui
imageOutput("logo")

# server
output$logo <- renderImage({
  list(src = "www/logo.png", contentType = "image/png",
       width = 200, alt = "Company logo")
}, deleteFile = FALSE)

Utilisez renderImage pour des fichiers qui existent déjà (ou que vous générez vers un chemin temporaire) — c’est le bon outil quand la source est une image, pas du code de tracé R. Pour un graphique que vous dessinez en R, utilisez plutôt renderPlot/plotOutput ; cette voie n’a pas besoin de fichier.

Interface dynamique

renderUI() avec uiOutput() est la seule sortie qui construit de l’interface, pas des données. Le server renvoie des éléments d’interface Shiny — entrées, HTML, un panneau entier — et Shiny les insère dans la page à l’emplacement. C’est ainsi que vous créez des contrôles dont l’existence ou les options ne sont pas connues avant l’exécution.

# ui
uiOutput("controls")

# server — build a control list from data, after launch
output$controls <- renderUI({
  selectInput("col", "Column:", choices = names(mtcars))
})

Utilisez renderUI quand l’interface elle-même doit être calculée : une liste déroulante dont les choices proviennent d’un fichier téléversé, un ensemble de curseurs générés un par colonne, un panneau qui n’apparaît que lorsqu’une case est cochée. Pour un contrôle que vous connaissez au démarrage, déclarez-le directement dans le uirenderUI est pour les parties que vous ne pouvez pas écrire à l’avance.

NoterenderUI pour construire des contrôles, update*Input() pour les modifier

Si un widget existe déjà dans le ui et que vous avez seulement besoin de le modifier — recharger ses choices, réinitialiser sa valeur — utilisez l’update*Input(session, "id", …) correspondant (voir contrôles d’entrée). Utilisez renderUI seulement quand le contrôle doit être créé depuis le server, et non simplement mis à jour.

Quelle sortie pour quelle tâche

Une recherche rapide. Le render que vous choisissez découle de ce que vous mettez sur la page ; chacun s’associe à exactement une famille d’emplacements.

Vous voulez afficher… server render*() ui *Output() Ce qu’il affiche
Un graphique (base R / ggplot2) renderPlot() plotOutput() une figure dessinée
Une courte chaîne calculée renderText() textOutput() une ligne de texte de page
Une sortie de type console (summary(), str()) renderPrint() verbatimTextOutput() du texte de console préformaté
Un petit tableau statique renderTable() tableOutput() un tableau HTML simple
Un tableau triable / cherchable DT::renderDataTable() DT::DTOutput() un tableau interactif
Un fichier image renderImage() imageOutput() une image issue d’un fichier
Des contrôles / du HTML générés côté server renderUI() uiOutput() de l’interface construite à l’exécution

Le motif ne change jamais : déclarez l’emplacement dans le ui avec un id, remplissez-le dans le server avec output$id <- renderX(...), et gardez les deux dans la même famille.

Problèmes fréquents

La zone de sortie est vide ou génère une erreur. Presque toujours une non-concordance de famille : un plotOutput("x") rempli avec renderText, ou un tableOutput("y") rempli avec renderPlot. L’emplacement et le render doivent être de la même famille — plotOutput↔︎renderPlot, tableOutput↔︎renderTable, verbatimTextOutput↔︎renderPrint. Alignez-les et le contenu apparaît.

Rien ne s’affiche parce qu’il n’y a pas d’emplacement dans le ui. Affecter output$result <- renderPlot(…) dans le server ne fait rien à lui seul — le résultat n’a nulle part où aller tant que vous n’ajoutez pas le plotOutput("result") correspondant au ui. Chaque sortie du server a besoin de sa contrepartie *Output() sur la page.

Une faute de frappe dans l’outputId fait disparaître silencieusement la sortie. output$summry <- … dans le server et verbatimTextOutput("summary") dans le ui ne se connectent jamais — les ids ne correspondent pas, l’emplacement reste donc vide sans erreur. L’id doit être identique octet pour octet des deux côtés, casse comprise. Quand une sortie ne s’affiche pas, vérifiez d’abord l’orthographe de l’id sur les deux moitiés.

Questions fréquentes

Utilisez la paire renderPlot/plotOutput. Mettez plotOutput("myplot") dans le ui pour réserver l’emplacement, puis output$myplot <- renderPlot({ ... }) dans le server pour le dessiner. Tout code base R ou ggplot2 dans le corps fonctionne ; référencez un input$<id> à l’intérieur et le graphique se redessine automatiquement quand cette entrée change.

renderText() affiche une chaîne calculée unique comme du texte ordinaire — utilisez-le pour un message ou un effectif que vous construisez avec paste(). renderPrint() affiche tout ce qui s’afficherait dans la console R, dans un bloc préformaté — utilisez-le pour un summary() de modèle, un str(), ou toute sortie dont la mise en forme compte. Ils s’associent à textOutput() et verbatimTextOutput() respectivement.

Utilisez le package DT : DT::DTOutput("table") dans le ui et output$table <- DT::renderDataTable({ df }) dans le server. Cela donne des colonnes triables, une barre de recherche et la pagination d’emblée. Le simple renderTable/tableOutput ne donne qu’un tableau HTML statique — préférez DT dès que les données sont assez volumineuses pour que les utilisateurs aient besoin de trier, filtrer ou parcourir par pages.

Trois causes habituelles. (1) Le render*() et le *Output() ne sont pas de la même famille — un plotOutput rempli avec renderText n’affiche rien. (2) Il n’y a pas d’emplacement *Output() dans le ui pour la sortie du server. (3) L’outputId est mal orthographié, les deux moitiés ne se connectent donc pas. Vérifiez la concordance de famille, la présence de l’emplacement, et l’orthographe de l’id des deux côtés.

Utilisez renderUI/uiOutput. Mettez uiOutput("controls") dans le ui, puis renvoyez de l’interface Shiny depuis le server : output$controls <- renderUI({ selectInput("col", "Column:", choices = names(df())) }). C’est pour des contrôles que vous devez construire à l’exécution ; pour seulement changer les choix ou la valeur d’un widget existant, utilisez l’ update*Input() correspondant à la place.

Testez vos connaissances

Vous construisez un panneau de résultats. Ajoutez trois sorties et remplissez chacune dans le server : un nuage de points de mtcars$wt contre mtcars$mpg, un résumé texte sur une ligne donnant le nombre de lignes, et un tableau interactif de mtcars. Nommez les ids "scatter", "summary" et "table", et associez chaque emplacement à la bonne fonction de rendu.

Une figure dessinée → plotOutput("scatter") + renderPlot. Une courte chaîne calculée → textOutput("summary") + renderText avec paste(). Un tableau triable et cherchable → DT::DTOutput("table") + DT::renderDataTable. Chaque emplacement va dans le ui ; chaque output$<id> <- renderX(...) va dans le server, même id des deux côtés.

# ui
mainPanel(
  plotOutput("scatter"),
  textOutput("summary"),
  DT::DTOutput("table")
)

# server
output$scatter <- renderPlot({
  plot(mtcars$wt, mtcars$mpg, xlab = "Weight", ylab = "MPG")
})

output$summary <- renderText({
  paste("The dataset has", nrow(mtcars), "rows.")
})

output$table <- DT::renderDataTable({
  mtcars
})

L’id de chaque sortie relie les deux moitiés, et chaque render correspond à la famille de son emplacement : un graphique à plotOutput, une chaîne à textOutput, un tableau interactif à DT::DTOutput.

Dans le server vous écrivez output$report <- renderPrint({ summary(mtcars) }). Quel emplacement du ui fait s’afficher correctement le résumé du modèle ?

A. textOutput("report") — c’est du texte, après tout. B. verbatimTextOutput("report")renderPrint s’associe à une sortie verbatim. C. tableOutput("report")summary() renvoie un tableau. D. plotOutput("report") — pour l’afficher comme une figure.

B. renderPrint capture la sortie de console et doit s’associer à verbatimTextOutput, qui conserve la mise en forme préformatée à largeur fixe. A (textOutput) est la mauvaise famille — il attend une chaîne unique de renderText et mutilerait le résumé multiligne. C et D sont des familles entièrement différentes ; une non-concordance de famille n’affiche rien.

Conclusion

Vous disposez désormais de la boîte à outils de sortie complète : graphiques (renderPlot/plotOutput), texte (renderText/textOutput pour une chaîne, renderPrint/verbatimTextOutput pour une sortie de console), tableaux (renderTable/tableOutput pour le statique, DT::renderDataTable/DT::DTOutput pour l’interactif), images (renderImage/imageOutput), et interface dynamique (renderUI/uiOutput). Chacune suit le même contrat — réservez un emplacement avec *Output("id"), remplissez-le avec output$id <- renderX(...), gardez les deux dans la même famille — et chacune est réactive, se redessinant d’elle-même quand les entrées qu’elle lit changent.

Les entrées collectant les choix et les sorties affichant les résultats, la pièce restante est leur agencement sur la page — les mises en page qui réunissent vos widgets et vos affichages.

Leçons connexes

Cette page vous a-t-elle été utile ?

Recevez les nouvelles leçons R & Python par e-mail

Pratique, reproductible, sans spam. Désinscription à tout moment.

Double opt-in. Nous ne partageons jamais votre e-mail.

Partager cette pageXLinkedInRedditHN

Réutilisation

Citation

BibTeX
@online{2026,
  author = {},
  title = {Affichages de sortie Shiny : fonctions render et emplacements
    Output en R},
  date = {2026-06-28},
  url = {https://www.datanovia.com/learn/programming/shiny/ui/output-displays},
  langid = {fr}
}
Veuillez citer ce travail comme suit :
“Affichages de sortie Shiny : fonctions render et emplacements Output en R.” 2026. June 28. https://www.datanovia.com/learn/programming/shiny/ui/output-displays.