plotly::subplot annotations titles disappear in R Shiny - r

I have made a Shiny Application which includes an interactive plot via ggplotly in R. For plotting two of these interactive plots together I used plotly::subplot. Subplot works fine as intended, however the titles of the two disappear in the Shiny application.
How can this be fixed?
Relevant Code:
# Define UI for application that draws a plotlys
options(shiny.maxRequestSize=30*1024^2)
ui = navbarPage("Title", theme = shinytheme("spacelab"),
tabPanel("Interactive Plot",
icon = icon("chart-area"),
# Show plots side by side
splitLayout(
plotlyOutput(outputId = "Comparison_Plots"),
width = "1080px",
height = "1280px")))
# Tell the server how to assemble inputs into outputs
server = function(input, output) {
output$Comparison_Plots = renderPlotly({
....
fig1 = ggplotly(gg_plot1, tooltip = "text")
fig2 = ggplotly(gg_plot2, tooltip = "text")
# Plot them together
sub_plot = subplot(fig1, fig2, margin = 0.05) %>%
layout(annotations = list(
list(x = 0 , y = 1.1, text = "Group 1", showarrow = FALSE, xref='paper', yref='paper'),
list(x = 1 , y = 1.1, text = "Group 2", showarrow = FALSE, xref='paper', yref='paper'))
)
sub_plot
})
}
Snapshot from viewer window just showing the sub_plot
Snapshot of sub_plot as shown via the Shiny app

You have to increase the top-margin in layout:
layout(
annotations = list(
list(x = 0.2 , y = 1.1, text = "Title 1", showarrow = FALSE,
xref = 'paper', yref = 'paper'),
list(x = 0.8 , y = 1.1, text = "Title 2", showarrow = FALSE,
xref = 'paper', yref = 'paper')
),
margin = list(l = 50, r = 50, b = 50, t = 100)
)

Related

Plotly:: gauge plot does not render in Shiny Dashboard

I am trying to make a shiny app based on historical data. I am using a multiple shiny page approach.
For some reason when I run app, my output gets outputted only in the Viewer of RStudio and not on the main panel of the Shiny popup.
Here's the code:
Code in UI:
body <- dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
fluidRow(
plotlyOutput(outputId="chart1")
),
fluidRow(
gaugeOutput(outputId="gauge")
)
)
))
Code in Server:
output$gauge <- renderPlotly({
plot_ly(
domain = list(x = c(0, 1), y = c(0, 1)),
value = fatality_rate,
number= list(valueformat=".2f", suffix = "%"),
title = list(text = "Fatality Rate", font = list(size = 24, color = "black")),
type = "indicator",
mode = "gauge+number",
gauge = list(
axis = list(range=list(NULL, 50)),
bar= list(color="darkorange"),
borderwidth = 2,
bordercolor = "black",
threshold = list(
line = list(color="red", width = 4),
thickness = 0.75,
value = 49
)
))
})

Toggle between plotly bar chart to plotly column chart by using an actionButton

I have the shiny app below which displays a bar chart with Country in yaxis and Value in xaxis. Im trying to change it to: Country as xaxis and Value as yaxis by clicking on Exchange actionButton(). I should toggle between those two bu clicking on Exchange
library(shiny)
library(DT)
Country<-c("EU","CHE","ITA")
Value<-c(3,2,1)
dat<-data.frame(Country,Value)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("exc",
"Exchange")
),
mainPanel(
uiOutput(outputId = "plot")
)
)
)
server <- function(input, output) {
excplot <- reactiveVal(TRUE)
observeEvent(input$exc, {
excPlot(!excplot())
})
output[["bar1"]]<-renderPlotly({
fig1 <- plot_ly(dat, x = ~Value, y = ~Country,
type = 'bar', orientation = 'h',
hovertemplate = paste('%{y}', '<br>Value: %{x}<br>'),
marker = list(color = 'green')
)
fig1 <- fig1 %>% layout(
yaxis = list(title="",showgrid = FALSE, showline = FALSE, showticklabels = TRUE, domain= c(0, 0.85)),
xaxis = list(title="",zeroline = FALSE, showline = FALSE, showticklabels = FALSE, showgrid = FALSE))
fig1 <- fig1 %>% add_annotations(xref = 'x1', yref = 'y',
x = dat$Value* 1.1 + 0.5, y = dat$Country,
text = paste(round(dat$Value, 2), '%'),
font = list(family = 'Arial', size = 12, color = 'black'),
showarrow = FALSE)
fig1
})
output$plot <- renderUI({
plotlyOutput("bar1")
})
}
shinyApp(ui = ui, server = server)
Perhaps this will meet your needs.
library(shiny)
library(DT)
Country<-c("EU","CHE","ITA")
Value<-c(3,2,1)
dat<-data.frame(Country,Value)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
actionButton("exc", "Exchange")
),
mainPanel(
uiOutput(outputId = "plot")
)
)
)
server <- function(input, output) {
excplot <- reactiveVal(TRUE)
observeEvent(input$exc, {
excplot(!excplot())
})
output[["bar1"]]<-renderPlotly({
if (excplot()) {
dat$xvar <- dat$Value
dat$yvar <- dat$Country
hv <- "h"
myyaxis = list(title="",showgrid = FALSE, showline = FALSE, showticklabels = TRUE, domain= c(0, 0.85) )
myxaxis = list(title="",zeroline = FALSE, showline = FALSE, showticklabels = FALSE, showgrid = FALSE)
xx <- dat$xvar*1.1 + 0.1
yy <- dat$yvar
}else {
dat$yvar <- dat$Value
dat$xvar <- dat$Country
hv <- "v"
myxaxis = list(title="",showgrid = FALSE, showline = FALSE, showticklabels = TRUE, domain= c(0, 0.85) )
myyaxis = list(title="",zeroline = FALSE, showline = FALSE, showticklabels = FALSE, showgrid = FALSE)
xx <- dat$xvar
yy <- dat$yvar*1.1 + 0.1
}
fig1 <- plot_ly(dat, x = ~xvar, y = ~yvar,
type = 'bar', orientation = hv,
hovertemplate = paste('%{y}', '<br>Value: %{x}<br>'),
marker = list(color = 'green')
)
fig1 <- fig1 %>% layout(yaxis = myyaxis, xaxis = myxaxis )
fig1 <- fig1 %>% add_annotations(xref = 'x1', yref = 'y',
x = xx , y = yy,
text = paste(round(dat$Value, 2), '%'),
font = list(family = 'Arial', size = 12, color = 'black'),
showarrow = FALSE)
fig1
})
output$plot <- renderUI({
plotlyOutput("bar1")
})
}
shinyApp(ui = ui, server = server)

