Positioning of shiny widets like box and selectInputs in R - html

Please run the R shiny script below, I shall attach two screens and need a little assistance with positioning of the widgets here:
Screen 1:
I want to increase the width of the selectInput widget such that the options are clearly visible with equal spacing from the KPI boxes.
I want same width and height for the two big boxes such that it entirely covers the screen from left to right.
Note: The left border of the box should coincide with the left border of selectInput widget.
Screen 2:
1. Please help with shifting of the first and second selectInput widget, and kpi boxes above such that the box plots width can be increased like the requirement in the above screen. Please help.
## app.R ##
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Iris Chart"),
dashboardSidebar(
width = 0
),
dashboardBody(
tags$head(tags$style(HTML('.info-box {min-height: 45px;} .info-box-icon
{height: 45px; line-height: 45px;} .info-box-content {padding-top: 0px;
padding-bottom: 0px;}
'))),
fluidRow(
column(1,
selectInput("Position", "",
c("User_Analyses","User_Activity_Analyses"),selected = "Median", width =
"400"),
conditionalPanel(
condition = "input.Position == 'User_Analyses'",
selectInput("stats", "", c("Time","Cases"),selected = "Median", width =
"400"))),
tags$br(),
column(10,
infoBox("User1", paste0(10), icon = icon("credit-card"), width = "3"),
infoBox("User2",paste0(10), icon = icon("credit-card"), width =
"3"),
infoBox("User3",paste0(10), icon = icon("credit-card"), width =
"3"),
infoBox("User4",paste0(16), icon = icon("credit-card"), width =
"3")),
column(10,
conditionalPanel(
condition = "input.Position == 'User_Analyses'",
box(title = "Plot1", status = "primary",height = "537" ,solidHeader = T,
plotOutput("case_hist",height = "466")),
box(title = "Plot2", status = "primary",height = "537" ,solidHeader = T,
plotOutput("trace_hist",height = "466"))
),
conditionalPanel(
condition = "input.Position == 'User_Activity_Analyses'",
box(title = "Plot3",status = "primary",solidHeader = T,height = "537",width = "6",
plotOutput("sankey_plot")),
box(title = "Plot4",status = "primary",solidHeader = T,height = "537",width = "6",
plotOutput("sankey_table"))
)
)
)
)
)
server <- function(input, output)
{
output$case_hist <- renderPlot(
plot(iris$Sepal.Length)
)
output$trace_hist <- renderPlot(
plot(mtcars$mpg)
)
output$sankey_plot <- renderPlot({
plot(diamonds$carat)
})
#Plot for Sankey Data table
output$sankey_table <- renderPlot({
plot(iris$Petal.Length)
})
}
shinyApp(ui, server)

Is this somewhat what you want.
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Iris Chart"),
dashboardSidebar(
width = 0
),
dashboardBody(
tags$head(tags$style(HTML('.info-box {min-height: 45px;} .info-box-icon
{height: 45px; line-height: 45px;} .info-box-content {padding-top: 0px;
padding-bottom: 0px;}
'))),
fluidRow(
column(
width = 12,
column(
width = 2,
selectInput("Position", "",
c("User_Analyses","User_Activity_Analyses"),selected = "Median", width =
"400"),
conditionalPanel(
condition = "input.Position == 'User_Analyses'",
style = "margin-top:-22px;",
selectInput("stats", "", c("Time","Cases"),selected = "Median", width = "400"))
),
column(
style = "padding-top:20px;",
width = 10,
infoBox("User1", paste0(10), icon = icon("credit-card"), width = "3"),
infoBox("User2",paste0(10), icon = icon("credit-card"), width ="3"),
infoBox("User3",paste0(10), icon = icon("credit-card"), width ="3"),
infoBox("User4",paste0(16), icon = icon("credit-card"), width ="3"))
),
column(
width = 12,
conditionalPanel(
condition = "input.Position == 'User_Analyses'",
box(title = "Plot1", status = "primary",height = "537" ,solidHeader = T,
plotOutput("case_hist",height = "466")),
box(title = "Plot2", status = "primary",height = "537" ,solidHeader = T,
plotOutput("trace_hist",height = "466"))
),
conditionalPanel(
condition = "input.Position == 'User_Activity_Analyses'",
box(title = "Plot3",status = "primary",solidHeader = T,height = "537",width = "6",
plotOutput("sankey_plot")),
box(title = "Plot4",status = "primary",solidHeader = T,height = "537",width = "6",
plotOutput("sankey_table"))
)
)
)
)
)
server <- function(input, output)
{
output$case_hist <- renderPlot(
plot(iris$Sepal.Length)
)
output$trace_hist <- renderPlot(
plot(mtcars$mpg)
)
output$sankey_plot <- renderPlot({
plot(diamonds$carat)
})
#Plot for Sankey Data table
output$sankey_table <- renderPlot({
plot(iris$Petal.Length)
})
}
shinyApp(ui, server)

Related

R Shiny / CSS: Relative and absolute positioning of divs

I'm working on a shiny app that requires a lot of interaction with plots. Its quite complex, therefore I'll provide minimal examples that try to abstract the problem and reduce the code you have to copy and paste to a minimum.
One problem that I faced regarding computational efficiency when the plot changes has been solved here.
With this solution however I'm running into a different problem. Before incorporating the solution the app looked like this.
library(shiny)
ui <- fluidPage(
wellPanel(
fluidRow(
column(
width = 12,
fluidRow(
sliderInput(inputId = "slider_input", label = "Reactive values (Number of red points):", min = 1, max = 100, value = 10),
plotOutput(outputId = "plotx")
),
fluidRow(
selectInput(
inputId = "color_input",
label = "Choose color:",
choices = c("red", "blue", "green")
),
sliderInput(
inputId = "size_input",
min = 1,
max = 5,
step = 0.25,
value = 1.5,
label = "Choose size:"
)
)
)
)
)
)
slow_server <- function(input, output, session){
base_data <- reactiveVal(value = data.frame(x = rnorm(n = 200000), y = rnorm(n = 200000)))
output$plotx <- renderPlot({
# slow non reactive layer
plot(x = base_data()$x, y = base_data()$y)
# reactive layer
points(
x = sample(x = -4:4, size = input$slider_input, replace = T),
y = sample(x = -4:4, size = input$slider_input, replace = T),
col = input$color_input,
cex = input$size_input,
pch = 19
)
})
}
shinyApp(ui = ui, server = slow_server)
It differs from the example given in the solved question in so far as that it now features a well panel and some additional inputs below the plot. I had not mentioned this before because I thought it was not important to the problem.
Incorporating the solution the app now looks like this:
library(shiny)
library(ggplot2)
ui <- fluidPage(
wellPanel(
fluidRow(
column(
width = 12,
fluidRow(
sliderInput(inputId = "slider_input", label = "Reactive values (Number of red points):", min = 1, max = 100, value = 10),
div(
class = "large-plot",
plotOutput(outputId = "plot_bg"),
plotOutput(outputId = "plotx")
),
tags$style(
"
.large-plot {
position: relative;
}
#plot_bg {
position: absolute;
}
#plotx {
position: absolute;
}
"
)
),
fluidRow(
selectInput(
inputId = "color_input",
label = "Choose color:",
choices = c("red", "blue", "green")
),
sliderInput(
inputId = "size_input",
min = 1,
max = 5,
step = 0.25,
value = 1.5,
label = "Choose size:"
)
)
)
)
)
)
quick_server <- function(input, output, session){
base_data <- reactiveVal(value = data.frame(x = rnorm(n = 200000), y = rnorm(n = 200000)))
output$plot_bg <- renderPlot({
ggplot(base_data()) +
geom_point(aes(x,y)) +
scale_x_continuous(breaks = -4:4) +
scale_y_continuous(breaks = -4:4) +
xlim(-5, 5) +
ylim(-5, 5)
})
output$plotx <- renderPlot({
data.frame(
x = sample(x = -4:4, size = input$slider_input, replace = T),
y = sample(x = -4:4, size = input$slider_input, replace = T)
) %>%
ggplot() +
geom_point(mapping = aes(x,y), color = input$color_input, size = input$size_input) +
scale_x_continuous(breaks = -4:4) +
scale_y_continuous(breaks = -4:4) +
theme(
panel.background = element_rect(fill = "transparent"),
plot.background = element_rect(fill = "transparent", color = NA),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.background = element_rect(fill = "transparent"),
legend.box.background = element_rect(fill = "transparent")
)+
xlim(-5, 5) +
ylim(-5, 5)
}, bg="transparent")
}
shinyApp(ui = ui, server = quick_server)
The plot has become way quicker. But now the plot inputs are placed on top of it. I assume it is due to the relative positioning in the new CSS class 'large-plot'. I have been fiddling around with shiny::tags$style() and shiny::verticalLayout() but my knowledge of CSS only allows my to understand CSS code not reakky to change it and I'm not making any progress.
How can I keep the relative positioning of the two overlapping plots (like in example 2) and place the additional inputs in the row below the plot (as in example 1)?
Any help is appreciated. If you need more information about the app please tell me and I'll provide it!
Thanks in advance!!
so just add some height to the large-plot class. I didn't know you wanted to add content below. So the absolute position of plots will make container large-plot have no height.
Fix is very easy. Since the plotOutput is fixed height of 400px, you can just add the same height to the container:
.large-plot {
position: relative;
height: 400px;
}

How to put an icon to the title of an input widget in Shiny and Shiny dashboard

Is it possible to add an icon to the title of an input widget in Shiny and Shiny and Shiny dashboard? Below is an example. I want to add an icon to each input widget to indicate if it is a numeric input (using a bar-chart icon) or a text input (using a font icon). For now, I am using two columns. One with width = 1 for the icon, and the other is for the input widget. It would be great if I can add the icon to the title directly. Please let me know if there are ways to achieve this.
library(shiny)
library(shinydashboard)
header <- dashboardHeader(
title = "Icon Example"
)
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem(
text = "Input",
tabName = "Input"
)
)
)
body <- dashboardBody(
tabItem(
tabName = "Input",
fluidRow(
column(
width = 6,
box(
status = "primary", solidHeader = TRUE,
width = 12,
title = "Box 1",
fluidRow(
column(width = 1,
tags$div(HTML('<i class="fa fa-bar-chart" style = "color:#0072B2;"></i>'))
),
column(width = 11,
numericInput(inputId = "Num", label = "This is a numeric input", value = 1000))
),
fluidRow(
column(width = 1,
tags$div(HTML('<i class="fa fa-font" style = "color:#D55E00;"></i>'))
),
column(width = 11,
textInput(inputId = "Text", label = "This is a text input")
)
)
)
)
)
)
)
# User Interface
ui <- dashboardPage(
header = header,
sidebar = sidebar,
body = body
)
# Server logic
server <- function(input, output, session){}
# Complete app with UI and server components
shinyApp(ui, server)
Here is a screenshot of my code example. I would like to have the beginning of the input field aligned with the icon (as indicated by the red arrows). In other words, I hope the icon can be part of the title of the input widget.
Edit:
To increase the readability of the code we can use icon instead of HTML:
numericInput(inputId = "Num", label = div(icon("bar-chart", style = "color:blue;"), " This is a numeric input"), value = 1000)
Initial answer:
Just use your div as the label:
library(shiny)
library(shinydashboard)
header <- dashboardHeader(title = "Icon Example")
sidebar <- dashboardSidebar(sidebarMenu(menuItem(text = "Input", tabName = "Input")))
body <- dashboardBody(tabItem(tabName = "Input",
fluidRow(column(
width = 6,
box(
status = "primary",
solidHeader = TRUE,
width = 12,
title = "Box 1",
fluidRow(column(
width = 11,
numericInput(
inputId = "Num",
label = tags$div(HTML('<i class="fa fa-bar-chart" style = "color:#0072B2;"></i> This is a numeric input')),
value = 1000
)
)),
fluidRow(column(
width = 11,
textInput(
inputId = "Text",
label = tags$div(HTML('<i class="fa fa-font" style = "color:#D55E00;"></i> This is a text input'))
)
))
)
))))
# User Interface
ui <- dashboardPage(header = header,
sidebar = sidebar,
body = body)
# Server logic
server <- function(input, output, session) {}
# Complete app with UI and server components
shinyApp(ui, server)
Result:
You can achieve this by wrapping icon() to span() and tagList(). Check the updated code below:
library(shiny)
library(shinydashboard)
header <- dashboardHeader(
title = "Icon Example"
)
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem(
text = "Input",
tabName = "Input"
)
)
)
body <- dashboardBody(
tabItem(
tabName = "Input",
fluidRow(
column(
width = 6,
box(
status = "primary", solidHeader = TRUE,
width = 12,
title = span(tagList(icon("bar-chart"), "Box 1")),
fluidRow(
column(width = 1,
tags$div(HTML('<i class="fa fa-bar-chart" style = "color:#0072B2;"></i>'))
),
column(width = 11,
numericInput(inputId = "Num", label = "This is a numeric input", value = 1000))
)
),
box(
status = "primary", solidHeader = TRUE,
width = 12,
title = span(tagList(icon("font"), "Box 2")),
fluidRow(
column(width = 1,
tags$div(HTML('<i class="fa fa-font" style = "color:#D55E00;"></i>'))
),
column(width = 11,
textInput(inputId = "Text", label = "This is a text input")
)
)
)
)
)
)
)
# User Interface
ui <- dashboardPage(
header = header,
sidebar = sidebar,
body = body
)
# Server logic
server <- function(input, output, session){}
# Complete app with UI and server components
shinyApp(ui, server)

