Undefined columns selected in sidebarpanel in Rshiny - r

I am quite new in Shiny, so forgive me for asking a so basic question.
I am trying to develop a basic data analysis app, in order to deal with big databases. I have already been able of importing the DDBB and to visualize it as a table. However, when trying to perform a summary statistics about the variables, I have the error of: "Undefinded columns selected" and I cannot see anything. If I do not add any code in the server, I can see the output (boxplot, histogram and summary) in the app, but I cannot see variable names (only 1,2,3...). I show my code below.
I will really appreciate any help to solve this issue. Thank you very much.
shinyUI(fluidPage(
main_page <- tabPanel(
title = "Statistics",
titlePanel("Statistical Analysis"),
sidebarLayout(
sidebarPanel(
# Añado el archivo que quiero cargar
fileInput('DDBB', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)),
#checkboxInput('header', 'Header', TRUE),
#tags$hr(),
selectInput('Variable', 'Select a variable', "",
choice=c((1:33)), multiple = FALSE,
selectize = TRUE
),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 200,
value = 30)
),
mainPanel(
tabsetPanel(
tabPanel(
title = "Data Visualization",
DT::dataTableOutput("sample_table")
),
tabPanel(
title = "Summary Statistics",
verbatimTextOutput("sum"),
fluidRow(splitLayout(cellWidths = c("50%", "50%"),
plotOutput("box"),
plotOutput('hist'))
)
)
)
)
)
)
))
# Define server logic required to draw a histogram
shinyServer(function(input, output, session) {
# Output a file input (cargar archivo).
df_products_upload <- reactive({
inFile <- input$DDBB
print(inFile)
if (is.null(inFile))
return(NULL)
df <- read.csv(inFile$datapath, header = TRUE,sep = ';')
# updateSelectInput(session, "Variable", choices = names(df))
return(df)
})
output$sample_table<- DT::renderDataTable({
df <- df_products_upload()
DT::datatable(df,
filter = 'top') %>%
formatRound(columns= c(1:ncol(df)), digits = 2)
})
observeEvent(df_products_upload(), {
updateSelectInput(session, "Variable", choices = colnames(df_products_upload()))
})
output$sum <- renderPrint({
updateSelectInput(session, "Variable", choices = colnames(df)
summary(df[,as.numeric(input$Variable)])
})
output$box <- renderPlot({
updateSelectInput(session, "Variable", choices = colnames(df_products_upload))
x<-summary(df[,as.numeric(input$Variable)])
boxplot(x,col="sky blue",border="purple",main=names(df[as.numeric(input$Variable)]))
})
output$hist <- renderPlot({
updateSelectInput(session, "Variable", choices = colnames(df_products_upload))
# generate bins based on input$bins from ui.R
x<-df[,as.numeric(input$Variable)]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x,
main=names(df[as.numeric(input$Variable)]) ,
breaks = bins, col = 'darkgray', border = 'black',
xlab = 'samples')
})
})

