Renaming coulmns names of a reactive dataframe in Shiny - r

I have an R dataframe with several columns and I'd like users to select one column to plot against time. However, when I try to run this code, I get an error message.
country <- reactive({
input$variable
})
date_start <- reactive({
input$dateRange[1]
})
date_end <- reactive({
input$dateRange[2]
})
new_data <- reactive({
data[which(data$location== country() & data$date >= date_start() & data$date<=date_end()),c("date","location",input$info)]
names(new_data()) <- c("date", "location", "col1")
})
The error is:
Error in names(new_data()) <- c("date", "location", "col1") :
invalid (NULL) left side of assignment
Can anyone help me with that, please?

This should do the trick:
new_data <- reactive({
data_selection <- data[which(data$location== country() & data$date >= date_start() & data$date<=date_end()),c("date","location",input$info)]
colnames(data_selection) <- c("date", "location", "col1")
data_selection
})
You were referencing the reactive value inside the reactive call, which is then assigned to the new_data. Because this happens before the assignment, the value of the new_data within the call is null. Fortunately there is no need to do that.
Note: as you didn't post your data, I had no way to actually test your code.
However here is a minimal working example to illustrate the concept:
library(shiny)
ui <- fluidPage(
dataTableOutput("geysers")
)
server <- function(input, output) {
test <- reactive({
a <- faithful[1:3,]
colnames(a) <- c("a", "b")
a
})
output$geysers <- renderDataTable({test()})
}
shinyApp(ui = ui, server = server)

Related

Filtering 2 tables in R, based on selected choices and displaying graph in a shinny app

I am new to r and shinny, and can't figure out how to fix my code. I have 2 dfs (df and historical), and I filter the df to display results selected from SelectInput (col, and col2, "Market" and "Month"). At the same time, I want to filter historical by the same values choosen for "Market" and "Month", and display below the table, a histogram of the filtered price_vector - that is, "average_price" from "historical" but filtered by chosen "Market" and "Month".
Any feedback is appreciated, and by the way, if you have a solution that uses reticulate, I dont mind it (no problem for me filtering a df using python/pandas, but I am teaching myself shinny and can't figure this out)
library(shiny)
library(reticulate)
df <- read.csv(file = 'scores.csv')
historical <- read.csv('TRAIN.csv')
price_vector <- historical$average_price
lmkt <- unique(df$market)
mth <- unique(df$month)
ui <- fluidPage(
selectInput('col','Market',lmkt),
selectInput('col2','Month',mth),
dataTableOutput('table')
)
server <- function(input,output)
output$table <- renderDataTable({
df <- df
{
df = df[df[["market"]] == input$col,]
df = df[df[["month"]] == input$col2,]
}
})
shinyApp(ui = ui, server = server)
You can combine the two statements into one using & operator.
df <- read.csv('https://raw.githubusercontent.com/lmsanch/pyABS/master/scores.csv')
historical <- read.csv('https://raw.githubusercontent.com/lmsanch/pyABS/master/TRAIN.csv')
price_vector <- historical$average_price
lmkt <- unique(df$market)
mth <- unique(df$month)
ui <- fluidPage(
selectInput('col','Market',lmkt),
selectInput('col2','Month',mth),
dataTableOutput('table'),
plotOutput('plot')
)
server <- function(input,output) {
output$table <- renderDataTable({
df[df$market == input$col & df$month == input$col2, ]
})
output$plot <- renderPlot({
hist(price_vector[df$market == input$col & df$month == input$col2])
})
}
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 subset data based on inputs from renderUI

I am trying to subset my data based on inputs from renderUI. This data would then be passed to further work in an observe chunk.
Below is an example, where there is an issue with the server code. I am having difficulties with the code recognising the input to an if clause - or more accurately it starts of NULL and then "Every row" from the input is recognised. If I uncomment carbData() in observe below I get the following error. Also receive a similar error if I move the subset inside the observe environment.
Listening on http://127.0.0.1:7400
NULL ### from check()
Warning: Error in if: argument is of length zero
61: reactive:carbData [#9]
45: carbData
44: [#17]
1: runApp
Is this due to some delayed evaluation from using renderUI? If so, or otherwise how do I fix it please?
My code:
server <- function(input, output) {
amData <- reactive({ mtcars[am %in% input$am, ] })
output$gear <- renderUI({ selectInput("Gear", "GEAR",
choices=unique(amData()[, "gear"]), selected=4 ) })
gearData <- reactive({ amData()[gear %in% input$Gear, ] })
output$carb <- renderUI({ selectInput("Carb", "CARB",
choices=c("Every row", unique(gearData()[, "carb"])), selected="Every row") })
carbData <- reactive({ if(input$Carb %in% "Every row") gearData() else gearData()[ carb %in% input$Carb ] }) #### PROBLEM
# Some text where it can be seen that input$Carb is initially NULL
check <- reactive({ p <- input$Carb; print(p) })
observe({
check();
# problems with if clause in both of these:
# carbData()
# Moving the data subset inside `observe` doesn't help
# df <- if(input$Carb %in% "Every row") gearData() else gearData()[ carb %in% input$Carb ]
})
}
And the rest of the code to allow it to run:
library(shiny)
library(shinydashboard)
data(mtcars); data.table::setDT(mtcars)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
selectInput("am", "AM", unique(mtcars$am), selected = "0"),
uiOutput("gear"),
uiOutput("carb")
)),
dashboardBody())
runApp(shinyApp(ui, server))
I'm a bit uncertain whether this question is closed. However, I took the luxury of editing your codes to locate the problem.
I used tibbles instead of data.table as I am not familiar with the syntax. So far #stefan is absolutely correct, req(input$Carb) will relieve you of your troubles.
The reason that gear %in% input$Gear works, and input$Carb %in% "Every row" does not, is that the reactive-hierachy does not favor input$Carb, and as it is null at startup, you are essentially testing NULL %in% "Every Row". Where as gear exists by construction at app start up.
This is not, as Im certain that you are aware of, the same as input$Carb %in% "NULL", or NULL for that matter.
This is your code that I played around with,
server <- function(input, output) {
amData <- reactive({
mtcars %>% filter(am %in% input$am)
})
gearData <- reactive({
amData() %>% filter(gear %in% input$Gear)
})
output$gear <- renderUI({
selectInput("Gear",
"GEAR",
choices = unique(amData()[, "gear"]),
selected = 4)
})
output$carb <- renderUI({
selectInput(
"Carb",
"CARB",
choices = c("Every row", unique(gearData()[, "carb"])),
selected = "Every row"
)
})
carbData <-
reactive({
req(input$Carb)
if (input$Carb %in% "Every row")
gearData()
else
gearData() %>% filter(carb %in% input$Carb)
}) #### PROBLEM
# Some text where it can be seen that input$Carb is initially NULL
check <- reactive({
p <- input$Carb
print(p)
})
observe({
check()
# problems with if clause in both of these:
carbData()
})
}

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.

