Redraw plot once if one reactive value changes but not the other? - r

I have two reactive values input$code and input$variants and I want to redraw the plot once if any of the following conditions are true.
code changes and variants changes
code changes and variants does not change
code does not change and variants changes
I can't call both input$code and input$variants in renderPlotly or else the plot will get redrawn twice for #1 above.
output$choose_test <- renderUI({
data_sets <- loadTest()
selectizeInput(
'test', 'Test', choices = data_sets$test, selected = data_sets$test[1]
)
})
output$choose_code <- renderUI({
validate(
need(input$test, 'Please choose a test.')
)
code <- loadCode(input$test)
selectizeInput(
'code', 'Code', choices = code$code, selected = code$code[1]
)
})
output$choose_variants <- renderUI({
validate(
need(input$test, 'Please choose a test.'),
need(input$code, 'Please choose a code.')
)
dat <- loadVariants(input$test, input$code)
default_select <- dat$variant[grep('v1|v2', dat$variant)]
if (identical(default_select, factor(0))) {
default_select <- dat$variant[1]
}
checkboxGroupInput("variants", "Variants",
choices = dat$variant,
selected = default_select)
})
output$plot1 <- renderPlotly({
runLocations <- isolate(loadRunsBetweenDates(input$test, input$code, input$variants))
total_min_df <-
runLocations %>%
group_by(change_number, variant) %>%
summarize(memory = min(memory))
total_min_df$change_number <- as.numeric(as.character(total_min_df$change_number))
p <- ggplot(total_min_df,
aes(x=change_number,
y=memory,
group=variant,
color=variant))+
geom_point()+
geom_smooth(se = FALSE)+
scale_x_continuous(labels = function(n){format(n, scientific = FALSE)})+
scale_y_continuous(labels = function(n){format(n, scientific = FALSE)})+
labs(x = "Change Number", y = "Megabytes")
ggplotly(p)
})

Related

R Shiny recoloring of points

