download bottom after filter dataset - r

I am trying to download my file after filtering my data. when i run the below code the result is the only empty file is downloaded (not the filtered data).
Please note that this is multiple shiny app not a single one.
the first part is the UI and second part is the server.
please see the code below:
library(shiny)
#library(DT)
library(dplyr)
library(ggplot2)
#UI
fluidPage(
titlePanel("IN_PATIENT"),
# Create a new Row in the UI for selectInputs
fluidRow(
column(2,selectInput("HOSPITAL_NAME",
"Hospital Name:",
c("All",
unique(as.character(IN_PATIENT$HOSPITAL_NAME))))
),
column(2,selectInput("FINAL_GENDER",
"Gender:",
c("All",
unique(as.character(IN_PATIENT$FINAL_GENDER))))
),
column(2,selectInput("FINAL_NATIONALITY_STATUS",
"Nationality Status:",
c("All",
unique(as.character(IN_PATIENT$FINAL_NATIONALITY_STATUS))))
)
),
# Button
downloadButton("downloadData", "Download"),
DT::dataTableOutput("table")
)
#Server
function(input, output,session) {
# Filter data based on selections
output$table <- DT::renderDataTable(DT::datatable({
df <- IN_PATIENT
if (input$HOSPITAL_NAME != "All") {
df <- df[df$HOSPITAL_NAME == input$HOSPITAL_NAME,]
}
if (input$FINAL_GENDER != "All") {
df <- df[df$FINAL_GENDER == input$FINAL_GENDER,]
}
if (input$FINAL_NATIONALITY_STATUS != "All") {
df <- df[df$FINAL_NATIONALITY_STATUS == input$FINAL_NATIONALITY_STATUS,]
}
df
}))
output$downloadData <- downloadHandler(
filename = function() {
paste("df-",Sys.Date(), ".csv", sep = "")
},
content = function(file) {
write.csv(df, file, row.names = FALSE)
}
)
}

Since you don't provide sample data, I made test data with mtcars. The best solution in Shiny is to make your data as a reactive object that is passed to renderDT and downloadHandler:
library(shiny)
library(DT)
library(dplyr)
library(ggplot2)
IN_PATIENT <- mtcars %>% tibble::rownames_to_column() %>% rename(HOSPITAL_NAME = rowname,
FINAL_GENDER = vs,
FINAL_NATIONALITY_STATUS = carb)
ui <- fluidPage(
titlePanel("IN_PATIENT"),
# Create a new Row in the UI for selectInputs
fluidRow(
column(2,selectInput("HOSPITAL_NAME",
"Hospital Name:",
c("All",
unique(as.character(IN_PATIENT$HOSPITAL_NAME))))
),
column(2,selectInput("FINAL_GENDER",
"Gender:",
c("All",
unique(as.character(IN_PATIENT$FINAL_GENDER))))
),
column(2,selectInput("FINAL_NATIONALITY_STATUS",
"Nationality Status:",
c("All",
unique(as.character(IN_PATIENT$FINAL_NATIONALITY_STATUS))))
)
),
# Button
downloadButton("downloadData", "Download"),
DT::DTOutput("table")
)
#Server
server <- function(input, output,session) {
df <- reactive({
df <- IN_PATIENT
if (input$HOSPITAL_NAME != "All") {
df <- df[df$HOSPITAL_NAME == input$HOSPITAL_NAME,]
}
if (input$FINAL_GENDER != "All") {
df <- df[df$FINAL_GENDER == input$FINAL_GENDER,]
}
if (input$FINAL_NATIONALITY_STATUS != "All") {
df <- df[df$FINAL_NATIONALITY_STATUS == input$FINAL_NATIONALITY_STATUS,]
}
df
})
# Filter data based on selections
output$table <- DT::renderDT(datatable(df()))
output$downloadData <- downloadHandler(
filename = function() {
paste("df-",Sys.Date(), ".csv", sep = "")
},
content = function(file) {
write.csv(df(), file, row.names = FALSE)
})
}
shinyApp(ui, server)

