I'm trying to make a reactive table using shiny and am having trouble making my sliderInput and dateRangeInput filters reactive and am not sure where to go from here. I'm using a data frame named "joined" to make an interactive table with. I've already been able to make my columns reactive luckily meaning I can choose which columns from the data frame joined are present in the table, so any of the code about selecting certain columns can be ignored.
My goal for the dateRangeInput is that a date range can be put into the dateRangeInput and only dates that fall into that range in the "actiondate" column on my table "joined" will be displayed in the resulting table.
My goal for the sliderInput is that I can choose a range in the slider and only values of "EPM_scores" column in my table "joined" will be displayed in the resulting table.
Below is my code. Any advice I could get would be much appreciated. Thanks!
The current error message I'm getting is as follows: "error in evaluating the argument 'condition' in selecting a method for function 'filter': unused argument (input$dates[2])"
titlePanel("title"),
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "Value", "1. Enter value", min = 0, max = 1, c(0,1), step = 0.01),
dateRangeInput(inputId = "dates",
"2. Enter date range",
start = min(joined$actiondate),
end = max(joined$actiondate)),
uiOutput("picker"),
actionButton("view", "View selection"),
textOutput("DateRange")),
mainPanel(ui <-
tableOutput("mytable"),
textOutput("mytext")
)),
textInput(inputId = "text",
label = "4. Enter Notes Here", "")
)
server <- function(input, output, session) {
#columns selected
data <- reactive({
joined
})
output$picker <- renderUI({
pickerInput(inputId = 'pick',
label = '3. Choose variables',
choices = colnames(data()),
options = list(`actions-box` = TRUE), multiple = TRUE)
})
datasetInput <- eventReactive(input$view,{
datasetInput <- data() %>%
dplyr::select(input$pick)
return(datasetInput)
})
#dates selected
newDates <- reactive({
filter(joined, between(actiondate, input$dates[1], input$dates[2]))
})
#slider values selected
sliderValues <- reactive({
Value = c(input$value[1], input$value[2])
})
output$mytext <- renderText(input$text)
output$mytable <- renderTable({
datasetInput()
newDates()
sliderValues()
})
}
Related
I have a dataframe with a time series as index. The data in the data frame are updated by a dashboard action (e.g. a download button) and therefore the dataframe is reactive. With a slider I want to be able to select only certain rows of the dataframe. The min max values of the slider therefore refer to the rownames of the reactive data frame. So far I am not able to get this implemented. Below the code. The if(0) part in the SERVER section is the one I am talking about. Any help appreciated.
require(shiny)
AquireData <- function(){
# In this function the data are created
df <- data.frame(replicate(3,sample(0:50,1000,rep=TRUE)))
rownames(df) <- seq(from = as.POSIXct("2012-05-15 07:00"),
to = as.POSIXct("2019-05-17 18:00"), by = "min")[0:dim(df)[1]]
names(df) <- c('A','B','C')
return (df)
}
ui <- fluidPage(
# App title
titlePanel("my dashboard"),
# define stuff for the sidebar (buttons, selectlists etc.). These items will
# be displayed for all panels
sidebarLayout(
sidebarPanel(
actionButton("Button_GetAndUpdate", "Update data"),
sliderInput("start_end_dates", "Date range", min =0, max=0, value=1)
),
# Main panel. Here you can display your graphs, plots and tables
mainPanel("observed data", tableOutput("rawdata"))
)
)
server <- function(input, output,session) {
# When the app is called an update of the data is drawn
df_data <- reactive({AquireData()})
# Check what the update button is doing. If its getting pressed pull and update
observeEvent (input$Button_GetAndUpdate,{df_data <<- reactive({AquireData()})})
# set date range slider values using the dates from the data frame index
if(0){
updateSliderInput(session, "start_end_dates",
label = "Date range",
min = as.POSIXct(min(rownames(df_data())),"%Y-%m-%d %H:%M:%S",tz=""),
max = as.POSIXct(max(rownames(df_data())),"%Y-%m-%d %H:%M:%S",tz="")
)
}
# get the head of the dataframe
data_head <- reactive({
input$Button_GetAndUpdate
isolate({
head(df_data())
})
})
output$rawdata <- renderTable({
data_head()
})
}
shinyApp(ui = ui, server = server)
runApp("Header_dashboard")
You could use shinyWidgets::sliderTextInput and shinyWidgets::updateSliderTextInput respectively instead of sliderInputfor this:
shinyWidgets::updateSliderTextInput(
session, "start_end_dates",
choices = rownames(df_data())
)
That means for your app:
require(shiny)
AquireData <- function(){
# In this function the data are created
df <- data.frame(replicate(3,sample(0:50,1000,rep=TRUE)))
rownames(df) <- seq(from = as.POSIXct("2012-05-15 07:00"),
to = as.POSIXct("2019-05-17 18:00"), by = "min")[0:dim(df)[1]]
names(df) <- c('A','B','C')
return (df)
}
ui <- fluidPage(
# App title
titlePanel("my dashboard"),
# define stuff for the sidebar (buttons, selectlists etc.). These items will
# be displayed for all panels
sidebarLayout(
sidebarPanel(
actionButton("Button_GetAndUpdate", "Update data"),
shinyWidgets::sliderTextInput(
"start_end_dates",
label = "Time range",
choices = c(as.POSIXct("2019-01-01 12:00:00"), as.POSIXct("2019-12-31 14:00:00")),
)
),
# Main panel. Here you can display your graphs, plots and tables
mainPanel("observed data", tableOutput("rawdata"))
)
)
server <- function(input, output,session) {
# When the app is called an update of the data is drawn
df_data <- reactive({AquireData()})
# Check what the update button is doing. If its getting pressed pull and update
observeEvent (input$Button_GetAndUpdate,{df_data <<- reactive({AquireData()})})
# set date range slider values using the dates from the data frame index
observe({
shinyWidgets::updateSliderTextInput(
session, "start_end_dates",
choices = rownames(df_data())
)
})
# get the head of the dataframe
data_head <- reactive({
input$Button_GetAndUpdate
isolate({
head(df_data())
})
})
output$rawdata <- renderTable({
data_head()
})
}
shinyApp(ui = ui, server = server)
Hoping for some expertise. the following code snippet does the following:
allows the user to select which variables (columns) they want from a CSV file, then generates numeric input fields for each one.
populates the dataframe with the values entered by the user.
However, Shiny assigns column headers to the data frame, and I've tried everything I could find to change them and nothing seems to work.
Can anyone tell me what I'm doing wrong?
df_sel() - this the function that selected the variables
this is the R.UI Section
ui <- fluidPage(
# App title ----
titlePanel(title = h1("Variable Selection Example", align = "center")),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# Input: Select a file ----
fileInput("uploaded_file", "Choose CSV File",
multiple = TRUE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
# Horizontal line ---- This allows the user to create a bunch of repeated values for the numerica inputs they later create
sliderInput("months", "Forecast Months:",
min = 0, max = 60,
value = 1),
tags$hr(),
# Input: Checkbox if file has header ----
checkboxInput("header", "Header", TRUE),
# Input: Select separator ----
radioButtons("sep", "Separator",
choices = c(Semicolon = ";",
Comma = ",",
Tab = "\t"),
selected = ","),
# Horizontal line ----
tags$hr(),
# Input: Select number of rows to display ----
radioButtons("disp", "Display",
choices = c(All = "all",
Head = "head"),
selected = "all"),
# Select variables to display ----
uiOutput("checkbox")
),
# Main panel for displaying outputs ----
mainPanel(
uiOutput("input_ui"), #numeric inputs
tableOutput("table1")) #table to display input values
)
)
this is in the R.Server section
server <- function(input, output, session) {
#assign csv file to dataframe df
df <- reactive({
req(input$uploaded_file)
read.csv(input$uploaded_file$datapath,
header = input$header,
sep = input$sep)
})
# Dynamically generate UI input when data is uploaded ----
output$checkbox <- renderUI({
checkboxGroupInput(inputId = "select_var",
label = "Select variables",
choices = setdiff(names(df()), input$select_dev),
selected = setdiff(names(df()), input$select_dev))
})
# Select columns to print ----
df_sel <- reactive({
req(input$select_var)
df_sel <- df() %>% select(input$select_var)
})
output$input_ui <- renderUI({ #this creates dynamic numeric inputs based on the variables selected by the user
pvars <- df_sel()
varn = names(df_sel())
lapply(seq(pvars), function(i) {
numericInput(inputId = paste0("range", pvars[i]),
label = varn,
value = 0)
})
})
numbers <- reactive({ #this creates a reactive dataframe for the numbers
pvars <- df_sel()
num = as.integer(ncol(pvars))
print(num)
pred <- data.frame(lapply(1:num, function(i) {
input[[paste0("range", pvars[i])]]
}))
n = input$months #pull number from that slider up in the UI section
pd = data.frame(pred, i=rep(1:n,ea=NROW(input$months)))
pd[1:(length(pd)-1)]
#colnames(pd, c(df_sel())) #this does not seem to work at all!!!
})
output$table1 <- renderTable({
numbers()
fv = numbers()
print(dim(fv)) #check the dimensions of the table
print(fv) # chcek the table is populating correctly.
#df1 <- fv #show the table
})
}
# Create Shiny app ----
shinyApp(ui = ui, server = server)
I came up with a solution to my own question. If anyone can improve upon it, please let me know. This code goes in the R.Server section.
#This creates sliders from the selected variables from the reactive function called
#"df_sel()". Note the use of "tagList". The RenderUI function below creates as
#many sliders as variables selected, and passes in the correct variable name.
#It selects the last data value from each column, since this is time series data,
#the last data value \ (most recent) was desired.
output$scplan <- renderUI({
vars <- df_sel()
n = nrow(vars)
tagList(lapply(colnames(vars), function(z) {
sliderInput(
sprintf("%s",z),
label = z,
min = ceiling(min(vars[[z]])), # min value is the minimum of the column
max = ceiling(max(vars[[z]])), # max is the max of the column
value = vars[[z]][[n]])
}))
#this reactive function creates a dataframe from variables that were selected from
#checkboxes. The user moves the sliders to generate the values, and the code
#repeats the values for as many "input$months" as were selected.
sp_numbers <- reactive({
vars <- df_sel()
num = as.integer(ncol(vars))
sp_pred <- data.frame(lapply(colnames(vars), function(z) {
input[[z]]
}))
names(sp_pred) <- colnames(vars)
n = input$sp_months
df_sp_pred = data.frame(sp_pred, z=rep(z:n,ea=NROW(input$sp_months)))
df_sp_pred[1:(length(df_sp_pred)-1)] #this removes the last column which just shows the repeat count
})
#this code renders the table of the dataframe created above.
output$spo_table <- renderTable({
sp_numbers()
})
TL;DR, this is my first Shiny App ever, and I am stuck on this reactive problem.
I am writing a Shiny app that will take Excel survey data and put it into a ggplot function. The function should work, but survey questions vary from year to year. I want the app to do the following:
Take multiple Excel files and read them
Display three drop-down menus for organization name, number of volunteers/hours, and the year the survey was taken, and display three text-entry forms for X and Y labels and Title
Print a histogram that shows, for each organization, the number of volunteers with dodged bars for each year the organization appeared.
The problem is with the second task. I want the app to react when the files get uploaded by placing the whole list of colnames() into the drop-down menu for the user to choose which columns had the organization name. I have tried solutions from other questions on Stack Overflow, but they all ended up throwing errors.
Here is my UI and Server code:
library(rsconnect)
library(readxl)
library(shiny)
library(ggplot2)
dataset <- file
ui <- fluidPage(
shinythemes::themeSelector(),
titlePanel("Volunteer stats"),
sidebarLayout(
sidebarPanel(
#I need: names of each of the files,
# columns for org, num_vol, and survey year,
# labels for x axis, y axis, and title,
# name for the PDF to be created
fileInput(inputId = "file", label = "Choose Excel file", multiple = TRUE),
uiOutput("org_select"),
uiOutput("num_select"),
uiOutput("year_select"),
textInput(inputId = "org_label", label = "X axis label"),
textInput(inputId = "vols_label", label = "Y axis label"),
textInput(inputId = "plot_title", label = "Chart title"),
textInput(inputId = "pdf_title", label = "PDF title")),
mainPanel(
plotOutput(
outputId = "histogram"
)
)
))
server <- function(input, output) {
output$org_select <- renderUI({
selectInput("org_col", "Which column has the organization name?", choices = list(colnames(read_excel(input$file))), label = "Organization")
})
output$num_select <- renderUI({
selectInput("num_vols", "Which column has the relevant metric?", choices = list(colnames(read_excel(input$file))), label = "Number of Volunteers")
})
output$year_select <- renderUI({
selectInput("year", "Which column has the year?", choices = list(colnames(read_excel(input$file))), label = "Year")
})
#assemble all the files into a list based on the input, to be passed to ggplot (not shown)
getData <- reactive({
if (is.null(input$file)){
return(NULL)
}else{
numfiles = nrow(input$file)
files_list = list(
for(i in 1:numfiles)
{
XL_file = read_excel(input$file[[i, 'datapath']], header = TRUE)
lastrow = nrow(XL_file)
shift = function(x, n){
c(x[-(seq(n))], rep(NA, n))
}
XL_file$identity = shift(XL_file$identity, 1)
files_list[[i]] = XL_file[-lastrow, ]
}
)
}
})
getData()
shinyApp(ui = ui, server = server)
I have not included my ggplot function for brevity. If I need help with that, I'll submit a separate question later.
Many thanks,
Fearless
Just two minor fixes to make it work:
input$file is an object (or list if you want), but read_excel() expect a string containing the file path. Use input$file$datapath.
The choices argument expect either a named list of named or unnamed values. With list(colnames(...)) you are passing it a list with a single element containing the chioices:
list(colnames(read_excel('path/to/file')))
[[1]]
[1] "COL_1" "COL_2" "COL_3" "COL_4"
Just pass it the colnames().
server <- function(input, output) {
output$org_select <- renderUI({
selectInput("org_col", "Which column has the organization name?", choices = colnames(read_excel(input$file$datapath)), label = "Organization")
})
output$num_select <- renderUI({
selectInput("num_vols", "Which column has the relevant metric?", choices = colnames(read_excel(input$file$datapath)), label = "Number of Volunteers")
})
output$year_select <- renderUI({
selectInput("year", "Which column has the year?", choices = colnames(read_excel(input$file$datapath)), label = "Year")
})
}
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
})
}
)
)
I'm trying to add a dynamic ggvis plot to a Shiny app. First, user picks a dimension, and then adds items from that dimension.
For global.R and sample data, see https://gist.github.com/tts/a41c8581b9d77f131b31
server.R:
shinyServer(function(input, output, session) {
# Render a selectize drop-down selection box
output$items <- renderUI({
selectizeInput(
inputId = 'items',
label = 'Select max 4. Click to delete',
multiple = TRUE,
choices = aalto_all[ ,names(aalto_all) %in% input$dim],
options = list(maxItems = 4, placeholder = 'Start typing')
)
})
selected <- reactive({
if (is.null(input$items)) {
return(aalto_all)
}
df <- aalto_all[aalto_all[[input$dim]] %in% input$items, ]
df$keys <-seq(1, nrow(df))
df
})
selected %>%
ggvis(~WoS, ~NrOfAuthors, fill = ~School, key := ~keys) %>%
layer_points() %>%
add_tooltip(show_title) %>%
bind_shiny("gv")
show_title <- function(x=NULL) {
if(is.null(x)) return(NULL)
key <- x["keys"][[1]]
selected()$Title20[key]
}
})
ui.R:
shinyUI(fluidPage(
titlePanel('Some (alt)metric data for articles published since 2010'),
sidebarLayout(
sidebarPanel(
selectInput(
inputId = "dim",
label = "Dimension",
choices = dimensions,
selected = c("Title")),
uiOutput("items")
),
mainPanel(
tabsetPanel(
# I'll add more tabs
tabPanel("Plot with ggvis", ggvisOutput("gv"))
)
)
)
))
This is OK
in the beginning, when there are no items selected, and all data is plotted. This is a hack because the ggvis object throws an error if there is no data served.
when all selected items are deleted (which is the same as 1.) and another dimension is chosen
But when I try to switch to another dimension without deleting the items first, I get this:
Error in `$<-.data.frame`(`*tmp*`, "keys", value = c(1L, 0L)) :
replacement has 2 rows, data has 0
I understand that ggvis is very new and constantly developing, but I suspect that there is merely something in Shiny reactive values that is out of sync. If anyone could point out what I'm doing wrong, thanks a lot!
The error is caused because you have a data.frame with zero rows and have a resulting 1:0.
You can change your selected function to:
selected <- reactive({
if (is.null(input$items)) {
return(aalto_all)
}
df <- aalto_all[aalto_all[[input$dim]] %in% input$items, ]
df$keys <-seq_along(df[,1])
if(nrow(df) == 0){
return(aalto_all)
}
df
})