R Shiny - How to use local csv file and custom function - shiny

I started to learn R Shiny recently and I tried to build an shiny app and failed. My problem is: I try to use local csv file on my computer and run simple look up using the custom function, like type in the student's name and return his/her student ID. The following is my codes:
ui.R
library(shiny)
shinyUI(fluidPage(
# application title
titlePanel("FGMC Search Engine"),
sidebarLayout(
sidebarPanel(
textInput("text",label = h3("Correspondent Search"), value = "Enter Here...")
),
mainPanel(
textOutput("text1")
)
)
))
and then
server.R
library(shiny)
# define function for inputing the corr array & input and return channel source
corr_search <- function(corr,input_name){
# lowercase of input names
name_lower = tolower(input_name)
# lowercase of corr names
corr_lowercase = substr(tolower(corr$TPO.Company.Name),1,nchar(test_lowercase))
# look up the corresponding channel source accounding to matched corr indexing
result = corr$Channel.Source[match(test_lowercase, corr_lowercase)]
# check if search result is Null
if (is.na(result)){
result = "Wrong Input! Please Search Again"
}
# return search result
return(result)
}
shinyServer(
function(input, output) {
textInput <- reactive({
corr = read.csv("C:\\Users\\carl.qin\\Desktop\\Projects\\Modelling & Analytics\\R Modelling\\App-2\\fgmc_correspondent.csv",header=TRUE)
input_name = input$text
If(is.na(input_name)){
input_name = "nothing"
}
})
result = corr_search(corr,input_name)
output$text1 <- renderPrint({
result
})
}
)
I keep getting the error: Object not found. It would be great if someone could help solve this problem.
Thank you!