I would like click-select points and group them based on color.
I can save selected points with color information into a new data frame and plot it, however I would like to keep track and see what was already selected on the interactive plot.
How can I show/label already selected points or make it permanent after "Add selection"?
library(shiny)
library(tidyverse)
library(DT)
library(colourpicker)
ui = fluidPage(
colourInput("col", "Select colour", "purple"),
actionButton("addToDT", "Add selection", icon = icon("plus")), hr(),
plotOutput("plot", click = "plot_click", dblclick = "plot_reset"),
DT::dataTableOutput('plot_DT'), hr(),
textOutput("clickcoord"),
DT::dataTableOutput('final_DT'),
plotOutput("plotSelected")
)
server = function(input, output, session) {
selectedPoint = reactiveVal(rep(FALSE, nrow(mtcars)))
output$clickcoord <- renderPrint({
print(input$plot_click)
})
observeEvent(input$plot_click, {
clicked = nearPoints(mtcars, input$plot_click, allRows = TRUE)$selected_
selectedPoint(clicked | selectedPoint())
})
observeEvent(input$plot_reset, {
selectedPoint(rep(FALSE, nrow(mtcars)))
})
output$plot_DT = DT::renderDataTable({
mtcars$sel = selectedPoint()
mtcars = dplyr::filter(mtcars, sel == TRUE) %>% mutate(group_color = input$col)
})
final_DT = reactiveValues()
final_DT$df = data.frame()
FinalData = eventReactive(input$addToDT, {
mtcars$sel = selectedPoint()
mtcars = dplyr::filter(mtcars, sel == TRUE) %>% mutate(group_color = input$col)
final_DT$df = bind_rows(final_DT$df, mtcars)
})
output$final_DT = renderDataTable({FinalData()})
output$plot = renderPlot({
mtcars$sel = selectedPoint()
ggplot(mtcars, aes(wt, mpg, color = mtcars$sel, fill=mpg)) +
geom_point(shape = 21, size = 6, stroke = 2) +
scale_color_manual(values = c("#ffffff00", input$col)) +
scale_fill_viridis_c() +
theme_bw()
})
output$plotSelected = renderPlot({
sel_df = FinalData()
ggplot(sel_df, aes(wt, mpg, fill = group_color, colour = group_color)) +
geom_point(shape = 21, size = 6, stroke = 2) +
scale_color_manual(values = unique(sel_df$group_color)) +
scale_fill_manual(values = unique(sel_df$group_color)) +
theme_bw()
})
observeEvent(input$addToDT, {
selectedPoint(rep(FALSE, nrow(mtcars)))
})
}
shinyApp(ui, server)
I think this is the "crux" of what your are looking for. I used a very similar example that I found in the help for entitled:
A demonstration of clicking, hovering, and brushing
(https://shiny.rstudio.com/reference/shiny/0.13.1/plotoutput)
It is very similar to your example.
I create a matrix of T/F elements where the rows are the observations and the columns are in which batch the observation is selected. So when you launch the whole matrix is False, but as you click on observations the switch to positive in the first column. Then if you click addSelection and continue you start switching the observations in the next column.
Could you confirm that this what you are looking for?
Below is the code.
shinyApp(
ui = basicPage(
fluidRow(
column(
width = 4,
plotOutput("plot",
height = 300,
click = "plot_click", # Equiv, to click=clickOpts(id='plot_click')
),
actionButton("addToDT", "Add selection", icon = icon("plus")), hr(),
h4("Clicked points"),
tableOutput("plot_clickedpoints"),
),
column(
width = 4,
verbatimTextOutput("counter"),
),
)
),
server = function(input, output, session) {
data <- reactive({
input$newplot
# Add a little noise to the cars data so the points move
cars + rnorm(nrow(cars))
})
output$plot <- renderPlot({
d <- data()
plot(d$speed, d$dist, main = paste("No of Sets Chosen", input$addToDT))
})
output$plot_clickinfo <- renderPrint({
cat("Click:
")
str(input$plot_click)
})
selectedPoints <- reactiveVal(rep(FALSE, nrow(cars)))
selectionMatrix <- reactiveVal(matrix(data = F, nrow = nrow(cars), ncol = 7))
observeEvent(input$plot_click, {
clicked <- nearPoints(data(), input$plot_click, "speed", "dist", allRows = TRUE)$selected
selectedPoints(clicked | selectedPoints())
tmp <- unlist(selectionMatrix())
tmp[, (input$addToDT + 1)] <- selectedPoints()
selectionMatrix(tmp)
})
observeEvent(input$addToDT, {
selectedPoints(rep(FALSE, nrow(cars)))
})
output$plot_clickedpoints <- renderTable({
# if (input$addToDT==0) {
res <- selectionMatrix()
return(res)
})
}
)

Interactive plotting on RShiny

I am currently trying to make an interactive app on shiny where with my data frame "keep_df" you can choose which kind of plot you want to use and for the x and y axes you can choose any of the columns from keep_df. Below is my code. I'm not getting any error messages, but the code is not running as desired. I was wondering if anyone had any suggestions. Thanks!
ui <- navbarPage ("Title",
tabPanel("Chart builder",
sidebarLayout(
sidebarPanel(
pickerInput(inputId = 'chart', label = '1. Select chart type', choices = c("Scatter plot", "Bar chart", "Histogram", "Pie chart", "Box plot"), selected = NULL, multiple = FALSE),
pickerInput(inputId = 'xaxis', label = '2. Select X-axis', choices = colnames(keep_df), selected = NULL, multiple = FALSE),
pickerInput(inputId = 'yaxis', label = '3. Select Y-axis', choices = colnames(keep_df), selected = NULL, multiple = FALSE),
uiOutput("picker2"),
actionButton("view", "View selection"),
),
mainPanel(ui <- DT::dataTableOutput("charttable"), plotOutput("plots")),
)
)
)
server <- function(input, output, session) {
data <- reactive(
keep_df
)
plots <- reactive({
if (input$chart == 'Scatter plot') {
ggplot(data(), aes(x = input$xaxis, y = input$yaxis)) +
geom_point(colour = "black")
}
if (input$chart == 'Bar chart') {
ggplot(data(), aes(x = input$xaxis, y = input$yaxis)) +
geom_point(colour = "black")
}
})
output$plots <- renderPlot(
plots()
)
}
You were pretty close with your code, I noticed a few issues. First, you have an extra ui <- which I could see causing an error. Second, in the plots reactive, where you had x = input$xaxis, it would send a string to the ggplot, rather than a variable. Meaning it wouldn't read the column. I also made the plots reactive as an if and else if, rather than two if statements. Hope this helps!
Note that I didn't have the dataframe, so I just used mtcars for simplicity. There were a few lines I blocked out too. I also added the library and the shinyApp call too, since it wasn't in your example.
library(shiny)
library(ggplot2)
library(shinyWidgets)
keep_df<-mtcars #Don't have the data, just using mtcars
ui <- navbarPage ("Title",
tabPanel("Chart builder",
sidebarLayout(
sidebarPanel(
pickerInput(inputId = 'chart', label = '1. Select chart type', choices = c("Scatter plot", "Bar chart", "Histogram", "Pie chart", "Box plot"), selected = NULL, multiple = FALSE),
pickerInput(inputId = 'xaxis', label = '2. Select X-axis', choices = colnames(keep_df), selected = NULL, multiple = FALSE),
pickerInput(inputId = 'yaxis', label = '3. Select Y-axis', choices = colnames(keep_df), selected = NULL, multiple = FALSE)#,
# uiOutput("picker2"), #Not doing anything
# actionButton("view", "View selection") #Not doing anything
),
mainPanel(DT::dataTableOutput("charttable"), plotOutput("plots")), #Removed the ui <-
)
)
)
server <- function(input, output, session) {
data <- reactive(
keep_df
)
plots <- reactive({
if (input$chart == 'Scatter plot') {
#without the eval(parse(text =)), it reads as string, not variable
ggplot(data(), aes(x = eval(parse(text = input$xaxis)), y = eval(parse(text = input$yaxis)))) +
geom_point(colour = "black")
} else if (input$chart == 'Bar chart') {
ggplot(data(), aes(x = eval(parse(text = input$xaxis)), y = eval(parse(text = input$yaxis)))) +
geom_boxplot(colour = "black")
}
})
output$plots <- renderPlot(
plots()
)
}
shinyApp(ui, server)

R Shiny: Computing new Variables selected by "selectInput"

I'm working on a dashbord with Shiny and want to compute new variables based on the selected Variabels by selectInput.
Comparable to this in normal R-Code:
library(dplyr)
new_df <- old_df %>% mutate(new_1 = old_var1 + old_var2)
I'm able to compute new values with the sliderInput, but this are only single values. I want to compute a hole new variable with all the oppertunities of displaying the new variable in Tables and graphics.
Please try the followring syntax (the data is online avalible).
As you mentioned, all Inputs are working as they should.
library(shiny)
library(readr)
library(ggplot2)
library(stringr)
library(dplyr)
library(DT)
library(tools)
load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata"))
ui <- fluidPage(
sidebarLayout(
# Inputs
sidebarPanel(
h3("Plotting"), # Third level header: Plotting
# Select variable for y-axis
selectInput(inputId = "y",
label = "Y-axis:",
choices = c("IMDB rating" = "imdb_rating",
"IMDB number of votes" = "imdb_num_votes",
"Critics Score" = "critics_score",
"Audience Score" = "audience_score",
"Runtime" = "runtime"),
selected = "audience_score"),
# Select variable for x-axis
selectInput(inputId = "x",
label = "X-axis:",
choices = c("IMDB rating" = "imdb_rating",
"IMDB number of votes" = "imdb_num_votes",
"Critics Score" = "critics_score",
"Audience Score" = "audience_score",
"Runtime" = "runtime"),
selected = "critics_score"),
# Select variable for color
selectInput(inputId = "z",
label = "Color by:",
choices = c("Title Type" = "title_type",
"Genre" = "genre",
"MPAA Rating" = "mpaa_rating",
"Critics Rating" = "critics_rating",
"Audience Rating" = "audience_rating"),
selected = "mpaa_rating"),
hr(),
# Set alpha level
sliderInput(inputId = "alpha",
label = "Alpha:",
min = 0, max = 1,
value = 0.5),
# Set point size
sliderInput(inputId = "beta",
label = "Beta:",
min = 0, max = 5,
value = 2)
),
# Output:
mainPanel(plotOutput(outputId = "scatterplot"),
textOutput(outputId = "description"),
DT::dataTableOutput("moviestable"))
)
)
server <- function(input, output, session) {
output$scatterplot <- renderPlot({
ggplot(data = movies, aes_string(x = input$x, y = input$y,
color = input$z)) +
geom_point(alpha = input$alpha, size = input$beta) +
labs(x = toTitleCase(str_replace_all(input$x, "_", " ")),
y = toTitleCase(str_replace_all(input$y, "_", " ")),
color = toTitleCase(str_replace_all(input$z, "_", " ")))
})
vals <- reactiveValues()
observe({
vals$x <- input$alpha
vals$y <- input$beta
vals$sum <- vals$x + vals$y
})
output$description <- renderText({
paste0("Alpha: ",input$alpha, " Beta:", input$beta," and the sum of alpha and beta:",vals$sum, ".")
})
output$moviestable <- DT::renderDataTable({
DT::datatable(data = movies,
options = list(pageLength = 10),
rownames = FALSE)
})
}
shinyApp(ui = ui, server = server)
I tried different ways to solve this problem:
1st try:
vals2 <- reactiveValues()
observe({
vals2$x <- input$y
vals2$y <- input$x
vals2$sum <- vals2$x + vals2$y
})
output$description2 <- renderText({
paste0("Input y: ",input$y, " Input x:", input$x," and the sum of both variables is:",vals2$sum, ".")
})
Warning: Error in +: non-numeric argument to binary operator
Stack trace (innermost first):
56: observerFunc [C:/Users/XXXXXX/Desktop/app.R#110]
1: runApp
ERROR: [on_request_read] connection reset by peer
2nd try:
output$try2 <- renderUI({
movies_2 <- movies %>% mutate(new_1 = input$y + input$x)
})
output$moviestable2 <- DT::renderDataTable({
DT::datatable(data = movies_2,
options = list(pageLength = 10),
rownames = FALSE)
})
Warning: Error in inherits: object 'movies_2' not found
I've no idea where I what I can try next...
I'm very happy for every kind of help!
You should make movies_2 in a reactive. Your output$try2 won't work because its expecting UI objects.
To match the call you make on the UI side I've renamed back to moviestable and have changed input$x + input$y to paste0(input$y, input$x) since they are both character.
movies_2 <- reactive({
movies %>% mutate(new_1 := movies[[input$x]] + movies[[input$y]])
})
output$moviestable <- DT::renderDataTable({
DT::datatable(data = movies_2(),
options = list(pageLength = 10),
rownames = FALSE)
})

How to feed input from multiple Shiny Widgets into one global reactive value?

I'm trying to build a Shiny widget such that users can choose a value from one of several drop downs or type in their own value:
textInput("select0", label = h5("Currently selected user")),
actionButton("generateInsights", label = "Show info"),
selectInput("select1", label = h5("Select high data volume user"),
choices = make_named_list(top_users$userid),
selected = 1),
selectInput("select2", label = h5("Select new user"),
choices = make_named_list(new_users$objectid),
selected = 1)
I would then like to make an interface that is reactive to an adjustment in any of these values:
current_userid = ""
shinyServer(function(input, output) {
current_userid_reactive = reactive({
print("current userid got updated inside reactive expression")
return(current_userid)
})
output$distPlot <- renderPlot({
print("updating plot")
user_data = get_user_data_from_user_id1(current_userid_reactive(), big_data)
print(user_data)
cat("number rows userdata is ", nrow(user_data))
ggplot(data=user_data, aes(x=displaydate, y=measurementvalue, color=datatype)) +
geom_point(size=.6) + geom_line(aes(displaydate, mav),color="black", size = .2) +
facet_grid(datatype ~ ., scales = "free_y", labeller=label_both) + labs(x = "time", y = "Measurement")
})
output$momentCountPlot <- renderPlot({
plot(get_user_moment_count(input$select, big_data))
})
output$carbCountPlott <- renderPlot({
plot(get_user_carb_count(input$select, big_data))
})
output$activityCountPlot <- renderPlot({
plot(get_user_activity_count(input$select, big_data))
})
observe({
current_userid <- input$select1
cat("updated current_userid to ", current_userid)
})
observe({
current_userid <- input$select2
cat("updated current_userid to ", current_userid)
})
output$ui <- renderUI({
h1(current_userid)
})
})
What I am trying to do is update the value of current_userid from either input$select1 or input$select2 and then replot regardless of whether the user selected a new value from one or the other of the selections.
However, I am finding that the observe functions run as expected (when I make a drop down selection), but their adjustment of the global current_userid does not lead to any accompanying action in current_userid_reactive or in output$distPlot. How can I achieve what I'm trying to do? Why doesn't this use of a reactive element work?

Shiny - Brushed dataset feature not working

server.ui
shinyServer(
function(input, output) {
plot <- eventReactive(input$button, {
if (input$gtype == "Time to Change") {
dataset = subset(TDU, LBTEST == input$study, drop=FALSE)
ggplot(dataset, aes_string(x= 'VISITNUM', y = 'LBBLCHGR' , col='factor(ARMAN)')) +
geom_line(data = dataset, aes_string(x='VISITNUM',y = 'LBBLCHGR' ,group='SUBJID')) +
}
else {
dataset = subset(TDU, LBTEST == input$study, drop=FALSE)
ggplot(dataset, aes_string(x = 'ARMCD', y = 'LBBLCHGR', col='factor(VISITNUM)')) + geom_line()
}
output$plot <- renderPlot({
plot()
})
output$brush_info <- renderPrint({
brushedPoints(dataset, input$plot_brush)
})
})
})
I have a corresponding ui.r file which is supposed to display brush_info. But whenever I try to highlight a point in my graph, I get some error stating that the object dataset doesn't exist? Why is that? It clearly exists within a loop. Why would R make this an obstacle to allowing dataset to become a useable dataframe?
shinyUI(fluidPage(titlePanel('Biomarker Comparison'),
fluidRow(column(12, plotOutput('plot', brush = brushOpts(id = "plot_brush"), dblclick = "plot_dblclick"))),
fixedRow(column(3,selectInput('type', label='Select a Study',choices= c('', 'ADLB_TDU', 'ADLB_TDR', 'ADBM_TDR'))), column(3, uiOutput('selectUI'))),
fluidRow(column(3, radioButtons('gtype', label='Graph Type', choices = list('Dosage to Change', 'Time to Change'))) , column(3, uiOutput('UImeasure')), column(6, h4("Brushed points"),verbatimTextOutput("brush_info"))),
actionButton('button', 'Draw Graph')
))
In simpler terms, how do I access a dataframe, or any object embedded in a loop?
EDIT :
Here is a solution that I came up with.
data = reactive({
dataset = subset(TDU, LBTEST == input$study, drop=FALSE)
})
output$brush_info <- renderPrint({
brushedPoints(data(), input$plot_brush)
})
So I put the dataframe into a reactive function, and then I substituted the dataframe name for the function that generates it. I can't believe that I haven't tried this before.

Resources