Welcome to Stack-Overflow, Enrique :) I added a line to save iris dataset as ';'-separated csv and used that as uploadable data example. I must say, your code had multiple errors, both shiny and also a bit basic base R data.frame manipulation. I have corrected them and added comments. All beginnings are hard. I would suggest you to go back and do some more shiny exercises and tutorials. I think you will advance faster that way.
Especially revisit reactive expressions:
https://shiny.rstudio.com/tutorial/written-tutorial/lesson6/
It matters if you pass as parameter the value of a reactive sum(my_reactive_numbers()) or the reactive it self sum(my_reactive_numbers).
Also check out scope rules for shiny reactive contexts. Basically like functions, what is defined within one reactive context, is not automatically exposed to others, hence the df issues. If you would want to (probably not) make a variable global, here is a deeper intro into that:
https://shiny.rstudio.com/articles/scoping.html
library(DT)
write.table(iris,file = "./sample_upload_data_set.csv",sep = ";") #; because assmed in code
ui <- shinyUI(fluidPage(
main_page <- tabPanel(
title = "Statistics",
titlePanel("Statistical Analysis"),
sidebarLayout(
sidebarPanel(
# Añado el archivo que quiero cargar
fileInput('DDBB', 'Choose file to upload',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)),
#checkboxInput('header', 'Header', TRUE),
#tags$hr(),
selectInput('Variable', 'Select a variable', NULL,
choices = NULL, #edits start with NULL as no data set yet
multiple = FALSE,
selectize = TRUE
),
sliderInput("bins",
"Number of bins:",
min = 1,
max = 200,
value = 30)
),
mainPanel(
tabsetPanel(
tabPanel(
title = "Data Visualization",
DT::dataTableOutput("sample_table")
),
tabPanel(
title = "Summary Statistics",
verbatimTextOutput("sum"),
fluidRow(splitLayout(cellWidths = c("50%", "50%"),
plotOutput("box"),
plotOutput('hist'))
)
)
)
)
)
)
))
# Define server logic required to draw a histogram
server <- function(input, output, session) {
#expose an uplaoded csv file as a reactive data.frame
df_products_upload <- reactive({ #todo consider a shorter name e.g. r_prod_up.df
inFile <- input$DDBB #
print(inFile)
#if (!is.null(inFile))
# return(NULL) do not use return in any shiny reactive context, it is not a function
#req is practical replacement of if '(is.null(inFile)) return(NULL)'-pattern
req(inFile$datapath) #must be not null, non_empty character, or reactive will not complete
df <- read.csv(inFile$datapath, header = TRUE,sep = ';')
# updateSelectInput(session, "Variable", choices = names(df))
#return(df) ## EDIT do not use return
df
})
#let data.frame column names be choices of an input
observe({ #edit observeEvent was redundant, just use observe here
df <- df_products_upload()
#the following code expects numeric columns
the_numeric_columns <- colnames(df)[sapply(df,is.numeric)]
updateSelectInput(session, "Variable", choices = the_numeric_columns)
})
#render the data.frme with data.table
output$sample_table <- DT::renderDataTable({
df <- df_products_upload()
DT::datatable(df, filter = 'top') %>%
#formatRound will mask non numeric columns
formatRound(
columns = which(sapply(df,is.numeric)), #only format numeric columns
digits = 2
)
})
# but this render makes absolutely no sense, you should
output$sum <- renderPrint({
#edit it is bad behavior to do side effects in render scopes
# updateSelectInput(session, "Variable", choices = colnames(df_products_upload()) #edit df was not assign in scope
# summary(df[,as.numeric(input$Variable)])
# })
}) # edit missing bracket
output$box <- renderPlot({
#browser()
#edit bad behaviour, maybe you missunderstood the update functionSelectInput
#updateSelectInput(session, "Variable", choices = colnames(df_products_upload())) #edit reactive must be read not passed directly to colnames
#edit df is not assigened in this scope
df <- df_products_upload()
#x<-summary(df[,as.numeric(input$Variable)]) #edit this is no bueno, what if varaible names were ... names
# edit since plucking only one column and dropping data.frame wrap
# you may just use [[]] brackets to make it more explicit to the reader
x<-df[[input$Variable]] #this can only return the vector of one column or NULL
x<-summary(x)
boxplot(
x,
col="sky blue",
border="purple",
#comma was missing here, and why not just use Varaible
main = input$Variable
)
})
output$hist <- renderPlot({
#browser()
#edit df is not assigened in this scope
df <- df_products_upload()
#update makes no sense here
#updateSelectInput(session, "Variable", choices = colnames(df)) #edit if introducing df anyways just use that
# generate bins based on input$bins from ui.R
# edit since plucking only one column and dropping data.frame wrap
# you may just use [[]] brackets to make it more explicit to the reader
x<-df[[input$Variable]] #this can only return the vector of one column or NULL
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x,
#main=names(df[as.numeric(input$Variable)]) , # you're assuming columns would be named by numbers...
#...and it is quite like crossing the river to get water,
main = input$Varible,
breaks = bins, col = 'darkgray', border = 'black',
xlab = 'samples'
)
})
}
shiny::shinyApp(ui = ui, server = server)

