How to extract values from a reactive list? - shiny

I am having trouble accessing elements inside a reactive list I retrieved by reading from a url.
I am having a googlesheet with multiple sheets, and I am reading all the sheet once into a list. However, it seems that I can't retrieve each dataframe stored inside the list.
Code:
read_all_sheet <- function(url){
gs4_deauth()
sheets_names <- sheet_names(url)
lst <- lapply(sheets_names, function (x) read_sheet(url, x))
return(lst)
}
server <- function(input, output, session) {
file_url <- "url"
lst <- reactiveFileReader(1000, NULL, file_url, read_all_sheet)
output$table <- renderDataTable({
dat <- lst()
return(dat[1])
})
}
ui <- fluidPage(
dataTableOutput("table")
)
Error:
Warning: Error in serverFuncSource: server.R returned an object of unexpected type: list
[No stack trace available]
Error in serverFuncSource() :
server.R returned an object of unexpected type: list
I think the function is working all right and but it is returning a list instead of a dataframe. So I think I am having something wrong with my reactiveFileReader or the way I am accessing elements inside lst.
PLEASE HELP!

Related

lapply with a list of lists

I believe that there must be some related questions in the community, but I failed to find the one very informative to my case:
Basically, I am trying to produce three plots with the lapply function. Below are my codes.
p_grid <- seq(0,1,length.out=20)
prior_uni <- rep(1,20)
prior_bi <- ifelse( p_grid < 0.5 , 0 , 1)
prior_exp <- exp(-5*abs(p_grid-0.5))
prior_list <- list(prior_uni, prior_bi, prior_exp)
ggs <- lapply(prior_list, function(x){
likelihood <- dbinom(6,9, prob = p_grid)
unstd.post <- likelihood*x
std.post <- unstd.post/sum(unstd.post)
plot_post <- plot(p_grid,std.post,type="b", ylim = c(0,max(x)))
mtext(paste0(x))
}
)
By doing so, I get the plots but the mtext function does not work well. Instead of showing the title prior_uni, prior_bi, prior_exp respectively, it gives every single value of the list (e.g., prior_uni) with overlapping each other.
It is a bit confusing to me. According to the plot results, the function within lapply seems to take the three lists of prior_list, not every single value. In other words, x is the three elements of prior_list, not the sixty (3*20) elements, but the function mtext does oppositely.
I hope I have expressed clearly. Look for your responses.
Best regards,
Jilong

Use map inside map?

I have two lists: One with some tidy data and another with models made with tidymodels package
data_list <- list(train,test)
model_fits <- list(tree,forest,xgb)
I want to make a new list with a confusion matrix for train and test for every model.
The function that calculates confusion matrix:
ConfMat <-
function(df,data){
df <-
predict(df,new_data = data, type = "class") %>%
mutate(truth = data$NetInc) %>%
conf_mat(truth,.pred_class)}
I have tried to do this (x,y is arbitrary).:
map(data_list,map(model_fits,ConfMat(x,y)))
My problem is that I have no idea how to actually set "x" and "y" right.
PS: double for loop works. I'm asking specifically for map solution or equivalent.
Appreciate all help i can get! cheers
Use an anonymous function -
library(purrr)
result <- map(data_list,function(x) map(model_fits,function(y) ConfMat(x,y)))
result

My checkboxinput value does not work

I have a small shiny application which plot a graph with a log scale when the variable 'logEch' is "x".
This works:
output$plot <- renderPlot({
logEch<-"x"
Plotfigure(XHydrau,DataQs, ParHydrau, Rescal,logEch)
})
But when I affect the value "x" from the inputcheckbox 'xlog':
output$plot <- renderPlot({
if(input$xlog){logEch<-"x"}
Plotfigure(XHydrau,DataQs, ParHydrau, Rescal,logEch)
})
I obtain the error message: argument is of length zero
What do I need to do to fix this?
As you have not posted full reproducible example i can only assume where the problem lays...
I guess you need to expand your if statement --> there must be if...else... arguments!
so i would add to renderPlot:
if(input$xlog){logEch<-"x"}else{NULL}

Scoping between output functions

I have been through (hopefully thoroughly enough) the shiny help article on scoping, and have also seen the answer regarding setting a global object here. Neither addresses, however, what I think (emphasis on "think") I need to do. If a variable is only created in an output function, can it be seen in another? Using action buttons, I'm trying to control lengthy calculations and some will only happen on condition of other things happening. As a minimal example,
library(shiny)
library(stringr)
fruitref <- c("apple","peach","pear","plum","banana","kiwi")
textareaInput <- function(inputID, label, value="", rows=10, columns=30) {
HTML(paste0('<div class="form-group shiny-input-container">
<label for="', inputID, '">', label,'</label>
<textarea id="', inputID, '" rows="', rows,'" cols="',
columns,'">', value, '</textarea></div>'))
}
ui <- fluidPage(titlePanel("minimal example"),
sidebarLayout(
sidebarPanel(
textareaInput("inputfruit", "Enter some fruits:"),
actionButton("checkfruit", "Check fruits"),
verbatimTextOutput("fruitstat")
),
mainPanel(
textOutput("fruits")
)
)
)
server <- function(input,output){
flag <- F
inputs <- eventReactive(input$checkfruit,{input$inputfruit})
continue <- reactive(flag)
output$fruitstat <- renderText({
inputs <- inputs()
inputs <- str_trim(unlist(strsplit(inputs,split="\n")),side="both")
if(length(setdiff(inputs,fruitref)) != 0 | length(inputs) == 0){
flag <- F
paste(paste(setdiff(inputs,fruitref), collapse=", "),"not in table.")
} else {
flag <- T
"All fruits ok."
}
})
output$fruits <- renderText({
paste("Continue? ",continue())
})
}
shinyApp(ui = ui, server = server)
There's a reference table and user input is checked against that table. User enters list in pieces until hitting the check button, then gets feedback whether all are OK, or if there's a mismatch. Only if all are okay do I want to continue. I tried setting a "continue" flag in the output function, but that didn't work, and setting it in the server outside of the output function would not update the value. I also tried creating an environment in the server function and using assign, but that too did not update the value when I tried to retrieve it for renderText later. Since it's not an input, accessible through input$, I figured I cannot use any of the update* functions.
This may not be the best way to set this kind of conditional. I saw in the tutorial the conditional pane, but that depends on an input, rather than something created in the function. More generally, there are more complicated objects to be created in the output functions (there will be four large tables and a plot at most; all or some subset will actually be output) that then other output functions should see, I did not think I could define them as reactive global objects, because until some later things happen, they can't be calculated.
Define continue as an eventReactive:
continue <- eventReactive(input$checkfruit, flag)
And also use the global assignment operator inside function
flag <<- F
flag <<- T
Then it will work. Tested.

Assign names to variable using regular expression in R

So I have a bunch of variables in my workspace. I want to assign a subset of them to a new variable, so I can easily run functions on this subset:
workspace:
...
group10
group40
location40
test
desired assignment:
groupList <- list(group10,group40, ...)
intended regular expression:
^group[0-9]+
Any ideas?
ls accepts a pattern argument:
group10 <- group40 <- location40 <- test <- NA
mysub <- ls(pattern="^group[0-9]+")
mysub
#[1] "group10" "group40"
You can use lapply to loop over the list of variable names and get their values
groupList <- lapply(mysub, get)
or, in one line
groupList <- lapply(ls(pattern="^group[0-9]+"), get)