how to refer two data frames from one reactive function in shiny - r

I have following reactive function in server.r
test <- reactive({
test_1
test_2
})
output$table1 <- renderTable({
test_1
})
output$table2 <- renderTable({
test_2
})
I want to refer test_1 & test_2 from one reactive function to two different output tables.
How can I achieve above ?

Correct way of referring multiple dataframes is as follows
test <- reactive({
test_1
test_2
list(df1 = test_1, df2 = test_2)
})
output$table1 <- renderTable({
test()[['df1']]
})
output$table2 <- renderTable({
test()[['df2']]
})

Have one function, but return:
list(df1=test_1, df2=test_2)
Then refer to these in your your other functions
test()$df1
test()$df2
Don't forget the parenthesis before the $

Try putting reactive data frames into a list:
test <- reactive({
test_1
test_2
testData <- list(test_1, test_2)
testData ## added this
})
output$table1 <- renderTable({
testData <- test()
testData$test_1
})
output$table2 <- renderTable({
testData <- test()
testData$test_2
})
An expanded version of this works for me in a 'renderLeaflet` application.

Related

Rename Colnames from dataframe

I am making a Shiny App and I would like to rename the first variable from dataframe, to make after a corrplot.
In normal R the code is:
library(lares)
names(Dataset)[1] <- "DR"
corr_var(Dataset, DR, top=20)
And in Shiny I have something:
dataReg2 = reactive({
inFile <- input$fileReg
if (is.null(inFile))
return(NULL)
else
data1 = read_excel(inFile$datapath)
return(data1)
})
plot=reactive({
names(dataReg2())[[1]]='DR'
corr_var(dataReg2(), DR , top = 20 )
})
But it doesn't work, the error is invalid (NULL) left side of assignment...
Thank you in advance.
You cannot change the column names of reactive object. Copy the data in another variable and you can change the column name of that variable. See this simple example using mtcars.
library(shiny)
ui <- fluidPage(
tableOutput('tab')
)
server <- function(input, output) {
data <- reactive(mtcars)
output$tab <- renderTable({
new_table <- data()
names(new_table)[1] <- 'new'
head(new_table)
})
}
shinyApp(ui, server)

Shiny manipulating input$df with reactive

I am new to shiny and trying to modify this code to allow for the function to be used from a dynamically selected csv.
## function to return random row number from data set
getTweet <- function(){
tweetData[sample(nrow(tweetData), 1), ]
}
our_tweet <- isolate(appVals$tweet)
output$tweet <- renderText({ our_tweet$tweet })
output$screen_name <- renderText({ our_quote$screen_name })
output$resultsTable <- renderDataTable({appVals$ratings})
The above code works when tweetData is a static csv read in through read.csv() but when I try to use a drop down to select csv the only way I am able to run without error is putting it inside of a renderDataTable() function. How could I use reactive values within input$file and still be able to run the above code.
Code using renderDataTable():
output$test <- renderDataTable({
req(input$file)
csvName <- paste0('../path/to/file/', input$file)
selectedData <- read.csv(csvName)
selectedData
})
I want to be able to do something like this:
csvName <- paste0('../path/to/file/', input$file)
selectedData <- read.csv(csvName)
selectedData[sample(nrow(selectedData), 1), ]
You could create reactive functions:
csvName <- reactive(paste0('../path/to/file/', input$file))
selectedData <- reactive(read.csv(csvName()))
You can then use the reactive functions in other reactives like renderDataTable:
output$test <- renderDataTable({
selectedData()[sample(nrow(selectedData()), 1), ]
})
Don't forget the () when calling the result of reactive functions : csvName(), selectedData(), , ...

Can I create a bunch of reactive input-output pairs from a list in Shiny?

In Shiny, is it possible to create several reactive input-output pairs from a vector/list of strings using a functional?
i.e something like
id_list <- c("ID_1", "ID_2", "ID_3")
server <- function(input, output) {
lapply(id_list, function(x) quote(output$as.character(x) <- renderText({ input$x })))
}
The result would in effect be
output$ID_1 <- renderText({ input$ID_1 })
output$ID_2 <- renderText({ input$ID_2 })
output$ID_2 <- renderText({ input$ID_2 })
etc. for all items in the list, with each working in a reactive manner in the server function.
server <- function(input, output) {
for(id in id_list){
local({
localId <- id
output[[localId]] <- renderText({
input[[localId]]
})
})
}
}

How to change a value in a reactive tibble in R Shiny