Related

How make selectInput() pick up only columns with more than one category/factor in R shiny?

I'm building a Shiny App where I'm uploading multiple files, carry out some operations and output some plots. My plots have a functionality to facet_wrap() by selecting from selectInput(). The selectInput() will refer to the columns in an uploaded dataset and sometimes these columns only have one factor level or a repeated value.
I do not want selectInput() to pick up these columns as faceting or grouping by them makes no difference to the plot (i.e. searching for something that facets or group can get annoying because it's a large dataset). I want to implement an observe() event where the selectInput() only picks up columns with factor levels greater than 1. I have tried using both if statements and ifelse statements but Shiny seems to crash everytime.
The original code is very complex but here's a reproducible example:
library(shiny)
library(ggplot2)
sample <- data.frame(column1 = rep('cat',10), column2 = c(rep('cat',5), rep('dog',5)),
column3 = c(rep('turtle',3), rep('wolf',7)), column4 = rnorm(10))
write.csv(sample, "sample.csv") #Creating sample csv to be ingested in R shiny
ui <- fluidPage(
headerPanel("Webpapp"),
sidebarPanel(
fileInput(inputId = "filedata", #Upload sample.csv here
label = "Upload the Raw Data File",
accept = c("text/csv", "text/comma-separated-values,text/plain",
".csv")),
selectInput("col1", "Select column:", choices = ""), #will be updated in server
),
mainPanel(plotOutput('boxplot')),
)
server <- function(session, input, output) {
data <- reactive({
req(input$filedata)
df <- read.csv(input$filedata$datapath, header = T)
df[1] <- rep('dog', 10)
#I can hardcode it here to delete all columns with less than 2 unique values but prefer not to hard code
list(df = df)
})
observe({
req(data()$df)
updateSelectInput(session, "col1", choices =
list(
if(length(levels(as.factor(data()$df[,1])))>1){
"Column 1" = colnames(data()$df)[1]},
if(length(levels(as.factor(data()$df[,2])))>1){
"Column 2" = colnames(data()$df)[2]},
if(length(levels(as.factor(data()$df[,3])))>1){
"Column 3" = colnames(data()$df)[3]}
)
)
})
output$boxplot <- renderPlot({
ggplot(data()$df, aes(x = as.factor(input$col1), y=column4)) +
geom_boxplot() + geom_point()
})
}
shinyApp(ui = ui, server = server)
I return two datasets from the reactive, original_data which is the data uploaded by the user and filtered_data which is the data returned for selectInput.
In ggplot code using as.factor(input$col1) would not work directly, use .data pronoun.
library(shiny)
library(ggplot2)
library(dplyr)
sample <- data.frame(column1 = rep('cat',10), column2 = c(rep('cat',5), rep('dog',5)),
column3 = c(rep('turtle',3), rep('wolf',7)), column4 = rnorm(10))
write.csv(sample, "sample.csv", row.names = FALSE) #Creating sample csv to be ingested in R shiny
ui <- fluidPage(
headerPanel("Webpapp"),
sidebarPanel(
fileInput(inputId = "filedata", #Upload sample.csv here
label = "Upload the Raw Data File",
accept = c("text/csv", "text/comma-separated-values,text/plain",
".csv")),
selectInput("col1", "Select column:", choices = ""), #will be updated in server
),
mainPanel(plotOutput('boxplot')),
)
server <- function(session, input, output) {
data <- reactive({
req(input$filedata)
df <- read.csv(input$filedata$datapath, header = T)
list(original_data = df,
filtered_data = df %>% select(column1:column3) %>% select(where(~n_distinct(.) > 1)))
})
observe({
req(data()$filtered_data)
updateSelectInput(session, "col1", choices = names(data()$filtered_data))
})
output$boxplot <- renderPlot({
req(data()$original_data, input$col1)
ggplot(data()$original_data, aes(x = .data[[input$col1]], y=column4)) +
geom_boxplot() + geom_point()
})
}
shinyApp(ui = ui, server = server)

Get input values from conditionalPanel

I am trying to generate a shiny app that will first allow the user to (using the notion of dplyr verbs) select the variables they are interested in and then filter those variables based on subsequent selections. I am trying to do this using conditionalPanel() but I am getting stuck finding a way to access the input$ from each conditional panel.
Here is an example:
library('shiny')
library('tidyverse')
library('shinyWidgets')
#Create the data
data <- select(mtcars, c(gear, carb))
#Create page with sidebarlayout
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
#Create picker input where relevant variables are selected
pickerInput(
inputId = 'vars',
label = 'Variables',
choices = colnames(data),
selected = colnames(data),
multiple = T,
pickerOptions(actionsBox = TRUE)
),
#Create conditional panels which show when the variable above is selected
#These panels will be used to filter the data that is selected based on the above variables
conditionalPanel(condition = "input.vars.includes('gear')",
pickerInput(inputId = 'gear',
label = 'Gear',
choices = unique(data$gear),
selected = unique(data$gear),
multiple = T,
pickerOptions(actionsBox = TRUE)
)
),
conditionalPanel(condition = "input.vars.includes('carb')",
pickerInput(inputId = 'carb',
label = 'Carb',
choices = unique(data$carb),
selected = unique(data$carb),
multiple = T,
pickerOptions(actionsBox = TRUE)
)
)
),
mainPanel(
#Show the selected data
verbatimTextOutput('term_selected'),
#Show the selected and filtered data - this won't show
verbatimTextOutput('term_selected_filtered'),
#Try debug with just getting the
verbatimTextOutput('debug_print')
)
)
)
server <- function(input, output) {
#Create the reactive selected data
selected_data <- reactive ({
data %>%
select(input$vars)
})
#Render the selected data
output$term_selected <- renderPrint(selected_data())
#This is where i am stuck
#I need to find a way to access the inputs related to the conditional functions
# selected_filtered_data <- reactive ({
# for (i in length(input$vars)) {
# selected_data() %>%
# filter(input$[first condiitonal panel select] %in% as.symbol(input$vars[i])
# }
# })
#
output$term_selected_filtered <- renderPrint(selected_filtered_data())
#Try to render input input$[first item of input.vars]
output$debug_print <- renderPrint(input$as.symbol(input$vars[1]))
}
shinyApp(ui = ui, server = server)
The problem lies in the server. I have tried input$as.symbol(input$vars[1]) to access the input$gear (assuming that was selected), but it just throws the error: attempt to apply non-function. I tried adding !! as syntactic sugar in front of as.symbol(), but that makes no difference.
I also tried this, in the hope that i could conditionally filter, and had no luck.
selected_filtered_data <- reactive({
selected_data() %>%
if('gear' %in% input$vars) {
filter(gear %in% input$gear) %>%
}
if('carb' %in% input$vars) {
filter(carb %in% input$carb)
}
})
How should I go about doing this?
We may use across (if we want to filter the rows when both column conditions are TRUE) or replace across with if_any (if either one of them is TRUE when they are both selected)
selected_data() %>%
filter(across(all_of(intersect(input$vars,
c('gear', "carb"))), ~ .x %in% input[[cur_column()]]))
-full code
library('shiny')
library('dplyr')
library(tidyr)
library('shinyWidgets')
#Create the data
data <- select(mtcars, c(gear, carb))
#Create page with sidebarlayout
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
#Create picker input where relevant variables are selected
pickerInput(
inputId = 'vars',
label = 'Variables',
choices = colnames(data),
selected = colnames(data),
multiple = TRUE,
pickerOptions(actionsBox = TRUE)
),
#Create conditional panels which show when the variable above is selected
#These panels will be used to filter the data that is selected based on the above variables
conditionalPanel(condition = "input.vars.includes('gear')",
pickerInput(inputId = 'gear',
label = 'Gear',
choices = unique(data$gear),
selected = unique(data$gear),
multiple = T,
pickerOptions(actionsBox = TRUE)
)
),
conditionalPanel(condition = "input.vars.includes('carb')",
pickerInput(inputId = 'carb',
label = 'Carb',
choices = unique(data$carb),
selected = unique(data$carb),
multiple = TRUE,
pickerOptions(actionsBox = TRUE)
)
)
),
mainPanel(
#Show the selected data
verbatimTextOutput('term_selected'),
#Show the selected and filtered data - this won't show
verbatimTextOutput('term_selected_filtered'),
#Try debug with just getting the
verbatimTextOutput('debug_print')
)
)
)
server <- function(input, output) {
#Create the reactive selected data
selected_data <- reactive ({
req(input$vars)
data %>%
select(input$vars)
})
#Render the selected data
output$term_selected <- renderPrint(selected_data())
#This is where i am stuck
#I need to find a way to access the inputs related to the conditional functions
selected_filtered_data <- reactive ({
selected_data() %>%
filter(across(all_of(intersect(input$vars, c('gear', "carb"))), ~ .x %in% input[[cur_column()]]))
})
#
output$term_selected_filtered <- renderPrint(
selected_filtered_data()
)
output$debug_print <- renderPrint(input[[input$vars[1]]])
}
shinyApp(ui = ui, server = server)
-output

