R shiny checkergroupinputbox Group by reactive input, summarize by reactive input - r

I am trying to build a shiny app that gives user the flexibility to choose the variables for group by and summarize. Checkbox will have an option for selecting group by variables. Right now I haven't given measure variables as selections, since I struggling with group by. I want the numbers to be aggregated basis the selection.
library(shiny)
library(ggplot2) # for the diamonds dataset
library(shinydashboard)
library(dplyr)
y1<-diamonds
ui <- fluidPage(
checkboxGroupInput("variable", "Variables to show:",
c("cut","color","clarity"),selected = "cut"),
tableOutput("data"),
textOutput("result")
)
server <- function(input, output, session) {
base <- reactive({
groupby <- enquo(input$variable)
print(groupby)
res <-y1%>% group_by(!!!groupby,x) %>%
tally() %>%
ungroup() %>%
summarise(sum = sum(x)) %>%
pull()
res
})
output$result <- renderText({
input$variable
})
output$data<-renderTable({
base()
}
)
}
shinyApp(ui, server)
Thanks,
Hema

I'm not sure that I understood your question exactly, but maybe something like this:
library(shiny)
library(ggplot2) # for the diamonds dataset
library(shinydashboard)
library(dplyr)
y1<-diamonds
ui <- fluidPage(
checkboxGroupInput("variable", "Variables to show:",
c("cut","color","clarity"),selected = "cut"),
tableOutput("data"),
textOutput("result")
)
server <- function(input, output, session) {
base <- reactive({
res <- y1 %>% group_by(eval(parse(text = input$variable)),x) %>%
tally() %>%
#ungroup() %>%
summarise(sum = sum(x)) %>%
pull()
res
})
output$result <- renderText({
input$variable
})
output$data<-renderTable({
base()
})
}
shinyApp(ui, server)

if it's possible to select multiple from the check boxes such that you'd want something like group_by(x,y) this may help you get what you want:
group_by(across(all_of(input$group)))

Related

How to group data dynamically in r shiny app

I am creating a shiny App where it will do two things on mtcars dataset
group data based on user selected values and calculate the mean mpg
and then filter based on selected values to display the output
library(shiny)
library(dplyr)
ui <- fluidPage(
titlePanel(" APP"),
sidebarLayout(
sidebarPanel(selectInput("x","Select cylinder",choices = c(mtcars$cyl),multiple = TRUE),
selectInput("y","Select gear",choices = c(mtcars$gear),multiple = TRUE),
submitButton("Submit")),
mainPanel(
tableOutput("m")
)))
server <- function(input,output){
check <- reactive({
if(is.null(input$x) & is.null(input$y)){
mtcars %>% summarise(Average_mpg = mean(mpg))
}else if(!is.null(input$x) & is.null(input$y)){
a <- mtcars %>% group_by(cyl) %>% summarise(Average_mpg = mean(mpg))
a %>% filter(cyl==input$x)
}else if(is.null(input$x) & !is.null(input$y)){
a <- mtcars %>% group_by(gear) %>% summarise(Average_mpg = mean(mpg))
a %>% filter(gear==input$y)
}else{
a <- mtcars %>% group_by(gear,cyl) %>% summarise(Average_mpg = mean(mpg))
a %>% filter(cyl==input$x & gear==input$y)
}
})
output$m <- renderTable(
check()
)
}
shinyApp(ui = ui, server = server)
Currently I have hard coded all possible combination using if else statement and then realized its not efficient way. If the filters/widgets increase then its difficult to manage
for e.g. If I add one more filter here for variable "carb" in mtcars dataset I have to include all possible scenarios what the user will select and hard code it.
My actual app is having 5 -6 more filters.
Is there any way where whatever the user selects the app will group by on the fly and then filter and show results.
This is not a perfect approach as it still involves some copy & paste and duplicated code. But as a first step it gets rid of the if-else to filter your data:
library(shiny)
library(dplyr)
choices_cyl <- unique(mtcars$cyl)
choices_gear <- unique(mtcars$gear)
ui <- fluidPage(
titlePanel(" APP"),
sidebarLayout(
sidebarPanel(
selectInput("x", "Select cylinder", choices = choices_cyl, multiple = TRUE),
selectInput("y", "Select gear", choices = choices_gear, multiple = TRUE),
submitButton("Submit")
),
mainPanel(
tableOutput("m")
)
)
)
server <- function(input, output) {
check <- reactive({
cyls <- input$x
gears <- input$y
grps <- c("cyl", "gear")[c(!is.null(cyls), !is.null(gears))]
if (is.null(cyls)) cyls <- choices_cyl
if (is.null(gears)) gears <- choices_gear
mtcars %>%
filter(cyl %in% cyls, gear %in% gears) %>%
group_by(across(all_of(grps))) %>%
summarise(Average_mpg = mean(mpg))
})
output$m <- renderTable(
check()
)
}
shinyApp(ui = ui, server = server)

