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

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.

Related

Trouble modifying reactive dataframe in Shiny

I'm working on an app which takes up a CSV via reactiveFileReader and applies some functions. I would like to modify the contents of the data before applying these functions.
I understand that reactive objects cannot be modified directly, but I can't even seem to be able to make a new object with the desired modifications (in this case, new column names in the dataframe).
This is where I am at in the server code:
data <- reactiveFileReader(1000, session, "path", read.csv)
data_new <- reactive({ colnames(data) <- c("Col 1"," Col 2","Col 3") })
output$data <- renderDataTable(data_new())
Unfortunately this yields the error "Error: attempt to set 'colnames' on an object with less than two dimensions".
Any suggestions on how to properly modify and store the data?
Many thanks!
Try this
ui <- fluidPage(
uiOutput("data1"),
uiOutput("data")
)
server <- function(input, output, session) {
data <- reactiveFileReader(1000, session, "file2.csv", read.csv)
data_new <- reactive({
df <- data()
colnames(df) <- c("Col 1"," Col 2","Col 3")
df
})
output$data <- renderTable(data_new())
output$data1 <- renderTable(head(data()))
}
shinyApp(ui, server)

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)

How to save data in database from shiny app?

I want to save user'S data in the db.
Every user's data should be submitted per row without any error. The data is in a function with if else condition. Every if else's output is to be saved against it's user. How can I do it?
I tried creating a dataframe for it but still the data wasn't saved in it.
Here is reprex of my code.
library(shiny)
library(tidyverse)
ui <- fluidPage(
textInput("my_in","type a value for an entry"),
actionButton("newline_but","press for a new entry"),
tableOutput("showmytable")
)
server <- function(input, output, session) {
mydf <- reactiveVal(tibble(msg=NA_character_))
output$showmytable <- renderTable({
mydf()
})
observeEvent(input$my_in,{
local_df <- req(mydf())
curr_row <- nrow(local_df)
local_df[curr_row,1] <- input$my_in
mydf(local_df)
})
observeEvent(input$newline_but,{
local_df <- req(mydf())
mydf(add_row(local_df))
})
observeEvent(mydf(),
{
#export to a global but would be better to maybe write to a database
assign(x="exported_df",
value=mydf(),
envir = .GlobalEnv)
})
}
shinyApp(ui,server)```

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

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.

How can I change the input dataset in Shiny R?

I would like to select some rows of a dataset given an input defined by the user. In this case I would like to run different classification trees depending on the different positions in the field. I have a selectInput() in Shiny R which expands a menu where you can select for which field position you want to run the tree. However, for the moment it only runs for all the positions but not for each one individually. I'd appreciate some help on how to switch between datasets depending on user selection.
server.R
library(shiny)
library("rpart")
library("party")
library("partykit")
setwd("~/UNIVERSIDAD/EUR/Block 2/Machine Learning/Shiny App Both")
dat <- read.csv("Voetballers.csv")
dat <- dat[,3:20]
shinyServer(function(input, output, session) {
observe({
if(input$position=="All"){
dat <- dat
}
else if(input$position=="Forward"){
dat <- dat[dat$Position=="Forward",]
}
else if(input$position=="Midfielder"){
dat <- dat[dat$Position=="Midfielder",]
}
else if(input$position=="Defender"){
dat <- dat[dat$Position=="Defender",]
}
else if(input$position=="Goalkeeper"){
dat <- dat[dat$Position=="Goalkeeper",]
}
})
output$independent <- renderUI({
checkboxGroupInput("independent", "Independent Variables:",names(dat)[!names(dat) %in% input$dependent],names(dat)[!names(dat) %in% input$dependent])
})
runRegression <- reactive({
ctree(as.formula(paste(input$dependent," ~ ",paste(input$independent,collapse="+"))),data=dat)
})
runRegression2 <- reactive({
rpart(as.formula(paste(input$dependent," ~ ",paste(input$independent,collapse="+"))),data=dat)
})
output$plot1 <- renderPlot({
plot(runRegression())})
output$plot2 <- renderPlot({
plot(as.party(runRegression2()))})
})

Resources