I have a R shiny code which makes various reports, word cloud, sentiment analysis and various other things. Now I want that by click of a button all these reports which are generated can be downloaded in one single shot and attached to ppt. So, for instance it should look like:
Slide 1: Word cloud
Slide 2: Sentiment Analysis
Slide 3: Report 1 ...and so on
Till now, I can download all these reports separately i.e. I have different tabs in my Shiny UI, for every report and I go to it and click "Download" and it get downloaded by downloadHandler.
Also, In one click I can download all these reports in one pdf i.e. in one page I have report 1 and so and so forth.
Till now I have reached till below:
#downloadReport is my action button
#on click of this button I am expecting the ppt. to be downloaded
observeEvent(input$downloadReport, {
# Create a PowerPoint document
doc = pptx( )
# Slide 1 : Title slide
#+++++++++++++++++++++++
doc <- addSlide(doc, "Title Slide")
doc <- addTitle(doc,"Create a PowerPoint document from R software")
doc <- addSubtitle(doc, "R and ReporteRs package")
# Slide 2 : Add Word Cloud
#+++++++++++++++++++++++
doc <- addSlide(doc, "Title and Content")
doc <- addTitle(doc, "Bar Plot")
newData=rawInputData(); # Function which captures data (.csv file) when I have input it through R shiny
words_list = strsplit(as.character(newData$CONTENT), " ") #CONTENT is the column which contains the test data
words_per_tweet = sapply(words_list, length)
pptwordcloud<-barplot(table(words_per_tweet), border=NA,main="Distribution of words per tweet", cex.main=1,col="darkcyan")
#pptwordcloud<-barplot(table(words_per_tweet), col="darkcyan")
doc <- addPlot(doc, fun= print, x = pptwordcloud,vector.graphic =FALSE )
writeDoc(doc,'file1.pptx')
})
The ppt. is getting generated but I can't see barplot in it by using vector.graphic =FALSE as a option. If I remove this,I am getting this error
Warning: Unhandled error in observer:
javax.xml.bind.UnmarshalException
- with linked exception: [org.xml.sax.SAXParseException: The markup in the document preceding the root element must be well-formed.]
observeEvent(input$downloadReport)
Can somebody point out my error.
Let try to reproduce =)
1) I havent your data so i use iris and select input used for choise second colunm for table
UI
library(shiny)
shinyUI(
# Use a fluid Bootstrap layout
fluidPage(
selectInput("sel",label = "col",choices = colnames(iris)[2:ncol(iris)]),
downloadButton('downloadData', 'Download')
)
)
Server
library(shiny)
library(DT)
library(ReporteRs)
shinyServer(function(input, output,session) {
output$downloadData <- downloadHandler(
filename = "file.pptx",
content = function(file) {
doc = pptx( )
# Slide 1 : Title slide
#+++++++++++++++++++++++
doc <- addSlide(doc, "Title Slide")
doc <- addTitle(doc,"Create a PowerPoint document from R software")
doc <- addSubtitle(doc, "R and ReporteRs package")
# Slide 2 : Add Word Cloud
#+++++++++++++++++++++++
doc <- addSlide(doc, "Title and Content")
doc <- addTitle(doc, "Bar Plot")
#newData=rawInputData(); # Function which captures data (.csv file) when I have input it through R shiny
#words_list = strsplit(as.character(newData$CONTENT), " ") #CONTENT is the column which contains the test data
#words_per_tweet = sapply(words_list, length)
words_per_tweet=iris
pptwordcloud<-function(){
barplot(table(words_per_tweet[,c("Sepal.Length",input$sel)]), border=NA,main="Distribution of words per tweet", cex.main=1,col="darkcyan")
}#pptwordcloud<-barplot(table(words_per_tweet), col="darkcyan")
doc <- addPlot(doc, fun= pptwordcloud,vector.graphic =FALSE )
writeDoc(doc,file)
}
)
})
Related
this is my first time using and exploring R shiny. The process seems pretty straightforward but I am having some difficulties getting everything to run smoothly.
I am trying to build an app that will allow a user to upload a word doc, PDF, or other text file (would be cool if there was also an option to paste text directly instead of uploading a file), and then a function would run on the file or pasted text which would result in a returned list of text.
My code works fine when not using R shiny:
library(dplyr)
library(stringr)
library(readtext)
library(XML)
library(here)
### option to manually paste in text to use instead of uploading file:
text <- "This is a test. The purpose of the below function is to extract and return and in-text cictations with the following formats:(Smith, 2010), and (Smith 2010; Jones, 2001; Brown 2020), or Cooper (2015), or John Granger et al. (2015), and (Brown and Green 2004)."
######Option to read in word doc######
wordtest<-readtext(here("Example.docx"))
text<-wordtest$text
######Option to read in PDF file######
PDFtest<-readtext("Example2.pdf")
text<-PDFtest$text
##Return citations alphabetically:
rx <- "(?:\\b(\\p{Lu}\\w*(?:\\s+\\p{Lu}\\w*)*(?:\\s+et\\s+al\\.)?)?)\\s*\\(([^()]*\\d{4})\\)"
res <- str_match_all(text, rx)
result <- lapply(res, function(z) {ifelse(!is.na(z[,2]) & str_detect(z[,3],"^\\d+$"), paste(trimws(z[,2]), trimws(z[,3])), z[,3])})
sort(unique(unlist(sapply(result, function(z) strsplit(paste(z, collapse=";"), "\\s*;\\s*")))))
The result from running this code is the following:
[1] "Brown 2020" "Brown and Green 2004" "Cooper 2015" "John Granger et al. 2015"
[5] "Jones, 2001" "Smith 2010"
I want to run this same process with these same features, on an R shiny app where the user could upload a file containing such text or paste the text directly and it would return the same result.
here is what I have for my app right now:
# Load R packages
library(shiny)
library(shinythemes)
library(dplyr)
library(stringr)
library(readtext)
library(XML)
library(data.table)
# Define UI
ui <- fluidPage(theme = shinytheme("cerulean"),
navbarPage(
theme = "cerulean", # <--- To use a theme, uncomment this
"Extracting in-text citations app", #app title
tabPanel("Alphabetical Order", # tab title
sidebarPanel(
# Input: Select a file ----
fileInput(inputId ="text", "Choose File",
multiple = FALSE,
accept = c("text/plain",".doc",".docx",".pdf")),
p("Accepted Files: .doc, .docx, .pdf, text/plain"),
), # sidebarPanel
mainPanel(
h1("Output"),
h4("List of citations in Alphabetical Order"),
verbatimTextOutput("txtout"),
) # mainPanel
), # Navbar 1, tabPanel
tabPanel("Chronological Order", "This panel is intentionally left blank"),
) # navbarPage
) # fluidPage
#Define Server:
server<- function (input,output){
output$txtout<-renderPrint({
wordtest<-readtext(input$text)
text2<-wordtest$text
rx <- "(?:\\b(\\p{Lu}\\w*(?:\\s+\\p{Lu}\\w*)*(?:\\s+et\\s+al\\.)?)?)\\s*\\(([^()]*\\d{4})\\)"
res <- str_match_all(text2, rx)
result <- lapply(res, function(z) {ifelse(!is.na(z[,2]) & str_detect(z[,3],"^\\d+$"), paste(trimws(z[,2]), trimws(z[,3])), z[,3])})
return(sort(unique(unlist(sapply(result, function(z) strsplit(paste(z, collapse=";"), "\\s*;\\s*"))))))
})
}
# Create Shiny object
shinyApp(ui = ui, server = server)
I can get the app to run (open), but when I go to upload a file, nothing happens, or I get the following error: "file must be a character (specifying file location(s))."
As I said I am very new to R shiny so any insight would be helpful, thanks!
fileInput doesn't return the filename/path directly.
It returns a dataframe with the name , size, type and datapath.
What you probably want is datapath, so try this.
file <- input$text
wordtest<-readtext(file$datapath)
U have a Shiny app and I run some analysis on a dataframe and get results like this:
brand %
nike 50 %
adidas 35 %
umbro 15 %
Instead of just showing this table in Shiny, is it possible to show the corresponding images (no need to have the numbers) so that they change the order those are shown depending on the applied filter, so the resulting element in Shiny should look like this:
I will have the images in the wwww folder.
Is this possible with Shiny?
Thx!
You can create any output you want with a uiOutput. The renderUI section on the server allows you to create HTML. This way you can identify which images are in the top 3 (which I did by ordering the data frame woth order) and then ouput the ccording images using HTML <img/> by using the HTML builder functions from the htmltools package.
Test the code and see how the order of the images changes depending on the values by reloading the shiny app.
Please Note: this sample will not render the images correctly because I do not know the correct file names they have in your 'www' directory. Adapt the paste0() statement to point to the correct path.
library(shiny)
ui <- fluidPage(
titlePanel("Brand Stats"),
uiOutput("uiTopBrands"),
h1("Top 3 Brands as Table"),
tableOutput("tblTopBrands")
)
# Define server logic required to draw the brand stats
server <- function(input, output) {
df <- data.frame(
brands = c("nike", "adidas", "umbro", "puma", "reusch"),
percent = sample(100, 5))
df$percent <- df$percent / sum(df$percent) * 100
df <- df[order(df$percent, decreasing = TRUE),]
output$uiTopBrands <- renderUI({
Output <- tagList(
h1("Top 3 Brands in Images"),
p(df$brands[1], "will appear below"),
img(src = paste0(df$brands[1], ".jpg"), alt = df$brands[1]), # make sure you create the correct url here with "paste0"
p(df$brands[2], "will appear below"),
img(src = paste0(df$brands[2], ".jpg"), alt = df$brands[2]),
p(df$brands[3], "will appear below"),
img(src = paste0(df$brands[3], ".jpg"), alt = df$brands[3])
)
return(Output)
})
output$tblTopBrands <- renderTable({
df
})
}
# Run the application
shinyApp(ui = ui, server = server)
I have looked at all similar problems posted to StackOverflow and none of them seem to be adaptable to solve my problem (so please don't mark as duplicate). I tried to make the reprex as concise as possible... Thanks in advance for any help.
The Problem:
I have a set of related images whose filepaths are in a dataframe, along with their category and type assignments (see the dput dataframe below). When the user clicks the "Generate Image" button, the images are read into a nested list structure according to their category and type, and then aggregated into a single jpeg to be viewed in the app. That part I have already accomplished (see the R Shiny server logic below). However, I would also like the user to be able to download this list of images as a single pdf, with each row/type of image on a separate page (see below for desired output). I've tried adapting other solutions I've found online, but can't seem to figure it out. Every attempt either results in a file error or a completely empty pdf.
R Shiny UI and Server logic
### Load packages.
library(tidyverse)
library(shiny)
library(magick)
### Define UI.
ui <- fluidPage(
sidebarLayout(
### Sidebar menu with two buttons.
sidebarPanel(fluid = FALSE, width = 2,
actionButton("go", "Generate Image"),
downloadButton("downloadImage", "Download Image")
),
### Main panel to view aggregate image.
mainPanel(
imageOutput("img")
)
)
)
### Define server logic.
server <- function(input, output, session) {
# Dput dataframe containing URLs to public images and their category/type assignment.
filenames <- structure(list(category = c("animal", "animal", "animal", "animal",
"animal", "nature", "nature", "nature", "nature", "nature"),
type = c("dog", "dog", "dog", "human", "human", "leaf", "leaf",
"flower", "flower", "flower"), img_url = c("https://images.freeimages.com/images/large-previews/ce3/puppies-1-1308839.jpg",
"https://images.freeimages.com/images/large-previews/006/young-dachshund-1362378.jpg",
"https://images.freeimages.com/images/large-previews/20c/my-puppy-maggie-1362787.jpg",
"https://media.istockphoto.com/photos/fitness-picture-id172628456",
"https://media.istockphoto.com/photos/seventy-year-old-man-smiling-picture-id173612705",
"https://images.freeimages.com/images/large-previews/6df/water-drop-on-leaf-1639205.jpg",
"https://images.freeimages.com/images/large-previews/34c/close-up-macro-of-green-leaf-1641721.jpg",
"https://images.freeimages.com/images/large-previews/0cf/tulips-1-1377350.jpg",
"https://images.freeimages.com/images/large-previews/d2f/tulips-1400882.jpg",
"https://images.freeimages.com/images/large-previews/3d3/droplets-1395002.jpg"
)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"
))
### When the user clicks the "Generate Image" button, this generates a nested list of the
### images, appended by type.
img_list <- eventReactive(input$go, {
by(filenames, filenames$category, function (cat) {
by(cat, cat$type, function (t) {
pull(t, img_url) %>%
image_read() %>%
image_scale("x200") %>%
image_join() %>%
image_append()
})
})
})
### Render aggregated image for viewing in the app.
output$img <- renderImage({
req(input$go)
tmpfile <- image_join(img_list()) %>%
image_append(stack = TRUE) %>%
image_write(tempfile(fileext = '.jpg'), format = 'jpg')
list(src = tmpfile, contentType = "image/jpeg")
}, deleteFile = FALSE)
### Download image.
output$downloadImage <- downloadHandler(
filename = "images.pdf",
contentType = "application/pdf",
content = function(file) {
### Here is where I'm stuck!
###
### The list of images I want to print is stored in img_list()
### and rows of images are already correctly appended. I just
### can't figure out how to print each level of the nested
### list to a separate page in the pdf.
}
)
### Stop 'listening' when browser window is closed.
session$onSessionEnded(function() {
stopApp()
})
}
shinyApp(ui = ui, server = server)
My desired output looks like this, where the black lines represent a page break in the downloaded pdf:
I'm new to R markdown here and I am trying to create an R Shiny app which I can enter a list of names, and then download the output (like a name list) as HTML file. I am using R markdown to create the HTML file. Here are my sample codes:
R Shiny:
library(shiny)
ui <- list(
textInput("name", "Type new text input name", value = ""),
actionButton("btn", "click me to create text input"),
uiOutput("newInputs"),
downloadButton("download_report", "Download")
)
server <- function(input, output)
{
family_member <- reactiveValues(
add_family_info = list()
)
observeEvent(input$btn, {
newid <- paste(length(family_member$add_family_info))
family_member$add_family_info <- c(family_member$add_family_info, list(c(newid, input$name)))
family_member
})
output$newInputs <- renderUI({
lapply(family_member$add_family_info, function(a)
c(paste(a[2])))
})
output$download_report <- downloadHandler(
filename = "name.html",
content = function(file) {
tempReport <- file.path(tempdir(), "name.Rmd")
file.copy("name.Rmd", tempReport, overwrite = TRUE)
params <- list(report = uiOutput("newInputs"))
rmarkdown::render(tempReport, output_file = file,
params = params,
envir = new.env(parent = globalenv()))
}
)
}
runApp(list(ui = ui, server = server))
R Markdown:
---
runtime: shiny
output: html_document
params:
report: NA
---
\
\
# Member names
`r params$report`
Appreciate any help! Thanks in advance!!!!
If you are just using a Shiny to render an Rmarkdown document, you don't need the runtime of the document to be Shiny. This is only needed if the document itself will ultimately be a shiny app.
Looking at the download handler
params <- list(report = uiOutput("newInputs"))
The uiOutput function generates the html for the element. It doesn't retrieve the values (you can see this if you run execute it in the console by itself). Additionally newInputs just refers to the container for the text (it's not actually inputs). Instead, you would want to use the reactive value storing the list
params <- list(report = family_member$add_family_info)
However, since this will be printed it can't be an arbitrary R object. It has to be something that cat can handle. In this case family_member$add_family_info is a list of list. Try flattening it with something like
params <- list(report = unlist(family_member$add_family_info))
I am trying to write a Shiny application just for practice
The app takes an excel sheet, grabs an ID number from the excel sheet and runs those IDs against a database returning some additional details from the database
Just for this example i have imported the data and counted the number of rows in the dataset. I then pass this dataset to the function get_DWwhich will return a dataframe and i want to count the number of records in the returned dataframe. This step occurs when the user presses the button Go
When i run my shiny app, the data imports and the number of records are counted. I also have managed to get it to return records from the database and count those.
Im having trouble exporting them using the output$downloadData, nothing happens. I press the button get the dialog box to save but when i enter the file name and press save nothing gets saved to the folder
Can anyone see where in the code i might be going wrong. I have seen the question Downloading Excel File from XLConnect with R Shiny but it doesn't use the library i want and im not quite clear on the explanation given
I have updated the code below to use the iris Dataset. Its a bit messy but it replicates the lack of saving
Server Code
# Server Code
server <- shinyServer(function(input, output) {
# Create a reactive expression which will grab the data
# We pass that to the outputs reactive element to the outputs
data <- reactive({
iris
})
# Return the number of records
output$Inputnum <- renderText({
paste(nrow(data()), "records to be checked")
})
# Data returned by Database
en_data <- eventReactive(input$go, {
get_DW(data())
})
# Return the number of records
output$Outputnum <- renderText({
paste(nrow(en_data()), "records matched")
})
output$downloadData<- downloadHandler(
filename = function() { "name.xlsx" },
content = function(file) {
tempFile <- tempfile(fileext = ".xlsx")
write.xlsx(en_data(), tempFile)
file.rename(tempFile, file)
})
})
UI Code
shinyUI(
fluidPage(
titlePanel("POC"),
sidebarLayout(
sidebarPanel(
fileInput(inputId = 'file1',label = 'Choose An Excel File',
accept=c('.xlxs')),
radioButtons(inputId = "radio", label = "Search By:",
choices = list("option 1" = 1,
"option 2" = 2,
"option 3" = 3),
selected = 1),
hr(),
fluidRow(column(1,
actionButton("go", "Get Records")),
column(2,offset = 2,
downloadButton('downloadData', 'Download')),
br()
)),
mainPanel(
verbatimTextOutput("Inputnum"),
br(),
verbatimTextOutput("Outputnum")
)
)
))
GLOBAL R FILE
#in global.R
options (scipen=FALSE,stringsAsFactors=FALSE)
library(xlsx)
library(RODBC)
library(dplyr)
get_DW <- function (mydf) {
mydf
}
I encountered this same problem a couple of weeks ago. Try running your app externally instead of locally. This worked for me using your sample code.