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)
Related
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)
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)```
I have this question: In a Shiny App, I construct a varible with a reactive(). The thing is that, in the midle of this process (that is a long one) I construct other varibles that I need too.
For example:
#---------------UI------------------
ui <- navbarPage(
title = "example",
tabPanel('panel',
tableOutput("my_table"),
tableOutput("colum_names"))
)
#---------------SERVER------------------
server <- function(input, output) {
a <- reactive({
df_1 <- data.frame("fc"=c(1,2,3), "sc"=c(1,2,3), "tc"=c(1,2,3) )
df_2 <- subset(df_1,select=-c(fc))
column_names <- colnames(df_2)
df_3 <- df_2*2
df_3
})
output$my_table = renderTable({
a()
})
output$colum_names = renderTable({
df_column_names = data.frame(column_names())
df_column_names
})
}
#---------------APP------------------
shinyApp(ui = ui, server = server)
In this (very short) example, I would need the variable "a" (of course) and the variable "column_names". I can do something like create a new reactive that reproduce all the process until the line that contain "column_names" and finish it there. But the process is too long and I prefer to do it more "eficiently".
Any idea??
Thank you so much!
The process you're describing is correct : instead of assigning variables, just assign reactives and Shiny will handle the depedencies between them.
Note that in the example you provided, reactives aren't needed because the content is up to now static.
library(shiny)
#---------------UI------------------
ui <- navbarPage(
title = "example",
tabPanel('panel',
tableOutput("my_table"),
tableOutput("column_names"))
)
#---------------SERVER------------------
server <- function(input, output) {
df_1 <- data.frame("fc"=c(1,2,3), "sc"=c(1,2,3), "tc"=c(1,2,3) )
a <- reactive({subset(df_1,select=-c(fc))})
column_names <- reactive({colnames(a())})
output$my_table = renderTable({a()})
output$column_names = renderTable({column_names()})
}
#---------------APP------------------
shinyApp(ui = ui, server = server)
I found a interesting answer to my own question: if you want to do something like that, you can use "<<-" instead of "<-" and it save the variable when you are working insede a function (like reactive()). Let´s see:
#---------------UI------------------
ui <- navbarPage(
title = "example",
tabPanel('panel',
tableOutput("my_table"),
tableOutput("colum_names"))
)
#---------------SERVER------------------
server <- function(input, output) {
a <- reactive({
df_1 <- data.frame("fc"=c(1,2,3), "sc"=c(1,2,3), "tc"=c(1,2,3) )
df_2 <- subset(df_1,select=-c(fc))
column_names <- colnames(df_2)
# HERE THE SOLUTION!!
column_names_saved <<- column_names
df_3 <- df_2*2
df_3
})
output$my_table = renderTable({
a()
})
output$colum_names = renderTable({
df_column_names = data.frame(column_names_saved)
df_column_names
})
}
#---------------APP------------------
shinyApp(ui = ui, server = server)
Then, into the funtion you must continues with the variable "column_names", but when you need to use it later, you can use "column_name_saved". (just be carefull with one thing: onece you save the variable into the funtion, you canot change it)
Thanks!!!
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.
I am trying to create a shiny app where I want the user to enter a few (but variable number of) rows of a data frame (with 3 columns). The best way would be to have the user enter a row at a time, and perhaps push a button to create a new row.
What is an intuitive way to implement this in a shiny gui?
You can do something like this:
rm(list = ls())
library(shiny)
# Sample data
my_data <- data.frame(matrix(1,nrow=1,ncol=3))
colnames(my_data) <- c("one","two","three")
emptry_row <- as.data.frame(matrix(1,nrow=1,ncol=3))
colnames(emptry_row) <- colnames(my_data)
ui =fluidPage(
sidebarPanel(actionButton("add_row", "Add a row")),
mainPanel(dataTableOutput("my_table"))
)
server = function(input, output, session){
values <- reactiveValues()
values$df <- my_data
newEntry <- observe({
if(input$add_row > 0) {
isolate(values$df <- rbind(values$df, emptry_row))
}
})
output$my_table <- renderDataTable({
if(input$add_row==0){return(values$df)}
values$df
})
}
runApp(list(ui = ui, server = server))