In the function corr_search you use a variable test_lowercase which is nowhere defined (doesn't exist and hence an error). In reactive you use if-statement but you have a typo. (Instead of If you should have if). You should also move result = corr_search(corr, input_name) to the reactive expression textInput (where you have defined input_name) and return a value which you finally pass to renderPrint via textInput()

Related

Interactive Shiny Table Download and Page Length Issues

The code below is adapted from https://gist.github.com/wch/4211337 and perfectly illustrates my challenges. I have two main issues:
I cannot get the interactive tables to download; and
I can't figure out how to make the table print with a page length, for example that shows 25 rows and lets you toggle to the next page.
Here is the code:
server.r
data_sets <- c("mtcars", "morley", "rock")
shinyServer(function(input, output) {
# Drop-down selection box for which data set
output$choose_dataset <- renderUI({
selectInput("dataset", "Data set", as.list(data_sets))
})
# Check boxes
output$choose_columns <- renderUI({
# If missing input, return to avoid error later in function
if(is.null(input$dataset))
return()
# Get the data set with the appropriate name
dat <- get(input$dataset)
colnames <- names(dat)
# Create the checkboxes and select them all by default
checkboxGroupInput("columns", "Choose columns",
choices = colnames,
selected = colnames)
})
# Output the data
output$data_table <- renderTable({
# If missing input, return to avoid error later in function
if(is.null(input$dataset))
return()
# Get the data set
dat <- get(input$dataset)
# Make sure columns are correct for data set (when data set changes, the
# columns will initially be for the previous data set)
if (is.null(input$columns) || !(input$columns %in% names(dat)))
return()
# Keep the selected columns
dat <- dat[, input$columns, drop = FALSE]
# Return
dat
})
output$downloadData <- downloadHandler(
filename = function() {
('test.csv')
},
content = function(con) {
write.table(dat, row.names = FALSE, col.names=T, sep=",",con)
},
contentType="csv"
)
})
ui.r
shinyUI(pageWithSidebar(
headerPanel(""),
sidebarPanel(
uiOutput("choose_dataset"),
uiOutput("choose_columns"),
downloadButton("downloadData", style = "color: white;background-color: #303030")
),
mainPanel(
tableOutput("data_table")
)
))
I am getting an error code in the downloadHandler that says it doesn't recognize dat. I have tried wrapping the elements in reactive({}), but that didn't work either.
I have tried several things to get the table to show with a page length, but nothing I am doing is working, so I don't have any code for that presented here.
Thanks for any help!
Just do the data wrangling outside. Try this
server <- shinyServer(function(input, output) {
# Drop-down selection box for which data set
output$choose_dataset <- renderUI({
selectInput("dataset", "Data set", as.list(data_sets))
})
# Check boxes
output$choose_columns <- renderUI({
# If missing input, return to avoid error later in function
if(is.null(input$dataset))
return()
# Get the data set with the appropriate name
dat <- get(input$dataset)
colnames <- names(dat)
# Create the checkboxes and select them all by default
checkboxGroupInput("columns", "Choose columns",
choices = colnames,
selected = colnames)
})
dat <- reactive({
# If missing input, return to avoid error later in function
if(is.null(input$dataset))
return()
# Get the data set
dat <- get(input$dataset)
# Make sure columns are correct for data set (when data set changes, the
# columns will initially be for the previous data set)
if (is.null(input$columns) || !(input$columns %in% names(dat)))
return()
# Keep the selected columns
dat <- dat[, input$columns, drop = FALSE]
# Return
dat
})
# Output the data
output$data_table <- renderTable({
dat()
})
output$downloadData <- downloadHandler(
filename = function() {
('test.csv')
},
content = function(con) {
write.table(dat(), row.names = FALSE, col.names=T, sep=",",con)
},
contentType="csv"
)
})

How to format R Shiny numericInput?

I have a Shiny app with numerous numericInput fields. I would like a way to format the numericInput fields with commas separating every 10^3. For example, I want 5,000,000 instead of 5000000.
I can do this in R with the format and prettyNum functions. But I don't have a way to do this in Shiny.
This would be very helpful for the UI because it would work with percents, money, etc. Does anyone have any idea how to incorporate this into the numericInput field?
Thanks!
library(shiny)
# Define UI for application that draws a histogram
ui <- fluidPage(
mainPanel(
numericInput("formatNumber",
"Number should be formatted, e.g."5,000,000",
value = 1000),
p(format(5000000.10, big.mark=",", big.interval=3L,
digits=0, scientific=F))
)
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
The shinyWidgets package has a great new function (added as of version 0.5.4, also a disclaimer, I added it via a pull request), autonumericInput that will allow you to do just this. It is based on the javascript library autonumeric. There are a lot of options to the function, but the documentation is extensive and for simple uses most can be ignored.
What you are trying to do can be accomplished as follows:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
h1("Autonumeric Input Example"),
shinyWidgets::autonumericInput(
inputId = "num",
label = "Enter a large number:",
value = 1000000,
currencySymbolPlacement = "p",
decimalPlaces = 2,
digitGroupSeparator = ",",
decimalCharacter = "."
),
verbatimTextOutput("res1")
)
server <- function(input, output) {
output$res1 <- renderText(input$num)
}
shinyApp(ui = ui, server = server)
This is especially nice because it provides as-you-type formatting, so that the user can easily know how big the number is as they put it in. I know from experience that it is a real pain to try to put large numbers into the base shiny numericInput, trying to count digits in a small little box and figure out how many zeros there are. The goal of this function is to make formatting numeric inputs much easier.
Hopefully this is useful!
I could not find anything that would help with numericInput(), but here's what works with textInput() instead.
library(shiny)
if(interactive()){
shinyApp(
ui <- fluidPage(
mainPanel(
textInput("formatNumber1", "Number should be formatted, e.g.5,000,000", value = 1000),
textInput("formatNumber2", "Number should be formatted, e.g.5,000,000", value = 1000)
)
),
server <- function(input, output, session) {
observe({
updateTextInput(session, "formatNumber1", "Number should be formatted, e.g.5,000,000",
value = prettyNum(input$formatNumber1, big.mark=",", scientific=FALSE))
updateTextInput(session, "formatNumber2", "Number should be formatted, e.g.5,000,000",
value = prettyNum(input$formatNumber2, big.mark=",", scientific=FALSE))
})
}
)
}
That is the only method I found, however if you're too slow or add a digit after the commas have been added, the number is not displayed properly (e.g., 3,000 becomes 3,0,000 if you add a 0 at the end of the string). To correct that, I've changed the updateTextInput() function as below:
updateTextInput(
session,
"formatNumber1",
"Number should be formatted, e.g.5,000,000",
value = prettyNum(
gsub(",", "", input$formatNumber1),
big.mark=",", scientific=FALSE
)
)
In effect gsub() function is used to reset the input to a number every time the input is amended, otherwise the prettyNum() function is only using the digits after the comma and ignoring all digits on the left of the last comma.
If you've got multiple inputs to reformat, then create a function as follows (NB: I've also added req(input[[x]]) to avoid NA appearing when the input is blank):
updatetoprettynb <- function(x) {
req(input[[x]])
updateTextInput(
session,
x,
value = prettyNum(
gsub(",", "", input[[x]]),
big.mark = ",",
scientific = FALSE
)
)
}
You still have to use the function in a similar fashion but don't forget to use "":
observe({
updatetoprettynb("formatNumber1")
})

How do I write to a bigquery table from shiny?

I'm trying to write a shiny app that takes a file as an input and uploads the data in that file to a bigquery table where some other stuff will go on. Everything appears to be working fine in terms of getting the data into my app, but when I try to upload the data to bigquery, nothing happens. No error messages, just nothing.
I can run the code on its own and it executes just fine. I'm having a little trouble figuring out how to create a reproducible example because you can't write to a public dataset, but I've included my code below.
Additional info:
working directory contains my .httr-oauth file
data is visible in my shiny app
Please let me know if there's something I can add to make this question easier to answer. Thanks.
############# UI ############
#
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Upload"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
fileInput('list', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)),
tags$hr(),
textInput('sql', 'Or give a query to get the customer_ids you want'),
tags$hr(),
actionButton('go', 'Go')
),
# Show a plot of the generated distribution
mainPanel(
tableOutput('log')
)
)
))
############# server ##############
### setting up the environment
library(shiny)
library(data.table)
library(bigrquery)
### setting up the constants
project <- 'xxxxxxx'
dest_dataset <- 'temp'
dest_table <- 'custs_hash'
cd <- 'CREATE_IF_NEEDED'
wd <- 'WRITE_TRUNCATE'
options(shiny.maxRequestSize = 100*1024^2)
shinyServer(function(input, output) {
logs <- eventReactive(input$go, {
inFile <- input$list
dat <- fread(inFile$datapath)
dat <- head(dat)
return(list(dat = dat))
})
upload <- eventReactive(input$go, {
data <- dat()$dat
ins <- insert_upload_job(project, dataset = dest_dataset, table = dest_table, values = data,
create_disposition = cd, write_disposition = wd)
return(list(ins = ins))
})
output$log <- renderTable(logs()$dat)
})
An eventReactive returns a reactive expression object. Like other reactive objects, you need to expressly call it like a function. Otherwise it won't run by itself.
So in your case, you have upload <- eventReactive(...), then you need to call it using upload().