Select specific data from R DataTable in Shiny with checkboxes and create histogram

I have created a data table with DT in Shiny that looks like this:
I would like to select data with checkboxes on a side panel that satisfies certain attributes (e.g. Mfr=Mitsubish, Joint=1, etc.) and then updates a histogram of deg/s in real time to view.
I've read through the material I could find on the web, but I can't figure out how to do this. Does anyone have any hints?
#guero64 Here is an example I had that I believe has examples of what you're looking for. I hope this is helpful. It is based on the diamonds dataset and has a couple of checkbox filters you can apply to the data.
library(shiny)
library(DT)
library(tidyverse)
ui <- shinyUI(pageWithSidebar(
headerPanel("Example"),
sidebarPanel(
checkboxInput("cb_cut", "Cut (Ideal)", FALSE),
checkboxInput("cb_color", "Color (I)", FALSE)
),
mainPanel(
DT::dataTableOutput("data_table"),
plotOutput("data_plot")
)
))
server <- shinyServer(function(input, output) {
filtered_data <- reactive({
dat <- diamonds
if (input$cb_cut) { dat <- dat %>% filter(dat$cut %in% "Ideal") }
if (input$cb_color) { dat <- dat %>% filter(dat$color %in% "I") }
dat
})
output$data_table <- DT::renderDataTable({
filtered_data()
})
output$data_plot <- renderPlot({
hist(filtered_data()$price, main = "Distribution of Price", ylab = "Price")
})
})
shinyApp(ui = ui, server = server)

Shiny in R: How to properly use reactive, observe and renderUI?

I have a problem with my code. Every time I click a button my plot (built with ggvis) is showing up but vanishes immediately. Since my code is very long, the following code reproduces my problem. I want to reuse the reactive data frame test0 in my render function and I guess this is exactly what causes my problem. But this is essential to me. The three steps (reactive, observe, render) are the same than in my code. I would very much appreciate your help!
server.R
library(shiny)
library(ggvis)
library(dplyr)
data(mtcars)
shinyServer(function(input, output) {
test0 <- reactive({
df <- mtcars %>% select(mpg, wt)
(input$NextCounter + 1)*df
})
observe({
df <- test0()
if (!is.null(df)) {
ggvis(df, x = ~wt, y = ~mpg) %>% bind_shiny("plotggvis")
}
})
output$test1 <- renderUI({
df <- test0()
ggvisOutput("plotggvis")
})
})
ui.R
library(shiny)
shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("NextCounter", "Next")
),
mainPanel(
uiOutput("test1")
)
)
))
this one working for me
library(shiny)
library(ggvis)
library(dplyr)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("NextCounter", "Next")
),
mainPanel(
ggvisOutput("plotggvis")
)
)
))
server <- shinyServer(function(input, output) {
data(mtcars)
test0 <- reactive({
df <- mtcars %>% select(mpg, wt)
(input$NextCounter + 1)*df
})
my_graph <- reactive({
df <- test0()
ggvis(df, x = ~wt, y = ~mpg)
})
my_graph %>% bind_shiny("plotggvis")
})
})
shinyApp(ui = ui, server = server)
You don't need to have a ggvisOutput in the UI to solve your problem. Actually the problem in your code is having the bind_shiny function inside an observer that will be executed again every time your test0 data changes. It is expected to bind your ggvis only once, otherwise it will have that behavior of showing up and vanishes immediately. Also, one great feature of ggvis is having a nice transitions when data is changing, so you don't need to create a ggvis object every time your data changes, just make sure that you only bind that ggvis object once in your UI.
Below is a modified version of your code to solve your problem and show the animated transition of data.
library(shiny)
library(ggvis)
library(dplyr)
data(mtcars)
ui <- fluidPage(fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("NextCounter", "Next")
),
mainPanel(
uiOutput("test1")
)
)
))
server <- function(input, output) {
test0 <- reactive({
input$NextCounter
df <- mtcars %>% select(mpg, wt)
df[sample(nrow(df),nrow(df)/2), ]
})
output$test1 <- renderUI({
# bind the ggvis only once
test0 %>% ggvis(x = ~wt, y = ~mpg) %>% bind_shiny("plotggvis")
ggvisOutput("plotggvis")
})
}
shinyApp(ui, server)
You can also modify some ggvis parameters using input widgets by putting the ggvis inside of a reactive expression.

Reactive input not working with ggvis and Shiny

