So a plotly plot has an embedded rangeslider however I do not like the looks of it. The rangeslider in R Shiny looks much better and professional, however how do i connect the two?
Lets say you have a dataframe with some values and a daterange like:
library(lubridate)
df <- data.frame(
"Date" = c(seq(ymd('2015-09-15'), ymd('2015-09-24'), by = "1 days")),
"values" = c(3,6,5,3,5,6,7,7,4,2)
)
Code for the plotly plot
library(plotly)
plot_df <- plot_ly(df)
plot_df <- plot_df %>% add_lines(type = 'scatter', mode = "lines",
x = ~Date, y = ~values)
Code Shiny
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Basic dashboard"),
dashboardSidebar(),
dashboardBody(
# Boxes need to be put in a row (or column)
fluidRow(
box(plotlyOutput("plotdf", height = 250)),
box(
title = "Controls",
sliderInput("Date", "", min = df$Date[1], tail(df$Date, 1), value = tail(df$Date, 1)
)
)
)
)
)
server <- function(input, output) {
output$plotdf<-renderPlotly({
plot_df
})
}
shinyApp(ui, server)
We can use dplyr::filter and pipe it to plot_ly().
output$plotdf<-renderPlotly({
filter(df, Date <= input$Date) %>%
plot_ly() %>%
add_lines(type = 'scatter', mode = "lines",
x = ~Date, y = ~values)
})
Edit: Below is the plot code separated from the app with a sliderInput to select a range of dates.
library(shiny)
library(dplyr)
library(lubridate)
library(plotly)
source(file = 'my_functions_script.R', local = TRUE)
df <- data.frame(
"Date" = c(seq(ymd('2015-09-15'), ymd('2015-09-24'), by = "1 days")),
"values" = c(3,6,5,3,5,6,7,7,4,2)
)
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Basic dashboard"),
dashboardSidebar(),
dashboardBody(
# Boxes need to be put in a row (or column)
fluidRow(
box(plotlyOutput("plotdf", height = 250)),
box(
title = "Controls",
shiny::sliderInput("Date", "", min = df$Date[1], tail(df$Date, 1), value = c(df$Date[1],tail(df$Date, 1))
)
)
)
)
)
server <- function(input, output) {
output$plotdf<-renderPlotly({
filter(df,Date >= input$Date[[1]], Date <= input$Date[[2]]) %>%
plt()
})
}
shinyApp(ui, server)
Related
Please see attached image. Do you have suggestions how to avoid that the plot is outside the white area, or to make the grey area below the plot white?
ui <- dashboardPage(
# Application title
dashboardHeader(title=h4(HTML("Virus Coverage plot"))),
dashboardSidebar(
useShinyjs(),
selectInput("Taxa", "Taxa", choices = unique(files.Vir.DNA.df.test$V1))
),
dashboardBody(
tabsetPanel(
tabPanel("Taxa", plotOutput("myplot1"))
)
)
)
server <- function(input, output, session) {
data_selected <- reactive({
filter(files.Vir.DNA.df.test, V1 %in% input$Taxa)
})
output$myplot1 <- renderPlot({
#data_selected() %>%
# filter(Cancer=="Anus" | Cancer=="Cervix") %>%
p <- ggplot(data_selected(),aes(position,rowSums, fill = V1)) +
#theme_bw(base_size = 6) +
geom_bar(stat="identity") +
facet_grid(Cancer~. , scales = "free_x", space = "free_x", switch = "x") +
theme(strip.text.y = element_text(angle = 0),
strip.text.x = element_text(angle = 90),
strip.background = element_rect(colour = "transparent", fill = "transparent"),
plot.background = element_rect(colour = "white", fill = "white"),
panel.background = element_rect(colour = "white", fill = "white"),
axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
labs(y="Sum coverage within cancer type", x="", title="") +
scale_fill_manual(values=mycolors) +
theme(legend.position = "none")
#scale_y_log10()
print(p)
},res = 100,width = 600, height = 1200)
}
shinyApp(ui, server)
Your example isn't reproducible - so I made a new one.
You just need to wrap the plotOutput in a fluidRow:
library(shiny)
library(ggplot2)
library(datasets)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
# dashboardBody(plotOutput("myplot")) # exceeds body
dashboardBody(fluidRow(plotOutput("myplot"))) # works
)
server <- function(input, output, session) {
output$myplot <- renderPlot({
scatter <- ggplot(data=iris, aes(x = Sepal.Length, y = Sepal.Width))
scatter + geom_point(aes(color=Species, shape=Species)) +
xlab("Sepal Length") + ylab("Sepal Width") +
ggtitle("Sepal Length-Width")
}, height = 1200)
}
shinyApp(ui, server)
I want the user of my Shiny app to be able to choose between two types of plots by clicking on radiobuttons in the Events panel. The code I have written works, but the page leaves a huge white space when going from "Map" to "Plot". Is there any way to get rid of the white space and position the plot at the very top?
# Load R packages
library(shiny)
library(shinythemes)
library(tidyverse)
library(leaflet)
set.seed(123)
year <- 2001:2020
event <- sample(1:100, size = 20, replace = TRUE)
dat <- as.data.frame(cbind(year, event))
# Define UI
ui <- fluidPage(
shinyjs::useShinyjs(),
theme = shinytheme("journal"),
navbarPage(
"Title",
tabPanel("About",
),
tabPanel("Events",
fluidPage(
titlePanel("Title"),
sliderInput("range", label = "Move slider to select time period", min(2001), max(2020),
value = range(2001:2002), step = 1, sep = "", width = "65%"),
sidebarLayout(
sidebarPanel(
radioButtons("plotType", "Plot type", choices = c("Map" = "m", "Chart" = "l"))),
mainPanel(
leafletOutput("map"),
plotOutput("plot"))
)
)
)
)
)
# Define server function
server <- function(input, output, session) {
observeEvent(input$plotType, {
if(input$plotType == "l"){
shinyjs::disable("range")
}else{
shinyjs::enable("range")
}
})
output$plot <- renderPlot({
if (input$plotType == "l") {
ggplot(dat, aes(year, event)) +
geom_line() +
labs(x = "Year", y = "Events") +
theme_bw()
}
})
output$map <- renderLeaflet({
if ( input$plotType == "m") {
leaflet(dat) %>% addTiles() %>%
fitBounds(~min(11), ~min(54), ~max(67), ~max(24))
}
})
} # server
# Create Shiny object
shinyApp(ui = ui, server = server)
There is a big space because the map html object still exists, but is empty. To avoid this, I created and observeEvent that hides or show the map output depending on input value. I did the same thing with the plot, in cas you need to add others elements below it.
Please note that there are others solutions (conditionalPanel for example), I am just giving you the one I think is the simpliest here.
# Load R packages
library(shiny)
library(shinythemes)
library(tidyverse)
library(leaflet)
set.seed(123)
year <- 2001:2020
event <- sample(1:100, size = 20, replace = TRUE)
dat <- as.data.frame(cbind(year, event))
# Define UI
ui <- fluidPage(
shinyjs::useShinyjs(),
theme = shinytheme("journal"),
navbarPage(
"Title",
tabPanel("About",
),
tabPanel("Events",
fluidPage(
titlePanel("Title"),
sliderInput("range", label = "Move slider to select time period", min(2001), max(2020),
value = range(2001:2002), step = 1, sep = "", width = "65%"),
sidebarLayout(
sidebarPanel(
radioButtons("plotType", "Plot type", choices = c("Map" = "m", "Chart" = "l"))),
mainPanel(
leafletOutput("map"),
plotOutput("plot"))
)
)
)
)
)
# Define server function
server <- function(input, output, session) {
# hide or show map and plot
observeEvent(input$plotType, {
if(input$plotType == "l"){
shinyjs::disable("range")
shinyjs::hide("map")
shinyjs::show("plot")
}
if(input$plotType == "m"){
shinyjs::enable("range")
shinyjs::show("map")
shinyjs::hide("plot")
}
})
output$plot <- renderPlot({
req(input$plotType == "l") # good practice to use req instead of if
ggplot(dat, aes(year, event)) +
geom_line() +
labs(x = "Year", y = "Events") +
theme_bw()
})
output$map <- renderLeaflet({
req(input$plotType == "m")
leaflet(dat) %>% addTiles() %>%
fitBounds(~min(11), ~min(54), ~max(67), ~max(24))
})
} # server
# Create Shiny object
shinyApp(ui = ui, server = server)
im trying to create a popup window depending on a click event in Shiny.
The window should open up when the user clicks on a row in a DT table. It should contain a plotly graph, that is filtered by the row element in column v1 in df (when a row with v1 == "B" was clicked, all rows with v1 == "B" go in the graph). I can create all objects (see code), but struggle with dependent filtering and opening the popup window based on row click event.
I'm new to Shiny and tried to implement snippets from similar questions, but i couldn't find exactly what i need and bring everything together.
library(shiny)
library(DT)
library(plotly)
library(dplyr)
id <- c(1:100)
v1 <- rep(LETTERS[1:10], times = 10)
v2 <- sample.int(100, 100)
v3 <- sample.int(200, 100)
v4 <- sample.int(300, 100)
v5 <- rep(c(2000:2019), times = 5)
df <- data.frame(id, v1, v2, v3, v4, v5)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("first", tabName = "first"
)
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "first",
box(width = 12, solidHeader = TRUE,
DT::dataTableOutput("table"),
plotlyOutput("plot")
)
)
)
)
)
server <- function(input, output) {
output$table <- DT::renderDataTable({
DT::datatable(df,
options = list(
pageLength = 10, paging = TRUE, searching = TRUE
),
rownames = FALSE, selection = "single",
)
})
# table_subset <- reactive({
# df %>% filter(v1 == "B")
# })
click_subset <- df %>% filter(v1 == "B")
#Plot in popup window
output$plot <- renderPlotly({
plot_ly(click_subset, type = 'bar') %>%
add_trace(
x =~v5, y =~v3
)
})
}
shinyApp(ui, server)
We can use modalDialog function from shiny to show the plot in a pop-up and
input$tableID_rows_selected to filter the data:
df_subset <- reactiveVal(NULL)
observeEvent(input$table_rows_selected, {
v1_value <- df[input$table_rows_selected, "v1"]
df_subset(filter(df, v1 == v1_value))
showModal(modalDialog(plotlyOutput("plot"), size = "m"))
})
App:
library(shiny)
library(DT)
library(plotly)
library(dplyr)
library(shinyWidgets)
library(shinydashboard)
id <- c(1:100)
v1 <- rep(LETTERS[1:10], times = 10)
v2 <- sample.int(100, 100)
v3 <- sample.int(200, 100)
v4 <- sample.int(300, 100)
v5 <- rep(c(2000:2019), times = 5)
df <- data.frame(id, v1, v2, v3, v4, v5)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
menuItem("first", tabName = "first")
)
),
dashboardBody(
tabItems(
tabItem(
tabName = "first",
box(
width = 12, solidHeader = TRUE,
DT::dataTableOutput("table"),
# plotlyOutput("plot")
)
)
)
)
)
server <- function(input, output) {
df_subset <- reactiveVal(NULL)
output$table <- DT::renderDataTable({
DT::datatable(df,
options = list(
pageLength = 10, paging = TRUE, searching = TRUE
),
rownames = FALSE, selection = "single",
)
})
observeEvent(input$table_rows_selected, {
v1_value <- df[input$table_rows_selected, "v1"]
df_subset(filter(df, v1 == v1_value))
showModal(modalDialog(plotlyOutput("plot"), size = "m"))
})
click_subset <- df %>% filter(v1 == "B")
# Plot in popup window
output$plot <- renderPlotly({
req(df_subset)
plot_ly(df_subset(), type = "bar") %>%
add_trace(
x = ~v5, y = ~v3
)
})
}
shinyApp(ui, server)
Can we add a small icon next to values in DT table. Example
if (interactive()) {
library(shiny)
library(shinyWidgets)
library(DT)
ui <- fluidPage(
tags$h3("Material switch examples"),
fluidRow(column(width = 12),
fluidRow(box(width = 4, dateInput("date","Date", value = Sys.time(), min = Sys.time(), max = Sys.time()-30)),
box(width = 7, selectInput("df","DF",choices = unique(iris$Species)),offset = 0),
box(width = 2, actionButton("ab","Action")))),
dataTableOutput("df")
)
server <- function(input, output) {
output$df <- DT::renderDataTable({
datatable(head(iris),caption = "Iris",options = list(dom = 'ft'))
})
}
shinyApp(ui, server)
}
IN the above DT table, can we add upward arrow next to Setosa . (It should be clickable)
Expect Output
You could use icon to display an up arrow.
library(shiny)
library(shinyWidgets)
library(DT)
library(dplyr)
ui <- fluidPage(
tags$h3("Material switch examples"),
dataTableOutput("df")
)
server <- function(input, output) {
data <- head(iris) %>% mutate(Species = paste(Species,as.character(icon("arrow-up", lib = "glyphicon"))))
output$df <- DT::renderDataTable({
datatable(data,caption = "Iris",options = list(dom = 'ft'),escape=FALSE, selection = list(mode = 'single',target = 'cell'))
})
}
shinyApp(ui, server)
I have tried this in different ways and achieved one task, either add or delete., but i couldn't get complete solution in one, i might be missing some small concept somewhere.. I am adding the code , please help me complete my basic app.
library(shiny)
library(DT)
x<- data.frame(v1 = NA,
v2 = NA
),
ui = shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
textInput("v1","v1","a"),
numericInput("V2","V2","1"),
# Row selection
numericInput(inputId = "row.selection", label = "Select row to be
deleted", min = 1, max = 100, value = "")
# Add button
actionButton(inputId = "add.button", label = "Add", icon =
icon("plus")),
# Delete button
actionButton(inputId = "delete.button", label = "Delete", icon =
icon("minus")),
),
mainPanel(
dataTableOutput('table')
)
)
)
),
Server side code
server = function(input, output, session) {
values <- reactiveValues()
values$df <- x
newEntry <- observe({
cat("newEntry\n")
if(input$add.button > 0) {
newRow <- data.frame(input$v1, input$v2)
isolate(values$df <- rbind(values$df,newRow))
}
})
deleteEntry <- observe({
cat("deleteEntry\n")
if(input$delete.button > 0) {
if(is.na(isolate(input$row.selection))){
values$df <- isolate(values$df[-nrow(values$df), ])
} else {
values$df <- isolate(values$df[-input$row.selection, ])
}
}
})
output$table = renderDataTable({
values$df
})
}
Try to use observeEvent rather than obser with actionbutton
and also, you have uppercase and lowercase issue with input$v2 (should be input$V2)
Try this modified code:
library(shiny)
library(DT)
x<- data.frame(v1 = NA,
v2 = NA
)
ui = shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
textInput("v1","v1","a"),
numericInput("V2","V2","1"),
# Row selection
numericInput(inputId = "row.selection", label = "Select row to be
deleted", min = 1, max = 100, value = ""),
# Add button
actionButton(inputId = "add.button", label = "Add", icon =
icon("plus")),
# Delete button
actionButton(inputId = "delete.button", label = "Delete", icon =
icon("minus"))
),
mainPanel(
dataTableOutput('table')
)
)
)
)
server = function(input, output, session) {
values <- reactiveValues()
values$df <- x
observeEvent(input$add.button,{
cat("addEntry\n")
print(input$v1)
print(input$V2)
newRow <- data.frame(input$v1, input$V2)
colnames(newRow)<-colnames(values$df)
values$df <- rbind(values$df,newRow)
print(nrow(values$df))
})
observeEvent(input$delete.button,{
cat("deleteEntry\n")
if(is.na(input$row.selection)){
values$df <- values$df[-nrow(values$df), ]
} else {
values$df <- values$df[-input$row.selection, ]
}
})
output$table = renderDataTable({
values$df
})
}
shinyApp(ui,server)
Just run all the code above, and it should work properly.