Can typeahead be implemented over a dynamically changing dataframe using shinysky?

I am trying to populate a Typeahead box in Shiny, using the ShinySky package in R.
I'm trying to extend the example, where the data used to prepopulate the Typeahead is hardcoded into the textInput.typeahead function:
textInput.typeahead(
id="thti"
,placeholder="type 'name' or '2'"
,local=data.frame(name=c("name1","name2"),info=c("info1","info2")) #<- LOOK!
,valueKey = "name"
,tokens=c(1,2)
,template = HTML("<p class='repo-language'>{{info}}</p> <p class='repo-name'>{{name}}</p> <p class='repo-description'>You need to learn more CSS to customize this further</p>")
)
Having a local dataframe defined in the middle of the function is not what I would like to do, as the example has done here:
,local=data.frame(name=c("name1","name2"),info=c("info1","info2"))
I would like to supply an argument to local that is a reactive object, which is created elsewhere in Shiny.
So far I've been unable to do so.
Here's my strategy for attempting to populate the Lookhead options dynamically using reactivity:
1) Let the user subset a dataframe using a slider.
2) Set up the Lookahead to read in the subsetted dataframe, using something like ,local=subset(DF)
3) Hope that the Lookahead works as it's supposed to.
Seems simple enough? Here's a screenshot, where you can clearly see that the Lookhead doesn't appear underneath the user input of 111. Below is my code. Any help would be greatly appreciated.
library(shiny)
library(shinysky)
options(shiny.trace = F) # change to T for trace
DF <- data.frame(ID=c("111", "222", "333", "444"), info=c("info1", "info2", "info3", "info4"))
runApp(list(ui = pageWithSidebar(
headerPanel("This is a test"),
sidebarPanel(
helpText("I couldn't live without StackOverflow"),
sliderInput("range",
label = "Pick how many rows you want in your dataframe:",
min = 2, max = 4, value = 2, step=1),
helpText("After subsetting the dataframe using the controls above, can we make the Lookahead work?"),
textInput.typeahead(
id="thti"
,placeholder="type ID and info"
,local=subset(DF)
,valueKey = "ID"
,tokens=c(1,2)
,template = HTML("<p class='repo-language'>{{info}}</p> <p class='repo-name'>{{ID}}</p> <p class='repo-description'></p>"))
),
mainPanel(textOutput("text1"),
htmlOutput("text"),
tableOutput('table')
)
),
server = function(input, output, session) {
subsetDF <- reactive({ DF <- DF[1:input$range, ]
DF
})
output$text <- renderUI({
str <- paste("This is how many rows you've chosen for your dataframe:",
input$range)
HTML(paste(str, sep = '<br/>'))
})
output$table <- renderTable(subsetDF())
}
)
)

Using Shiny to create a comma delimited string list

How do you handle it in Shiny when you need to append a value to an already existing output?
To simplify my problem:
I want to create a comma separated code list in a single variable ie:
02,04,05,11,31
and display the list as I go creating it. I validate the codes as I go, that is not the problem.
I currently have a text input widget to enter my codes.
I want to append to the list the value in the text input field, every time I press an action button.
Are there any examples of how to do this?
Shiny does not like it when I try to use an output object and append something to it.
You can use Paste to do that. Im sure there are many other ways to do it, look into this example here reactivePoll and reactiveFileReader in the gallery section. Below are a sample code where I simply print out the Sys.time() and append it to the last entry.
Here are two examples:
Example 1 without the button
library(shiny)
runApp(list(ui = fluidRow(wellPanel(verbatimTextOutput("my_text"))),
server = function(input, output, session) {
autoInvalidate <- reactiveTimer(1000,session)
my_file <- as.character(Sys.time())
output$my_text <- renderText({
autoInvalidate()
my_file <<- paste(my_file,as.character(Sys.time()), sep=",")
})
})
)
Example 2 with the ActionButton
library(shiny)
runApp(list(ui = fluidRow(actionButton("push","Append"),wellPanel(verbatimTextOutput("my_text"))),
server = function(input, output, session) {
my_file <- as.character(Sys.time())
output$my_text <- renderText({
if(input$push==0)
{
return(my_file)
}
isolate({
input$push
my_file <<- paste(my_file,as.character(Sys.time()), sep=",")
})
})
})
)