Using renderText under certain condition Shiny

i'm newly to the R world and i'm just trying to build a Dashboard on Shiny.
My problem is that i want to display some text only if certain conditions are met in the renderplotly function.
shinyUI(fluidPage(
titlePanel("Posti occupati in terapia intensiva"),
sidebarLayout(
sidebarPanel(
selectInput("region","Scegli regione",unique(as.character(region_dataset$denominazione_regione),)
),
dateInput("day","Scegli data", min=region_dataset$data[1], max=region_dataset$data[nrow(region_dataset)], format="dd/mm/yyyy",value=region_dataset$data[nrow(region_dataset)]
),
),
mainPanel(
plotlyOutput(outputId = "TI"),
textOutput(outputId= "text")
)
),
))
This is the ui page and i show you the server
shinyServer(function(input, output) {
output$TI <- renderPlotly({
day <- input$day
region <- input$region
request <- filter(region_dataset,region_dataset$data==day & region_dataset$denominazione_regione==region)
plot_ly(as.data.frame(request$terapia_intensiva),
domain = list(x = c(0, 1), y = c(0, 1)),
value = request$terapia_intensiva,
title = list(text = "Posti occupati TI"),
type = "indicator",
mode = "gauge+number+delta",
delta = (reference = as.integer(request$terapia_intensiva[nrow(request$data)-1])),
gauge = list(
axis =list(range = list(NULL, request$posti_TI)),
bar = list(color = "darkmagenta"),
borderwidth = 3,
steps = list(
list(range = c(0, 0.33*request$posti_TI), color = "green"),
list(range = c(0.33*request$posti_TI, 0.66*request$posti_TI), color = "yellow"),
list(range = c(0.66*request$posti_TI, request$posti_TI), color = "red")),
threshold = list(
line = list(color = "cyan", width = 5),
thickness = 0.75,
value = request$posti_TI)))
})
output$text <- renderText("Numero massimo di posti occupati")
})
My problem is that i want to display the text in the panel only if request$terapia_intensiva>request$posti_TI
I can't find out a solution to this problem, i've tried using reactive function and conditional panel but with no results.
Thanks for helping.
renderText() can contain logic, so
output$text <- renderText({
if (request$terapia_intensiva>request$posti_TI) "Numero massimo di posti occupati"
})
If the if() returns FALSE, renderText returns NULL. If you want to be explicit, you can always add else NULL or else rturn(NULL) if you wish.

Use ggplot and ggplotly instead of plot_ly to create a pie chart

