How to use test.R to unmerge the column using R shiny - r

After I get the column name from the user, I want to unmerge the column 'alpha.'
I have the dataframe, and I have the same dataframe on my system as a csv file. (I'm highlighted the dataframe here for clarity) -> All of the following is occurring in the r script named test.R
What I'm looking for is a way to use test.R When I click the "Unmerge" button in R shiny, I should get the results (with unmerging columns) and the final dataset should render in the main panel.
Since I'm new to R Shiny, I'm not sure how to go about doing it.
Could someone please help me?
Note: The browse button should take the same data frame as csv and provide the unmerged results in the main panel.
test.R
library(dplyr)
library(tidyr)
library(stringr)
library(tidyverse)
library(stringr)
library(svDialogs)
column_name <- dlg_input("Enter a number", Sys.info()["user"])$res
before_merge<- data.frame(ID=21:23, alpha=c('a b', 'c d', 'e z'))
before_merge
library(reshape2)
newColNames <- c("type1", "type2")
#column_name <- readline(prompt="Enter the desired column name: ")
newCols <- colsplit(before[[column_name]], " ", newColNames)
after_merge <- cbind(before, newCols)
after[[column_name]] <- NULL
after_merge
Shiny App
## Only run examples in interactive R sessions
library(shiny)
if (interactive()) {
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File", accept = ".csv"),
checkboxInput("header", "Header", TRUE),
actionButton("dataset2", "Extract", class = "btn-primary"),
),
mainPanel(
tableOutput("contents")
)
)
)
server <- function(input, output) {
output$contents <- renderTable({
file <- input$file1
ext <- tools::file_ext(file$datapath)
req(file)
validate(need(ext == "csv", "Please upload a csv file"))
read.csv(file$datapath, header = input$header)
})
observeEvent(input$dataset2, {
source("test.R", local = TRUE)
})
}
shinyApp(ui, server)
}

So what you want to do is twofold:
First, remove the dialog input from test.R and put in a corresponding input in Shiny itself. This is to identify the column, right? You can make a selectInput with the options being the column names that the dataframe has.
Next, put all the relevant code into a function. This function should do the following: take in an input dataframe (you are creating this before_merge in test.R, instead, use the dataframe that you are getting from the upload), do whatever you need to do (the colsplit, etc.), and then return the final result.
Once you have that, then it's just a matter of putting a line at the top of your Shiny file where you source your test.R, and then you can call the function directly.
Alternatively, you don't even need a separate test.R file - just put your function above the output$contents section and use it directly. It's useful to have a separate helper file if you have a lot of functions (or the functions are used elsewhere), but in this case you don't need it.

Related

uploading multiple file input and accessing them through the shiny app to perfrom a loop