Shiny, reuss reactive input pickerInput

I am trying to create my first shiny app but I am facing a difficulty: in the reproducible example below I am creating a reactive pickerInput (i.e. only show brands proposing a cylindre equal to the input visitors select).
I then want that based on the combination input_cyl and picker_cny (remember that picker_cny depends on input_cyl) to display a table which shows the relevant data for the observation matching the combination input_cyl and picker_cny.
Thank you for your help!
df <- mtcars
df$brand <- rownames(mtcars)
df$brand <- gsub("([A-Za-z]+).*", "\\1", df$brand)
if (interactive()) {
library(shiny)
library(shinyWidgets)
library(shinythemes)
library(shinycssloaders)
# Define UI -----------------------------------------------
ui <- fluidPage(
# Application title
titlePanel("Reproducible Example"),
# Parameters
sidebarLayout(
sidebarPanel(
selectInput(inputId = "input_cyl", label = "Cyl",
choices = c("6", "4", "8")),
pickerInput(
inputId = "picker_cny",
label = "Select Company",
choices = paste0(unique(df$brand)),
options = list(`actions-box` = TRUE),
multiple = TRUE),
width = 2),
# Show Text
mainPanel(
tableOutput("table"),
width = 10)
))
# Define Server ------------------------------------------
server <- function(input, output, session) {
# Reactive pickerInput ---------------------------------
observeEvent(input$input_cyl, {
df_mod <- df[df$cyl == paste0(input$input_cyl), ]
# Method 1
disabled_choices <- !df$cyl %in% df_mod$cyl
updatePickerInput(session = session,
inputId = "picker_cny",
choices = paste0(unique(df$brand)),
choicesOpt = list(
disabled = disabled_choices,
style = ifelse(disabled_choices,
yes = "color: rgba(119, 119, 119, 0.5);",
no = "")
))
}, ignoreInit = TRUE)
output$table <- renderTable(df)
}
}
# Run the application
shinyApp(ui = ui, server = server)
You need a reactive that will handle the change in the input and subset the dataframe before giving it to the output table. For that, you just need to add this block to your server:
data <- reactive({
if (length(input$picker_cny) > 0)
df[df$brand %in% input$picker_cny,]
else
df
})
and update the output$table like this:
output$table <- renderTable(data())
Note: feel free to remove the if else in the reactive to get that:
data <- reactive({
df[df$brand %in% input$picker_cny,]
})
The only difference in that case is: would you show all or nothing when no input has been entered yet. That's a matter of taste.