I would like to update the content of a reactive object that is holding a tibble in response to a button push and I can't figure out the syntax. The solution that was posted here contains a solution that used to work but now it throws an error.
Below is a reprex of the issue I am having. Run the write.csv(iris, "text.csv") first.
library(shiny)
library(tidyverse)
# create the test data first
# write.csv(iris, "text.csv")
server <- shinyServer(function(input, output) {
in_data <- reactive({
inFile <- input$raw
x <- read.csv(inFile$datapath, header=TRUE)
})
subset <- reactive({
subset <- in_data() %>%
filter(Species == "setosa")
})
observeEvent(input$pushme, {
subset()$Sepal.Length[2] <- 2
})
output$theOutput <- renderTable({
subset()
})
})
ui <- shinyUI(
fluidPage(
fileInput('raw', 'Load test.csv'),
actionButton("pushme","Push Me"),
tableOutput('theOutput')
)
)
shinyApp(ui,server)
My code to change the value:
subset()$Sepal.Length[2] <- 2
Throws this error:
Error in <-: invalid (NULL) left side of assignment
What is the syntax for programmatically changing the value in a reactive tibble?
You can't modify directly the value of a reactive object. You have to define first a static object that will take the value of the reactive object, and then you can modify the value of the static object. Two options for you (no modifications in ui):
The first one is to use renderTable just after having subseted your data, and then to modify your table inside observeEvent:
server <- shinyServer(function(input, output) {
in_data <- reactive({
inFile <- input$raw
x <- read.csv(inFile$datapath, header=TRUE)
})
test1 <- reactive({
data <- in_data() %>%
filter(Species == "setosa")
data
})
output$theOutput <- renderTable({
req(input$raw)
test1()
})
observeEvent(input$pushme, {
output$theOutput <- renderTable({
req(input$raw)
test1 <- test1()
test1$Sepal.Length[2] <- 2
test1
})
})
})
The second one is to define another dataset (test2 here) that will be computed with eventReactive only if the button is pushed. Then you have to define which of the two datasets you want to use in renderTable using conditions on their existence:
server <- shinyServer(function(input, output) {
in_data <- reactive({
inFile <- input$raw
x <- read.csv(inFile$datapath, header=TRUE)
})
test1 <- reactive({
data <- in_data() %>%
filter(Species == "setosa")
data
})
test2 <- eventReactive(input$pushme, {
test1 <- test1()
test1$Sepal.Length[2] <- 2
test1
}
)
output$theOutput <- renderTable({
if (input$pushme) {
test2()
}
else {
req(input$raw)
test1()
}
})
})
By the way, you shouldn't call datasets (reactive or not) like function names. In your example, you have called subset the reactive dataset you modify. This is not good since this dataset will be used as subset() (because it is reactive). It may be confusing both for you and for the execution of the code.

Replace non-reactive data with reactive data

I have a complicated shiny app where I have used '<-' to create new columns on a non-reactive data.something like:
# Without reactive expression
ui <- fluidPage(tableOutput("contents"))
server1 <- function(input, output) {
myData <- mtcars
myData$New1 <- rep("NV1", nrow(myData))
myData$New2 <- rep("NV2", nrow(myData))
myData$New3 <- rep("NV3", nrow(myData))
myData$New4 <- rep("NV4", nrow(myData))
output$contents <- renderTable(myData)
}
shinyApp(ui, server1)
Now I want to replace the non-reactive data with reactive. How can I do that with minimal change?
I have tried something like:
# With reactive expression
ui <- fluidPage(tableOutput("contents"))
server2 <- function(input, output) {
all <- reactiveValues()
all$d <- mtcars
all$d$New1 <- rep("NV1", nrow(all$d))
all$d$New2 <- rep("NV2", nrow(all$d))
all$d$New3 <- rep("NV3", nrow(all$d))
all$d$New4 <- rep("NV4", nrow(all$d))
output$contents <- renderTable(all$d)
}
shinyApp(ui, server2)
You could do something like this:
ui <- fluidPage(tableOutput("contents"))
server2 <- function(input, output) {
# you can assign variables in reactiveValues(), no need to make a new line
all <- reactiveValues(d = mtcars)
observeEvent(all$d, { # update all$d, after it is created
req(!is.null(all$d))
all$d$New1 <- rep("NV1", nrow(all$d))
all$d$New2 <- rep("NV2", nrow(all$d))
all$d$New3 <- rep("NV3", nrow(all$d))
all$d$New4 <- rep("NV4", nrow(all$d))
})
output$contents <- renderTable(all$d)
}

Resources