Related

How to have shiny app that allows users to identify the key column and then filter based off columns and rows inputs?

I have the following shiny app that almost does what I want. My goal is to have a user be able to upload a csv file into my app and have it output as a table. I would also want my users to be able to have the following few inputs.
Select the columns needed from the data frame.
Of the selected columns, allow the user to identify the primary key
From the primary key allow the user to filter what rows they need.
Right now I am stuck on number 3 and can't get the the table to filter the rows.
Here is the code
library(shiny)
library(tidyverse)
library(readxl)
library(shinyWidgets)
library(data.table)
means_out <- mtcars
setDT(means_out, keep.rownames = TRUE[])
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
#Staff would need to specify the rows and columns from the extract to be included in the table.
uiOutput("colControls"),
div(style="text-align:left","Select Columns:"),
textOutput("selectedTextc"),
#ROWKEY
uiOutput("keyControls"),
#ROWS
uiOutput("rowControls"),
div(style="text-align:left","Select Rows:"),
textOutput("selectedTextr")
)
,
mainPanel(
tableOutput("tbl")
)
)
)
server <- function(input, output) {
#FILE SECTION
get_file_or_default <- reactive({
if (is.null(input$file1)) {
means_out
} else {
read.csv(input$file1$datapath)
}
})
#COLUMNS
output$colControls <- renderUI({
pickerInput(inputId="cols", "Choose Columns", choices= get_file_or_default() %>% colnames(),
multiple = TRUE)
})
txtc <- reactive({ input$cols })
output$selectedTextc <- renderText({paste0(txtc() ,sep=", ") })
#ROW KEY
output$keyControls <- renderUI({
selectInput(inputId="key", "Identify the Key Column", choices= get_file_or_default() %>% colnames(),
multiple = FALSE)
})
txtkey <- reactive({ input$key })
#SELECT ROWS NEEDED
output$rowControls <- renderUI({
pickerInput(inputId="rows", "Choose Rows", choices= get_file_or_default() %>% select(txtkey()),
multiple = TRUE)
})
txtr <- reactive({ input$rows })
output$selectedTextr <- renderText({paste0(txtr() ,sep=", ") })
output$tbl <- renderTable({
if (is.null(input$cols) & is.null(input$rows)) {
get_file_or_default()
} else {
get_file_or_default() %>% select({paste0(txtc()) }) #%>% filter(input$key %in% c(input$rows))
}
})
}
shinyApp(ui, server)
As the key variable may not be unique for all rows, you need to identify the selected rows. It is easier to do that in DT by using the input$tbl_rows_selected feature. Select the rows in the displayed table at the top, and selected rows are shown at the bottom in a separate table. Try this
library(shiny)
library(tidyverse)
library(readxl)
library(shinyWidgets)
library(data.table)
library(DT)
means_out <- mtcars
setDT(means_out, keep.rownames = TRUE[])
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
),
#Staff would need to specify the rows and columns from the extract to be included in the table.
uiOutput("colControls"),
div(style="text-align:left","Select Columns:"),
textOutput("selectedTextc"),
#ROWKEY
uiOutput("keyControls"),
#ROWS
#uiOutput("rowControls"),
div(style="text-align:left","Select Rows:"),
textOutput("selectedTextr")
)
,
mainPanel(
DTOutput("tbl"), DTOutput("selectedtable")
)
)
)
server <- function(input, output) {
#FILE SECTION
get_file_or_default <- reactive({
if (is.null(input$file1)) {
means_out
} else {
read.csv(input$file1$datapath)
}
})
get_file_or_defaultt <- reactive({
req(get_file_or_default())
get_file_or_default() %>% mutate(row_num = row_number())
})
#COLUMNS
output$colControls <- renderUI({
req(get_file_or_default())
pickerInput(inputId="cols", "Choose Columns", choices= get_file_or_default() %>% colnames(),
multiple = TRUE)
})
txtc <- reactive({ input$cols })
output$selectedTextc <- renderText({paste0(txtc() ,sep=", ") })
#ROW KEY
output$keyControls <- renderUI({
req(get_file_or_default())
if (is.null(input$cols)) df <- get_file_or_default()
else df <- get_file_or_default() %>% dplyr::select(all_of(input$cols))
selectInput(inputId="key", "Identify the Key Column", choices = df %>% colnames() ,
multiple = FALSE)
})
txtkey <- reactive({ input$key })
#SELECT ROWS NEEDED
output$rowControls <- renderUI({
pickerInput(inputId="rows", "Choose Rows", choices= get_file_or_default() %>% select(txtkey()),
multiple = TRUE)
})
output$tbl <- renderDT({
if (is.null(input$cols)) {
get_file_or_default()
} else {
get_file_or_default() %>% select({paste0(txtc()) })
}
}, rownames = FALSE)
selectedRows <- eventReactive(input$tbl_rows_selected,{
if (is.null(input$cols)) df <- get_file_or_default()
else df <- get_file_or_default() %>% dplyr::select(all_of(input$cols))
df[c(input$tbl_rows_selected),]
})
output$selectedtable <- renderDT({
selectedRows()
}, rownames = FALSE)
selectedRow <- eventReactive(input$tbl_rows_selected,{
row.names(get_file_or_default())[c(input$tbl_rows_selected)]
})
output$selectedTextr <- renderText({paste0(selectedRow()) })
}
shinyApp(ui, server)

