Save data instered (in the data table) using the R shiny package - r

I am making an R shiny app (I am quite new to R shiny) which gets data as an input and projects the data as a table (using DT package). However when new data is inserted and submitted new rows are not being added, but rather the previous observation (previous submitted data is simply updated. Thus, what can I do to make save the new data data ?

The main problem in your code was you were creating a new data frame and replacing it with the previous one. I have slightly modified your server code. I have added a global variable TabData to save the previous data in the data table and rbind it with the new data to be added to the table. Please see the modified code below:
library(shiny)
library(car) # Import library to use recode() function
shinyServer(function(input, output) {
#Global variable to save the previous data in the data table
TabData <- data.frame()
values <- reactiveValues()
# Calculate damage and loss (just ab experiment)
observe({
input$action_Calc
values$int <- isolate({input$reduction * 10})
values$amt <- isolate({input$lost}) + values$int
values$com<-isolate({input$community})
values$disaster <- isolate({input$disaster})
values$name <- isolate({input$name})
})
# Display values entered
output$text_principal <- renderText({
input$action_Calc
paste("reduction: ", isolate(input$reduction))
})
output$text_intrate <- renderText({
input$action_Calc
paste("Vegetation: ", isolate(input$veg))
})
output$text_int <- renderText({
if(input$action_Calc == 0) ""
else
paste("Damage:", values$int)
})
output$text_amt <- renderText({
if(input$action_Calc == 0) ""
else
paste("Loss:", values$amt)
})
Data <- reactive({
browser()
if (input$action_Calc > 0) {
df <- data.frame(
Community= values$com,
Disaster = values$disaster,
Name = values$name,
Damage=values$amt,
Loss=values$int
)
return(list(df=df))
}
})
output$responses <- DT::renderDataTable(DT::datatable({
if (is.null(Data())) {return()}
#Row bind the new data to be added to the table
TabData <<- rbind(TabData, Data()$df)
datum<-TabData
datum
}))
})
Hope it helps!

Related

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(), , ...

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)```

data tibble empties on shiny

I am having trouble sending a tibble loaded from a user file to a plotting function. It seems that the table is indeed read and modified properly, but when I ask another function to use it for plotting the entries are missing.
on the Shiny server I have the following:
myData <- reactive({
if (is.null(inFile())) {
return(NULL)
} else {
tmp_table = read_csv(inFile()$datapath[1])
# tmp_table = read_csv('Fazael_grain_size.csv')
big_table=tmp_table
# modify the factor columns into factors
big_table$sample_name <- factor(big_table$sample_name)
big_table$site <- factor(big_table$site)
big_table$fraction <- factor(big_table$fraction)
# remove NA rows
big_table=big_table[!is.na(big_table$sample_name),]
# make sure the table was loaded correctly
output$table <- renderTable((big_table))
return(big_table)
}
})
a screenshot showing the proper loading of the table
then I want to use this table for plotting, so I have the following chunk:
myPlot <- function(){
# make sure the data exists
req(myData())
big_table=myData()
# checking the tibble was properly sent to the plotting function
output$table <- renderTable(big_table)
# filter the data based on user selection
big_table = filter(big_table,sample_name %in% input$selected_sample_name)
big_table = filter(big_table,site %in% input$selected_site)
big_table = filter(big_table,fraction %in% input$fraction)
p = big_table %>%
ggplot(aes_string(x=colnames(big_table)[4],y=colnames(big_table)[4])) +
geom_point()
if (!(input$color_variable %in% c("none"))) {
p = p +
geom_point(aes_string(color=input$color_variable))
}
p
}
for some reason the plot remains empty, and after some debugging I found out that the tibble is forwarded empty to it. any answers?
a screenshot demonstrating that the entries in the table are not forwarded into the plotting function
and indeed, the plot doesn't show up:
output$plot1 <- renderPlot({
myPlot()
})
no plot appears on the plotting area
solved. there was a small bug in the filter function:
should have been:
big_table = filter(big_table,fraction %in% input$selected_fraction)

Reactive/Calculate column in Rhandsontable where source data is dataframe from reactive value

I have a shiny app that will display a rhandsontable depending on the Product Category that the user wants to review. I need to recalculate one of the columns if the user inputs different values into another column and I found this example to be useful:
Reactive/Calculate Columns in rhandsontable in shiny- rstudio
except that I get the data of my tables from a reactive object so when I redirect "datacopy" to the function to get the data, this code does not work. Could anyone please help me achieve it?
Here is a sample code:
library(shiny)
library(datasets)
library(rhandsontable)
library(data.table)
ui=fluidPage(
rHandsontableOutput("table1")
)
server=function(input, output, session) {
mt=reactive({
datacopy <- NULL
#For initial data upload
if(is.null(input$table1)){
datacopy= mtcars[, names(mtcars) %in% c("mpg" , "cyl" , "disp")]
datacopy=data.table(datacopy)
}else{
datacopy = hot_to_r(input$table1)
#If there is change in data
if(!is.null(input$table1$changes$changes)){
row.no <- unlist(input$table1$changes$changes)[1]
col.no <- unlist(input$table1$changes$changes)[2]
new.val <- unlist(input$table1$changes$changes)[4]
#If the changed value is mpg or cyl
if(col.no == 0 || col.no == 1){
datacopy[(row.no+1), 3] = datacopy[(row.no+1), 1]*datacopy[(row.no+1), 2]
}else{
datacopy[(row.no+1), 2] = datacopy[(row.no+1), 1]*datacopy[(row.no+1), 3]
}
}
}
datacopy
})
output$table1=renderRHandsontable({
rhandsontable(mt())
})
}
shinyApp(ui, server)

Working with reactiveValues and ggplot in shiny

Im using R and shiny to query an SQL database. The user can search and add to a reactive data frame, the output of which is plotted in ggplot. However, I need to change the columns of the reactive data frames to factors for plotting. I can do this directly with ggplot (aes(factor(...), ). However, if I add the option of changing the plotted variable using a reactive input, I must use aes_string. If I use aes_string it does not like aes(factor(...),. Here is a working example:
Server:
# Create example data
set.seed(10)
MeasurementA <- rnorm(1000, 5, 2)
MeasurementB <- rnorm(1000, 5, 2)
Wafer <- rep(c(1:100), each=10)
ID <- rep(c(101:200), each=10)
Batch <- rep(c(1:10), each=100)
dd <- data.frame(Batch, Wafer, ID, MeasurementA, MeasurementB)
# Create local connection (in reality this will be a connection to a host site)
con <- dbConnect(RSQLite::SQLite(), ":memory:")
dbWriteTable(con, "dd", dd)
query <- function(...) dbGetQuery(con, ...)
# Create empty data frames to populate
wq = data.frame()
sq = data.frame()
shinyServer(function(input, output){
# create data frame to store reactive data set from query
values <- reactiveValues()
values$df <- data.frame()
# Action button for first query
d <- eventReactive(input$do, { input$wafer })
# First stage of reactive query
a <- reactive({ paste("Select ID from dd where Wafer=",d(), sep="") })
wq <- reactive({ query( a() ) })
# Output to confirm query is correct
output$que <- renderPrint({ a() })
output$pos <- renderPrint( wq()[1,1] )
# Action button to add results from query to a data frame
e <- eventReactive(input$do2, { wq()[1,1] })
b <- reactive({ paste("select Wafer, Batch, MeasurementA, MeasurementB from dd where ID=",e()," Order by ID asc ;", sep="") })
# observe e() so that data is not added until user presses action button
observe({
if (!is.null(e())) {
sq <- reactive({ query( b() ) })
# add query to reactive data frame
values$df <- rbind(isolate(values$df), sq())
}
})
# output of results
# Without mesurement choice (works)
output$boxV <- renderPlot({
ggplot(values$df, aes(factor(Wafer), MeasurementA, fill=factor(Batch))) + geom_boxplot()
})
# With measurement choice (doesnt work)
#output$boxV <- renderPlot({
#ggplot(values$df, aes_string(factor('Wafer'), input$char, fill=factor('Batch'))) + geom_boxplot()
#})
})
UI:
library(markdown)
shinyUI(fluidPage(
titlePanel("Generic grapher"),
sidebarLayout(
sidebarPanel(
numericInput("wafer", label = h3("Input wafer ID:"), value = NULL),
actionButton("do", "Search wafer"),
actionButton("do2", "Add to data frame"),
selectInput("char", label="Boxplot choice:",
choices = list("A"="MeasurementA", "B"="MeasurementB"),
selected="Von.fwd")
),
mainPanel(
verbatimTextOutput("que"),
verbatimTextOutput("pos"),
plotOutput("boxV")
)
)
)
)
Ive added output plot code for both working and non-working (non-working is commented out).
Now, ive read this (Formatting reactive data.frames in Shiny) and this (R shiny modify reactive data frame) but im confused. Because im using reactiveValues to store data, I use the code values$df to access the data...but what if i I want to turn a column to a factor for purpose of above? this doesnt seem to work:
new <- reactive(as.factor(values$df$Wafer))
Perhaps I am barking up the wrong tree with this?
Ok, I solved the problem by changing the data type within the query itself:
b <- reactive({ paste("select cast(Wafer as varchar) as Wafer, cast(Batch as varchar) as Batch, MeasurementA, MeasurementB from dd where ID=",e()," Order by ID asc ;", sep="") })
That way I didnt have to mess about afterwards. It works for me but if anyone reading this wants to tell me that its a bad idea, please do. Im new to SQL and R so please correct me so I can learn. Thanks

Resources