Exporting texts and datatable from shiny to pdf

笑着哭i 提交于 2019-12-11 16:59:16

问题


I am trying to write an app for work to allow some simple advice for patients on certain drugs to be presented in a datatable format, with the option to add some additional text. I've looked around to see if there is some way of exporting the the text and datatable to a pdf so that we can print it out but have not been successful so far. This is the code for the app:

library(tidyverse)
library(shiny)
library(shinythemes)
library(xtable)


insulin <- readRDS("insulin.rda")

# User Interface

ui <- fluidPage(

  titlePanel("Pre-operative Advice on Insulin - For Patients with Diabetes Undergoing Elective Surgery v0.1"),

  p("Please refer to Guideline on Shared Drive or Intranet for full guidance"),

  sidebarLayout(
    sidebarPanel(
      p("Patient Name and Date of Birth (Optional)"),

      textInput("px_name", label = "Patient Name", placeholder = "Patient Name"),
      textInput("dob", label = "Date of Birth or CHI", placeholder = "Date of Birth or CHI"),

      selectInput("DM", "What type of diabetes does patient have?",
                  c("Type One" = "Type 1",
                    "Type Two on Insulin" = "Type 2"),
                  selected = "Type One"),

      selectInput("time", "Is patient on morning or afternoon list?",
                  c("Morning List" = "AM",
                    "Afternoon List" = "PM"),
                  selected = "Morning"),

      checkboxGroupInput("class", "Which type(s) of insulin is patient on?",
                         c("Long and Intermediate acting",
                           "Pre-Mixed",
                           "Rapid or Short acting"))

      ),

    mainPanel(
      uiOutput("insulin_sel"),

      h3(textOutput(outputId = "px_name")),

      br(),

      h4(textOutput(outputId = "dob")),

      br(),

      tableOutput("table"),




    )
  )
)

server <- function(input, output){
  output$px_name <- renderText({input$px_name})

  output$dob <- renderText({input$dob})


  output$insulin_sel <- renderUI({

    insulin_subset <- insulin %>% filter(DM == input$DM, 
                                         Time == input$time, 
                                         Class %in% input$class)

    selectizeInput("name", "Type in name of insulin",
                   choices = list("Type in insulin name" = "", 
                                  "Names" = insulin_subset$Name), 
                                  selected = NULL, 
                                  multiple = TRUE,
                                  options = NULL)
  })

  output$table <- renderTable({

    insulin_subset <- insulin %>% filter(DM == input$DM, 
                                         Time == input$time, 
                                         Class %in% input$class)

    tab <- insulin_subset %>% filter(Name %in% input$name)

    xtable(tab)

  })



}

shinyApp(ui = ui, server = server)

This is part of the instructions:

> dput(insulin)
structure(list(DM = c("Type 2", "Type 2", "Type 2", "Type 2", 
"Type 2", "Type 2", "Type 2", "Type 2", "Type 2", "Type 2", "Type 2", 
"Type 2", "Type 2", "Type 2", "Type 1", "Type 1", "Type 1", "Type 1", 
"Type 1", "Type 1", "Type 1", "Type 1", "Type 1", "Type 1", "Type 1", 
"Type 1", "Type 1", "Type 1", "Type 2", "Type 2", "Type 2", "Type 2", 
"Type 2", "Type 2", "Type 2", "Type 2", "Type 1", "Type 1", "Type 1", 
"Type 1", "Type 1", "Type 1", "Type 1", "Type 1", "Type 2", "Type 2", 
"Type 2", "Type 2", "Type 2", "Type 2", "Type 2", "Type 2", "Type 2", 
"Type 2", "Type 1", "Type 1", "Type 1", "Type 1", "Type 1", "Type 1", 
"Type 1", "Type 1", "Type 1", "Type 1"), Time = c("AM", "AM", 
"AM", "AM", "AM", "AM", "AM", "PM", "PM", "PM", "PM", "PM", "PM", 
"PM", "AM", "AM", "AM", "AM", "AM", "AM", "AM", "PM", "PM", "PM", 
"PM", "PM", "PM", "PM", "AM", "AM", "AM", "AM", "PM", "PM", "PM", 
"PM", "AM", "AM", "AM", "AM", "PM", "PM", "PM", "PM", "AM", "AM", 
"AM", "AM", "AM", "PM", "PM", "PM", "PM", "PM", "AM", "AM", "AM", 
"AM", "AM", "PM", "PM", "PM", "PM", "PM"), Class = c("Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Long and Intermediate acting", 
"Long and Intermediate acting", "Pre-Mixed", "Pre-Mixed", "Pre-Mixed", 
"Pre-Mixed", "Pre-Mixed", "Pre-Mixed", "Pre-Mixed", "Pre-Mixed", 
"Pre-Mixed", "Pre-Mixed", "Pre-Mixed", "Pre-Mixed", "Pre-Mixed", 
"Pre-Mixed", "Pre-Mixed", "Pre-Mixed", "Rapid or Short acting", 
"Rapid or Short acting", "Rapid or Short acting", "Rapid or Short acting", 
"Rapid or Short acting", "Rapid or Short acting", "Rapid or Short acting", 
"Rapid or Short acting", "Rapid or Short acting", "Rapid or Short acting", 
"Rapid or Short acting", "Rapid or Short acting", "Rapid or Short acting", 
"Rapid or Short acting", "Rapid or Short acting", "Rapid or Short acting", 
"Rapid or Short acting", "Rapid or Short acting", "Rapid or Short acting", 
"Rapid or Short acting"), Name = c("Abasaglar", "Lantus", "Levemir", 
"Toujeo", "Tresiba", "Insulatard", "Humulin I", "Abasaglar", 
"Lantus", "Levemir", "Toujeo", "Tresiba", "Insulatard", "Humulin I", 
"Abasaglar", "Lantus", "Levemir", "Toujeo", "Tresiba", "Insulatard", 
"Humulin I", "Abasaglar", "Lantus", "Levemir", "Toujeo", "Tresiba", 
"Insulatard", "Humulin I", "Humulin M3", "Novomix 30", "Insuman Comb 15/25/50", 
"Humalog Mix 25/50", "Humulin M3", "Novomix 30", "Insuman Comb 15/25/50", 
"Humalog Mix 25/50", "Humulin M3", "Novomix 30", "Insuman Comb 15/25/50", 
"Humalog Mix 25/50", "Humulin M3", "Novomix 30", "Insuman Comb 15/25/50", 
"Humalog Mix 25/50", "Novorapid/Fiasp", "Humalog", "Apidra", 
"Humulin S", "Actrapid", "Novorapid/Fiasp", "Humalog", "Apidra", 
"Humulin S", "Actrapid", "Novorapid/Fiasp", "Humalog", "Apidra", 
"Humulin S", "Actrapid", "Novorapid/Fiasp", "Humalog", "Apidra", 
"Humulin S", "Actrapid"), Plan = c("Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Usual dose at usual time", "Usual dose at usual time", "Usual dose at usual time", 
"Half usual morning dose taken with a sugary drink at 7am", "Half usual morning dose taken with a sugary drink at 7am", 
"Half usual morning dose taken with a sugary drink at 7am", "Half usual morning dose taken with a sugary drink at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a sugary drink at 7am", "Half usual morning dose taken with a sugary drink at 7am", 
"Half usual morning dose taken with a sugary drink at 7am", "Half usual morning dose taken with a sugary drink at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Omit breakfast dose", "Omit breakfast dose", "Omit breakfast dose", 
"Omit breakfast dose", "Omit breakfast dose", "Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Half usual morning dose taken with a light breakfast at 7am", 
"Omit breakfast dose", "Omit breakfast dose", "Omit breakfast dose", 
"Omit breakfast dose", "Omit breakfast dose", "Usual morning dose taken with a light breakfast at 7am, oral fluids until 11am, omit lunchtime dose", 
"Usual morning dose taken with a light breakfast at 7am, oral fluids until 11am, omit lunchtime dose", 
"Usual morning dose taken with a light breakfast at 7am, oral fluids until 11am, omit lunchtime dose", 
"Usual morning dose taken with a light breakfast at 7am, oral fluids until 11am, omit lunchtime dose", 
"Usual morning dose taken with a light breakfast at 7am, oral fluids until 11am, omit lunchtime dose"
)), row.names = c(NA, -64L), class = c("tbl_df", "tbl", "data.frame"
))

I've tried the method described here. I pasted the code from the link directly but seem to be getting nowhere with the following error:

Warning in normalizePath(path.expand(path), winslash, mustWork) :
  path[1]="report.Rmd": The system cannot find the file specified
Warning in normalizePath(path.expand(path), winslash, mustWork) :
  path[1]="report.Rmd": The system cannot find the file specified
Warning: Error in abs_path: The file 'report.Rmd' does not exist.
  [No stack trace available]

At this point, even if I could just export the DT to a pdf would be useful.

Edit: For the query about displaying an output object. Code on server side:

my_ortho_table <- reactive({
    ortho_table <- drugsUI %>%
      filter(Ortho == "yes") %>%
      select(Name, Recommendations)
    return(ortho_table)
  })  

  observeEvent(input$ortho, {
    if(input$ortho == "yes"){
      output$ortho_tab <- renderTable({
        xtable(my_ortho_table())})
      output$ortho_text <- renderText("Additional information for patients undergoing hip and knee replacement or revision,
                                      if taking the following medications")
    }else{
      output$ortho_tab <- NULL
      output$ortho_text <- NULL
    }

On the ui side:

textOutput("ortho_text"),
tableOutput("ortho_tab"),

It is the ortho_text I would like to display (or not, depending on the input) in the pdf.

Further Edit: This is what I tried

my_ortho_table <- reactive({
    ortho_table <- drugsUI %>%
      filter(Ortho == "yes") %>%
      select(Name, Recommendations)


    if(input$ortho == "yes"){
      output$ortho_tab <- renderTable({
        xtable(ortho_table)})

    }else{
      output$ortho_tab <- NULL
      }
  })  

  my_ortho_text <- reactive({
    if(input$ortho == "yes"){

      output$ortho_text <- renderText("Additional information for patients undergoing hip and knee replacement or revision,
                                      if taking the following medications")
    }else{

      output$ortho_text <- NULL
    }

  })

with the corresponding output:

output$ortho_table <- my_ortho_table()


output$ortho_text <- my_ortho_text()

but got the following error:

Error in .getReactiveEnvironment()$currentContext() : 
  Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

回答1:


It sounds like you don't have a report.Rmd file already created in R Markdown (or it couldn't find the file).

Below is code that should generate a report. The first part is updated ui and server code. You can add format to allow for different file formats if desired, and a download button. You will want your filtering done in a reactive block.

The second part is an example report.Rmd file that will show the data table using xtable. You can further modify your report to include whatever information you want and other boilerplate info.

library(tidyverse)
library(shiny)
library(shinythemes)
library(xtable)
library(rmarkdown)

insulin <- readRDS("insulin.rda")

# User Interface

ui <- fluidPage(
  titlePanel("Pre-operative Advice on Insulin - For Patients with Diabetes Undergoing Elective Surgery v0.1"),
  sidebarLayout(
    sidebarPanel(
      p("Patient Name and Date of Birth (Optional)"),
      textInput("px_name", label = "Patient Name", placeholder = "Patient Name"),
      textInput("dob", label = "Date of Birth or CHI", placeholder = "Date of Birth or CHI"),
      selectInput("DM", "What type of diabetes does patient have?",
                  c("Type One" = "Type 1",
                    "Type Two on Insulin" = "Type 2"),
                  selected = "Type One"),
      selectInput("time", "Is patient on morning or afternoon list?",
                  c("Morning List" = "AM",
                    "Afternoon List" = "PM"),
                  selected = "Morning"),
      checkboxGroupInput("class", "Which type(s) of insulin is patient on?",
                         c("Long and Intermediate acting",
                           "Pre-Mixed",
                           "Rapid or Short acting")),
      radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'), inline = TRUE),
      downloadButton('downloadReport')
    ),
    mainPanel(
      uiOutput("insulin_sel"),
      h3(textOutput(outputId = "px_name")),
      br(),
      h4(textOutput(outputId = "dob")),
      br(),
      tableOutput("table")
    )
  )
)

server <- function(input, output){

  my_insulin_table <- reactive({
    insulin_subset <- insulin %>% filter(DM == input$DM, 
                                         Time == input$time, 
                                         Class %in% input$class)
    tab <- insulin_subset %>% filter(Name %in% input$name)
  })

  output$px_name <- renderText({input$px_name})
  output$dob <- renderText({input$dob})
  output$insulin_sel <- renderUI({
    insulin_subset <- insulin %>% filter(DM == input$DM, 
                                         Time == input$time, 
                                         Class %in% input$class)
    selectizeInput("name", "Type in name of insulin",
                   choices = list("Type in insulin name" = "", 
                                  "Names" = insulin_subset$Name), 
                   selected = NULL, 
                   multiple = TRUE,
                   options = NULL)
  })

  output$table <- renderTable({
    xtable(my_insulin_table())
  })

  output$downloadReport <- downloadHandler(
    filename = function() {
      paste('my-report', sep = '.', switch(
        input$format, PDF = 'pdf', HTML = 'html', Word = 'docx'
      ))
    },
    content = function(file) {
      src <- normalizePath('report.Rmd')

      # temporarily switch to the temp dir, in case you do not have write
      # permission to the current working directory
      owd <- setwd(tempdir())
      on.exit(setwd(owd))
      file.copy(src, 'report.Rmd', overwrite = TRUE)

      out <- render('report.Rmd', switch(
        input$format,
        PDF = pdf_document(), HTML = html_document(), Word = word_document()
      ))
      file.rename(out, file)
    }
  )
}

shinyApp(ui = ui, server = server)

The report.Rmd file could include the following as an example:

# Pre-operative Advice on Insulin

```{r echo = FALSE, results = 'asis'}
options(xtable.comment = FALSE)
xtable(my_insulin_table())
```

Note the use of asis for xtable to remove the additional comments added when a table is created. Also, for this example with xtable it targets pdf format only.

Edit: To pass the name and date of birth to your report, you can also use parameters.

First, add the parameters in a list in your render statement:

out <- render('report.Rmd', 
        params = list(name = input$px_name, dob = input$dob),
        switch(input$format,
          PDF = pdf_document(), 
          HTML = html_document(), 
          Word = word_document()
      ))

Then reference them as inline r code in your report.Rmd:

---
title: "Pre-operative Advice on Insulin"
output: pdf_document
params:
  name: 'NULL'
  dob: 'NULL'
---

# Demographics

Name: `r params[["name"]]`

Date of Birth: `r params[["dob"]]`

# Insulin Schedule

```{r echo = FALSE, results = 'asis'}
options(xtable.comment = FALSE)
xtable(my_insulin_table())
```


来源:https://stackoverflow.com/questions/58902374/exporting-texts-and-datatable-from-shiny-to-pdf

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!