Unable to place element to inline-block

I have an example, where dateRangeInput and actionButton are added dynamically.
I need elements to be positioned side by side and not in the block.
library(shiny)
library(shinydashboard)
library(shinyjs)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(),
dashboardBody(
useShinyjs(), #Set up shinyjs
tabsetPanel(
tabPanel("Settings",
br(),
fluidRow(
column(width = 8,
box(
title = "Set parameters", id = "RO_05_param_box", width = NULL, solidHeader = TRUE, status ="primary", collapsible = TRUE,
fluidRow(
box(radioButtons("RO_05_param_radio", h6("Company"), choices = list("A" = 1,
"B" = 2), selected = 1), br(),
dateRangeInput("date_range_view", h6("Timeline"), start = "2019-06-30", end = "2020-06-30"), br(),
selectInput("RO_05_param_select", h6("Distribute over time"), choices = list("Stepped line" = 2, "Linear funcion" = 1))
),
box(id= "step_box", dateRangeInput("RO05_date1", h6("Start and end date"), start = "2019-06-30", end = "2020-06-30"),
tags$div(id = 'placeholder_dateRangeInput'),
actionButton("add_lag", "Add dates")
)
)
)
)
)
)
)
)
)
server <- function(input, output) {
observeEvent(input$RO_05_param_select, {
if(input$RO_05_param_select == 2){
show(id = "step_box")
} else {
hide(id = "step_box")
}
})
observeEvent(input$add_lag, {
add <- input$add_lag + 1
addID <- paste0("NO", add)
daterangeID <- paste0('RO05_date', add)
removeID <- paste0('remove_lag', add)
insertUI(
selector = '#placeholder_dateRangeInput',
ui = tags$span(id = addID,
tags$span(dateRangeInput(daterangeID, h6("Near lag and far lag"), start = "2019-06-30", end = "2020-06-30")),
tags$span(actionButton(removeID, label= '', icon("minus")))
)
)
observeEvent(input[[removeID]], {
removeUI(selector = paste0('#', addID))
})
})
}
# Run the application
shinyApp(ui = ui, server = server)
I tried adding this css:
#placeholder_dateRangeInput {
display: inline-block;
}
But all it does it only shrinks dateRangeInput widget.
However, #placeholder_dateRangeInput wraps all added elements, so I think that css should be wrapped around addID.
Here is a way that you can use to make your elements side by side. In css, you tell the element that your want on the left to be
float:left;
and the element that you want on the right to be
float:right;
This should make them side by side.
Here is an example of this being used:
https://www.geeksforgeeks.org/how-to-float-three-div-side-by-side-using-css/

