I have a simple shiny app and when I press a button a .csv file is saved in the directory where the file app.R is.
I want to be able to read this csv file and render the information in a table on my shiny app.
This is a similiar example about what I would like to do
df <- data.frame(no =c(1:3),money=c(9999:10001),penalty=c(999:1001))
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),actionButton("sort","Do Sorting")
),
mainPanel(
tableOutput("contents"),tableOutput("sortedcontents")
)
)
)
server <- function(input, output) {
rawInputData = reactive({
rawData = input$file1
if(!is.null(rawData)) {
data = read.csv(rawData$datapath);
} else {
return(NULL);
}
});
output$contents <- renderTable({
newData = rawInputData()
if(is.null(newData))
return();
newData;
})
sorting = reactive({
if(input$sort){
newData = rawInputData()
newData$moneysort <- ifelse(newData$money >=10000, 1, 0)
newData$penaltysort <- ifelse(newData$penalty >=1000, 1, 0)
}
newData
})
output$sortedcontents <- renderTable({
newData = sorting()
if(is.null(newData))
return();
newData;
})
}
}
shinyApp(ui, server)
Instead to have the opportunity to choose the file with a fileInpunt() I would like to avoid this step and automatically check a specific directory to look for the csv called "myData.csv" and render this csv in a table.
Here is an example of just reading data from local directory and rendering in shiny.
library(shiny)
write.csv(iris, 'iris.csv')
df = read.csv('iris.csv')
shinyApp(
ui = fluidPage(
fluidRow(
column(12,
tableOutput('iris_table')
)
)
),
server = function(input, output) {
output$iris_table <- renderTable(df)
}
)
This example uses a slight modification from this shiny TableOutput reference.
Related
I am trying to create a Shiny dashboard where the user can upload data sets, naming them, and then selecting one data set from a dropdown menu.
I dont fully understand how a user can upload a data, save it and further access it. I tried using assign(), but the dataset does not show up under ls(). My try:
library(data.table)
library(shinyWidgets)
library(shinydashboard)
if (interactive()) {
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
actionButton('show_ls', 'show_ls'),
# Name data
textInput('name_data', 'Store data as' , value = ''),
# Action button to upload
actionButton('upload_data', 'Upload and save data')
),
mainPanel(
tableOutput('ls')
# textOutput('ls'))
)
)
)
server <- function(input, output, session) {
# This part uploads one row from the file, so the user can selects columns and choose name of the file
data <- reactive({
file1 <- input$file1
if(is.null(file1)){return()}
data_input <- fread(file=file1$datapath, sep=",")
updateTextInput(
session,
'name_data',
value = file1$name
)
return(data_input)
})
#### ASSIGNING THE DATA
assign_data <- eventReactive(input$upload_data, {
assign(input$name_data, data(), envir = .GlobalEnv)
})
assign_the_data <- reactive(assign_data())
output$contents <- renderTable({
if(is.null(data())) return(NULL)
data()
})
outputOptions(output, 'contents', suspendWhenHidden = FALSE)
show_ls <- eventReactive(input$show_ls, {data.frame(a = ls(.GlobalEnv))})
output$ls <- renderTable({
show_ls()
})
}
shinyApp(ui, server)
}
Using assign() can be difficult because the search path through the namespace can be difficult to predict. A better solution would be to store the datasets in a reactive values list and access them from there. You can dynamically render the dataset picker UI based on the names of the datasets stored in the reactive values list.
if (interactive()) {
ui <- fluidPage(sidebarLayout(
sidebarPanel(
fileInput(
"file1",
"Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv"
)
),
# Name data
textInput('name_data', 'Store data as' , value = ''),
# Action button to upload
actionButton('upload_data', 'Upload and save data')
),
mainPanel(uiOutput("dataset_picker"),
tableOutput('selected_table')
# textOutput('ls')))
))
server <- function(input, output, session) {
# This part uploads one row from the file, so the user can selects columns and choose name of the file
dfs <- reactiveValues()
observeEvent(input$upload_data, {
req(input$file1, input$name_data)
dfs[[input$name_data]] <- read.csv(input$file1$datapath[1])
print(names(dfs))
})
output$dataset_picker <- renderUI({
req(length(dfs) > 0)
pickerInput(
"dataset_picker",
label = "Choose dataset",
choices = names(reactiveValuesToList(dfs)),
selected = NULL
)
})
output$selected_table <- renderTable({
req(input$dataset_picker)
dfs[[input$dataset_picker]]
})
}
shinyApp(ui, server)
}
Here is an example. What I wanted is to display the example data if user click Show example or will display the data uploaded by user.
df<-data.frame(x=rnorm(9),
y=rnorm(9),
z=rnorm(9))
write.table(df, "test.txt", quote=F)
library(shiny)
ui <- shinyUI(pageWithSidebar(
headerPanel("test"),
sidebarPanel(
actionButton("evReactiveButton", "Show example"),
fileInput("file1", "Upload File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv"))
),
mainPanel(
tableOutput("matrix")
)
))
server <- function(input, output, session) {
#if action button show example
datobj<-reactive({
dat<-matrix(1:100, nrow=10)
return(dat)
})
#if user upload
datobj <- reactive({
req(input$file1)
dat <- read.table(input$file1$datapath)
return(dat)
})
### matrix file
output$matrix <- renderTable({
return(datobj())
})
}
shinyApp(ui=ui,server=server)
Here's one way to do it using observeEvent. I added an actionButton to switch more easily between the example data (not reactive here) and the data the user imports. If you want to remove this button, don't forget to replace also the second observeEvent environment by observe.
df<-data.frame(x=rnorm(9),
y=rnorm(9),
z=rnorm(9))
write.table(df, "test.txt", quote=F)
library(shiny)
ui <- shinyUI(pageWithSidebar(
headerPanel("test"),
sidebarPanel(
actionButton("example", "Show example"),
fileInput("file1", "Upload File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
actionButton("import", "Show data imported")
),
mainPanel(
tableOutput("matrix")
)
))
server <- function(input, output, session) {
#if action button show example
datobj<- mtcars
#if user upload
datobj2 <- reactive({
req(input$file1)
dat <- read.table(input$file1$datapath, sep = " ")
return(dat)
})
### matrix file
observeEvent(input$example, {
output$matrix <- renderTable({
datobj
})
})
observeEvent(input$import, {
if (!is.null(datobj2())){
output$matrix <- renderTable({
datobj2()
})
}
else {}
})
}
shinyApp(ui=ui,server=server)
I am not sure if it makes sense. But I am looking for some help with using Shiny. Here is what I need, first, read some csv file on the shiny server. Second, by clicking a button as an if-then-else statement proceeds each observation's value of data sorted somehow.
csv:
no,money,penalty
1,10000,1000
2,20000,1000
3,30000,2000
if-then-else statement:
if money >10000 then 1 else 0
if penalty >1000 then 1 else 0
here is the r-shiny code I am working on:
# Load packages
library(shiny)
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({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, it will be a data frame with 'name',
# 'size', 'type', and 'datapath' columns. The 'datapath'
# column will contain the local filenames where the data can
# be found.
inFile <- input$file1
if (is.null(inFile))
return(NULL)
read.csv(inFile$datapath, header = input$header)
})
}
shinyApp(ui, server)
}
Thank you for your help ahead.
I have taken below df as an example
df <- data.frame(no =c(1:3),money=c(9999:10001),penalty=c(999:1001))
Below is the complete code which will work if you input any file with column names like the above df
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),actionButton("sort","Do Sorting")
),
mainPanel(
tableOutput("contents"),tableOutput("sortedcontents")
)
)
)
server <- function(input, output) {
rawInputData = reactive({
rawData = input$file1
if(!is.null(rawData)) {
data = read.csv(rawData$datapath);
} else {
return(NULL);
}
});
output$contents <- renderTable({
newData = rawInputData()
if(is.null(newData))
return();
newData;
})
sorting = reactive({
if(input$sort){
newData = rawInputData()
newData$moneysort <- ifelse(newData$money >=10000, 1, 0)
newData$penaltysort <- ifelse(newData$penalty >=1000, 1, 0)
}
newData
})
output$sortedcontents <- renderTable({
newData = sorting()
if(is.null(newData))
return();
newData;
})
}
}
shinyApp(ui, server)
If you are looking something like this, let me know I can fine tune it a bit.
I am building an app in shiny (R). At the beginning the user can upload a file to use (I am doing a sort data analysis). My goal is to be able to use files without knowing how many columns this file has, and how the data exactly looks like.
So now I have to select the columns by number, and I made a small preview app for this to select columns and then display them next to the original:
library(shiny)
ui <-fluidPage(
headerPanel("Select data"),
sidebarLayout(
sidebarPanel(
fileInput("uploadFile", "XLSX file"),
textInput('vec1', 'Choose training columns', "3,4"),
actionButton("choose","choose data")
),
mainPanel(
fluidRow(
column(6,tableOutput("data_raw")),
column(6,tableOutput("data_selected"))
)
)
)
)
server <- function(input, output) {
output$data_raw <- renderTable({
inFile <- input$uploadFile
if (is.null(inFile))
return(NULL)
data_raw <<-read.xlsx(inFile$datapath, 1)
})
observe({
if(input$choose>0){
selectvec <- as.numeric(unlist(strsplit(input$vec1,",")))
output$data_selected <- renderTable(
data_selected<- data_raw[,selectvec]
)
}
})
}
shinyApp(ui,server)
Now I would like to be able to select the columns to use on basis of their header.
It feels unnatural: changing the app while running.. but in a reactive environment.. why not?
QUESTION: How can I change the UI while it is allready running, with values originating from the input?
kind regards,
Pieter
To make me feel not as dirty for answering this...I didn't debug or handle reactives properly. But here ya go. You need to respond to the file that is uploaded on the server side, extract the column names, and append thosed to the choices in a select input that then passes down to the table function as a column filter.
upload_app <- function(){
library(shiny)
ui <- bootstrapPage(
tags$div(class = "container",
column(3,
fluidRow(
fileInput(inputId = 'user_data',
label = 'Upload Data (csv)',
multiple = FALSE,
accept = c(
'text/csv',
'text/comma-separated-values',
'text/tab-separated-values',
'text/plain',
'.csv',
'.tsv'
))
),
fluidRow(
uiOutput('column_vars')
)
),
column(9,
tableOutput('filtered_table'))
)
)
server <- function(session, input, output){
var_table <- reactive({
var_data <- input$user_data
read.csv(var_data$datapath, header = TRUE,sep = ",", quote = '')
})
output$column_vars <- renderUI({
if(!is.null(var_table())){
selectInput(inputId = 'cols',
choices = colnames(var_table()),
multiple = T,
label = "Choose Columns")
}
})
output$filtered_table <- renderTable({
if(!is.null(var_table())){
if(length(input$cols)>0){
get_these <- input$cols
new_table <- var_table()[,c(get_these)]
}else {
new_table <- var_table()
}
}else {
new_table <- data.frame(data = 'Waiting')
}
return(new_table)
})
}
shinyApp(ui, server)
}
I have a shiny app, that reads in files that are uploaded by a user
Different people have different versions of excel. So if a user is using excel 2007 or excel 2010 we use one section of code. If they upload it in excel 2003 we use a different library to read the file. The user specifies in the form which version of excel they have
The function to do this is below
get_data <- function(strFilePath, storageType) {
if (is.null(strFilePath))
return(NULL)
if (storagetType == 'xls2010' || storagetType == 'xls2007'){
df <- openxlsx:read.xlsx(strFilePath,sheet = 1)
}
else if (storagetType == 'xls2003'){
df <- XLConnect:readWorksheetFromFile(strFilePath)
}
return(df)
}
To implement this in shiny, i have two widgets. A fileInput and a selectInput. The user selects which version of excel they are running and then selects the file which then is read in by the function get_data. I suspect its because I'm not utilizing the reactivity correctly. When i run the app and upload the file i get the error message
Error: object 'storagetType' not found
# Global.R
storage_types <- c(
"Excel 2010" = "xls2010",
"Excel 2007" = "xls2007",
"Excel 2003" = "xls2003"
)
# UI.R
ui <- shinyUI(fluidPage(
navbarPage("Navbar!",
# Tab contains all the information to upload a file
tabPanel("Upload Data",
# Side Panel with Options
fluidRow(
column(4, wellPanel(
id = "leftPanel",
div(
id = "Header",
h3("Options", align = "center"),
tags$hr()
),
div(
selectInput("xlsversion", "2. Select your Excel version", storage_types),
fileInput(inputId = 'file1',label = '3. Choose An Excel File'),
)
)))))))
# Server.R
server <- shinyServer(
function(input, output) {
# When the Browser to the file location gets updated
upload_data <- reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
get_data(inFile$datapath, input$xlsversion)
})
})
You not need selectInput simply parse name of file.
Also some typo fixed
library(shiny)
get_data <- function(strFilePath, storageType) {
if (is.null(strFilePath))
return(NULL)
file_ext=substring(storageType,nchar(storageType)-3)
if (file_ext == 'xlsx' ){
df <- openxlsx::read.xlsx(strFilePath,sheet = 1)
}
else if (file_ext == '.xls'){
df <- XLConnect::readWorksheetFromFile(strFilePath,sheet=1)
} else{
return(data.frame("Bad file format"))
}
return(df)
}
# UI.R
ui <- shinyUI(fluidPage(
navbarPage("Navbar!",
# Tab contains all the information to upload a file
tabPanel("Upload Data",
# Side Panel with Options
fluidRow(
column(4, wellPanel(
id = "leftPanel",
div(
id = "Header",
h3("Options", align = "center"),
tags$hr()
),
div(
fileInput(inputId = 'file1',label = '3. Choose An Excel File')
)
))),
dataTableOutput("result")))))
# Server.R
server <- function(input, output) {
# When the Browser to the file location gets updated
upload_data <- reactive({
if (is.null(input$file1))
return(NULL)
get_data(input$file1$datapath, input$file1$name)
})
output$result=renderDataTable({
upload_data()
})
}
shinyApp(ui,server)