Displaying True When Shiny Files Are Split into Different Folders

displaying TRUE when shiny files are split into different folders

What's happening is that source returns a list with 2 things inside: value which is the actual R code inside, and visible which is whether or not the code returned visibly or invisibly. The TRUE you are seeing is a reflection of the fact that the code returned visibly.

What you want to do is include the value of that list. So instead of

source("file.R", local = TRUE)

Change it to

source("file.R", local = TRUE)$value

That should fix it

Selected local files not displaying Shiny app with different criteria

When writing a Shiny application, it is always good to follow reactive programming principles (by using reactives() often but this is not the only requirement) and to sanitize your input with req() (see here) as much as possible.

Your question about having the specific combination in file names is more related to R than Shiny. Using paste() with lapply() should be sufficient to achieve what you need. On the other hand, as a rule of thumb, you should never leave spaces in the file names, use a hyphen or underscore if needed.

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
titlePanel("Compare"),
sidebarLayout(
sidebarPanel(
pickerInput(inputId = "countyInput", label = "Filter county",
choices = c("County1", "County2", "County3", "County4", "County5"),
options = list(`actions-box` = TRUE,size = 10, `selected-text-format` = "count > 9"),
multiple = TRUE),
checkboxGroupInput(inputId = "reasonInput", label = "Filter reason",
choices = c("Reason1", "Reason2", "Reason3"))
),
mainPanel(
uiOutput("images")
)
)
)

server <- function(input, output, session) {

file_name <- reactive({
req(input$countyInput)
req(input$reasonInput)
paste0(unlist(lapply(input$countyInput, function(i) {
paste0(i, input$reasonInput)
})), ".png")
})

# creating multiple outputs:
output$images <- renderUI({
tagList(
lapply(file_name(), function(file) {
output[[paste("img", file, sep = "_")]] <- renderImage({

filename <- file.path(Sys.getenv("HOME"), file)
# validation intermed objects and msg displayed in UI:
shiny::validate(
shiny::need(file.exists(filename), "File not found.")
)

list(src = filename,
alt = paste("Image name", file))
}, deleteFile = FALSE) # we don't want Shiny to delete our file after read.
})
)
})
}

shinyApp(ui, server)

How to split Shiny app code over multiple files in RStudio?

Yes, you can achieve that very easily in the same way you do that with every other project in RStudio: by using the R mechanisms provided to achieve that:

  • define functions and/or objects in separate files.
  • use source() in your main file to load their definitions

Code completion for shiny functions only occurs in RStudio when the shiny package is loaded using library(shiny). The 'Run App' button will be visible for the main file in the application. In the example below, that would be the app.R file. So if you want to run your app from within RStudio, you always have to go back to the main file.

standard example

An example :

In a file app.R you put:

library(shiny)
source('myUI.R', local = TRUE)
source('myServer.R')

shinyApp(
ui = myUI,
server = myserver
)

This code does nothing else but initiate the objects myUI and myserver and call the app.

The file myUI.R contains

source('Tabs.R')
myUI <- shinyUI({
fluidPage(
tabsetPanel(
Tab1,
Tab2
)
)
})

This file defines the UI object used in app.R. The function tabsetPanel takes a number of tabPanels as arguments. These tabPanels are created in the following file (Tabs.R), so that one has to be sourced before the UI is constructed.

The file Tabs.R contains:

Tab1 <- tabPanel("First Tab",
selectInput("select",
"Choose one",
choices = letters[1:3],
selected = 'a'))

Tab2 <- tabPanel("Second Tab",
textOutput('mychoice'))

This file creates the tabPanel objects to be added to the tabsetPanel. In my own code, I store every tabPanel definition in a separate file.

The file myServer.R contains:

myserver <- function(input,output,session){
output$mychoice <- renderText(
input$select
)
}

And if you want, you can again create separate files with functions that can be used inside the server function. But you always have to follow the classic R logic: assign things to an object and refer to that object at the position you want to insert it.