Hello I have a simple shiny app which creates a pie chart based on the input FacilityName of my dataset. I want every time that I choose a different facility my pie chart to display the share between EXT/INT (OriginId). Also every piece should display the share and the number of "kunden".Unfortunately plot_ly() does not seem to work properly for me so I would to use ggplot() instead and then convert it to plotly with ggplotly().
#data
OriginId=c("INT","EXT","INT","INT","EXT","INT","EXT","INT")
FacilityName=c("t1","t1","t2","t2","t1","t3","t4","t5")
FacId=c("t1","t1","t2","t2","t1","t3","t4","t5")
Testdata2<-data.frame(OriginId,FacilityName,FacId)
#ui.r
library(shinydashboard)
library(plotly)
library(data.table)
dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody()
)
#
ui <- dashboardPage(skin = "black",
dashboardHeader(title = img(src="Logo1.jpg", height = 50, align = "left")
),
## Sidebar content
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard"))
)
),
## Body content
dashboardBody(
tabItems(
# Dashboard tab
tabItem(tabName = "dashboard",
fluidRow(
box(title = "Verhältnis interner / externer Aufträge", status = "primary", solidHeader = TRUE,
plotlyOutput("pie",height = 250)),
uiOutput("var")
)
)
)
)
)
#server.r
server <- function(input, output,session) {
# Auftrag INT vs Ext
output$pie<-renderPlotly({
data <- dplyr::tbl_df(subset(Testdata2,Testdata2$FacilityName %in% input$variable))
ttestdata <- data.frame(data %>% group_by(OriginId) %>% mutate(Counts = n()))
p <- plot_ly(data, labels=data$OriginId, values = table(data$OriginId), type = 'pie',
textposition = 'inside',
insidetextfont = list(color = '#FFFFFF'),
hoverinfo = 'text',
text = ~paste(ttestdata$Counts, ' Kunden'),
marker = list(
line = list(color = '#FFFFFF', width = 1)),
showlegend = FALSE) %>%
layout(
title = paste(input$variable),
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
})
output$var<-renderUI({
selectInput("variable",
h4("Abteilung wählen:"),
choices = Testdata2 %>% distinct(FacilityName),selected = 1)
})
}
Pie chart in ggplot2:
Here is how you can do a pie chart in ggplot2:
data <- Testdata2 %>% filter(FacilityName == "t1")
p <- ggplot(data, aes(x = '', fill = OriginId)) +
geom_bar(width = 1, stat = "count") +
coord_polar(theta = "y", start = 0)
The idea is to use a barplot and switch to polar coordinates.
This yields the following graph:
Support in ggplotly():
Polar coordinates are not yet supported by ggplotly() though.
You can refer to this github issue to follow this point: https://github.com/ropensci/plotly/issues/878

How to put two plotly graphs in one row?

I have multiple pie graphs from plotly in my Shiny app and I cannot seem to move them so that they fit in the same row. I can move them around either by changing the position in a .css file or using absolutePanel() but either option leaves me with a giant chunk of empty white space at the bottom. I cannot post code from my app so I made a smaller example in which i tried moving with column() function to no avail. Any help would be appreciated. In my actual app I have about 5 graphs so the amount of white space is VERY big and i wish to resolve it. It might be an easy answer but bear with me guys Im a newb...
library(shiny)
library(plotly)
ui = fluidPage(
plotlyOutput("graph1",width="40%",height="350px"),
column(width=12,offset=4,plotlyOutput("graph2",width="40%",height="350px"))
)
server = function(input, output,session) {
output$graph1<-renderPlotly({
USPersonalExpenditure <- data.frame("Categorie"=rownames(USPersonalExpenditure), USPersonalExpenditure)
data <- USPersonalExpenditure[,c('Categorie', 'X1960')]
p <- plot_ly(data, labels = ~Categorie, values = ~X1960, type = 'pie') %>%
layout(title = 'Graph 1',
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
})
output$graph2<-renderPlotly({
USPersonalExpenditure <- data.frame("Categorie" = rownames(USPersonalExpenditure), USPersonalExpenditure)
data <- USPersonalExpenditure[, c('Categorie', 'X1960')]
colors <- c('rgb(211,94,96)', 'rgb(128,133,133)', 'rgb(144,103,167)', 'rgb(171,104,87)', 'rgb(114,147,203)')
p <- plot_ly(data, labels = ~Categorie, values = ~X1960, type = 'pie',
textposition = 'inside',
textinfo = 'label+percent',
insidetextfont = list(color = '#FFFFFF'),
hoverinfo = 'text',
text = ~paste('$', X1960, ' billions'),
marker = list(colors = colors,
line = list(color = '#FFFFFF', width = 1)),
#The 'pull' attribute can also be used to create space between the sectors
showlegend = FALSE) %>%
layout(title = 'Graph 2',
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
})
}
# Run the application
shinyApp(ui = ui, server = server)
You could try using a fluidRow and segment that by columns as in below. The columns space is base 12, so two column(6,..) calls within one fluidRow will split you into two. The example below splits into 4. I'm not clear on what the "white space at the bottom" issue is that you describe, so this may not be the fix you're after.
ui = fluidPage(
fluidRow(
column(3,
plotlyOutput("graph1")
),
column(3,
plotlyOutput("graph2")
),
column(3,
plotlyOutput("graph3")
),
column(3,
plotlyOutput("graph4")
)
)
)

Resources