Related
I've managed to filter a DataTable with two SelectInput in my code. But, when I try to do the same in my boxplot and histogram it doesn't seem to filter. Is there, by any chance, someone to help me with this? I'm new to shiny.
My code is something like this:
afastamentos <- readr::read_csv("base_afastamentos.csv", locale = locale(encoding = "latin1"))
colnames(afastamentos) <- c(
"Descrição do Cargo", "Nome do Órgão de Origem", "UF", "Cidade da Residência",
"Nível da Escolaridade", "Início do Afastamento", "Ano/Mês Referência",
"Valor do Rendimento Líquido", "Descrição do Afastamento", "Ano Início Afastamento",
"Mês Início Afastamento", "Rendimento Líquido Hora")
ui <- dashboardPage(
dashboardHeader(title = "COBRADI",
titleWidth = 500,
tags$li(class = "dropdown",
tags$a(href = "https://www.ipea.gov.br/portal/index.php?option=com_content&view=article&id=39285&Itemid=343",
icon("globe", lib = "glyphicon"),
"Site COBRADI",
target = "_blank"))
),
dashboardSidebar(
sidebarMenu(
id = "sidebar",
menuItem("Dataset",
tabName = "data",
icon = icon("database")),
menuItem("Visualização",
tabName = "viz",
icon = icon("chart-line")),
menuItem("Informações",
tabName = "info",
icon = icon("info-circle"))
)
),dashboardBody(
tabItems(
tabItem(tabName = "viz",
tabBox(id = "t2", width = 12,
tabPanel(title = "Distribuição Amostral",
icon = icon("fas fa-chart-area"),
value = "trends",
fluidRow(
column(width = 12,
box(title = "Filtros", width = "100%",
column(width = 6,
box(width = "100%",
selectizeInput(inputId = "select_UF",
label = "Estados:",
choices = c("TODOS", unique(afastamentos$UF)),
multiple = T,
selected = "TODOS"))
),
column(width = 6,
box(width = "100%",
selectizeInput(inputId = "descricao_2",
label = "Descrição do Afastamento:",
choices = c("TODOS", unique(afastamentos$`Descrição do Afastamento`)),
multiple = T, options = list(maxItems = 5),
selected = "TODOS"))),
)
)
),
fluidRow(
column(width = 12,
box(title = "BoxPlot - Valor do Rendimento Bruto Mensal",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
width = "100%",
plotlyOutput("boxplot"))
),
column(width = 12,
box(title = "Histograma - Valor do Rendimento Bruto Mensal",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
width = "100%",
plotlyOutput("histplot")))
)
)
)
)
)
)
)
And the server is:
server <- function(input, output, session){
meus_dados <- reactive({
## filtro UF
print(input)
if (! "TODOS" %in% input$select_UF){
a <- a |>
filter(`UF` %in% input$select_UF)
}
#Filtro Descricao
if(! "TODOS" %in% input$descricao_2){
a <- a |>
filter(`Descrição do Afastamento` %in% input$descricao_2)
return(a)
}
})
output$boxplot <- renderPlotly({
boxplot <- meus_dados()|>
plot_ly() |>
add_boxplot(~`Valor do Rendimento Líquido`) |>
layout(xaxis = list(title = "Valor do Rendimento Bruto"))
})
output$histplot <- renderPlotly({
hist <- meus_dados() |>
plot_ly() |>
add_histogram(~`Rendimento Líquido Hora`) |>
layout(xaxis = list(title = "Valor da Hora Técnica"))})
}
And I get the following error: First argument data must be a data frame or shared data.
Data is available here: https://www.dropbox.com/s/kjilkkskggi27vo/base_afastamentos.csv?dl=0
Your reactive object was the problem. This works fine for me using the original names.
ui <- dashboardPage(
dashboardHeader(title = "COBRADI",
titleWidth = 500,
tags$li(class = "dropdown",
tags$a(href = "https://www.ipea.gov.br/portal/index.php?option=com_content&view=article&id=39285&Itemid=343",
icon("globe", lib = "glyphicon"),
"Site COBRADI",
target = "_blank"))
),
dashboardSidebar(
sidebarMenu(
id = "sidebar",
menuItem("Dataset",
tabName = "data",
icon = icon("database")),
menuItem("Visualização",
tabName = "viz",
icon = icon("chart-line")),
menuItem("Informações",
tabName = "info",
icon = icon("info-circle"))
)
),dashboardBody(
tabItems(
tabItem(tabName = "viz",
tabBox(id = "t2", width = 12,
tabPanel(title = "Distribuição Amostral",
icon = icon("fas fa-chart-area"),
value = "trends",
fluidRow(
column(width = 12,
box(title = "Filtros", width = "100%",
column(width = 6,
box(width = "100%",
selectizeInput(inputId = "select_UF",
label = "Estados:",
choices = c("TODOS", unique(afastamentos$UF_da_UPAG_de_vinculacao)),
multiple = T,
selected = "TODOS"))
),
column(width = 6,
box(width = "100%",
selectizeInput(inputId = "descricao_2",
label = "Descrição do Afastamento:",
choices = c("TODOS", unique(afastamentos$Descricao_do_afastamento)),
multiple = T, options = list(maxItems = 5),
selected = "TODOS"))),
)
)
),
fluidRow(
column(width = 12,
box(title = "BoxPlot - Valor do Rendimento Bruto Mensal",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
width = "100%",
plotlyOutput("boxplot"))
),
column(width = 12,
box(title = "Histograma - Valor do Rendimento Bruto Mensal",
status = "primary",
solidHeader = TRUE,
collapsible = TRUE,
width = "100%",
plotlyOutput("histplot")))
)
)
)
)
)
)
)
server <- function(input, output, session){
meus_dados <- reactive({
## filtro UF
print(input)
a <- afastamentos
if (! "TODOS" %in% input$select_UF){
a <- a |>
filter(UF_da_UPAG_de_vinculacao %in% input$select_UF)
}
#Filtro Descricao
if(! "TODOS" %in% input$descricao_2){
a <- a |>
filter(Descricao_do_afastamento %in% input$descricao_2)
}
return(a)
})
output$boxplot <- renderPlotly({
boxplot <- meus_dados()|>
plot_ly() |>
add_boxplot(~Valor_rendimento_liquido) |>
layout(xaxis = list(title = "Valor do Rendimento Bruto"))
})
output$histplot <- renderPlotly({
hist <- meus_dados() |>
plot_ly() |>
add_histogram(~Rendimento_Liquido_Hora) |>
layout(xaxis = list(title = "Valor da Hora Técnica"))})
}
shinyApp(ui = ui, server = server)
I am hoping for some help. I am the newest of the newbees and attempting to make this code work utilizing ShinyApp. Upon running my codes, I am receiving the error message of:
Warning: Error in $<-.data.frame: replacement has 0 rows, data has 1352
Is there anything that appears incorrect with my code that stands out? or any suggestions on next tries?
ui.R Code
library(shiny)
library(plotly)
library(DT)
mobility <- read.csv("mobility_data.csv", sep = ',')
mobility$Date <- as.Date(mobility$Date, format="%m/%d/%Y")
mobility$Province <- as.factor(mobility$Province)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
h2("COVID-19 Mobility Data"),
selectInput(inputId = "dv", label = "Category",
choices = c("Retail_Recreation", "Grocery_Pharmarcy", "Parks", "Transit_Stations", "Workplaces", "Residential"),
selected = "Grocery_Pharmarcy"),
selectInput(inputId = "provinces", "Province(s)",
choices = levels(mobility$Province),
multiple = TRUE,
selected = c("Utrecht", "Friesland", "Zeeland")),
dateRangeInput(inputId = "date", label = "Date range",
start = min(mobility$Date),
end = max(mobility$Date)),
downloadButton(outputId = "download_data", label = "Download"),
),
mainPanel(
plotlyOutput(outputId = "plot"),
em("Postive and negative percentages indicate an increase and decrease from the baseline period (median value between January 3 and February 6, 2020) respectively."),
DT::dataTableOutput(outputId = "table")
)
)
)
server.R code
server <- function(input, output) {
filtered_data <- reactive({
subset(mobility,
Province %in% input$provinces &
Date >= input$date[1] & Date <= input$date[2])})
output$plot <- renderPlotly({
ggplotly({
p <- ggplot(filtered_data(), aes_string(x = "Date", y = input$dv, color = "Province")) +
geom_point(alpha = 0.5) + theme(legend.position = "none") + ylab("% change from baseline")
p
})
})
output$table <- DT::renderDataTable({
filtered_data()
})
output$download_data <- downloadHandler(
filename = "Mobility_Data.csv",
content = function(file) {
data <- filtered_data()
write.csv(data, file, row.names = FALSE)
}
)
}
Here is the first seven rows from of sample data from my dataset entitled "mobility_data" as well:
structure(list(Country = c("Netherlands", "Netherlands", "Netherlands",
"Netherlands", "Netherlands", "Netherlands", "Netherlands"),
Province = c("Flevoland", "Flevoland", "Flevoland", "Flevoland",
"Flevoland", "Flevoland", "Flevoland"), Date = c("2/15/2020",
"2/16/2020", "2/17/2020", "2/18/2020", "2/19/2020", "2/20/2020",
"2/21/2020"), Retail_Recreation = c(-2L, -17L, 0L, 6L, 2L,
-2L, 4L), Grocery_Pharmarcy = c(-3L, -13L, -6L, -2L, -7L,
-5L, -1L), Parks = c(4L, -30L, 3L, 30L, 27L, 3L, 21L), Transit_Stations = c(5L,
-9L, -14L, -13L, -15L, -16L, -11L), Workplaces = c(-1L, -7L,
-19L, -18L, -18L, -20L, -21L), Residential = c(0L, 1L, 3L,
3L, 2L, 3L, 2L)), row.names = c(NA, 7L), class = "data.frame")
You can read the csv file using fileInput. Try this
library(shiny)
library(plotly)
library(DT)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
h2("COVID-19 Mobility Data"),
fileInput("file1", "Choose CSV file to upload", accept = ".csv"),
selectInput(inputId = "dv", label = "Category",
choices = c("Retail_Recreation", "Grocery_Pharmarcy", "Parks", "Transit_Stations", "Workplaces", "Residential"),
selected = "Grocery_Pharmarcy"),
selectInput(inputId = "provinces", "Province(s)",
choices = levels(mobility$Province),
multiple = TRUE,
selected = c("Utrecht", "Friesland", "Zeeland")),
dateRangeInput(inputId = "date", label = "Date range",
start = min(mobility$Date),
end = max(mobility$Date)),
downloadButton(outputId = "download_data", label = "Download"),
),
mainPanel(
plotlyOutput(outputId = "plot"),
em("Postive and negative percentages indicate an increase and decrease from the baseline period (median value between January 3 and February 6, 2020) respectively."),
DT::dataTableOutput(outputId = "table")
)
)
)
server <- function(input, output) {
mobility <- reactive({
infile <- input$file1
req(infile)
return(read.csv(infile$datapath, header=TRUE, sep=','))
})
filtered_data <- reactive({
subset(mobility(),
Province %in% input$provinces &
Date >= input$date[1] & Date <= input$date[2])})
output$plot <- renderPlotly({
ggplotly({
p <- ggplot(filtered_data(), aes_string(x = "Date", y = input$dv, color = "Province")) +
geom_point(alpha = 0.5) + theme(legend.position = "none") + ylab("% change from baseline")
p
})
})
output$table <- DT::renderDataTable({
filtered_data()
})
output$download_data <- downloadHandler(
filename = "Mobility_Data.csv",
content = function(file) {
data <- filtered_data()
write.csv(data, file, row.names = FALSE)
}
)
}
shinyApp(ui, server)
I want to fetch user choice from selectInput and store it as a string to be use as filename to save a plot. If user change selectInput choice, the string variable should also update to reflect change.
Here are my code so far and the xxx variable obviously is not a string. Can anyone assist?
pacman::p_load(dplyr, tidyverse, reshape, ggplot2, shiny, shinydashboard)
mtcars_colName <- colnames(mtcars)
x_coord <- mtcars_colName[c(1:2)]
y_coord <- mtcars_colName[c(3:7)]
#Put plots on shiny ui
ui <- dashboardPage(
dashboardHeader(title = 'mtcars data'),
dashboardSidebar(
sidebarMenu(
menuItem("mtcars data comparison", tabName = 'mtcars_data_comparison', icon = icon('dragon'))
)
),
dashboardBody(
tabItems(
tabItem('mtcars_data_comparison',
fluidPage(
downloadButton("downloadPlot", "Download mtcars plot"),
box(plotOutput('metrics_plot'), width = 8, height = '100%'),
box(selectInput('y_metrics', 'mtcars y-axis', choices = y_coord), width = 4),
box(selectInput('x_metrics', 'mtcars x-axis', choices = x_coord), width = 4)
),
)
)
)
)
server <- function(input, output, session){
mtcars_plot <- reactive({ggplot(mtcars, aes_string(x=input$x_metrics, y=input$y_metrics)) +
geom_jitter(width =0.05) +
scale_y_continuous(labels = scales::comma) +
theme(
axis.text.x = element_blank(),
axis.line = element_line(),
axis.ticks.x = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank())
})
output$metrics_plot <- renderPlot({
mtcars_plot()
})
rv <- reactiveValues(value_store = character())
observeEvent(input$y_metrics, {
rv$value_store <- input$y_metrics
})
output$download10XPlot <- downloadHandler(
file = paste(rv$value_store, '.pdf', sep=''),
content = function(file) {
sep <- switch(input$filetype, "csv" = ",", "tsv" = "\t")
# pdf(file = file, width = 11, height = 8.5)
pdf(file, sep = sep)
print(TenX_plot())
dev.off()}
)
}
shinyApp(ui, server)
We can try
output$download10XPlot <- downloadHandler(
file = function() {paste(isolate(input$y_seq_metrics), '.pdf', sep='')},
content = function(file) {
pdf(file = file, width = 11, height = 8.5)
print(TenX_plot())
dev.off()}
)
I've been trying for hours on end to get this working however it does not work. I simply wish to render the charts in this dashboard for the different tabs. I have tried enclosing it with box(), using renderHighchart2 and highchartOutput2. The chart renders outside shiny just fine, what is wrong?
Edit: The charts I am referring to are the highcharts, not the valueboxes! Furthermore, the app does show the correct titles for each graph and fluidRow however fails to plot the highcharts
This is the code:
library(shiny)
library(shinydashboard)
library(highcharter)
library(tidyverse)
ui <- dashboardPage(
skin = "purple",
dashboardHeader(title = h4(HTML("Generic company name<br/>Something to analyze")),
titleWidth = 275),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard",icon = icon("dashboard"),
menuSubItem('Samenvatting', tabName = "samenvatting", icon = icon('atlas')),
menuSubItem('Statusverloop', tabName = "statusverloop", icon = icon('battery-three-quarters')),
menuSubItem('Tijdsverloop', tabName = "tijdsverloop", icon = icon("hourglass-end")),
menuSubItem('Affiliates', tabName = "affiliates", icon = icon("handshake")),
menuSubItem('Klanten informatie', tabName = "klanteninformatie", icon = icon("address-card"))
),
menuItem("Kijkglas",tabname = "kijkglas",icon = icon("search"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = 'samenvatting',
#contents
fluidRow(
valueBoxOutput("YTDnieuweA"),
valueBoxOutput("YTDomvangA")
),
fluidRow(
valueBoxOutput("YTDnieuweP") ,
valueBoxOutput("YTDomvangP")
),
fluidRow(
column( width = 6,h4("Wekelijkse statistieken", align = 'center'), highchartOutput('a') ),
column( width = 6,h4("Wekelijkse totale statistieken", align = 'center'), highchartOutput('b'))
)
),
tabItem(tabName = "statusverloop"
#Empty TODO:
),
tabItem(tabName = "tijdsverloop"
#EMPTY: TODO
),
tabItem(tabName = "affiliates",
fluidRow(
column( width = 6,h4("Affiliates over aanmeldingen", align = 'center'), highchartOutput('a') ),
column( width = 6,h4("Affiliates over passen", align = 'center'), highchartOutput('b'))
)
),
tabItem(tabName = "klanteninformatie",
fluidRow(
column( width = 4,h4("Wekelijkse statistieken", align = 'center'), highchartOutput('a') ),
column( width = 4,h4("Wekelijkse totale statistieken", align = 'center'), highchartOutput('b')),
column( width = 4,h4("Wekelijkse totale statistieken", align = 'center'), highchartOutput('a'))
)
)
)
)
)
server <- function(input, output) {
output$a <- renderHighchart2({
hc <- highcharts_demo() %>%
hc_rm_series("Berlin") %>%
hc_chart(type = 'line')
theme <- sandsignika = hc_theme_sandsignika()
hc <- hc %>% hc_add_theme(theme)
}
hc
})
output$b <- renderHighchart2({
hc <- highcharts_demo() %>%
hc_rm_series("Berlin") %>%
hc_chart(type = 'line')
theme <- hc_theme_economist()
hc <- hc %>% hc_add_theme(theme)
}
hc
})
}
shinyApp(ui,server)
In shiny, you can't refer to any output more than once in the UI.
Try storing the chart in an object (could use either a reactiveValues or reactive() to store it), then assigning that object into separate outputs.
I am creating a Shinyapp in line of below template :
library(shinydashboard)
sidebar <- dashboardSidebar(
sidebarMenu(id="tabs",
menuItem("Tab1", tabName="Tab1", selected=TRUE),
menuItem("Tab2", tabName = "Tab2")
),
conditionalPanel("input.tabs=='Tab1'",
fluidRow()
),
conditionalPanel("input.tabs=='Tab2'",
fluidRow()
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "Tab1",
fluidRow( sliderInput("aa", "aa", value = 0.9, min = 0, max = 2, step=0.1))
),
tabItem(tabName = "Tab2",
fluidRow(navbarPage(id = 'ab', title = "",
tabPanel(title = "aa1", value = 'aa1', fluidRow()),
tabPanel(title = "aa2", value = 'aa2', fluidRow())))
)))
ui = dashboardPage(
dashboardHeader(title = "My tab"),
sidebar,
body
)
server = function(input, output) {}
shinyApp(ui = ui, server = server)
Now what I want basically, a sliderInput should appear in the Side panel only when TabPanel = 'aa2' from tabItem = 'Tab2'. Therefore user should not see that sliderInput if TabPanel = 'aa1' is selected.
So far I have tried something like below :
sidebar <- dashboardSidebar(
sidebarMenu(id="tabs",
menuItem("Tab1", tabName="Tab1", selected=TRUE),
menuItem("Tab2", tabName = "Tab2")
),
conditionalPanel("input.tabs=='Tab1'",
fluidRow()
),
conditionalPanel("input.tabs=='Tab2'",
fluidRow(sliderInput("aa5", "aa", value = 0.9, min = 0, max = 2, step=0.1))
)
)
However with this the sliderInput is visible for both tabPanel = "aa1" & tabPanel = "aa2", which I do not want.
Any suggestion, how can I make sliderInput is visible only for tabPanel = "aa2".
Thanks for your pointer.
#SBista thanks for pointer. Below is updated code. Thanks,
library(shinydashboard)
library(shinyjs)
sidebar <- dashboardSidebar(
sidebarMenu(id="tabs",
menuItem("Tab1", tabName="Tab1", selected=TRUE),
menuItem("Tab2", tabName = "Tab2")
),
conditionalPanel("input.tabs=='Tab1'",
fluidRow()
),
conditionalPanel("input.tabs=='Tab2'",
fluidRow(useShinyjs(),
column(12, sliderInput("aa4", "aa", value = 0.9, min = 0, max = 2, step=0.1)))
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "Tab1",
fluidRow( sliderInput("aa", "aa", value = 0.9, min = 0, max = 2, step=0.1))
),
tabItem(tabName = "Tab2",
fluidRow(navbarPage(id = 'ab', title = "",
tabPanel(title = "aa1", value = 'aa1', fluidRow()),
tabPanel(title = "aa2", value = 'aa2', fluidRow())))
)))
ui = dashboardPage(
dashboardHeader(title = "My tab"),
sidebar,
body
)
server = function(input, output) {
observe(toggle(id = "aa4", condition = ifelse(input$ab == 'aa2', TRUE, FALSE)))
}
shinyApp(ui = ui, server = server)