You can also source code directly inside the server() function. In that case you should source locally using source(..., local = TRUE), so the created objects are contained inside the server function. See also : https://shiny.rstudio.com/articles/scoping.html

Using modules

If you want to take it up a notch and reuse a certain logic and layout (eg a plot option control panel that should be attached to some plots), you should go to modules. (see also http://shiny.rstudio.com/articles/modules.html )

Modules can again be stored in a separate file, and that file sourced in the app.R file you have.

Shiny - How to separate the Rendering functions into different files?

I don't think you need to call getRenderUI(), you could try this

In getRenderUI.R

output$text <- renderUI({...})

In server.R

shinyServer(function(input, output, session) {

source('...../getRenderUI.R', local = TRUE)$value

}))

For me , this works well.

Note: Pay attention not to use the same name for output$xxx, because all variables is in the same scope

Split files present in different Folders in R

Use -

dir <- "/home/folder"
my_dirs <- list.dirs(dir, recursive = FALSE)

for(i in my_dirs){
a <- list.files(path = i, full.names = TRUE, recursive = TRUE)
df <- read.csv(a)
a0 <- df[df$CN=="cn=0",]
a1 <- df[df$CN=="cn=1",]
a3 <- df[df$CN=="cn=3",]
a4 <- df[df$CN=="cn=4",]
write.csv(a0,paste(i,"cn0.csv",sep="/"))
write.csv(a1,paste(i,"cn1.csv",sep="/"))
write.csv(a3,paste(i,"cn3.csv",sep="/"))
write.csv(a4,paste(i,"cn4.csv",sep="/"))
}

Explanation

In your initial implementation, write.csv(a0,"cn0.csv") implies you are writing a csv file named cn0.csv to your present working directory.

Next time the loop comes, it is just overriding the existing file again and again.

To avoid this, you need to specify the directory correctly for each csv write, which has been done by modifying to write.csv(a0,paste(i,"cn0.csv",sep="/")), which populates the correct target directory.

How to create a list of files in shiny?

fileInput stores information about the selected files in a data frame. The data frame has the columns 'name', 'size', 'type' and 'datapath'. The files are internally copied with random path names (e.g. "...AppData\Local\Temp\RtmpMxmB1G/48101199adb41c8ae7de0e78/3.txt") that can be access with input$files$datapath.

Instead of your for loop and your function count_genes() you can use: tbl_list <- lapply(input$files$datapath, read.table, header=TRUE, sep=";") directly to read each file in into the list 'tbl_list' or if you need the the file paths only you can use with your function count_genes()

Depending on your function count_genes() your object lst1() contains different things, i.e. the object that is returned in the function count_genes(). Using your function count_genes() as given in your question, lst1() is a list object, which cannot be handled by renderDataTable. To use renderDataTable you first need to convert your list into a data frame in the function count_genes().

Here's a minimal example which may help:

library(shiny)

# Define UI for data upload app ----
ui <- fluidPage(

# App title ----
titlePanel("Uploading Files"),

# Sidebar layout with input and output definitions ----
sidebarLayout(

# Sidebar panel for inputs ----
sidebarPanel(

# Input: Select a file ----
fileInput("files", "Upload", multiple = TRUE, accept = c(".xls"))
),

# Main panel for displaying outputs ----
mainPanel(
# Output: Data file ----
dataTableOutput("tbl_out")

)

)
)

# Define server logic to read selected file ----
server <- function(input, output) {
lst1 <- reactive({
validate(need(input$files != "", "select files..."))

if (is.null(input$files)) {
return(NULL)
} else {

path_list <- as.list(input$files$datapath)
tbl_list <- lapply(input$files$datapath, read.table, header=TRUE, sep=";")

df <- do.call(rbind, tbl_list)
return(df)
}
})

output$tbl_out <- renderDataTable({
lst1()
})

}

# Create Shiny app ----
shinyApp(ui, server)


Related Topics



Leave a reply



Submit