R Shiny: Set default value for reactive filter

I set up a filter by year using year_filter and would like the default view to be 2021. How to do I this given the code below? Currently, the default display is to show all data entries for all years.
The complete code and file can be found here for reference: https://drive.google.com/drive/folders/1C7SWkl8zyGXLGEQIiBEg4UsNQ5GDaKoa?usp=sharing
Thank you for your assistance!
# Define UI for application
ui <- fluidPage(
tags$div(
style = "padding: 10px;",
# Application title
titlePanel("Testing and Quarantine Measures"),
fluidRow(
uiOutput("CountryFilter_ui"),
uiOutput("YearFilter_ui")
),
fluidRow(
tags$div(style = "width: 100%; overflow: scroll; font-size:80%;",
DT::dataTableOutput('travel_table')
)
)
)
)
server <- function(input, output) {
# Render UI
output$CountryFilter_ui <- renderUI({
countries <- travel_clean %>%
pull(country_area)
selectInput('country_filter', 'Member State Filter', choices = countries, multiple = TRUE)
})
output$YearFilter_ui <- renderUI({
year <- travel_clean %>%
pull(year)
selectInput('year_filter', 'Year Filter', choices = year, multiple = TRUE)
})
# Filter data
travel_filtered <- reactive({
tmp_travel <- travel_measures %>%
select(-Sources)
if(is.null(input$country_filter) == FALSE) {
tmp_travel <- tmp_travel %>%
filter(`Country/area` %in% input$country_filter)
}
return(tmp_travel)
})
travel_filtered <- reactive({
tmp_travel <- travel_measures %>%
select(-Sources)
if(is.null(input$year_filter) == FALSE) {
tmp_travel <- tmp_travel %>%
filter(`Year` %in% input$year_filter)
}
return(tmp_travel)
})

use rhandsontable package to edit multiple data frame on shiny

I am new to the shiny, I would like to edit different multiple data frames by radio button or selectinput by using rhandsontable package. However, my script can not show other data frame but only the first one, I don't know what is the problem.
ui.R:
library(rhandsontable)
fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("select2", label = h3("Choose to edit"),
choices = list("003.csv", "004.csv", "005.csv",
"006.csv", "007.csv"),
selected = "003.csv"),
actionButton("saveBtn", "Save changes")
),
mainPanel(
rHandsontableOutput("hot")
)))
server.R
values <- reactiveValues()
setHot <- function(x) values[["hot"]] <<- x
function(input, output, session) {
fname <- reactive({
x <- input$select2
return(x)
})
observe({
input$saveBtn # update csv file each time the button is pressed
if (!is.null(values[["hot"]])) {
write.csv(x = values[["hot"]], file = fname(), row.names = FALSE)
}
})
output$hot <- renderRHandsontable({
if (!is.null(input$hot)) { # if there is an rhot user input...
DF <- hot_to_r(input$hot) # convert rhandsontable data to R object
and store in data frame
setHot(DF) # set the rhandsontable values
} else {
DF <- read.csv(fname(), stringsAsFactors = FALSE) # else pull table from the csv (default)
setHot(DF) # set the rhandsontable values
}
rhandsontable(DF) %>% # actual rhandsontable object
hot_table(highlightCol = TRUE, highlightRow = TRUE, readOnly = TRUE) %>%
hot_col("Status", readOnly = FALSE)
})}
I can edit and save the dataframe that it shows the first one 003.csv, however when i use the drop down list to 004.csv, it didn't show the dataframe. please advise.
This will write (and possibly overwrite ⚠ any existing file with) dummy data:
for (i in c("003.csv", "004.csv", "005.csv", "006.csv", "007.csv")) {
write.csv(cbind(V1 = rep(i, 3), Status = "foo"), i, row.names = FALSE)
}
I overhauled server a bit:
library(shiny)
library(rhandsontable)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput(
"select2", label = h3("Choose to edit"), selected = "003.csv",
choices = list("003.csv", "004.csv", "005.csv", "006.csv", "007.csv")
),
actionButton("saveBtn", "Save changes")
),
mainPanel(
rHandsontableOutput("hot")
)
)
)
server <- function(input, output, session) {
DF <- reactiveVal()
observe({
DF(read.csv(input$select2, stringsAsFactors = FALSE))
})
observe({
if (!is.null(input$hot)) DF(hot_to_r(input$hot))
})
observeEvent(input$saveBtn, {
if (!is.null(DF())) write.csv(DF(), input$select2, row.names = FALSE)
})
output$hot <- renderRHandsontable({
rhandsontable(DF()) %>%
hot_table(highlightCol = TRUE, highlightRow = TRUE, readOnly = TRUE) %>%
hot_col("Status", readOnly = FALSE)
})
}
shinyApp(ui, server)

