I am new to shiny and trying to combine a couple features and having some trouble.
I want for the user to be able to select a CSV and then be presented with a random instance (in this case tweet) from that table. The following code worked when "tweetData" was a statically loaded csv using read_csv.
## function to return random row number from data set
getTweet <- function(){
tweetData[sample(nrow(tweetData), 1), ]
}
function(input, output, session) {
## set reactive values, get randomized tweet
appVals <- reactiveValues(
tweet = getTweet(),
ratings = data.frame(tweet = character(), screen_name = character(), rating = character())
)
I want to instead use a dynamically chosen csv for "tweetData", something like adding this??
csvName <- reactive(paste0('../folder_path/', input$file_name))
selectedData <- read.csv(csvName)
How can use reactively chosen csvs to fit into the structure of the first code chunk?
You might be looking for fileInput for giving user an option to upload a dataset.
This is a simple reproducible example -
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File"),
),
mainPanel(
tableOutput("contents")
)
)
)
server <- function(input, output) {
output$contents <- renderTable({
req(input$file1)
read.csv(input$file1$datapath)
})
}
shinyApp(ui, server)
Related
My goal is that user uploads an Excel file. Then, the user selects which sheets wants to be summarised, after the selection has been updated. I have managed to update selectInput with the name of the sheets but I have not been able to find\understand how to summarise based on what the sheet selected by the user. Thanks for any help.
library(shiny)
library(shinythemes)
library(data.table)
library(ggplot2)
library(dplyr)
library(readxl)
not_sel <- "Not Selected"
# Define UI for application that draws a histogram
ui <- fluidPage('MAIN TITLE',
theme = shinytheme('flatly'),
tabsetPanel(
sidebarLayout(
sidebarPanel(
fileInput('files','Import File', accept = c('.csv','.xlsx'),
multiple = F),
actionButton('boton1', 'Load', icon = icon('table')),
br(),
selectInput("indices", "Select SHEET:", choices = c(not_sel))
),
mainPanel(
tabsetPanel(
tabPanel('Data',
tableOutput('tabla'),
tableOutput('cabeza')),
tabPanel('Stats',
# selectInput('var01', 'Variable to summarise', choices = c(not_sel)),
tableOutput('stats')),
)
)
)
)
)
##############
server <- function(input, output, session) {
options(shiny.maxRequestSize=10*1024^2)
df <- eventReactive(input$boton1, {
req(input$files)
if(is.null(input$files))return(NULL)
# else{
read_excel(input$files$datapath)
# }
})
# Sheets of file uploaded
sheets_name <- reactive({
if (!is.null(input$files)) {
return(excel_sheets(path = input$files$datapath))
} else {
return(NULL)
}
})
# Update inputSelector with sheet names
observeEvent(df(),{
choices <- c(sheets_name())
updateSelectInput(inputId = "indices", choices = choices)
})
# DATA Tab
## This will show the name of the file
output$tabla <- renderTable({
input$files$name
})
## This Shows the head() but it is only showing the first sheet
output$cabeza <- renderTable({
tabla <- as_tibble(bind_cols(Date = format(as.Date(df()$Date),"%Y-%m-%d"),
Close.Price = df()$Close))
head(tabla)
})
# HERE is where I do not know how to calculate based on selection
# Table for STATS
output$stats <- renderTable({
datos <- df()
Value <- c(round(mean(datos$Close,na.rm = T),2)
)
Statistic <- c("Mean")
data.table(Statistic, Value)
})
}
# Run the application
shinyApp(ui = ui, server = server)
I want to assume that by knowing how to calculate mean based on the sheet selected, I. can replicate the code for the top rows (head()) shown in the Data Panel.
If I missed a similar question asked, I would appreciate any link and I will try the solution proposed first.
As I cannot share the file, this is how the file would look:
After working with this answer I made my app work. If there is a 'cleaner'/'better' answer, I will be happy to read.
Following the recommendation in the linked answer my server ended up like this:
ui <-fluidPage{
#My UI stayed the same with the exception of adding
uiOutput("dropdownUI") #Whererever I needed to appear
}
server <- function(input, output, session) {
...ANSWER FROM THE LINK...
## STATS Tab
output$stats <- renderTable({
Values <- c(round(mean(Dat()[,2],na.rm = T),2)
)
Statistics <- c("Mean")
data.table(Statistics, Values)
})
}
I'm working on a shiny app to manipulate data.
I'd like to read a zip file selectioned in a fileInput. This zip is composed by multiple csv files, and I'd like to save as reactive values all .csv dataframes.
For example, if test.zip contains file ONE.csv, TWO.csv, THREE.csv , i'd like to obtain 3 reactives values (as dataframes) called ONE , TWO, THREE .
I'm abble to do it if I know the name and number of csv files.
But if I don't know the number and names of .csv dataframes, how can I achieve it ?
## Only run examples in interactive R sessions
if (interactive()) {
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("ZIP", "Choose ZIP File",
accept = ".zip"
)
),
mainPanel(
DT::dataTableOutput("ONEtab")
)
)
)
server <- function(input, output) {
ONE <- reactive({
inFile <-req(input$ZIP)
read_csv(unzip(inFile$datapath,"ONE.CSV"))
})
TWO <- reactive({
inFile <-req(input$ZIP)
read_csv(unzip(inFile$datapath,"TWO.CSV"))
})
THREE <- reactive({
inFile <-req(input$ZIP)
read_csv(unzip(inFile$datapath,"THREE.CSV"))
})
output$ONEtab <- DT::renderDataTable({ DT::datatable(ONE(), option=list(scrollX=T),filter = 'top')})
}
shinyApp(ui, server)
}
Thanks for your help !
One option is to read all the dataframes into a single variable and then use a number to select the one of interest. Here's some code that does this. It uses lapply to read the contents of the zip file to create a reactive variable called all. To reference different dataframes, the code required is all()[[index]] and I have added something that shows this.
library(DT)
library(readr)
ui <- fluidPage(sidebarLayout(sidebarPanel(
fileInput("ZIP", "Choose ZIP File", accept = ".zip"),
selectInput("choice", 'Choose', choices = c(1,2,3), selected = 1)
),
mainPanel(DT::dataTableOutput("selectone"))))
server <- function(input, output) {
all <- reactive({
inFile <- req(input$ZIP)
filelist <- unzip(inFile$datapath, list = T)
lapply(filelist$Name, read_csv)
})
output$selectone <-
DT::renderDataTable({
choice = as.integer(input$choice)
DT::datatable(all()[[choice]], option = list(scrollX = T), filter = 'top')
})
}
shinyApp(ui, server)
Without the rest of your code that processes this, it's difficult to know if this will be what you need but perhaps it's a start.
I would like to use a Shiny app to load a file (tab-separated), dynamically create a checkboxGroupInput, after the loading of the file (using observeEvent) using the column headers, then subset the data frame that comes from the file based on the selected checkboxes. The data is then plotted using code I can't share right now.
All is working fine, apart from the last bit: subsetting the dataframe based on the selected checkboxes in checkboxGroupInput. The checkboxes all start selected, and the plot is created fine. If you un-select one of the checkboxes, the plot re-plots appropriately for a split second (so the subsetting is working fine) then the unselected checkbox re-selects itself and the plot goes back to the old plot.
This is the tiny problem I'm trying to solve, guessing it's one line of code. I'm assuming it's because of some reactivity that I don't understand and the checkbox constantly resetting itself.
Here is an example:
###
## Some functions I can't share
### Shiny app
library(shiny)
# Define UI
ui <- fluidPage(
# Application title
titlePanel("MagicPlotter"),
# Sidebar
sidebarLayout(
sidebarPanel(
fileInput(inputId = "myInputID",
label = "Your .csv file",
placeholder = "File not uploaded"),
uiOutput("mylist"),
uiOutput("submitbutton")
),
# Show a plot
mainPanel(
verticalLayout(
plotOutput("myPlot"))
)
)
)
# Define server
server <- function(input, output) {
output$myPlot <- renderPlot({
inputfile <- input$myInputID
if(is.null(inputfile))
{return()}
mydataframe <- read.table(file=inputfile$datapath, sep="\t", head=T, row.names = 1)
mydataframecolumnnames <- colnames(mydataframe[1:(length(mydataframe)-1)])
# the last column is dropped because it's not relevant as a column name
observeEvent(input$myInputID, {
output$mylist <- renderUI({
checkboxGroupInput(inputId="mylist",
label="List of things to select",
choices=mydataframecolumnnames,
selected=mydataframecolumnnames)
})
})
observeEvent(input$myInputID, {
output$submitbutton <- renderUI({
submitButton("Subset")
})
})
mysubset <- mydataframe[input$mylist]
myPlot(mysubset)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Thanks all
I think there are a few things that might help...
One, you can move your observeEvent methods outside of your renderPlot.
Also, you can create a reactive function to read in the data table.
I hope this helps.
server <- function(input, output) {
myDataFrame <- reactive({
inputfile <- input$myInputID
if(is.null(inputfile))
{return()}
read.table(file=inputfile$datapath, sep="\t", head=T, row.names = 1)
})
output$myPlot <- renderPlot({
req(input$mylist)
mysubset <- myDataFrame()[input$mylist]
plot(mysubset)
})
observeEvent(input$myInputID, {
mydata <- myDataFrame()
mydataframecolumnnames <- colnames(mydata[1:(length(mydata)-1)])
output$mylist <- renderUI({
checkboxGroupInput(inputId="mylist",
label="List of things to select",
choices=mydataframecolumnnames,
selected=mydataframecolumnnames)
})
})
observeEvent(input$myInputID, {
output$submitbutton <- renderUI({
submitButton("Subset")
})
})
}
I currently have a Shiny app in which you can upload a csv file and it will
show you the data.
I want to add a search bar where you can search for specific rows based on
three variables.
I then want these rows that I have searched for and then selected to form a
new downloadable csv.
Is this possible?
library(shiny)
library(shinyjs)
library(DT)
library(dplyr)
library(data.table)
#I don't need all these packages just yet but I will use them as I carry on the project hopefully
ui = fluidPage(
fileInput("Rams","Upload complete list of Rams", accept=".csv"),
#fileinput where a list of rams (male sheep) are loaded. I want to select a
few rams from the list based on their unique combinations of birth year, tag
number and flock number
br(),
DT::dataTableOutput("Rams1")
)
server = function(input, output, session) {
#server section of my app
#This shows me the data
output$Rams1 <- renderDataTable({
Rams2 <- input$Rams
if (is.null(Rams2))
return(NULL)
subset(read.csv(Rams2$datapath, header=T, sep=","))
})
}
shinyApp(ui=ui, server=server)
Even if I simply select 3 rows as done here, all 15 rows are shown in the downloaded file as shown in the next picture
The downloaded file simply produces all data rather than just the ones I am filtering for
Below code will solve the problem
library(shiny)
library(shinyjs)
library(DT)
library(dplyr)
library(data.table)
#I don't need all these packages just yet but I will use them as I carry on the project hopefully
ui = fluidPage(
fileInput("Rams","Upload complete list of Rams", accept=".csv"),
br(),
DT::dataTableOutput("Rams1"),downloadButton(outputId = "download_filtered",
label = "Download Filtered Data")
)
server = function(input, output, session) {
datasetInput <- reactive({
infile <- input$Rams
if(is.null(infile))
return(NULL)
read.csv(infile$datapath, header = TRUE)
})
output$Rams1 = DT::renderDataTable(datatable(datasetInput() ,filter = "top"),
server = FALSE)
output$download_filtered <-
downloadHandler(
filename = "Filtered Data.csv",
content = function(file){
write.csv(datasetInput()[input[["Rams1_rows_all"]], ],
file)
})
}
shinyApp(ui=ui, server=server)
Instead of specifying separate fileInput variables, I'd like to use reactiveValues to store uploaded CSV dataframes, manipulate them in some way, and then store them for accession later. My design is to name each dataframe by its filename and append to the reactiveValue rvTL. My questions are,
How can I access individual dataframes under the list I created using reactiveValuesToList(rvTL)?
Next step, how to create a selectInput menu to access the individual dataframes uploaded by fileInput
To learn this concept, I am piggybacking off the answer from Dean Attali and made rvTL the same as his values variable.
R shiny: How to get an reactive data frame updated each time pressing an actionButton without creating a new reactive data frame?
I've gone over many example codes on reactiveValues, yet still at an incomplete understanding. Most examples are using some sort variation on reactiveValuesToList(input) R Shiny: Keep/retain values of reactive inputs after modifying selection, I'm really not seeing the logic here. Any help/suggestions would be appreciated!
library(shiny)
runApp(shinyApp(
ui=(fluidPage(
titlePanel("amend data frame"),
mainPanel(
fileInput("file", "Upload file", multiple=T),
tabsetPanel(type="tabs",
tabPanel("tab1",
numericInput("Delete", "Delete row:", 1, step = 1),
actionButton("Go", "Delete!"),
verbatimTextOutput("df_data_files"),
verbatimTextOutput("values"),
verbatimTextOutput("rvTL"),
tableOutput("rvTL_out")
),
tabPanel("tab2",
tableOutput("df_data_out")
)
)))),
server = (function(input, output) {
values <- reactiveValues(df_data = NULL) ##reactiveValues
rvTL <- reactiveValues(rvTL = NULL)
observeEvent(input$file, {
values$df_data <- read.csv(input$file$datapath)
rvTL[[input$file$name]] <- c(isolate(rvTL), read.csv(input$file$datapath))
})
observeEvent(input$Go, {
temp <- values$df_data[-input$Delete, ]
values$df_data <- temp
})
output$df_data_files <- renderPrint(input$file$name)
output$values <- renderPrint(names(values))
output$rvTL <- renderPrint(names(reactiveValuesToList(rvTL))[1] )
output$rvTL_out <- renderTable(reactiveValuesToList(rvTL)[[1]])
output$df_data_out <- renderTable(values$df_data)
})
))
It really is as straightforward as you thought. You were close too, just fell into some syntax traps. I made the following changes:
that c(isolate(.. call was messing things up, I got rid of it. It was leading to those "Warning: Error in as.data.frame.default: cannot coerce class "c("ReactiveValues", "R6")" to a data.frame" errors.
Also you were reusing the rvTL name too often which is confusing and can lead to conflicts, so I renamed a couple of them.
I also added a loaded file name list (lfnamelist) to keep track of what was loaded. I could have used names(rvTL$dflist) for this but it didn't occur to me at the time - and I also this is a useful example of how to organize related reactive values into one declaration.
And then I added rendered selectInput so you can inspect what is saved in the reactiveValue list.
So here is the adjusted code:
library(shiny)
runApp(shinyApp(
ui=(fluidPage(
titlePanel("amend data frame"),
mainPanel(
fileInput("file", "Upload file", multiple=T),
tabsetPanel(type="tabs",
tabPanel("rvTL tab",
numericInput("Delete", "Delete row:", 1, step = 1),
uiOutput("filesloaded"),
actionButton("Go", "Delete!"),
verbatimTextOutput("df_data_files"),
verbatimTextOutput("values"),
verbatimTextOutput("rvTL_names"),
tableOutput("rvTL_out")
),
tabPanel("values tab",
tableOutput("df_data_out")
)
)))),
server = (function(input, output) {
values <- reactiveValues(df_data = NULL) ##reactiveValues
rvTL <- reactiveValues(dflist=NULL,lfnamelist=NULL)
observeEvent(input$file, {
req(input$file)
values$df_data <- read.csv(input$file$datapath)
rvTL$dflist[[input$file$name]] <-read.csv(input$file$datapath)
rvTL$lfnamelist <- c( rvTL$lfnamelist, input$file$name )
})
observeEvent(input$Go, {
temp <- values$df_data[-input$Delete, ]
values$df_data <- temp
})
output$df_data_files <- renderPrint(input$file$name)
output$values <- renderPrint(names(values))
output$rvTL_names <- renderPrint(names(rvTL$dflist))
output$rvTL_out <- renderTable(rvTL$dflist[[input$lftoshow]])
output$df_data_out <- renderTable(values$df_data)
output$filesloaded <- renderUI(selectInput("lftoshow","File to show",choices=rvTL$lfnamelist))
})
))
And here is a screen shot: