I show you my shiny application, but I have a problem, I cannot update the selectimput, I have used updateSelectInput but it does not work.
I have two selectInputs inside a tabsetPanel, since I need to update the table with two filters, one is the category and the other the subcategory.
here my code.
library(shiny)
library(tidyverse)
library(DT)
cat1<-rep("LINEA BLANCA", 75)
cat2<- rep("VIDEO", 75)
subcat1<-rep("LAVADORAS", 40)
subcat2<- rep("REFRIS", 35)
subcat3<- rep("TV", 40)
subcat4<- rep("SONIDO", 35)
vent<-sample(100:900, 150, replace=T)
segm1<-rep("AAA", 25)
segm2<-rep("BBB", 25)
segm3<-rep("CCC", 25)
segm4<-rep("ABB", 25)
segm5<-rep("ACC", 25)
segm6<-rep("BAC", 25)
db<- tibble(segment=c(segm1,segm2,segm3,segm4,segm5,
segm1),CATEGORIA=c(cat1,cat2), SUBCAT=c(subcat1,subcat2, subcat3, subcat4), vent=vent)
ui <- fluidPage(
# App title
titlePanel("EXAMPLE"),
# Sidebar layout with input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
),
# Main panel for displaying outputs ----
mainPanel(
# Output: Tabset w/ plot, summary, and table ----
tabsetPanel(type = "tabs",
tabPanel("Ana_inv", uiOutput("selectcat"), uiOutput("selectsubcat"),DT::dataTableOutput("ana_inv")),
#tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Table", tableOutput("table"))
)
)
)
)
server <- function(input, output, session) {
output$selectcat <- renderUI({
selectInput("Cat", "Seleccione Categoria", choices = c("ALL",as.vector(db$CATEGORIA)))
})
output$selectsubcat <- renderUI({
#opciones<- db_prueba %>% filter(CATEGORIA==input$CAT)
selectInput("Subcat", "Seleccione Subcategoria", choices = c("ALL",as.vector(db$SUBCAT)))
})
activar<- reactive({
req(input$Cat)
req(input$Subcat)
opciones<- db %>% filter(CATEGORIA==input$Cat)
if(input$Cat == "TODOS") {
filt1 <- quote(CATEGORIA != "#?><")
} else {
filt1 <- quote(CATEGORIA == input$Cat)
}
if (input$Subcat == "TODOS") {
filt2 <- quote(SUBCAT != "#?><")
} else {
filt2 <- quote(SUBCAT == input$Subcat)
}
db %>%
filter_(filt1) %>%
filter_(filt2) %>% group_by(segment)%>%
summarise(SKUs=n(),
vta=sum(vent))
})
# Return the formula text for printing as a caption ----
output$ana_inv <- DT::renderDataTable({
activar()
})
}
shinyApp(ui = ui, server = server)
So I need that if the category "LINEA BLANCA" is selected in the subcategory it only shows "REFRIS" and "LAVADORAS", but also if someone selects "ALL" in the category he can also select each subcategory, that is, it can be filtered by subcategory assuming I only want to see subcategories.
I have tried many ways but none works, any ideas? you can run the application in R to get an idea of what I want.
Try this
server <- function(input, output, session) {
output$selectcat <- renderUI({
selectInput("Cat", "Seleccione Categoria", choices = c("ALL",as.vector(db$CATEGORIA)))
})
output$selectsubcat <- renderUI({
req(input$Cat)
if (input$Cat=="ALL"){ df <- db
}else df <- db %>% filter(CATEGORIA %in% input$Cat)
selectInput("Subcat", "Seleccione Subcategoria", choices = c("ALL",as.vector(df$SUBCAT)))
})
activar<- reactive({
req(input$Cat,input$Subcat)
if (input$Cat=="ALL"){ df <- db
}else df <- db %>% filter(CATEGORIA %in% input$Cat)
if (input$Subcat=="ALL"){ df <- df
}else df <- df %>% filter(SUBCAT == input$Subcat)
df %>%
group_by(segment) %>%
summarise(SKUs=n(),
vta=sum(vent))
})
# Return the formula text for printing as a caption ----
output$ana_inv <- DT::renderDataTable({
activar()
})
}
Related
I want to let the user be able to select "NA" or enter empty values in the sliderInput. Maybe add a "NA" button near the slider input? Is there any way to do that?
example
Thanks
You can add a checkboxInput and pair it with an if condition inside the server. Here's an example using iris dataset.
library(shiny)
library(shinyWidgets)
library(tidyverse)
iris_df <- iris
#populate with some NA's
set.seed(123)
sample(1:nrow(iris), 10) %>%
walk(~ {
iris_df[.x, "Sepal.Width"] <<- NA
})
ui <- fluidPage(
checkboxInput("na", "Select NA Values", value = FALSE),
conditionalPanel(
condition = "input.na == false",
sliderInput("sepalw", "Sepal Width Range",
value = c(median(iris$Sepal.Width), max(iris$Sepal.Width)),
min = min(iris$Sepal.Width),
max = max(iris$Sepal.Width)
)
),
dataTableOutput("table")
)
server <- function(input, output, session) {
df <- reactive({
if (!input$na) {
iris_df %>%
filter(between(Sepal.Width, input$sepalw[[1]], input$sepalw[[2]]))
} else {
iris_df %>% filter(is.na(Sepal.Width))
}
})
output$table <- renderDataTable(
{
df()
},
options = list(pageLength = 10)
)
}
shinyApp(ui, server)
Can someone show me how to get the tabName of the selected argonTab in an argonTabSet please, in a shiny app. I need it for downstream data subsetting.
The example below follows, somewhat, my actual app, where I call argonTabSet with do.call. The tabnames in my real app can vary so I am looking for something without hard coding them. The app is modularised, though I can’t get any values to return with input$t_brnd if I also wrap the argonTabSet id in ns().
library(shiny)
library(argonR)
library(argonDash)
mod_price_ov_UI <- function(id) {
ns <- NS(id)
tagList(
uiOutput(ns('ot_cat_brnd_rtlr'))
, uiOutput(ns('selected_tab'))
)
}
mod_price_ov <- function(id){
moduleServer(id,function(input, output, session) {
output$ot_cat_brnd_rtlr <- renderUI({
ns <- session$ns
brands <- paste0('brand_', 1:4)
tagList(
do.call(argonTabSet, c(
# id = ns('t_brnd'),
id ='t_brnd',
lapply(1:length(brands), function(i) {
argonTab(
tabName = brands[i],
active = ifelse(i == 1, T, F)
)
})
))
)
})
output$selected_tab <- renderUI({
input$t_brnd
})
})
}
shiny::shinyApp(
ui = argonDashPage(
body = argonDashBody(mod_price_ov_UI('ov'))
),
server = function(input, output, session) {
mod_price_ov('ov')
}
)
UPDATE
A comment (which seems to have been deleted) asked for an example closer to the actual use case, which I present below. I may need to revise the question title as the example now illustrates my actual issue. I thought that getting the tabname would ultimately help me get to this point.
The table category_tally starts with an overall summary total. I require to provide some functionality (with a radiobutton ‘Brand Stats ’ for example) where the user can update the total filtered by the brand in the selected tabname (also reflected in the selected datatable) , and back again, if the button equals ‘NO’.
I can only seem to get the button to work on the last tab, not the first 3.
library(shiny)
library(argonR)
library(argonDash)
library(magrittr)
library(tidyverse)
library(DT)
set.seed(1234)
mod_price_ov_UI <- function(id) {
ns <- NS(id)
tagList(
tableOutput(ns('category_tally')),
uiOutput(ns('ot_cat_brnd_rtlr')))
}
mod_price_ov <- function(id){
moduleServer(
id,
function(input, output, session) {
toy_rtcv <- reactive({tibble(
category = sample(paste0('cat_' , 1:3), 100, replace = T)
, brand = sample(paste0('brand_', 1:4), 100, replace = T)
)})
output$category_tally <- renderTable({toy_rtcv() %>% summarise(total = n())})
output$ot_cat_brnd_rtlr <- renderUI({
ns <- session$ns
brands <- toy_rtcv() %>% select(brand) %>% distinct() %>% pull(brand)
tagList(
do.call(argonTabSet, c(id= 't_brnd', lapply(1:length(brands), function(i) {
argonTab(
tabName = brands[i]
, active = ifelse(i == 1, T, F)
, radioButtons(ns(paste0('rdio_cat_brnd_rtlr', brands[i]))
, 'Brand Stats'
, choices = c('YES', 'NO')
, selected = 'NO'
, inline = T
)
, dataTableOutput(ns(paste0('ot_retailer_', brands[i])))
)}))))})
observe({
brands <- toy_rtcv() %>% select(brand) %>% distinct() %>% pull(brand)
lapply(1:length(brands), function(i) {
output[[paste0('ot_retailer_', brands[i])]] = renderDataTable({
toy_rtcv() %>%
filter(brand == brands[i])
})})})
observe({
brands <- toy_rtcv() %>% select(brand) %>% distinct() %>% pull(brand)
lapply(1:length(brands), function(i){
if(is.null(input[[paste0('rdio_cat_brnd_rtlr', brands[i])]]))
return(NULL)
if(input[[paste0('rdio_cat_brnd_rtlr', brands[i])]] == 'YES'){
output$category_tally <- renderTable({
toy_rtcv() %>%
filter(brand == brands[i]) %>%
summarise(total = n())})
} else {
output$category_tally <- renderTable({
toy_rtcv() %>%
summarise(total = n())
})}})})})
}
shiny::shinyApp(
ui = argonDashPage(
body = argonDashBody(mod_price_ov_UI('ov'))
),
server = function(input, output, session) {mod_price_ov('ov')}
)
I set up a filter by year using year_filter and would like the default view to be 2021. How to do I this given the code below? Currently, the default display is to show all data entries for all years.
The complete code and file can be found here for reference: https://drive.google.com/drive/folders/1C7SWkl8zyGXLGEQIiBEg4UsNQ5GDaKoa?usp=sharing
Thank you for your assistance!
# Define UI for application
ui <- fluidPage(
tags$div(
style = "padding: 10px;",
# Application title
titlePanel("Testing and Quarantine Measures"),
fluidRow(
uiOutput("CountryFilter_ui"),
uiOutput("YearFilter_ui")
),
fluidRow(
tags$div(style = "width: 100%; overflow: scroll; font-size:80%;",
DT::dataTableOutput('travel_table')
)
)
)
)
server <- function(input, output) {
# Render UI
output$CountryFilter_ui <- renderUI({
countries <- travel_clean %>%
pull(country_area)
selectInput('country_filter', 'Member State Filter', choices = countries, multiple = TRUE)
})
output$YearFilter_ui <- renderUI({
year <- travel_clean %>%
pull(year)
selectInput('year_filter', 'Year Filter', choices = year, multiple = TRUE)
})
# Filter data
travel_filtered <- reactive({
tmp_travel <- travel_measures %>%
select(-Sources)
if(is.null(input$country_filter) == FALSE) {
tmp_travel <- tmp_travel %>%
filter(`Country/area` %in% input$country_filter)
}
return(tmp_travel)
})
travel_filtered <- reactive({
tmp_travel <- travel_measures %>%
select(-Sources)
if(is.null(input$year_filter) == FALSE) {
tmp_travel <- tmp_travel %>%
filter(`Year` %in% input$year_filter)
}
return(tmp_travel)
})
I have these data I want to scatter plot using an R shiny server:
library(dplyr)
library(permute)
set.seed(1)
meta.df <- data.frame(gene_id=paste0("id",1:10),symbol=paste0("n",rep(permute::shuffle(5),2)),stringsAsFactors=F)
clusters.df <- data.frame(cell=paste0("c",1:100),cluster=rep(permute::shuffle(10),10),sample=paste0("s",rep(permute::shuffle(5),20)),stringsAsFactors=F)
mat <- matrix(rnorm(10*100),10,100,dimnames=list(meta.df$gene_id,clusters.df$cell))
tsne.obj <- Rtsne::Rtsne(t(mat))
tsne.df <- as.data.frame(tsne.obj$Y) %>% dplyr::rename(tSNE1=V1,tSNE2=V2) %>% cbind(clusters.df)
samples <- c("all",unique(clusters.df$sample))
samples.choices <- 1:length(samples)
names(samples.choices) <- samples
Since I want to be able to select a specific meta.df$symbol, which is redundant within meta.df$gene_id, each has a selection list, where the second is conditioned on the first.
Since the data are comprised of several samples, I'd like to be able to subset the data by sample in a reactive way, hence I have a sample choice checkbox, with the "all" option that selects all samples (just coz it's easier than checking all boxes).
So here's my shiny code:
server <- function(input, output)
{
chosen.samples <- reactive({
validate(
need(input$samples.choice != "",'Please choose at least one of the sample checkboxes')
)
samples.choice <- input$samples.choice
if("all" %in% samples.choice) samples.choice <- samples[-which(samples == "all")]
samples.choice
})
output$gene_id <- renderUI({
selectInput("gene_id", "Gene ID", choices = unique(dplyr::filter(meta.df,symbol == input$symbol)$gene_id))
})
scatter.plot <- reactive({
if(!is.null(input$symbol) & !is.null(input$gene_id)){
# subset of data
gene.symbol <- input$symbol
gene.id <- input$gene_id
row.idx <- which(rownames(mat) == gene.id)
col.idx <- which(colnames(mat) %in% dplyr::filter(clusters.df,sample %in% chosen.samples())$cell)
gene.df <- suppressWarnings(dplyr::left_join(tsne.df %>% dplyr::filter(sample %in% chosen.samples()),data.frame(cell=colnames(mat)[col.idx],value=mat[row.idx,col.idx],stringsAsFactors=F),by=c("cell"="cell")))
scatter.plot <- plotly::plot_ly(marker=list(size=12),type='scatter',mode="markers",color=~gene.df$value,x=~gene.df$tSNE1,y=~gene.df$tSNE2,showlegend=F) %>%
plotly::layout(xaxis=list(title="tSNE1",zeroline=F,showticklabels=F),yaxis=list(title="tSNE2",zeroline=F,showticklabels=F))
scatter.plot
}
})
output$Embedding <- renderPlot({
scatter.plot()
})
output$save <- downloadHandler(
filename = function() {
paste0(dplyr::filter(meta.df,symbol == input$symbol,gene_id == input$gene_id)$symbol,"_",dplyr::filter(meta.df,symbol == input$symbol,gene_id == input$gene_id)$gene_id,".pdf")
},
content = function(file) {
plotly::export(scatter.plot(),file=file)
}
)
}
ui <- fluidPage(
# App title ----
titlePanel("Results Explorer"),
# Sidebar layout with a input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# select samples
checkboxGroupInput("samples.choice", "Samples",choices = samples.choices,selected=1),
# select gene symbol
selectInput("symbol", "Gene Symbol", choices = unique(meta.df$symbol)),
# select gene id
uiOutput("gene_id"),
# select plot type
selectInput("plot.type", "Plot Type", choices = c("tSNE","PCA")),
# save plot as html
downloadButton('save', 'Save as PDF')
),
# Main panel for displaying outputs ----
mainPanel(
# The plot is called Embedding and will be created in ShinyServer part
plotOutput("Embedding")
)
)
)
shinyApp(ui = ui, server = server)
The problem is that it doesn't seem to actually select the samples, and hence the plot that is displayed has no points.
It works find if I simply eliminate the samples selection code by replacing:
col.idx <- which(colnames(mat) %in% dplyr::filter(clusters.df,sample %in% chosen.samples())$cell)
gene.df <- suppressWarnings(dplyr::left_join(tsne.df %>% dplyr::filter(sample %in% chosen.samples()),data.frame(cell=colnames(mat)[col.idx],value=mat[row.idx,col.idx],stringsAsFactors=F),by=c("cell"="cell")))
with:
col.idx <- which(colnames(mat) %in% dplyr::filter(clusters.df,sample %in% samples[2:3])$cell)
gene.df <- dplyr::left_join(tsne.df %>% dplyr::filter(sample %in% samples[2:3]),data.frame(cell=colnames(mat)[col.idx],value=mat[row.idx,col.idx],stringsAsFactors=F),by=c("cell"="cell"))
I see that in this example the entire data are subsetted in the dat_reac reactive block. I'd expect simply getting the samples to subset by would be enough. Any idea why it doesn't work and how to get it right?
There are two mistakes in your code. The first one is in checkboxGroupInput
Instead of
checkboxGroupInput("samples.choice", "Samples",choices = samples.choices,selected=1)
it should be
checkboxGroupInput("samples.choice", "Samples",choices = names(samples.choices),selected="all")
The second is scatter.plot() is plotly object hence you should use plotly::plotlyOutput("Embedding") and output$Embedding <- plotly::renderPlotly({
scatter.plot()
})
Here is the code with above modification which should work:
server <- function(input, output)
{
chosen.samples <- reactive({
validate(
need(input$samples.choice != "",'Please choose at least one of the sample checkboxes')
)
samples.choice <- input$samples.choice
if("all" %in% samples.choice) samples.choice <- samples[-which(samples == "all")]
samples.choice
})
output$gene_id <- renderUI({
selectInput("gene_id", "Gene ID", choices = unique(dplyr::filter(meta.df,symbol == input$symbol)$gene_id))
})
scatter.plot <- reactive({
if(!is.null(input$symbol) & !is.null(input$gene_id)){
# subset of data
gene.symbol <- input$symbol
gene.id <- input$gene_id
row.idx <- which(rownames(mat) == gene.id)
col.idx <- which(colnames(mat) %in% dplyr::filter(clusters.df,sample %in% chosen.samples())$cell)
gene.df <- suppressWarnings(dplyr::left_join(tsne.df %>% dplyr::filter(sample %in% chosen.samples()),data.frame(cell=colnames(mat)[col.idx],value=mat[row.idx,col.idx],stringsAsFactors=F),by=c("cell"="cell")))
scatter.plot <- plotly::plot_ly(marker=list(size=12),type='scatter',mode="markers",color=~gene.df$value,x=~gene.df$tSNE1,y=~gene.df$tSNE2,showlegend=F) %>%
plotly::layout(xaxis=list(title="tSNE1",zeroline=F,showticklabels=F),yaxis=list(title="tSNE2",zeroline=F,showticklabels=F))
scatter.plot
}
})
output$Embedding <- plotly::renderPlotly({
scatter.plot()
})
output$save <- downloadHandler(
filename = function() {
paste0(dplyr::filter(meta.df,symbol == input$symbol,gene_id == input$gene_id)$symbol,"_",dplyr::filter(meta.df,symbol == input$symbol,gene_id == input$gene_id)$gene_id,".pdf")
},
content = function(file) {
plotly::export(scatter.plot(),file=file)
}
)
}
ui <- fluidPage(
# App title ----
titlePanel("Results Explorer"),
# Sidebar layout with a input and output definitions ----
sidebarLayout(
# Sidebar panel for inputs ----
sidebarPanel(
# select samples
checkboxGroupInput("samples.choice", "Samples",choices = names(samples.choices),selected="all"),
# select gene symbol
selectInput("symbol", "Gene Symbol", choices = unique(meta.df$symbol)),
# select gene id
uiOutput("gene_id"),
# select plot type
selectInput("plot.type", "Plot Type", choices = c("tSNE","PCA")),
# save plot as html
downloadButton('save', 'Save as PDF')
),
# Main panel for displaying outputs ----
mainPanel(
# The plot is called Embedding and will be created in ShinyServer part
# plotOutput("Embedding")
plotly::plotlyOutput("Embedding")
)
)
)
shinyApp(ui = ui, server = server)
Hope it helps!
I can create a data table in shiny that shows data for any individual buffalo but I can't figure out how to display all buffalo data at the same time. Any help is appreciated.
Sample Data:
cleanbuffalo <- data.frame(name = c("queen","toni","pepper"),
longitude = c(31.8,32,33),
latitude = c(-24,-25,-26))
Shiny UI:
shinyUI(navbarPage("Buffalo Migration", id ="nav",
tabPanel("Data",
fluidRow(
column(3,
selectInput("allnamesbuffalo", "Buffalo", c("All Buffalo" = "all buffalo", vars))
)
),
hr(),
DT::dataTableOutput("buffalotable")
)
)
)
Shiny Server:
shinyServer(function(input, output, session) {
observe({
allnamesbuffalo <- if (is.null(input$allnamesbuffalo)) character(0) else {
filter(cleanbuffalo, name %in% input$allnamesbuffalo) %>%
`$`('name') %>%
unique() %>%
sort()
}
})
output$buffalotable <- DT::renderDataTable({
df <- cleanbuffalo %>%
filter(
cleanbuffalo$name == input$allnamesbuffalo,
is.null(input$allnamesbuffalo) | name %in% cleanbuffalo$name
)
action <- DT::dataTableAjax(session,df)
DT::datatable(df, options = list(ajax = list(url = action)),
escape = FALSE)
})
})
Here is a working example. Note that I added stringsAsFactors=F in your data frame, otherwise you need to use levels(cleanbuffalo$name) to get the names.
library(shiny)
library(dplyr)
cleanbuffalo <- data.frame(name = c("queen","toni","pepper"),
longitude = c(31.8,32,33),
latitude = c(-24,-25,-26), stringsAsFactors = F)
ui <- shinyUI(fluidPage(
titlePanel("Example"),
sidebarLayout(
sidebarPanel(
selectInput("allnamesbuffalo", "Buffalo", c("all", cleanbuffalo$name))
),
mainPanel(
dataTableOutput("buffalotable")
)
)
))
server <- shinyServer(function(input, output, session) {
output$buffalotable <- renderDataTable({
names <- NULL
if (input$allnamesbuffalo == "all") {
names <- cleanbuffalo$name
} else {
names <- input$allnamesbuffalo
}
filter(cleanbuffalo, name %in% names)
})
})
shinyApp(ui = ui, server = server)