I'm pretty stuck here; I have created a simple shiny app with the possibility of uploading multiple files. However, I don't know how can I move on from here and access the files directly within the shiny app, for example, get all the uploaded data files into one data.frame to perform a loop later on.
for example we have
data_1 <- "data file 1"
data_2 <- "data file 2"
data_3 <- "data file 3"
data_4 <- "data file 4"
dataSet <- data.frame(DATA= c(1,2,3,4),
DATAFILE=c(data_1 ,data_2 ,data_3 ,data_4))
Is there any way to do that? I hope I have been able to explain myself thoroughly. I really appreciate any help you can provide.
library(shiny)
options(shiny.maxRequestSize = 30 * 1024^2)
ui <- fluidPage(
fileInput("upload", NULL, buttonLabel = "Upload...", multiple = TRUE),
tableOutput("files")
)
server <- function(input, output, session) {
output$files <- renderTable(input$upload)
}
shinyApp(ui, server)
input$upload is a data.frame containing four columns, to read the files we'll need datapath column that contains the temp path with the uploaded data, in this case they are csv's. From there we use a function like readr::read_csv() to transform the raw uploaded data into a df.
We can construct a reactive that consists in a list with all the uploaded files in it.
# read all the uploaded files
all_files <- reactive({
req(input$upload)
purrr::map(input$upload$datapath, read_csv) %>%
purrr::set_names(input$upload$name)
})
Full app:
library(shiny)
library(tidyverse)
library(DT)
# create some data to upload
write_csv(mtcars, "mtcars.csv")
write_csv(mpg, "mpg.csv")
write_csv(iris, "iris.csv")
options(shiny.maxRequestSize = 30 * 1024^2)
ui <- fluidPage(
fileInput("upload", NULL, buttonLabel = "Upload...", multiple = TRUE),
DT::DTOutput("files"),
tableOutput("selected_file_table")
)
server <- function(input, output, session) {
output$files <- DT::renderDT({
DT::datatable(input$upload, selection = c("single"))
})
# read all the uploaded files
all_files <- reactive({
req(input$upload)
purrr::map(input$upload$datapath, read_csv) %>%
purrr::set_names(input$upload$name)
})
#select a row in DT files and display the corresponding table
output$selected_file_table <- renderTable({
req(input$upload)
req(input$files_rows_selected)
all_files()[[
input$upload$name[[input$files_rows_selected]]
]]
})
}
shinyApp(ui, server)
There are two stages to this:
When you select a file what happens is that is gets copied into a temp directory. One of the values returned by the input is the location of the temp file, another is the original file name.
Once you have the file path you can use a function to read the data from that temp file.
The example at the bottom of this should be helpful (although your example needs a little bit more than this one because you have selected multiple files):
https://shiny.rstudio.com/reference/shiny/1.6.0/fileInput.html

Read zip file containing multiple .csv tables in R shiny app

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.

How to clean up CSV data after uploading to Shiny App

Please help!
I'm trying to build a Shiny App with the intent to classify data loaded from a CSV file. How do I successfully create a DataFrame from a CSV file (that is uploaded) so that I can move forward and clean/analyze it.
Please see code:
library(shiny)
library(lubridate)
library(utils)
library(dplyr)
library(tidytext)
ui <- (pageWithSidebar(
headerPanel("CSV File Upload Demo"),
sidebarPanel(
#Selector for file upload
fileInput('datafile', 'Choose CSV file',
accept=c('text/csv', 'text/comma-separated-values,text/plain')),
#These column selectors are dynamically created when the file is loaded
uiOutput("fromCol"),
uiOutput("toCol"),
uiOutput("amountflag"),
#The conditional panel is triggered by the preceding checkbox
conditionalPanel(
condition="input.amountflag==true",
uiOutput("amountCol")
)
),
mainPanel(
tableOutput("filetable")
)
))
Please advise whether to use Reactive
server <- (function(input, output) {
#This function is repsonsible for loading in the selected file
filedata <- reactive({
infile <- input$datafile
if (is.null(infile)) {
# User has not uploaded a file yet
return(NULL)
}
dataframe <- reactive({
readr::read_csv(infile()$datapath)
})
# Clean data by whole-case removal of missing cells (either NAs or "nan")
# Remove the rows which have NAs
myDataClean2 = dataframe[complete.cases(dataframe),]
# In order to turn it into a tidy text dataset, we first put the data into a data frame:
text_df <- data_frame(myDataClean2$text,myDataClean2$title,myDataClean2$author,myDataClean2$id,myDataClean2$label)
names(text_df) <- c("text","title","author","id","label")
# Within the tidy text framework, we break both the text into individual tokens and transform
# it to a tidy data structure. To do this, we use tidytextâs unnest_tokens() function.
tidy_text_df <- text_df %>%
unnest_tokens(word, text)
#This previews the CSV data file
output$filetable <- renderText({
tidy_text_df()
})
})
})
# Run the application
shinyApp(ui = ui, server = server)
You are mixing reactive blocks. Your filedata should end with something that outputs your data, likely the output from unnest_tokens(word, text). (It should put out all data you are interested in, I think that that line does.) From there, your output$filetable needs to be outside of filedata's reactive block, on its own. And it should be using filedata(), not tidy_text_df (which isn't available outside of the first reactive block).
Try this:
server <- (function(input, output) {
#This function is repsonsible for loading in the selected file
filedata <- reactive({
infile <- input$datafile
if (is.null(infile)) {
# User has not uploaded a file yet
return(NULL)
}
dataframe <- reactive({
readr::read_csv(infile()$datapath)
})
# Clean data by whole-case removal of missing cells (either NAs or "nan")
# Remove the rows which have NAs
myDataClean2 = dataframe[complete.cases(dataframe),]
# In order to turn it into a tidy text dataset, we first put the data into a data frame:
text_df <- data_frame(myDataClean2$text,myDataClean2$title,myDataClean2$author,myDataClean2$id,myDataClean2$label)
names(text_df) <- c("text","title","author","id","label")
# Within the tidy text framework, we break both the text into individual tokens and transform
# it to a tidy data structure. To do this, we use tidytextâs unnest_tokens() function.
text_df %>%
unnest_tokens(word, text)
})
#This previews the CSV data file
output$filetable <- renderText({
filedata()
})
})

