I'm trying to set codes to recode in shiny web application. However, it doesn't work for me.
Here's my code.
library(shiny)
library(rlang)
library(dplyr)
ui <- fluidPage(
titlePanel("Short Form Web App"),
sidebarPanel(
numericInput("num1","previous vector", value = NULL),
numericInput("num2","post vector", value = NULL),
selectInput("var","select Variable",names(mtcars)),
textInput("new_var","new variable names")
),
mainPanel(
verbatimTextOutput("tab1"),
verbatimTextOutput("tab2"),
actionButton("do","Do")
)
)
server <- function(input, output) {
output$tab1 <- renderPrint({
table(mtcars[["cyl"]])
})
rv <- reactiveValues(data = NULL)
rv$data <- mtcars
observeEvent(input$do,{
new_var <- input$new_var
new <- rv$data %>% transmute(!!new_var := case_when(input$var == input$num1 ~ input$num2))
rv$data <- bind_cols(rv$data,new)
output$tab2 <- renderPrint({
str(rv$data)
})
})
}
shinyApp(ui,server)
What I'm trying to do is recode previous vector to new vector like recode, but the result keeps showing NA..
Could anyone help me fix this problem?
I would very be very appreciated with your helps.
Thank you in advance.
Two issues:
As input$var is character you first have to convert to a symbol, i.e. use !!sym(input$var)
In your case_when you missed to set a default value. Hence, all values not specified to be recoded will be assigned NA.
Try this:
library(shiny)
library(rlang)
library(dplyr)
ui <- fluidPage(
titlePanel("Short Form Web App"),
sidebarPanel(
numericInput("num1","previous vector", value = NULL),
numericInput("num2","post vector", value = NULL),
selectInput("var","select Variable",names(mtcars)),
textInput("new_var","new variable names")
),
mainPanel(
verbatimTextOutput("tab1"),
verbatimTextOutput("tab2"),
actionButton("do","Do")
)
)
server <- function(input, output) {
output$tab1 <- renderPrint({
table(mtcars[["cyl"]])
})
rv <- reactiveValues(data = NULL)
rv$data <- mtcars
observeEvent(input$do,{
new_var <- input$new_var
new <- rv$data %>% transmute(!!sym(new_var) := case_when(
!!sym(input$var) == input$num1 ~ as.double(input$num2),
TRUE ~ !!sym(input$var)))
rv$data <- bind_cols(rv$data,new)
output$tab2 <- renderPrint({
str(rv$data)
})
})
}
Related
I am building a Shiny app and using the code from this question as an example: How to download editable data table in shiny. However, in my code the df <- reactiveVal(dat) does not work, because the dat itself is already a reactive value that comes from an eventReactive({}) function. This is the code I am working with, it works if I define the dat outside of the server, but not when it is created inside the server function of shiny. How do I make a copy of it so that I can show it in a new table (and potentially process further and download in later steps in the app)?
library(shiny)
library(DT)
library(shinyWidgets)
# if the data frame is just an object, it works
#dat <- iris[1:3, ]
ui <- fluidPage( actionBttn(
inputId = "btnProcess",
label = "Process",
size = "sm",
color = "success"
),
DTOutput("my_table"),
DTOutput("table2")
)
server <- function(input, output){
# if the dataframe is a reactive variable, this doesnt work.
dat <- eventReactive(input$btnProcess, {
iris[1:3, ]
})
output[["my_table"]] <- renderDT({
datatable(dat(), editable = "cell")
})
#############################
#### none of these work #####
#############################
#df <- reactiveVal(dat)
#df <- reactiveVal(dat())
#df <- dat()
#df <- dat
observeEvent(input[["my_table_cell_edit"]], {
cell <- input[["my_table_cell_edit"]]
newdf <- df()
newdf[cell$row, cell$col] <- cell$value
df(newdf)
})
output[["table2"]] <- renderDT({
datatable(df())
})
}
shinyApp(ui, server)
Try this
ui <- fluidPage( actionBttn(
inputId = "btnProcess",
label = "Process",
size = "sm",
color = "success"
),
actionBttn(inputId = "reset", label = "Reset", size="sm", color="warning"),
DTOutput("mytable"),
DTOutput("table2")
)
server <- function(input, output){
# if the dataframe is a reactive variable, this doesnt work.
dat <- eventReactive(input$btnProcess, {
iris[1:3, ]
})
mydf <- reactiveValues(data=NULL)
observe({
mydf$data <- dat()
})
output$mytable <- renderDT({
datatable(mydf$data, editable = "cell")
})
observeEvent(input$mytable_cell_edit, {
info = input$mytable_cell_edit
str(info)
i = info$row
j = info$col
v = info$value
mydf$data[i, j] <<- DT::coerceValue(v, mydf$data[i, j])
})
output[["table2"]] <- renderDT({
datatable(mydf$data)
})
observeEvent(input$reset, {
mydf$data <- dat() ## reset it to original data
})
}
shinyApp(ui, server)
Given the following shiny code:
library(shiny)
library(data.table)
df_fr<-data.table(x1=c("a","a","a","b","b","b"),x2=c("1","1","2","2","2","3"))
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("x1", "x1", unique(df_fr$x1),multiple=T),
selectInput("x1", "x1", unique(df_fr$x2),multiple=T)
),
mainPanel( plotOutput("plot1") )
)
)
server <- function(input, output,session) {
selectedData <- reactive({
selInputs<-list(input$x1,input$x2)
req( any( !sapply(selInputs,is.null) ) | any(sapply(selInputs,is.null)) )
df_fr[(if( is.null(input$x1) ) {T} else {x1 %in% input$x1})
& (if( is.null(input$x2) ) {T} else {x2 %in% input$x2})
]
})
output$plot1 <- renderPlot({
plot(table(selectedData()))
})
}
shinyApp(ui = ui, server = server)
I want that if I choose option 'a' for 'x1' that only '1' and '2' show up as possible options for 'x2'.
The other way arround, I choose '3' for 'x2' I want that programm shows only 'b' as possible options for 'x1'. So, changing one input should restrict all other inputs to the values that are defined in the data table. Is that possible? If yes, how? I tried already an observed-block which accesses selectedData(). This did not work, unfortunatly.
Thank you! I hope my question is clear.
one way to do it is to use updateSelectInput(). Try this
library(shiny)
library(data.table)
library(ggplot2)
df_fr<-data.table(x1=c("a","a","a","b","b","b"),x2=c("1","1","2","2","2","3"))
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("x1", "x1", unique(df_fr$x1),selected=NULL, multiple=T),
selectInput("x2", "x2", unique(df_fr$x2),selected=NULL, multiple=T)
),
mainPanel( plotOutput("plot1") )
)
)
server <- function(input, output,session) {
DF <- reactiveValues(data1 = NULL,
data2 = NULL)
observe({
if (is.null(input$x1)) {
DF$data1 <- df_fr
}else DF$data1 <- df_fr[x1 %in% input$x1,]
if (is.null(input$x2)) {
DF$data2 <- df_fr
}else DF$data2 <- df_fr[x2 %in% input$x2,]
if (is.null(input$x2)){
if (is.null(input$x1)) {
updateSelectInput(session, inputId="x2", choices=unique(df_fr$x2))
}else updateSelectInput(session, inputId="x2", choices=unique(DF$data1$x2))
}
if (is.null(input$x1)){
if (is.null(input$x2)) {
updateSelectInput(session, inputId="x1", choices=unique(df_fr$x1))
}else updateSelectInput(session, inputId="x1", choices=unique(DF$data2$x1))
}
})
selectedData <- reactive({
req(input$x1,input$x2)
df_fr[(x2 %in% input$x2) & (x1 %in% input$x1),]
})
output$plot1 <- renderPlot({
req(selectedData())
ggplot(selectedData(), aes(x=x1,y=x2)) + geom_point()
})
}
shinyApp(ui = ui, server = server)
I am making an app using the diamond dataset that I'd like to show the full table unless inputs are selected. However, if I select, say, cut by itself nothing appears. Also, if I select a lot of things no additional diamonds appear. Here's my code:
library(shiny)
library(DT)
library(tidyverse)
diamonds <- diamonds
#Shiny App
ui = fluidPage(
fluidRow(
column(2, selectizeInput(inputId = 'carat',
label = 'Select carat',
choices = unique(diamonds$carat),
selected = NULL,
multiple=TRUE)),
column(2, selectizeInput(inputId = 'cut',
label = 'Select cut',
choices = unique(diamonds$cut),
selected = NULL,
multiple=TRUE)),
column(2, selectizeInput(inputId = 'color',
label = 'Select color',
choices = unique(diamonds$color),
selected = NULL,
multiple=TRUE))
),
fluidRow (
column(12, dataTableOutput('data', height = '100px') )
)
)
server <- function(input, output, session) {
df_current <- reactive({
df <- diamonds%>%
filter(carat %in% ifelse(is.null(input$carat), carat, input$carat),
cut %in% ifelse(is.null(input$cut), color, input$cut),
color %in% ifelse(is.null(input$color), color, input$color))
df
})
output$data <- renderDataTable({
df_current()
})
}
shinyApp(ui = ui, server = server)
I am not sure why the reactive function df_current doesn't work correctly.
Thanks!
We could change the ifelse to if/else as ifelse requires all the inputs to be same length whereas the is.null returns a single TRUE/FALSE. So, it is better to use if/else. Also, calling unique inside ifelse is also not a correct way because it changes the length of the argument
server <- function(input, output, session) {
df_current <- reactive({
df <- diamonds%>%
filter(carat %in% if(is.null(input$carat)) carat else input$carat,
cut %in% if(is.null(input$cut)) cut else input$cut,
color %in% if(is.null(input$color)) color else input$color)
df
})
output$data <- renderDataTable({
df_current()
})
}
-output
The problem is that ifelse doesn't deal correctly with the factor variables and returns the numbers of the factor levels instead of the factor level. You can circumvent this by using as.character. Also, I've used unique because you don't need the complete column as the return value.
The second issue is that you have a typo in your filtering for cut as you use color instead of cut as the return value.
server <- function(input, output, session) {
df_current <- reactive({
df <- diamonds%>%
filter(carat %in% ifelse(is.null(input$carat), unique(carat), input$carat),
cut %in% ifelse(is.null(input$cut), as.character(unique(cut)), input$cut),
color %in% ifelse(is.null(input$color), as.character(unique(color)), input$color))
df
})
output$data <- renderDataTable({
df_current()
})
}
When using filtering and the verbatimTextOutput function in R Shiny, rows go seemingly go missing when I select more than one of the input choices in my checkboxGroupInput.
Below is my code. Any advice?
Thanks in advance.
infantmort <- read.csv("infantmort.csv", header = TRUE)
ui <- fluidPage(
checkboxGroupInput("regioninputID",
"Select Region(s)",
choices = unique(infantmort$whoregion)
),
mainPanel(
verbatimTextOutput("regionoutputID"), width = "auto", height = "auto"
)
)
server <- function(input, output) {
dataset <- reactive({
as.data.frame(infantmort %>% select(whoregion, year, deathsinthousands) %>%
filter(whoregion == input$regioninputID) )
})
output$regionoutputID <- renderPrint({ dataset()
})
}
shinyApp(ui = ui, server = server)
You need to change your filter from == to %in%
The following should do the trick
server <- function(input, output) {
dataset <- reactive({
as.data.frame(infantmort %>% select(whoregion, year, deathsinthousands) %>%
filter(whoregion %in% input$regioninputID) )
})
I am trying to build an app in shiny that will be able to load a dataset in the server function and then based on the user choose and then if there is a factor variable to open check box using conditionalPanel. is there a way to output variable from the server as the condition of the condtionalPanel?
Here is what I tried:
library(shiny)
library(caret)
ui <- fluidPage(
selectInput('dataset', 'Select Dataset',
list(GermanCredit = "GermanCredit",
cars = "cars")),
conditionalPanel(
condition = "output.factorflag == true",
checkboxInput("UseFactor", "Add Factor Variable")
)
)
server <- function(input, output) {
# Loading the dataset
df <- reactive({
if(input$dataset == "GermanCredit"){
data("GermanCredit")
df <- GermanCredit
}else if(input$dataset == "cars"){
data(cars)
df <- cars
}
return(df)
})
# Loading the variables list
col_type <- reactive({
col_type <- rep(NA,ncol(df()))
for(i in 1:ncol(df())){
col_type[i] <- class(df()[,i])
}
return(col_type)
})
outputOptions(output, "factorflag", suspendWhenHidden = FALSE)
output$factorflag <- reactive({
if("factor" %in% col_type()){
factor.flag <- TRUE
} else {factor.flag <- FALSE}
}
)
}
shinyApp(ui = ui, server = server)
Thank you in advance!
You were almost there, you need to put the outputOptions after the declaration of factorflag. Just reengineered a bit your code:
library(shiny)
library(caret)
ui <- fluidPage(
selectInput('dataset', 'Select Dataset',
list(GermanCredit = "GermanCredit",
cars = "cars")),
conditionalPanel(
condition = "output.factorflag == true",
checkboxInput("UseFactor", "Add Factor Variable")
)
)
server <- function(input, output) {
# Loading the dataset
df <- reactive({
if(input$dataset == "GermanCredit"){
data("GermanCredit")
GermanCredit
}else {
data("cars")
cars
}
})
output$factorflag <- reactive("factor" %in% sapply(df(),class))
outputOptions(output, "factorflag", suspendWhenHidden = FALSE)
}
shinyApp(ui = ui, server = server)