Using a selected row to subset another table in r shiny

I am new to using DT in R shiny.Basically what i am trying to do here is to use the select value from the first table to filter the second table.
my Ui.r is
library(shiny)
library(shinydashboard)
ui <- dashboardPage(skin="green",
dashboardHeader(title="Inventory Management"),
dashboardSidebar(disable = TRUE),
dashboardBody(fluidRow(column(4,box(status="success",
uiOutput("Firstselection"),
br(),
uiOutput("Secondselection"))
),
column(4,infoBoxOutput("salesbox")),
column(4,infoBoxOutput("Runoutbox")),
column(4,infoBoxOutput("Excessbox"))),
actionButton("actionbtn","Run"),
fluidRow(tabBox(tabPanel(
DT::dataTableOutput(outputId="table"),title = "Stock Available for the category chosen",width = 12),
tabPanel(DT::dataTableOutput(outputId="asso"),title = "Associated products",width = 12)))
))
and my server is
server <-function(input, output, session) {
observeEvent(input$actionbtn, {source('global.r',local = TRUE)
#choose sub category based on category
output$Firstselection<-renderUI({selectInput("ray",
"Category:",
c("All",unique(as.character(bestpred$lib_ray))))})
output$Secondselection<-renderUI({selectInput("sray",
"Sub Category:",
c("All",unique(as.character(bestpred[bestpred$lib_ray==input$ray,"lib_sray"]))))})
# Filter data based on selections
output$table <- DT::renderDataTable({
data <- bestpred
if (input$ray != "All"){
data <- data[data$lib_ray == input$ray,]
}
if (input$sray != "All"){
data <- data[data$lib_sray == input$sray,]
}
data
},filter="top"
)
output$salesbox<-renderInfoBox({infoBox("Total Sales",sum(data()$Total_Sales),icon = icon("line-chart"))})
output$Runoutbox<-renderInfoBox({infoBox("Total Runout",sum(data()$status=="Runout"),icon = icon("battery-quarter"))})
output$Excessbox<-renderInfoBox({infoBox("Total excess",sum(data()$status=="Excess"),icon = icon("exclamation-triangle"))})
output$asso <- DT::renderDataTable({
asso <- test1
s=data[input$tablatable_rows_selected,1]
asso <- asso[asso$num_art == s,]
asso
},filter="top")
})}
So when i select a row in the output table i wanna use that as an filter for my asso table
this code dosent poup any error but the output table asso is always empty
Find a generalized solution in the following:
Adapted from here: https://yihui.shinyapps.io/DT-rows/
library(shiny)
library(DT)
server <- shinyServer(function(input, output, session) {
output$x1 = DT::renderDataTable(cars, server = FALSE)
output$x2 = DT::renderDataTable({
sel <- input$x1_rows_selected
if(length(cars)){
cars[sel, ]
}
}, server = FALSE)
})
ui <- fluidPage(
fluidRow(
column(6, DT::dataTableOutput('x1')),
column(6, DT::dataTableOutput('x2'))
)
)
shinyApp(ui, server)