Specifying data range from excel in Shiny

I would like to know if its possible to create a shiny app which allows you to upload an excel file and which allows you to select a data range based on sheet name and cell range.
I would like to build upon it in order to showcase some regression analysis but haven't been able to find a starting point.
John, it is always a good idea to take a look at the Shiny gallery and take a look at past answers on Stack Overflow for code examples when faced with issues like these.
Here is a example tutorial for data upload. This can be CSV and not just xls.
https://shiny.rstudio.com/gallery/file-upload.html. But code layout may be useful for you to set up your inputs.
Keep it simple? You might be able to save the data range you want out as a csv file so your users do not have specify data range and sheet. I do this so users just simply need to look at what data sets they want in a select box and not go hunt for the data. See example below. (This may save you lots of error trapping code).
Do not forget to transform your data. Note this example where you might need to factor some of your variables.
As outlined above by Parth see https://www.r-bloggers.com/read-excel-files-from-r/ for more detail on packages Xl_Connect and xlsx. You can specify sheets.
WORKING WITH FILES
Some code snippets that may help you. I have the data blocks already available as csv files. Setting up an selectInput with a list of these files
# in ui.R
selectInput(("d1"), "Data:", choices = data.choices)
I fill data.choices in global.R with this code.
# filter on .csv
data.files <- list.files(path = "data", pattern = ".csv")
# dataset choices (later perhaps break by date)
# sort by date most recent so selectInput takes first one
data.choices <- sort(data.files, decreasing = TRUE)
I have a reactive around the selectInput that then loads the data. (I use data.tables package fread so you will need to install this package and use library(data.tables) if you use this code).
dataset1 <- reactive({
validate(
need(input$d1 != "", "Please select a data set")
)
if (!is.null(input$d1)) {
k.filename <- input$d1 # e.g. 'screendata20160405.csv'
isolate({
## part of code this reactive should NOT take dependency on
# LOAD CSV
s.dt <- fread(file.path("data", k.filename),
na.strings = c("NA", "#N/A")) %>%
rename(ticker = Ticker)
# You might choose to rather dot.the.column.names to save DT issues
#setnames(DT, make.names(colnames(DT)))
# SET KEYS IF RELEVANT
k.id.cols <- c("ticker")
if ("date" %in% names(s.dt)) {
k.id.cols <- c(k.id.cols, "date")
}
setkeyv(s.dt, k.id.cols)
# NAME CHANGES rename columns if necessary
setnames(s.dt, "Short Name", "name")
})
} else {
s.dt <- NULL #input$d1 is null
}
s.dt
})
Note the validates as my data is plotted and I want to avoid error messages. Please appreciate the key setting and renaming columns code above is not necessary but specific to my example, but shows you what you can do to get your data "ready" for user.
GET SHEET NAMES OUT
John this is very useful. Take a look at this long thread on google groups https://groups.google.com/forum/#!topic/shiny-discuss/Mj2KFfECBhU
Huidong Tian had this very useful code at 3/17/14 (but also see Stephane Laurent's code about closing XLConnect too to manage memory):
library(XLConnect)
shinyServer(function(input, output) {
Dat <- reactiveValues()
observe({
if (!is.null(input$iFile)) {
inFile <- input$iFile
wb <- loadWorkbook(inFile$datapath)
sheets <- getSheets(wb)
Dat$wb <- wb
Dat$sheets <- sheets
}
})
output$ui <- renderUI({
if (!is.null(Dat$sheets)) {
selectInput(inputId = "sheet", label = "Select a sheet:", choices = Dat$sheets)
}
})
observe({
if (!is.null(Dat$wb)) {
if (!is.null(input$sheet)){
dat <- readWorksheet(Dat$wb, input$sheet)
print(names(dat))
output$columns <- renderUI({
checkboxGroupInput("columns", "Choose columns",
choices = names(dat))
})
}
}
})
})
shinyUI(pageWithSidebar(
# Include css file;
tagList(
tags$head(
tags$title("Upload Data"),
tags$h1("Test")
)
),
# Control panel;
sidebarPanel(
fileInput(inputId = "iFile", label = "Escolha um arquivo:", accept="application/vnd.ms-excel"),
radioButtons("model", "Escolha do Modelo:",
list("CRS" = "crs",
"VRS" = "vrs")),
br(),
tags$hr(),
uiOutput(outputId = "ui"),
uiOutput(outputId = "columns")
),
# Output panel;
mainPanel()
))
You could include inputs for the file path and cell range, and use a shiny action button to send the input variables to read_excel()
https://shiny.rstudio.com/articles/action-buttons.html
http://readxl.tidyverse.org

Calling the filename from a reactive dataset in shiny r

I am currently writing a shiny app which imports a dataset and displays a manipulated version. To work on the shiny methods I am currently working on a simplified version which displays the imported dataset. I currently assign the imported dataset to a reactive value, and then use the render table as follows:-
shinyServer(function(input, output) {
DATA<-reactive({
input$filein
})
output$Dataset <- renderTable({
DATA()
})
})
The interface then produces a table with the following columns:-
name, size, type, datapath.
What I had in mind was to call the datapath variable, and use read.csv to call it within the renderTable function. I tried using:-
DATA()$datapath
However that doesn't seem to produce any result. Are there any other ways to extract this data within Shiny? I contemplated using vector indices as you would using regular R code however I am unsure as to whether or not that'll work within Shiny.
Here is an example for files in the current working directory. The example file I used was a minimal csv file (see bottom). Please note however that this is indeed limited to files in your working directory. If you want other files to be loaded you will need to have a further component to specify the path (possibly in the selectInput).
library(shiny)
library(tools)
runApp(
list(
ui = pageWithSidebar(
headerPanel("File Info Test"),
sidebarPanel(
p("Demo Page."),
selectInput("filein", "Choose File", choices=c("test.csv"))
),
mainPanel(
tableOutput("myTableInfo"),
tableOutput("myTable")
)
),
server = function(input, output){
mydata <- reactive({
read.csv(input$filein)
})
file_info <- reactive({
validate(
need(!is.null(input$filein), "please select file"
)
)
name <- input$filein
size <- file.info(input$filein)[['size']]
type <- file_ext(input$filein)
datapath <- file_path_as_absolute(input$filein)
cbind(name, size, type, datapath)
})
output$myTableInfo <- renderTable({
file_info()
})
output$myTable <- renderTable({
mydata()
})
}
)
)
test.csv
X1,X2,X3
1,2,3
4,5,6

Resources