Simple example of a Shiny app using ggvis. Trying to use a pulldown to filter a variable. So here I'm trying to filter by mtcars' gear (either 3, 4, or 5), then plotting x and y of mpg and hp for each of the unique values of gear.
I get the initial plot drawn with a default of '3' selected, but if I change the value via the pulldown nothing happens. I think I know where things are going wrong (commented in the code), but I've tried just about everything I can think of and have no idea what the actual mistake I'm making is.
Thanks
ui.R
# ui.R
library(shiny)
shinyUI(fluidPage(
titlePanel("Car Thing"),
sidebarLayout(
sidebarPanel(
uiOutput("choose_gear")
),
mainPanel(
ggvisOutput("ggvis")
)
)
))
server.R
#server.R
library(shiny)
library(ggvis)
library(dplyr)
gear_nos <- sort(unique(mtcars$gear))
shinyServer(function(input, output, session) {
output$choose_gear <- renderUI({
selectInput("gears", "Choose Gear", gear_nos, selected="3")
})
# I'm pretty sure this is where I'm messing something up
pickedGear <- reactive({
mtcars %>% filter(gear == input$gears)
})
if(is.null(dim(pickedGear))){
pickedGear <- mtcars[mtcars$gear == 3,]
}
pickedGear %>% ggvis(~mpg, ~hp) %>% layer_points(fill := "green") %>% bind_shiny("ggvis")
})
I think this might be what you want.
Note that it took me quite awhile to figure out the validate piece that eliminates an extraneous error message (incorrect string: length(0) 32 expected) on startup initialization of the shinyServer code, but I will remember it for the future now I guess.
library(shiny)
library(ggvis)
library(dplyr)
# library(googleVis) # used observe instead now
u <- shinyUI(fluidPage(
titlePanel("Car Thing"),
sidebarLayout(
sidebarPanel(
uiOutput("choose_gear")
),
mainPanel(
ggvisOutput("ggvis")
)
)
))
gear_nos <- sort(unique(mtcars$gear))
s <- shinyServer(function(input, output, session) {
output$choose_gear <- renderUI({
selectInput("gears", "Choose Gear", gear_nos, selected="3")
})
pickedGear <- reactive({
shiny::validate(need(input$gears, message=FALSE))
mtcars %>% filter(gear == input$gears)
})
# could also replace "observe" with this from googlevis : "output$ggvis <- renderGvis({"
observe({
pickedGear() %>% ggvis(~mpg,~hp) %>% layer_points(fill:="green") %>% bind_shiny("ggvis")
})
})
shinyApp(u,s)
Yielding:

Shiny & ggvis select subset of data dynamically

how can I select a subset of the data and plot it using shiny & ggvis?
As the ggvis documentation states, it is not possible to swap the dataset using ggvis input_select. Besides this limitation it would be awesome if the data preprocessing & filtering would have to be performed only once.
This is my try using selectInput(). I want to be able to choose parts or the whole dataset for display
library(ggvis)
library(dplyr)
set.seed(1233)
cocaine <- cocaine[sample(1:nrow(cocaine), 500), ]
shinyServer(function(input, output, session) {
output$choose_dataset <- renderUI({
selectInput("dataset", "Select", append("Give me all!", as.list(sort(unique(cocaine$state)))))
})
if(input$dataset != "Give me all!"){
a <- filter(rawData, cocaine$state == input$dataset)
}
if(input$dataset == "Give me all!"){
a <- cocaine
}
a$id <- 1:nrow(a)
return(a)
datFiltered %>%
ggvis(~weight, ~price, key := ~id) %>%
bind_shiny("plot1") # Very important!
})
Here is the UI
library(ggvis)
shinyUI(bootstrapPage(
uiOutput("choose_dataset"),
ggvisOutput("plot1")
))
Your code has a few problems and doesn't run... why are you returning from the main server function? And you're using two variables dataFiltered and rawData that aren't defined anywhere.
Here is the solution of what you're trying to do
runApp(shinyApp(
ui = fluidPage(
uiOutput("choose_dataset"),
ggvisOutput("plot1")
),
server = function(input, output, session) {
output$choose_dataset <- renderUI({
selectInput("dataset", "Select", append("Give me all!", as.list(sort(unique(cocaine$state)))))
})
observeEvent(input$dataset, {
if(input$dataset == "Give me all!"){
data <- cocaine
} else {
data <- filter(cocaine, cocaine$state == input$dataset)
}
data$id <- seq(nrow(data))
data %>%
ggvis(~weight, ~price, key := ~id) %>%
layer_points() %>%
bind_shiny("plot1")
})
}
))
Please try to post code that can be run or at least make in the code saying what doesn't run or what variables need to be defined etc :)
#daattali - I have a suggested improvement to your solution. You use filter in the observeEvent, which introduces NA's to the solution and causes the event to fire incorrectly. Instead, use subset as shown below:
runApp(shinyApp(
ui = fluidPage(
uiOutput("choose_dataset"),
ggvisOutput("plot1")
),
server = function(input, output, session) {
output$choose_dataset <- renderUI({
selectInput("dataset", "Select", append("Give me all!", as.list(sort(unique(cocaine$state)))))
})
observeEvent(input$dataset, {
if(input$dataset == "Give me all!"){
data <- cocaine
} else {
data <- subset(cocaine, cocaine$state == input$dataset)
}
data$id <- seq(nrow(data))
data %>%
ggvis(~weight, ~price, key := ~id) %>%
layer_points() %>%
bind_shiny("plot1")
})
}
))

Resources