Shiny Dynamic Filter variable selection and display of variable values for selection

I am still learning Shiny and R and feel it is a sea where I still need to learn quite a lot. Please excuse me if my method of coding is not ideal and do suggest where the code can be improvised.
I am creating this app where I need to generate cross tabs and charts. I need to filter my data basis variable selected by the user and based on that the tables and charts need to get updated.
So for example if user selects "Store_location" as the filter variable, I want to display the list of values for this variable below it with check box, so
loc1
loc2
loc3
loc4
should get displayed with checkbox, and user can select single / multiple of these values. Basis this my data should get filtered. So if user selects loc1 and loc2, data should get filtered based on the condition (Store_location == "loc1" | Store_location == "loc2")
Once the user unchecks a checkbox OR selects a different variable for filter, accordingly the data should get updated and the crosstabs and charts. I believe this should be possible to be done in Shiny, I was trying to use checkboxGroupInput but not able pass the variable selected and hence getting errors. Currently have commented this so that the code runs. I have created a sample data which is in CSV format and is been read in the app. Data is huge and hence using data.table fread to read the data. So any sub-setting would need to be done in data.table. I do some reformatting / creating of variables when the button "Prepare data for Analysis" is clicked. For this I am using the observeEvent({}) and all my renderTable / renderplot are inside this event. I feel there would be a better way to handle this. If yes do suggest.
Finally, my downloader is giving me error, "only 'grobs' allowed in "gList"" and sometimes error like "replacement has 17 rows, data has 0". I want generate a pdf file with the crosstabs and plot one below the other. Do suggest where I am going wrong.
Sample data can be found here - sample data
Below is the code snippet for my app -
library("shiny")
library("shinythemes")
library("tools")
library("readxl")
library("data.table")
library("bit64")
library("gmodels")
library("ggplot2")
library("plotly")
library("gridExtra")
### User Interface
ui <- shinyUI(
navbarPage('My Shiny App',
tabPanel("Insights",
sidebarPanel(
fileInput('file1', 'Choose input data',
accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv')),
tags$hr(),
actionButton(inputId = 'run1', label = "Prepare data for Analysis"),
tags$br(),
tags$br(),
fluidRow(
column(10,
div(style = "font-size: 13px;", selectInput("filtervar", label = "Select Filter Variable", ''))
),
tags$br(),
tags$br(),
wellPanel(
# checkboxGroupInput("filteroptions", "Filter Options", choices = sort(unique(fil)))
),
column(10,
div(style = "font-size: 13px;", selectInput("rowvar", label = "Select Row Variable", ''))
),
tags$br(),
tags$br(),
column(10,
div(style = "font-size: 13px;", selectInput("columnvar", "Select Column Variable", ''))
)),
downloadButton('export',"Download Outputs")
)
,
mainPanel(
tabsetPanel(id='mytabs',
tabPanel("Data", tags$b(tags$br("Below is the top 6 rows of the data prepared" )),tags$br(),tableOutput("table.output")),
tabPanel("Table",tags$b(tags$br("Table Summary" )),tags$br(),tableOutput("crosstab1"),tags$br(),verbatimTextOutput("datatab1")),
tabPanel("Chart",tags$b(tags$br("Graphical Output" )),tags$br(),plotlyOutput("plot1"))
)
)),
tabPanel("Help")
))
server <- shinyServer(function(input, output,session){
#Below code is to increase the file upload size
options(shiny.maxRequestSize=1000*1024^2)
observeEvent(input$run1,{
updateTabsetPanel(session = session
,inputId = 'myTabs')
inFile <- input$file1
if (is.null(inFile))
return(NULL)
data_input <- fread(inFile$datapath)
data_input[,`:=` (YN2014 = ifelse(Year == "Y2014",1,0),YN2015 = ifelse(Year == "Y2015",1,0))]
## vals will contain all plot and table grobs
vals <- reactiveValues(t1=NULL,t2=NULL,t3=NULL,p1=NULL,p2=NULL)
output$table.output <- renderTable({
# top6rows
head(data_input)
})
s <- reactive(
data_input
)
observe({
updateSelectInput(session, "rowvar", choices = (as.character(colnames(data_input))),selected = "Store_location")
})
observe({
updateSelectInput(session, "columnvar", choices = (as.character(colnames(data_input))),selected = "Year")
})
observe({
updateSelectInput(session, "filtervar", choices = (as.character(colnames(data_input))),selected = "Store_location")
})
output$conditionalInput <- renderUI({
if(input$checkbox){
selectInput("typeInput", "Product type",
choices = sort(unique(input$filtervar)))
}
})
output$crosstab1 <- renderTable({
validate(need(input$rowvar,''),
need(input$columnvar,''))
vals$t1 <- addmargins(xtabs(as.formula(paste0("~",input$rowvar,"+",input$columnvar)), s()))
},caption = "<b>Cross-Tab - 1</b>",
caption.placement = getOption("xtable.caption.placement", "top"),
caption.width = getOption("xtable.caption.width", 200))
output$datatab1 <- renderPrint({
validate(need(input$rowvar,''),
need(input$columnvar,''))
vals$t2 <- as.data.frame(with(s(), CrossTable(get(input$rowvar),get(input$columnvar),max.width = 1,prop.c = T,prop.r = F,prop.t = F,prop.chisq = F,chisq = F,format = "SPSS",dnn = c(input$rowvar,input$columnvar))))
})
#plotting theme
.theme<- theme(
axis.line = element_line(colour = 'gray', size = .75),
panel.background = element_blank(),
plot.background = element_blank()
)
output$plot1 <- renderPlotly({
vals$p1 <- ggplot(data_input, aes(get(input$rowvar), ..count..)) +
geom_bar(aes(fill = get(input$columnvar)), position = "dodge") +
theme(axis.text.x=element_text(angle=90, hjust=1),
axis.line = element_line(colour = 'gray', size = .75),
panel.background = element_blank(),
plot.background = element_blank()) +
xlab(input$rowvar) +
ylab("Frequency") +
labs(fill=input$columnvar)
})
## clicking on the export button will generate a pdf file
## containing all grobs
output$export = downloadHandler(
filename = function() {paste0("RES_Insights_Outputs_",Sys.Date(),".pdf")},
content = function(file) {
pdf(file, onefile = TRUE)
grid.arrange(vals$t1,vals$p1)
dev.off()
}
)
})
})
shinyApp(ui = ui, server = server)
So to summarize, need to your help to run this app for -
Dynamic display of values for the filter variable selected and filter the data so that crosstabs and plots get updated. Note data is big and in data.table
Downloader to download the outputs in pdf format.
Thank you!!
Here is a way to subset your data frame in function of selected values for the desired column.
I didn't really understand what you wanted to do with the row and column select input though.
ui <- navbarPage("My Shiny App",
tabPanel("Insights",
sidebarPanel(
fileInput("file1", "Choose input data"),
selectInput("filtervar", "Select Filter Variable", NULL),
checkboxGroupInput("filteroptions", "Filter Options", NULL)
),
mainPanel(
tabsetPanel(id = "mytabs",
tabPanel("Data", tableOutput("table.output"))
)
)
)
)
server <- function(input, output,session) {
values <- reactiveValues()
observe({
file <- input$file1
if (is.null(file))
return()
values$data <- fread(file$datapath)
vars <- names(values$data)
updateSelectInput(session, "filtervar", choices = vars)
})
observe({
data <- isolate(values$data)
filter.var <- input$filtervar
if (is.null(filter.var) || filter.var == "")
return()
values <- data[[filter.var]]
if (is.factor(values)) {
options <- levels(values)
} else {
options <- unique(values[order(values)])
}
updateCheckboxGroupInput(session, "filteroptions",
choices = options,
selected = as.character(options))
})
output$table.output <- renderTable({
isolate({
data <- values$data
var <- input$filtervar
})
values <- input$filteroptions
if(is.null(data)) {
return()
} else if (is.null(var) || var == "") {
return(data)
} else if (is.null(values)) {
return(data[FALSE])
} else {
if (is.numeric(data[[var]]))
values <- as.numeric(values)
setkeyv(data, var)
return(data[.(values)])
}
})
}
shinyApp(ui = ui, server = server)

Another Follow up to “add values to a reactive table in Shiny” when we already have a dataframe

I would like to extend this application when data frame exists at the beginning. To be honest, my question is bigger than this where you can find the problem in following link: How to add a new row to uploaded datatable in shiny
Via this question, I am gonna chase the big picture with minors.
I have a currently data frame, 2 columns and 3 rows. First column indicates the current date, other one is to be calculated. new row should be appeared like (Current Date - Like in Excel eg. 11.02.2015-, [Input$1 + "perivious value of column2's row"])
However, I have problem about showing the system date. Additionaly, I cannot produce a new line which gives a warning in newLine!
second version: data can be uploaded. with error: Error in read.table(file = file, header = header, sep = sep, quote = quote, :
'file' must be a character string or connection
Warning: Unhandled error in observer: object of type 'closure' is not subsettable
observeEvent(input$update)
library(shiny)
library(gtools)
runApp(
list(
ui = fluidPage(
pageWithSidebar(
headerPanel("Adding entries to table"),
sidebarPanel(
wellPanel(fileInput('file1', 'Choose Planning File:', accept=c('text/csv', 'text/comma-separated-values,text/plain', '.csv'), multiple = FALSE),
selectInput(inputId = "location",label = "Choose Location",
choices = c('All','Lobau'='LOB', 'Graz'='GRA', 'St. Valentin'='VAL'), selected = "GRA"),
selectInput(inputId = "product",label = "Choose Product",
choices = c('All','Gasoline'='OK', 'Diesel'='DK'), selected = "DK")),
numericInput("spotQuantity", "Enter the Spot Quantity",value=0),
actionButton("action","Confirm Spot Sales"),
numericInput("num2", "Column 2", value = 0),
actionButton("update", "Update Table")),
mainPanel(tableOutput("table1")))
),
server = function(input, output, session) {
values <- reactive({ #
#file.choose()
dm <- as.data.frame(read.csv(input$file1$datapath, sep=";",check.names = FALSE))
})
addData <- observeEvent(input$update, {
values$dm <- isolate({
newLine <- data.frame('Month'=1,'Day ID'=2,'Day'="28-11-2012",'starting inventory'=2,'planned (in kTO)'=2,'lifted (in kTO)'="2",'replenishment (in kTO)'="2", 'Product'="OK",'Location'="GRA", check.names=F)
rbind.data.frame(values$dm,newLine)
})
})
output$table1 <- renderTable({
values()
})
}
)
)
There are multiple issues with your code. You start reactiveValues but you never assign anything to it so no data could hope to be reactive. Also, you likely want to use observeEvent so that each time you hit the Update button you get a response. You can also isolate blocks of code. Furthermore, you should use a data.frame for your new data as the 'type' of the data matters (i.e. numeric, character, etc.). The following works well for me.
library(shiny)
runApp(
list(
ui = fluidPage(
pageWithSidebar(
headerPanel("Adding entries to table"),
sidebarPanel(
numericInput("num2", "Column 2", value = 0),
actionButton("update", "Update Table")),
mainPanel(tableOutput("table1")))
),
server = function(input, output, session) {
values <- reactiveValues(
dm = data.frame(Date = as.Date(c("2015-05-10", "2015-10-07", "2015-03-26","2015-07-18")),
Col2 = c(160, 150, 121, 93))
)
addData <- observeEvent(input$update, {
values$dm <- isolate({
newLine <- data.frame(Date = format(Sys.time(), "%Y-%m-%d"),
Col2 = tail(values$dm$Col2, n=1) - 4)
rbind(values$dm,newLine)
})
})
output$table1 <- renderTable({
values$dm
})
}
)
)

Resources