Warning handling with if/else blocks in Shiny

I am developing a shiny app. which selects nominal (factors) and ordinal(numeric) variables for a given dataset. Then it transform nominal variable(s) (male,female) to dummy variable(s). And eventually merges ordinal variables with dummy variables. The app works fine if I select both nominal and ordinal variables. But if I only want to choose nominal OR ordinal variables,I get warnings: "No character or factor columns found. Please use select_columns to choose columns." Here are my server.r and ui.R
library(fastDummies)
library(data.table)
data=data.frame(A=c(5,2,4),B=c('male','male','female'),C=c(1,3,5))
shinyServer(
function(input, output){
#Select Explanatory Nominal Variables
output$ColumnSelector_dummy <- renderUI({
selectInput("SelectedDummy","Select Nominal Variables (values: male,female)",
choices = as.list(names(data)),multiple=TRUE, selected = NULL)
})
#
df_subset_dummy <- reactive({
a <- subset(data, select = input$SelectedDummy)
return(a)
})
#Convert Nominal variables to Dummy variables
df_subset_dummy_tranformed <- reactive({
df1 <- lapply( df_subset_dummy(), factor)
df2 <- fastDummies::dummy_cols(df1)
drops <- names(df1)
df3 <- df2[, !(names(df2) %in% drops)]
return(df3)
})
#Select Explanatory Ordinal Variables
output$ColumnSelector_ordinal<- renderUI({
selectInput("SelectedOrdinal","Select Ordinal Variables (values: 1,2,3,4,5,6)",
choices = as.list(names(data)), multiple=TRUE,selected = NULL )
})
df_subset_ordinal <- reactive({
a <- subset(data, select = input$SelectedOrdinal)
return(a)
})
#Join Ordinal and Nominal dataframes
df_nominal_ordinal_bind <- reactive({
df <- cbind(df_subset_dummy_tranformed(),df_subset_ordinal())
return(df)
})
output$table_ordinal_nominal <- renderTable(head(df_nominal_ordinal_bind()))
})
shinyUI(
fluidPage(
tabsetPanel(
tabPanel("Data", fluid = TRUE,
sidebarLayout(
sidebarPanel(
uiOutput("ColumnSelector_dummy"),
uiOutput("ColumnSelector_ordinal")
),
mainPanel(
tabsetPanel(
tabPanel('Subsets',
tableOutput('table_ordinal_nominal')
) )) ) ))))
question: How can I use tryCatch and if/else blockes, so that if df_subset_dummy_tranformed() OR df_subset_ordinal() does not exist, I still get result for df_nominal_ordinal_bind and it also can be shown as a table in output$table_ordinal_nominal. Any help would be appreciated.
Without changing your code / approach too much, I guess you could start by adding a check on df_subset_dummy():
df_subset_dummy_tranformed <- reactive({
res <- df_subset_dummy()
if (length(res) == 0) return(res)
df1 <- lapply(res, factor)
df2 <- fastDummies::dummy_cols(df1)
drops <- names(df1)
df3 <- df2[, !(names(df2) %in% drops)]
return(df3)
})
At least this should address the warning you mention.

Resources