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")
)
)
)
Related
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)
)
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)
I'm trying to print an interactive pie chart. On a click on the plot another trace should be added. I'm using event_data for this. When the trace is added, on the next click anywhere on the page the trace shall be removed. I didn't find a solution for that. I don't know how to overwrite the onclick-event after another click.
The next Problem would be to remove the before added trace. I think i could use plotlyProxy for that like in Removing traces by name using plotlyProxy (or accessing output schema in reactive context)
Afterwards you can see my code
library(shiny)
library(data.table)
library(plotly)
ui <- basicPage(
mainPanel(
fluidRow(column(8, plotly::plotlyOutput("myplot", height = "800px")))
)
)
server <- function(input, output, session) {
testdata = data.frame("Orga" = c("Li", "La", "Le", "Lu", "De", "Va", "Xul", "Jin"),
"Dachorga" = c("Bla", "Bla", "Blu", "Blu", "Blub", "Blub", "Lol", "Lol"),
"Umsatz.Orga" = c(20000, 10000, 12000, 3000, 100, 2400, 205000, 95000))
testdata = data.table(testdata)
testdata_agg = testdata[, sum(Umsatz.Orga), by=Dachorga]
output$myplot <- renderPlotly({
p <- testdata_agg %>%
group_by(Dachorga) %>%
plot_ly(labels = ~Dachorga, values = ~V1, hoverinfo = 'label+percent+value') %>%
add_pie(hole = 0.6) %>%
layout(title = "Donut charts using Plotly", showlegend = F,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
d <- event_data("plotly_click")
if (!is.null(d)) {
p = add_pie(p, data = testdata[Dachorga == "Bla"], labels = ~Orga, values = ~Umsatz.Orga, hole = 0.5,
hoverinfo = 'label+percent+value', domain = list(
x = c(0.1, 0.9),
y = c(0.1, 0.9)),
marker = list(hover = list(color = "white")))
}
p
})
}
shinyApp(ui = ui, server = server)
Sorry for my bad english and thanks in advance
One can use a small javascript code to detect one click on the document, and send the result to the shiny server with Shiny.setInputValue. Then one can control the plot with the help of a reactive value.
library(shiny)
library(data.table)
library(plotly)
js <- "
$(document).ready(function(){
$(document).on('click', function(){
Shiny.setInputValue('click_on_doc', true, {priority: 'event'});
})
})"
ui <- basicPage(
tags$head(tags$script(HTML(js))),
mainPanel(
fluidRow(column(8, plotly::plotlyOutput("myplot", height = "800px")))
)
)
server <- function(input, output, session) {
testdata <- data.frame("Orga" = c("Li", "La", "Le", "Lu", "De", "Va", "Xul", "Jin"),
"Dachorga" = c("Bla", "Bla", "Blu", "Blu", "Blub", "Blub", "Lol", "Lol"),
"Umsatz.Orga" = c(20000, 10000, 12000, 3000, 100, 2400, 205000, 95000))
testdata <- data.table(testdata)
testdata_agg <- testdata[, sum(Umsatz.Orga), by=Dachorga]
plot <- testdata_agg %>%
group_by(Dachorga) %>%
plot_ly(labels = ~Dachorga, values = ~V1, hoverinfo = 'label+percent+value') %>%
add_pie(hole = 0.6) %>%
layout(title = "Donut charts using Plotly", showlegend = F,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))
click <- reactiveVal(FALSE)
observe({
event <- !is.null(event_data("plotly_click"))
click(event)
})
observeEvent(input$click_on_doc, {
click(FALSE)
})
output$myplot <- renderPlotly({
if (click()) {
p <- add_pie(plot, data = testdata[Dachorga == "Bla"], labels = ~Orga,
values = ~Umsatz.Orga, hole = 0.5,
hoverinfo = 'label+percent+value', domain = list(
x = c(0.1, 0.9),
y = c(0.1, 0.9)),
marker = list(hover = list(color = "white")))
}else{
p <- plot
}
p
})
}
shinyApp(ui = ui, server = server)
I have not understood your "next problem". Perhaps open a new question and try to clarify.
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
I would like for the 3 donut charts in the following application to be centered within their div, but they are all right-aligned. When changing the width of the browser window (Safari on macOS), they are centered as I would like them to, but not when the page loads initially.
any ideas how the 3 charts can always be centered above the title shown below them?
library(shiny)
library(plotly)
# Define UI for application
ui <- navbarPage("Home",
tabPanel("Tab1",
tags$style(type="text/css",
"h3 { text-align:center; }"
),
fluidRow(
column(4,
h2(plotlyOutput("plot1", height = "100%")),
h3("Score")
),
column(4,
h2(plotlyOutput("plot2", height = "100%")),
h3("Score")
),
column(4,
h2(plotlyOutput("plot3", height = "100%")),
h3("Score")
)
)
)
)
# Define server logic
server <- function(input, output) {
output$plot1 <- renderPlotly({
iScore <- sample(70:100, 1)
plot_ly(width = 150, height = 150,
marker = list(colors = c("#65b146", "rgba(0,0,0,0)"))) %>%
add_pie(values = c(iScore, 100 - iScore),
hole = .7,
textposition = 'none') %>%
layout(autosize = TRUE,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
showlegend = FALSE,
annotations = list(text = paste0("<b>",iScore,"</b>"),
align = "center",
font = list(size = 24),
showarrow = FALSE)) %>%
config(displayModeBar = F)
})
output$plot2 <- renderPlotly({
iScore <- sample(70:100, 1)
plot_ly(width = 150, height = 150,
marker = list(colors = c("#65b146", "rgba(0,0,0,0)"))) %>%
add_pie(values = c(iScore, 100 - iScore),
hole = .7,
textposition = 'none') %>%
layout(autosize = TRUE,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
showlegend = FALSE,
annotations = list(text = paste0("<b>",iScore,"</b>"),
align = "center",
font = list(size = 24),
showarrow = FALSE)) %>%
config(displayModeBar = F)
})
output$plot3 <- renderPlotly({
iScore <- sample(70:100, 1)
plot_ly(width = 150, height = 150,
marker = list(colors = c("#65b146", "rgba(0,0,0,0)"))) %>%
add_pie(values = c(iScore, 100 - iScore),
hole = .7,
textposition = 'none') %>%
layout(autosize = TRUE,
xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
showlegend = FALSE,
annotations = list(text = paste0("<b>",iScore,"</b>"),
align = "center",
font = list(size = 24),
showarrow = FALSE)) %>%
config(displayModeBar = F)
})
}
# Run the application
shinyApp(ui = ui, server = server)
To embed your plot in a div, you should use div() instead of h2(), and to center, just specify its align="center" parameter:
div(plotlyOutput("plot1", height = "100%"), align = "center")