I made a shiny dashboard that connects to a postegreDB and get a value from a table, then subset it, and then transform it to a wide format using reshape2. I want to update the value directly from the dashboard, and then push them into the database.
I used this link for inspiration: https://github.com/MangoTheCat/dtdbshiny
This is the code I made:
server <- function(input, output, session) {
# Generate reactive values
rvs <- reactiveValues(
data = NA,
dataWide = NA,
dataSub = NA,
cdfilTmp = NA,
cdfilTmp2 = NA,
dataWideTmp = NA,
dbdata = NA,
dataSame = TRUE,
req = NA,
tabId = NA,
listeSeuil = NA,
dataMod = NA
)
# Generate source via reactive expression
mysource <- reactive({
dbGetQuery(pool, "SELECT * from bilanmasse.v_export_r_scen_seuil")
})
# Observe the source, update reactive values accordingly
observeEvent(mysource(), {
# Lightly format data by arranging id
# Not sure why disordered after sending UPDATE query in db
data <- mysource() %>% arrange(idscenar)
data <- dbGetQuery(pool, "SELECT * from bilanmasse.v_export_r_scen_seuil")
rvs$cdfilTmp <- paste(data$ordreseuil, data$nomfiliere, sep="-")
data$cdfiliere <- rvs$cdfilTmp
data <- data[c("idscenar", "nomscenar", "codeparam", "cdusage", "cdlithoprof", "cdfiliere", "valseuil")]
rvs$data <- data
rvs$dbdata <- data
rvs$listeSeuil <- unique(rvs$data[,1])
rvs$tabId <- dbGetQuery(pool, "SELECT * from bilanmasse.scenar_testr")
updateSelectInput(session, "listScen",
label = "Choix du scenario",
choices = isolate(rvs$listeSeuil)
)
})
rvs$dataSub <- reactive({ subset(rvs$data, rvs$data[,1] == input$listScen) })
rvs$dataWide <- reactive({ dcast(rvs$dataSub(), idscenar+nomscenar+codeparam+cdusage+cdlithoprof~cdfiliere, value.var="valseuil") })
rvs$dataWideTmp <- reactive({ rvs$dataWide() })
ScenBase <- reactive({ subset(rvs$data, rvs$data[,1] == 2) })
listeParam <- reactive({ unique(ScenBase()[,3]) })
listeUsage <- reactive({ unique(ScenBase()[,4]) })
listeLithoProf <- reactive({ unique(ScenBase()[,5]) })
listeTraitement <- reactive({ unique(ScenBase()[,6]) })
#
# render the table
output$tabScSeuil <- renderDataTable(
rvs$dataWide(), rownames = FALSE, editable = TRUE, selection = 'none', filter= "top", options = list(
columnDefs = list(list(className = 'dt-center', targets = "_all")))
)
proxy3 = dataTableProxy('tabScSeuil')
observeEvent(input$tabScSeuil_cell_edit, {
info = input$tabScSeuil_cell_edit
i = info$row
j = info$col = info$col + 1 # column index offset by 1
v = as.numeric(info$value)
rvs$dataWideTmp[i,j] <- v
output$test <- renderPrint(rvs$dataWideTmp[i,j])
})
}
Everything work perfectly expect when I want to update the new value into the table: I got this error:
Error in [: object of type 'closure' is not subsettable
So I tried to use an SQL request instead of a subset:
observeEvent(input$listScen, {
val <- as.character(input$listScen)
req <- paste0("SELECT * from bilanmasse.v_export_r_scen_seuil WHERE idscenar = ", val)
observeEvent(input$listScen, { dataSub <- dbGetQuery(pool, req) })
#cdfilTmp2 <- paste(dataSub[,6], dataSub[,7], sep="-")
#dataSub[,9] <- cdfilTmp2
#dataSub <- dataSub[c("idscenar", "nomscenar", "codeparam", "cdusage", "cdlithoprof", "V9", "valseuil")]
#colnames(dataSub) <- c("idscenar", "nomscenar", "codeparam", "cdusage", "cdlithoprof", "cdfiliere", "valseuil")
#dataWide <- dcast(dataSub, idscenar+nomscenar+codeparam+cdusage+cdlithoprof~cdfiliere, value.var="valseuil")
#dataWideTmp <-dataWide
output$test <- renderPrint(req)
})
But I got a weird error, when I print req, the request is OK:
[1] "SELECT * from bilanmasse.v_export_r_scen_seuil WHERE idscenar =
2"
But in the R console, I got an error:
Warning in postgresqlQuickSQL(conn, statement, ...) : Could not
create execute: SELECT * from bilanmasse.v_export_r_scen_seuil WHERE
idscenar =
Does someone know a solution to make this?
Related
I tried to achieve when with a chosen split percentage, it returns the train set and then with a sampling method to resample train set and calculate its class freq and perc.
The error I got: object 'split.df' not found when I choose check box 'over'.
Should I use eventReactive or other syntax to achieve? The final return the table with either freq or perc should be dependent on 'split', 'sample' and dropdown 'freq' or 'perc'.
Here is portion that relates in ui:
sidebarLayout(
sidebarPanel(
h3("Train/test set"),
tags$br(),
selectInput(
"trainset",
"Select train component",
choices = list('freq'='freq', 'percentage'='perc'),
),
sliderInput(
"split",
label = "split percentage",
min = 0,
max = 1,
value = 0,
step = 0.1
),
h3("resampling train set"),
checkboxGroupInput('sample', label = "sampling method",
choices = list('original'='original','over'='over', 'under'='under', 'both'='both','ROSE'='ROSE'),
selected = list('original'='original'))
),
Here is a code relates for server:
split.df <- reactive({
index <- createDataPartition(df$class, p=input$split, list=FALSE)
Training_Data <- df[index,]
return(Training_Data)
})
train_set <- reactive({
if(input$sample == 'original')
Training_Data_class <- data.frame(class = split.df()$class)
return(Training_Data_class)
})
over_train_set <- reactive({
split.df <- split.df()
if(input$sample == 'over'){
over <- ovun.sample(class~., data = split.df, method = 'over')$data
Training_Data_class_over <- data.frame(class = over$class)
return(Training_Data_class_over)}
})
trainset_df <- reactive({
freq.df.train <- data.frame(table(train_set()))
colnames(freq.df.train) <- c('class', 'freq')
perc.df.train.=data.frame(prop.table(table(train_set()))*100)
colnames(perc.df.train) <- c('class','perc')
if(input$trainset == 'freq')
return(freq.df.train)
if(input$trainset == 'perc')
return(perc.df.train)
})
over_trainset_df <- reactive({
freq.df.train.over <- data.frame(table(over_train_set()))
colnames(freq.df.train.over) <- c('class', 'freq')
perc.df.train.over=data.frame(prop.table(table(over_train_set()))*100)
colnames(perc.df.train.over) <- c('class','perc')
if(input$trainset == 'freq')
return(freq.df.train.over)
if(input$trainset == 'perc')
return(perc.df.train.over)
})
output$trainsetdistr <- DT::renderDataTable({
if(input$sample == 'over'){
return(over_trainset_df())
}
if(input$sample == 'original'){
return(trainset_df())
}
}
)
I can't figure out what is wrong with this code. My shiny give the error when I click on the action button PlotContemp, so I think the problem is somewhere in the mvar function. When I run this code with the same data but outside the Shiny, it works great!So is there a problem with the reactive expressions? I will appreciate some help!
observeEvent(store$df, {
req(store$df)
updateSelectInput(session, "NetVariables", choices = colnames(store$df),
selected = "Anxiety")
})
Vars <- reactive({
Vars <- c(input$NetVariables)
return(Vars)
})
type <- reactive({
type <- rep("g",length(Vars()))
for (v in length(Vars())) {
if (class(store$df[Vars()][[v]]) == "character") {
type[v] <- "c"
}
}
})
levels <- reactive({
levels <- rep(1, length(Vars()))
for (v in length(Vars())) {
if (class(store$df[Vars()][[v]]) == "character") {
levels[v] <- 2
}
}
})
observeEvent(input$PlotContemp, {
req(store$df)
mvar1 <- mvar(store$df[,Vars()], type = type(),
level = levels(), lags=1, dayvar = store$df$day, beepvar = store$df$beep, lambdaSel = "CV", lambafolds = 10, overparameterize = FALSE, k=2, ruleReg = "AND")
qgraph(mvar1$wadj[,,1],
edge.color = mvar1$edgecolor,
layout = "spring",
labels = vars)
})
I am trying to built an async app using shiny and ran into a problem. Sometimes when starting the app, an error message appears in the console: "later: exception occured while executing callback: Evaluation error: object of type 'closure' is not subsettable.". The app runs as expected even when the message appears. My best guess is that it is some sort of race problem since it only appears about 50% of the times I start the app.
Thank you very much for your help and insights! Also, if you detect any other problems with my shiny implementation, feel free to let me know!
```
library(shiny)
library(promises)
library(future)
library(tidyverse)
library(glue)
plan(multisession) # plan(multicore) -> forking (not Windows/RStudio)
scopes_ui <- c('a', 'b', 'c')
ui <- function(){
tagList(
# numeric input for the first promise
numericInput(inputId = 'num1',
label = 'Choose your first number: ',
value = 0,
min = 0,
max = 10),
# numeric input for the second promise which relies on the first promise
numericInput(inputId = 'num2',
label = 'Choose your second number: ',
value = 3,
min = 0,
max = 10),
# input to test additional filter options
selectInput('ui_scope',
label = 'Choose scope: ',
scopes_ui,
selected = 'a'),
# this will receive the output of the future
h2('1. Table'),
tableOutput('res1'),
h2('2. Table'),
tableOutput('res2'),
# this plot will be drawn before the future is resolved
plotOutput('plot_inst'),
)
}
server <- function(input, output, session) {
# empty list sufficient (no need to actually initiate with NULLs)
rv <- reactiveValues(
last_id1 = NULL,
res1 = NULL,
res1_id = NULL,
value1 = NULL,
scope = NULL,
last_id2 = NULL,
value2 = NULL,
res2 = NULL
)
# ~~~~~~~~~~~~~~~~~~~~ #
# First promise #
# ~~~~~~~~~~~~~~~~~~~~ #
observe({
# initiate reactive variables BEFORE the promise
rv$last_id1 <- glue('ID_{input$num1}')
last_id1 <- rv$last_id1
rv$value1 <- input$num1
value1 <- rv$value1
rv$scope <- input$ui_scope
scope <- rv$scope
# promise
future_promise({
# make computation expensive
if(value1 %% 2 == 0) {
Sys.sleep(10)
}
data <- data.frame(treat = c('a', 'b', 'c'), outcome = c(value1, 1.9, 3.2))
data <- data %>% filter(treat == scope)
# return id and data from the future
list(
id = last_id1,
res = data
)
}) %...>%
(function(result){
# change value1 of `rv$res1` only if the current id is the same as the last_id
if (result$id == rv$last_id1){
rv$res1_id <- result$id
rv$res1 <- result$res
}
})
# this must return something (including "empty") to execute asynchronously
return()
}) %>%
bindEvent(input$num1, input$ui_scope)
# ~~~~~~~~~~~~~~~~~~~~ #
# Second promise #
# ~~~~~~~~~~~~~~~~~~~~ #
observe({
# initiate reactive variables BEFORE the promise
rv$last_id2 <- glue('ID_{input$num1}_{input$num2}')
last_id2 <- rv$last_id2
rv$value2 <- input$num2
value2 <- rv$value2
# ensure that rv$res1 is available
data <- req(rv$res1)
# promise
future_promise({
# make computation expensive
Sys.sleep(5)
data[1,2] <- value2
# return id and data from the future
list(
id = last_id2,
res = data
)
}) %...>%
(function(result){
# change value of `rv$res2` only if the current id is the same as last_id2
if (result$id == rv$last_id2){
rv$res2 <- result$res
}
})
# this must return something (including "empty") to execute asynchronously
return()
}) %>%
bindEvent(rv$res1, input$num2)
# output$res1 will be printed whenever rv$res1
# is available, i.e. returned from the future,
# and corresponds to the last input sent.
output$res1 <- renderTable({
req(rv$res1)
})
output$res2 <- renderTable({
req(rv$res2)
})
# output$plot_inst will be drawn immediately
my_plt <- reactive({
data <- data.frame(treat = c('a', 'b', 'c'), outcome = c(1, 2, 3)) %>%
filter(treat == input$ui_scope)
ggplot(data, aes(treat, outcome)) +
geom_col() +
theme(text = element_text(size = 20))
})
output$plot_inst <- renderPlot({
req(my_plt())
})
}
shinyApp(ui, server)
```
I am new to shiny and trying to figure out some reactive stuff.
Currently this works for a static csv.
## function to return random row from twitter csv
tweetData <- read.csv('twitterData1.csv')
## stores reactive values
appVals <- reactiveValues(
tweet = tweetData[sample(nrow(tweetData), 1), ],
ratings = data.frame(tweet = character(), screen_name = character(), rating = character())
)
I need the same block of reactive values to be funciton but using a selected csv using input$file.
appVals <- reactiveValues(
csvName <- paste0('../path/', input$file),
tweetData <- read.csv(csvName),
tweet = tweetData[sample(nrow(tweetData), 1), ],
ratings = data.frame(tweet = character(), screen_name = character(), rating = character())
)
I get the error:
Warning: Error in : Can't access reactive value 'file' outside of reactive consumer.
I've tried moving things around but I keep getting stuck, help appreciated!
The error is telling that you should update the values inside a reactive expression.
First initialize the reactive values:
tweetData <- read.csv('twitterData1.csv')
appVals <- reactiveValues()
appVals$tweet <- tweetData[sample(nrow(tweetData), 1), ]
appVals$ratings <- data.frame(tweet = character(), screen_name = character())
Then update them with a reactive:
observeEvent(input$file,{
csvName <- paste0('../path/', input$file)
if (file.exists(csvName) {
tweetData <- read.csv(csvName)
appVals$tweet = tweetData[sample(nrow(tweetData), 1), ]
appVals$ratings = data.frame(tweet = character(), screen_name = character(), rating = character())
}
})
I need to be able to access each variable's data in my data frame, after the user has selected and uploaded a local csv file. This code is the part of my Shiny script where I create and modify the csv file read in by the user. "rv" is the data, which is a reactiveValues dataframe, so it can be modified.
Variable names are chosen by the user through a radio button group (shown here, but defined in the ui part of the script). The other code is in the server portion of the script.
radioButtons('radiovarGroup1',label = h5("Choose a Variable to Analyze:"),
choices = list('TA' = 'TA','PP' = 'PP', 'US' = 'us', 'UD' = 'ud', 'UE' = 'ue',
'UG' = 'ug', 'UH' = 'uh', 'XR' = 'xr', 'RW' = 'rw', 'PA' = 'pa', 'TB4' = 'tb4',
'TV2' = 'tv2', 'TV4' = 'tv4', 'TV8' = 'tv8', 'TV20' = 'tv20', 'TV40' = 'tv40',
'MV2' = 'mv2', 'MV4' = 'mv4', 'MV8' = 'mv8', 'MV20' = 'mv20', 'MV40' = 'mv40',
'VB' = 'vb', 'TA40' = 'ta40', 'TA120' = 'ta120', 'SD' = 'sd'),inline = TRUE, selected = NULL),
var_names = c('TA','PP','US','UD','UE','UG','UH','XR','RW','PA','TB4','TV2','TV4',
'TV8','TV20','TV40','MV2','MV4','MV8','MV20','MV40','VB','TA40','TA120','SD')
rv <- reactiveValues(df = NULL)
#This function is responsible for loading in the selected file
observe({
req(input$file_selector)
rv$df <- read.csv(paste0(parseDirPath(c(home = 'C:\\Users\\Ruben\\Desktop\\Test_QC_Program\\FiveMin'), file_dir()),'\\',input$file_selector),skip=1) # Simplified for testing
})
# This previews the CSV data file
output$filetable <- renderDataTable({
rv$df
})
observeEvent(input$qc_final_cols, {
if (input$qc_final_cols){
for (v in 1:length(var_names)){
ind <- which(colnames(rv$df) == var_names[v])
rv$df <- rv$df %>%
add_column(z = NA,.after = ind)
colnames(rv$df)[ind+1] <- paste0(var_names[v],'_QC')
rv$df <- rv$df %>%
add_column(y = NA,.after = ind+1)
colnames(rv$df)[ind+2] <- paste0(var_names[v],'_Final')
}
}
})
output$checked_var <- renderPrint({
input$radiovarGroup1})
variable_data <- reactive({get(rv$df[,which(colnames(rv$df) == input$radiovarGroup1)])})
Why do I keep getting an "object of type closure is not subsettable' error returned for variable_data? I can render the rv$df data table just fine, but I can't extract data from it for some reason.