Shiny Data table display all data using filter

I can create a data table in shiny that shows data for any individual buffalo but I can't figure out how to display all buffalo data at the same time. Any help is appreciated.
Sample Data:
cleanbuffalo <- data.frame(name = c("queen","toni","pepper"),
longitude = c(31.8,32,33),
latitude = c(-24,-25,-26))
Shiny UI:
shinyUI(navbarPage("Buffalo Migration", id ="nav",
tabPanel("Data",
fluidRow(
column(3,
selectInput("allnamesbuffalo", "Buffalo", c("All Buffalo" = "all buffalo", vars))
)
),
hr(),
DT::dataTableOutput("buffalotable")
)
)
)
Shiny Server:
shinyServer(function(input, output, session) {
observe({
allnamesbuffalo <- if (is.null(input$allnamesbuffalo)) character(0) else {
filter(cleanbuffalo, name %in% input$allnamesbuffalo) %>%
`$`('name') %>%
unique() %>%
sort()
}
})
output$buffalotable <- DT::renderDataTable({
df <- cleanbuffalo %>%
filter(
cleanbuffalo$name == input$allnamesbuffalo,
is.null(input$allnamesbuffalo) | name %in% cleanbuffalo$name
)
action <- DT::dataTableAjax(session,df)
DT::datatable(df, options = list(ajax = list(url = action)),
escape = FALSE)
})
})
Here is a working example. Note that I added stringsAsFactors=F in your data frame, otherwise you need to use levels(cleanbuffalo$name) to get the names.
library(shiny)
library(dplyr)
cleanbuffalo <- data.frame(name = c("queen","toni","pepper"),
longitude = c(31.8,32,33),
latitude = c(-24,-25,-26), stringsAsFactors = F)
ui <- shinyUI(fluidPage(
titlePanel("Example"),
sidebarLayout(
sidebarPanel(
selectInput("allnamesbuffalo", "Buffalo", c("all", cleanbuffalo$name))
),
mainPanel(
dataTableOutput("buffalotable")
)
)
))
server <- shinyServer(function(input, output, session) {
output$buffalotable <- renderDataTable({
names <- NULL
if (input$allnamesbuffalo == "all") {
names <- cleanbuffalo$name
} else {
names <- input$allnamesbuffalo
}
filter(cleanbuffalo, name %in% names)
})
})
shinyApp(ui = ui, server = server)

Resources