Align image side-by-side in Shiny

I am trying to align the image I calling from the web to be in the center on my shiny app. I am using the html tag here because the image file is not saved in my computer, but I am calling it from the web. fifa_data[fifa_data$Name==input$player_name,]$Photo in my server.R file looks something like this: "https://cdn.sofifa.org/players/4/19/200104.png"
Here is an snapshot of what it looks like now, and the red square is where I want the image to be displayed:
Here is a snippet of my ui.R
ui2<- dashboardPage(
dashboardHeader(title="BIG Player Hunter"),
dashboardSidebar(
fluidRow(
uiOutput(outputId = "image")),
fluidRow(
uiOutput(outputId = "image2")),
fluidRow(
uiOutput(outputId = "image3")),
# uiOutput(outputId = "image2"),
# uiOutput(outputId = "image3")),
selectizeInput('player_name',"Player Name:",
choices=fifa_data$Name,
selected=NULL,
multiple=TRUE),
sliderInput("player_count",
"Number of players:",
min=1,
max=50,
value=5),
sliderInput("proximity",
"How close:",
min=0.01,
max=0.99,
value=0.05),
sliderInput("valuerange", "Price Range", min = 0, max = max(fifa_data$ValueNumeric_pounds),
value = c(25, 75)),
actionButton("search", "Search"),
sidebarMenu(
menuItem("Shoot 소개", tabName = "shoot_info", icon= icon("heart", lib= "glyphicon")),
menuItem("점수순위 및 분석", tabName = "leaderboard", icon= icon("bar-chart-o")),
menuItem("참가신청서", tabName = "signup", icon=icon("pencil", lib= "glyphicon"),
badgeLabel = "관리자", badgeColor = "red")
),
uiOutput("checkbox")
),
dashboardBody(
tabItem(tabName = "shoot_info",
fluidRow(
dataTableOutput("table1"),
chartJSRadarOutput("radarchart1")
)
)
)
)
Here is a sinner of my server.R
output$image<- renderUI({
tags$img(src= fifa_data[fifa_data$Name==input$player_name,]$Photo)
})
output$image2<- renderUI({
tags$img(src= fifa_data[fifa_data$Name==input$player_name,]$Flag)
})
output$image3<- renderUI({
tags$img(src= fifa_data[fifa_data$Name==input$player_name,]$`Club Logo`)
})
Try the below code for your requirement
library(shiny)
library(shinydashboard)
header <- dashboardHeader()
body <- dashboardBody()
sidebar <- dashboardSidebar(uiOutput("images"),
sliderInput("player_count",
"Number of players:",
min = 1,
max = 50,
value = 5),
sliderInput("proximity",
"How close:",
min = 0.01,
max = 0.99,
value = 0.05),
actionButton("search", "Search")
)
ui <- dashboardPage(header, sidebar, body)
server <- function(input, output) {
output$images <- renderUI({
tags$div(img(src = "image1.png", width = 70, height = 90), img(src = "image2.png", width = 70, height = 90), img(src = "image3.png", width = 70, height = 90))
})
}
shinyApp(ui, server)
The screenshot of output

ggplotly & Plotly missing values when I expand window

I am creating a shiny app and using plotly and ggplotly. For some reason when I expand the size of the window, the plot loses some of the data points. Your help is much appreciated.
dashboardBody(
tabItems(
tabItem(
tabName = "calendar",
fluidRow(width = 12,
column(width = 8,
box( width = NULL, height = 400,
title = "Yang Zhang Estimator", solidHeader = T, status = "danger",
plotlyOutput("yang_zhang", height = "320px")
)) ...
server <- function(input, output) {
spy = getSymbols("SPY", from = Sys.Date()-100, to = Sys.Date(), auto.assign =F)
yz_vol = reactive({
volatility(spy, n = as.numeric(input$slider_yz), calc = "yang.zhang", N = 252,
mean0 = F)
})
output$yang_zhang = renderPlotly({
plot_ly(as.data.frame(yz_vol()), x = as.Date(index(yz_vol())), y =
as.numeric(yz_vol()), type = "scatter")
})
}