I was wondering how to create a table with all the data from the user's csv file. I would like the data to be uploaded into a tabPanel. Currently, I am running into the issue that no data is being displayed.
library(shiny)
ui <- fluidPage(
navbarPage("Dashboard",
tabPanel(title = "Model",
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose .csv file", #add red asterisks to make this mandatory
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv"),
),
),
mainPanel(
tabsetPanel(
tabPanel("Data",
tableOutput("tableOne"))
)
)
)
)
)
)
server <- function(input,output){
data <- reactive({
file1 <- input$file
if(is.null(file1)){return()}
read.table(file=file1$datapath)
})
output$filedf <- renderTable({
if(is.null(data())){return ()}
input$file
})
output$tableOne <- renderTable({
if(is.null(data())){return ()}
data()
})
output$data <- renderTable(output$tableOne)
}
shinyApp(ui,server)
I'm not sure why the output$data <- renderTable(output$tableOne is not allowing the data to be displayed.
The input should match i.e. file1 is the input and not just file
library(shiny)
ui <- fluidPage(
navbarPage("Dashboard",
tabPanel(title = "Model",
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose .csv file", #add red asterisks to make this mandatory
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv"),
),
),
mainPanel(
tabsetPanel(
tabPanel("Data",
tableOutput("tableOne"))
)
)
)
)
)
)
server <- function(input,output){
data <- reactive({
req(input$file1)
file1 <- input$file1
if(is.null(file1)){return()}
read.table(file=file1$datapath)
})
output$tableOne <- renderTable({
req(input$file1)
if(is.null(data())){return ()}
data()
})
#output$data <- renderTable(output$tableOne)
}
shinyApp(ui,server)
-output
Related
I am working with R shiny for pheatmap, I want to read files and draw heatmaps, but it did not work. The csv file could be read, however, the content could not be seen from the web, and the heatmap could not be drawn.
library(shiny)
library(pheatmap)
ui = fluidPage("Test",
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
tags$hr(),
checkboxInput("header", "Header", TRUE)
),
tabPanel('map',
sidebarLayout(
sidebarPanel('side',
actionButton('getHmap', 'get heatmap')
),
mainPanel('main',
plotOutput("themap")
)
))
)
server = function(input, output, session) {
a <- reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
tbl <- read.csv(inFile$datapath, header=input$header, sep=input$sep, dec = input$dec)
return(tbl)
})
output$table.output <- renderTable({
a()
})
observeEvent(input$getHmap, {
row.names(a) <- a$Name
a <- a[,-1]
a[is.na(a)] <- 0
output$themap = renderPlot({
pheatmap(a)
})
})
}
shinyApp(ui, server)
```[![The original data I used][1]][1]
[1]: https://i.stack.imgur.com/S83cH.png
This could be a full working example. This seems to work at my end. The following changes were made:
Added tableOutput("table.output") to ui
Simplified read.csv as inputs for sep and dec were missing
Created plotData function as eventReactive to plot heatmap with action button
Converted data to matrix before adding rownames for plot
The output$themap calls the plotData function
library(shiny)
library(pheatmap)
ui = fluidPage("Test",
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
tags$hr(),
checkboxInput("header", "Header", TRUE)
),
tabPanel('map',
sidebarLayout(
sidebarPanel('side',
actionButton('getHmap', 'get heatmap')
),
mainPanel('main',
plotOutput("themap"),
tableOutput("table.output")
)
))
)
server = function(input, output, session) {
a <- reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
tbl <- read.csv(inFile$datapath, header=input$header) #, sep=input$sep, dec = input$dec)
return(tbl)
})
output$table.output <- renderTable({
a()
})
plotdata <- eventReactive(input$getHmap, {
a <- as.matrix(a()[-1])
row.names(a) <- a()$Name
a[is.na(a)] <- 0
a
})
output$themap = renderPlot({
pheatmap(plotdata())
})
}
shinyApp(ui, server)
I am developing a R Shiny application which will rely on a module in hopes that I can re-use the module for uploading and displaying two different data sets. As of now, my code works but I think I could make it a little bit cleaner as I don't think I have gotten the module correct. By that I mean, how do I move this code snippet (below) out of the app_server and into the module server and then use the callModule function for two different datasets. Similarly, I probably need to remove this code: tableOutput("metacontent") from the app ui and have that call in the module ui. See the module ui, module server, app ui, and app server below code snippet. Any suggestions? Thanks!
#code snippet
output$metacontents <- renderTable({
metafile()
})
# Module UI
mod_dataInput_ui <- function(id, label) {
# Create a namespace function using the provided id
ns <- NS(id)
tagList(
# Input: Select a file ----
fileInput(ns("id"), label,
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv",
".tsv")),
# Input: Select separator ----
radioButtons(ns("sep"), "Separator",
choices = c(Comma = ",",
Tab = "\t"),
selected = "\t"))
}
# Module Server
mod_dataInput_server <- function(input, output, session) {
userFile <- reactive({
validate(need(input$id !="", "Please import a data file"))
input$id
})
datafile <- reactive({
utils::read.table(userFile()$datapath,
header = FALSE,
sep = input$sep,
row.names = NULL,
skip = 1,
stringsAsFactors = FALSE)
})
}
#App UI
app_ui <- function() {
tagList(
# Leave this function for adding external resources
golem_add_external_resources(),
# List the first level UI elements here
navbarPage("Tinsel",
tabPanel("Load Data",
sidebarPanel(mod_dataInput_ui("dataInput_ui_meta", tags$div("User META data", tags$br(), "(.csv, .tsv, or .txt file format)")), helpText("Can add help text here"),
# Horizontal line ----
tags$hr(style="border-color: black;"),
mod_dataInput_ui("dataInput_ui_gene", tags$div("User GENETIC data", tags$br(), "(.csv, .tsv, or .txt file format)")),
tags$hr(style="border-color: black;")),
mainPanel(
tabsetPanel(
tabPanel("Meta Data",
tableOutput("metacontents")),
tabPanel("Genetic Data",
tableOutput("genecontents"))
)))
)
)
}
#App server
app_server <- function(input, output, session) {
# List the first level callModules here
metafile <- callModule(mod_dataInput_server, "dataInput_ui_meta")
output$metacontents <- renderTable({
metafile()
})
genefile <- callModule(mod_dataInput_server, "dataInput_ui_gene")
output$genecontents <- renderTable({
genefile()
})
}
As far as I see it, you've gotten the module correctly: you're reusing the UI and server on two different IDs for the data import.
You can optimize what you've done by creating a module for the table part, so writing:
# mod_table.R
mod_table_ui <- function(id, name){
ns <- NS(id)
tabPanel(
name,
tableOutput(ns("metacontents"))
)
}
# Module Server
#' #rdname mod_table
#' #export
#' #keywords internal
mod_table_server <- function(input, output, session, file){
ns <- session$ns
output$metacontents <- renderTable({
file()
})
}
And then in app_ui:
#' #import shiny
app_ui <- function() {
tagList(
# Leave this function for adding external resources
golem_add_external_resources(),
# List the first level UI elements here
navbarPage(
"Tinsel",
tabPanel(
"Load Data",
sidebarPanel(
mod_dataInput_ui(
"dataInput_ui_meta",
tags$div(
"User META data",
tags$br(),
"(.csv, .tsv, or .txt file format)"
)
),
helpText("Can add help text here"),
# Horizontal line ----
tags$hr(style="border-color: black;"),
mod_dataInput_ui(
"dataInput_ui_gene",
tags$div(
"User GENETIC data",
tags$br(),
"(.csv, .tsv, or .txt file format)"
)
),
tags$hr(style="border-color: black;")
),
mainPanel(
tabsetPanel(
mod_table_ui("table_ui_1", "Meta Data"),
mod_table_ui("table_ui_2", "Genetic Data")
)
)
)
)
)
}
And app_server:
app_server <- function(input, output, session) {
# List the first level callModules here
metafile <- callModule(mod_dataInput_server, "dataInput_ui_meta")
callModule(mod_table_server, "table_ui_1", metafile)
genefile <- callModule(mod_dataInput_server, "dataInput_ui_gene")
callModule(mod_table_server, "table_ui_2", genefile)
}
Let me know if that answers your question.
This is how I would do it.
library(shiny)
library(ggplot2)
#ui.R
ui <- fluidPage(
titlePanel("My shiny app"), sidebarLayout(
sidebarPanel(
helpText("This app shows how a user can upload a csv file. Then, plot the data.
Any file can be uploaded but analysis is only available
if the data is in same format as the sample file, downloadable below
"),
a("Data to be plotted", href="https://www.dropbox.com/s/t3q2eayogbe0bgl/shiny_data.csv?dl=0"),
tags$hr(),
fileInput("file","Upload the file"),
h5(helpText("Select the read.table parameters below")),
checkboxInput(inputId = 'header', label = 'Header', value = TRUE),
checkboxInput(inputId = "stringAsFactors", "stringAsFactors", FALSE),
br(),
radioButtons(inputId = 'sep', label = 'Separator', choices = c(Comma=',',Semicolon=';',Tab='\t', Space=''), selected = ',')
),
mainPanel(
uiOutput("tb"),
plotOutput("line")
)
)
)
#server.R
server <- function(input,output){
data <- reactive({
file1 <- input$file
if(is.null(file1)){return()}
read.table(file=file1$datapath, sep=input$sep, header = input$header, stringsAsFactors = input$stringAsFactors)})
output$filedf <- renderTable({
if(is.null(data())){return ()}
input$file
})
output$sum <- renderTable({
if(is.null(data())){return ()}
summary(data())
})
output$table <- renderTable({
if(is.null(data())){return ()}
data()
})
output$line <- renderPlot({
if (is.null(data())) { return() }
print(ggplot(data(), aes(x=date, y=aa)) + geom_line()+ facet_wrap(~station)) })
output$tb <- renderUI({if(is.null(data()))
h5()
else
tabsetPanel(tabPanel("About file", tableOutput("filedf")),tabPanel("Data", tableOutput("table")),tabPanel("Summary", tableOutput("sum")))
})
}
shinyApp(ui = ui, server = server)
I am trying to upload a file to Shiny to crunch it and then view it.
I already was able to create a table with a CSV document, but the output myData can't be used as an input for a boxplot or any other graph.
SERVER
shinyServer(function(input, output, session){
myData <- reactive({
inFile <- input$file1
if (is.null(inFile)) return(NULL)
data <- read.csv(inFile$datapath, header = TRUE)
data
})
output$contents <- renderTable({
myData()
})
}
UI
library(shiny)
write.csv(data.frame(a = 1:10, b = letters[1:10]), 'test.csv')
shinyUI(fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv'))
),
mainPanel(
tableOutput('contents'),
plotOutput('distPlot')
)
)
)
)
How can I use the data from the file I uploaded out of the function myData?
You should use the functions renderDataTable and dataTableOutput from the DT package for rendering your tables. Your code works fine like this:
library(shiny)
library(DT)
server <- function(input, output, session){
myData <- reactive({
inFile <- input$file1
if (is.null(inFile)) return(NULL)
data <- read.csv(inFile$datapath, header = TRUE)
data
})
output$contents <- DT::renderDataTable({
DT::datatable(myData())
})
}
write.csv(data.frame(a = 1:10, b = letters[1:10]), 'test.csv')
ui<- shinyUI(fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept=c('text/csv',
'text/comma-separated-values,text/plain',
'.csv'))
),
mainPanel(
DT::dataTableOutput('contents'),
plotOutput('distPlot')
)
)
)
)
shinyApp(ui,server)
Also see the article below:
It is also possible to have an user upload csv's to your Shiny app. The code below shows a small example on how this can be achieved. It also includes a radioButton input so the user can interactively choose the separator to be used.
library(shiny)
library(DT)
# Define UI
ui <- shinyUI(fluidPage(
fileInput('target_upload', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)),
radioButtons("separator","Separator: ",choices = c(";",",",":"), selected=";",inline=TRUE),
DT::dataTableOutput("sample_table")
)
)
# Define server logic
server <- shinyServer(function(input, output) {
df_products_upload <- reactive({
inFile <- input$target_upload
if (is.null(inFile))
return(NULL)
df <- read.csv(inFile$datapath, header = TRUE,sep = input$separator)
return(df)
})
output$sample_table<- DT::renderDataTable({
df <- df_products_upload()
DT::datatable(df)
})
}
)
# Run the application
shinyApp(ui = ui, server = server)
Here is an example that I could browse a file as input, but instead of browsing I would like to paste the data from clipboard. Any idea ?
if (interactive()) {
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
tags$hr(),
checkboxInput("header", "Header", TRUE)
),
mainPanel(
tableOutput("contents")
)
)
)
server <- function(input, output) {
output$contents <- renderTable({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
read.csv(inFile$datapath, header = input$header)
})
}
shinyApp(ui, server)
}
You can use textAreaInput() for user to paste his data and then do whatever you need to with it. See the doc page here.
ui <- fluidPage(
textAreaInput("caption", "Caption", "Data Summary", width = "1000px"),
verbatimTextOutput("value")
)
server <- function(input, output) {
output$value <- renderText({ input$caption })
}
shinyApp(ui, server)
Here is my plan for the website:
I use file upload to read a csv file from my local computer using the following code:
datatable <- reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
read.csv(inFile$datapath, header=input$header, sep=input$sep, quote=input$quote)
})
in my ui.R, I will use a select menu to show all the column names of datatable. I will pick more names, like 2, from here.
According to what column names I pick, I will generate some plots.
So, here are my questions:
How can I get those column names in ui.R from the data.frame generated in server.R?
How can I transfer the picked names in ui.R back to server.R so that I can generate the plots?
I read some examples like http://shiny.rstudio.com/gallery/update-input-demo.html or something about renderUI, but I just do not know how to use them or it they are the right way to do this.
Here is my all code. In server.R:
library(shiny)
options(shiny.maxRequestSize=300*1024^2)
shinyServer(function(input, output) {
datatable <- reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
read.csv(inFile$datapath, header=input$header, sep=input$sep, quote=input$quote)
})
output$contents <- renderDataTable({
datatable()
}, options = list(orderClasses = TRUE))
output$summary <- renderPrint({
summary(datatable(),20)
aaa <- "afefagfaegar"
list(summary(datatable(),20),aaa)
})
})
Here is the code in ui.R
library(shiny)
shinyUI(navbarPage("",
tabPanel("Data Summary",
fluidPage(
titlePanel("Uploading Files"),
sidebarLayout(
sidebarPanel(
width=2,
fileInput('file1', 'Choose CSV File',
accept=c('text/csv','text/comma-separated-values,text/plain','.csv')),
tags$hr(),
checkboxInput('header', 'Header', TRUE),
radioButtons('sep', 'Separator',c(Comma=',',Semicolon=';',Tab='\t'),','),
radioButtons('quote', 'Quote',c(None='','Double Quote'='"','Single Quote'="'"),'"')
),
mainPanel(
tabsetPanel(type = "tabs",
tabPanel("Table", dataTableOutput('contents')),
tabPanel("Summary", verbatimTextOutput("summary"))
)
)
)
)
),
tabPanel("Single factor",
fluidPage(
sidebarLayout(
sidebarPanel(
***#I think I should put something here for the select menu***
),
mainPanel()
)
)
),
tabPanel("Multiple factors")
)
)
I think I figure out how to do this.
In server.R, I put:
output$singlefactor <- renderUI({
selectInput("sfactor", "Feature selection:", names(datatable()))
})
In ui.R, I do like:
uiOutput("singlefactor")
So far, everything is fine.