Is it possible to create user defined report from shiny app?

谁都会走 提交于 2019-12-24 00:43:56

问题


The shiny app below is taken out of gallery. It allow user to choose a variable, build a linear regression and download report.

What if I do not know in advance how many plots and models user wants to build and include into report. Is it possible to create a report with dynamically added plots?

Server.R

function(input, output) {

    regFormula <- reactive({
        as.formula(paste('mpg ~', input$x))
    })

    output$regPlot <- renderPlot({
        par(mar = c(4, 4, .1, .1))
        plot(regFormula(), data = mtcars, pch = 19)
    })

    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)

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

}

ui.R

fluidPage(
    title = 'Download a PDF report',
    sidebarLayout(
        sidebarPanel(
            helpText(),
            selectInput('x', 'Build a regression model of mpg against:',
                        choices = names(mtcars)[-1]),
            radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
                         inline = TRUE),
            downloadButton('downloadReport')
        ),
        mainPanel(
            plotOutput('regPlot')
        )
    )
)

report.Rmd

Here is my regression model:

```{r model, collapse=TRUE}
options(digits = 4)
fit <- lm(regFormula(), data = mtcars)
b   <- coef(fit)
summary(fit)
```

The fitting result is $mpg = `r b[1]` + `r b[2]``r input$x`$.
Below is a scatter plot with the regression line.

```{r plot, fig.height=5}
par(mar = c(4, 4, 1, 1))
plot(regFormula(), data = mtcars, pch = 19, col = 'gray')
abline(fit, col = 'red', lwd = 2)
```

回答1:


Well, it looks like I have found the answer. The problem was in local/global variables. I had to put list initialisation outside server function. Also I had to use <<- instead of <- to assign new element to the plot rather than create new plot every time.

Many thanks to Peter Ellis to support!

So, the solution is (I have slightly changed initial code to focus on the important part):

server.R

library(ggplot2); library(shiny); library(grid); library(gridExtra)


plist <- list() # IMPORTANT - outside server function

shinyServer(function(input, output) {

    output$regPlot <- renderPlot({
        p <- do.call("grid.arrange", c(plotList(),
                                       ncol=floor(sqrt(length(plotList())+1)),
                                       top = "test"))
    })



    plotList <- eventReactive(input$plt2rprt, {
        p <- ggplot(data = mtcars, aes_string(x = input$x, y = "mpg")) +
            geom_point()
 #       isolate(
        plist[[length(plist)+1]] <<- p #IMPORTATNT <<- instead of <-
 #       )
        return(plist)
    })


    output$lengthOfList <- renderText({length(plotList())})
    output$lll <- renderText({length(plist)})

    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')

            owd <- setwd(tempdir())
            on.exit(setwd(owd))
            file.copy(src, 'report.Rmd', overwrite = TRUE)

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

}) #ShinyServer

ui.R

fluidPage(
    title = 'Download a PDF report',
    sidebarLayout(
        sidebarPanel(
            helpText(),
            selectInput('x', 'Build a regression model of mpg against:',
                        choices = names(mtcars)[-1]),
            actionButton("plt2rprt", label = "Include into report"),
            hr(),
            radioButtons('format', 'Document format', c('PDF', 'HTML', 'Word'),
                         inline = TRUE),
            downloadButton('downloadReport')
        ),
        mainPanel(
            plotOutput('regPlot'),
            #verbatimTextOutput("count"),
            hr(),
            textOutput("lengthOfList"),
            textOutput("lll"),
            helpText("test-test-test")
        )
    )
)

report.Rmd

Length of list of plots `r length(plotList())`

```{r plot, fig.height=5}
do.call("grid.arrange", c(plotList(),
                          ncol=floor(sqrt(length(plotList())+1)),
                          top = "test"))
```


来源:https://stackoverflow.com/questions/41350835/is-it-possible-to-create-user-defined-report-from-shiny-app

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