I am trying to figure out how to write a .csv based on selections made by the end user. The selections made will subset the "geodata.csv" and write a separate "solution.csv" file in the application folder.
N.B. - I have created a github repo to make solving the question easier. It contains the geodata.csv, ui.R & server.R but no solution.csv yet!
geodata.csv
Postcode,HC,BSL,Position Location
10,1,A,C
10,1,A,D
10,1,A,D
11,1,B,C
11,1,B,C
ui.R
shinyUI(
pageWithSidebar(
headerPanel('Min. working example - write a csv based on user input'),
sidebarPanel(
selectInput("filter1", "First selection:"
, choices = c(Choose='', "A", "B")
#, multiple=T
),
selectInput("filter2", "Second selection:",
choices = c(Choose='', "C", "D")
),
br(),
p("Include actionButton to prevent write occuring before user finalises selection"),
actionButton("generateButton","Write Data")
),
mainPanel()
)
)
server.R
# Load data
setwd("/Users/lukesingham/SOtestApp")
geodata <- read.csv("geodata.csv", na.string = "#N/A", row.names=NULL)
# Reactivity to subset data ####
shinyServer(function(input, output) {
geodatasetInput <- reactive({
# BSL switch
selection <-switch(input$BSL
, A = "A"
, B = "B"
)
# Location switch
selection2 <-switch(input$Location
, C = "C"
, D = "D"
)
# subset based on selection
Subgeodata <- subset(geodata, BSL == selection & Position.Location == selection2)
# Execute selections on data upon button-press
input$generateButton
# aggregate by postcode
Subgeodata <- Subgeodata[1:2] #no longer need other columns
AggSubGdata <- aggregate(. ~ Postcode, data=Subgeodata, FUN=sum)
isolate(write.csv(AggSubGdata
, file = "/Users/lukesingham/SOtestApp/solution.csv"
, row.names=F
))
})
})
solution.csv
For example, based on user selections of A and D the solution file should look like this:
Postcode,HC
10,2
Here is the working example:
# Load data
setwd("/Users/lukesingham/SOtestApp")
geodata <- read.csv("geodata.csv", na.string = "#N/A", row.names=NULL)
# Reactivity to subset data ####
shinyServer(function(input, output) {
geodatasetInput <- observe({
# Execute selections on data upon button-press
if(input$generateButton == 0) return()
inp.BSL <- isolate(input$filter1)
inp.loc <- isolate(input$filter2)
if (inp.BSL=='' | inp.loc=='') return()
# BSL switch
selection <-switch(inp.BSL
, A = "A"
, B = "B"
)
# Location switch
selection2 <-switch(inp.loc
, C = "C"
, D = "D"
)
# subset based on selection
Subgeodata <- subset(geodata, BSL == selection & Position.Location == selection2)
# browser()
# aggregate by postcode
Subgeodata <- Subgeodata[1:2] #no longer need other columns
AggSubGdata <- aggregate(. ~ Postcode, data=Subgeodata, FUN=sum)
write.csv(AggSubGdata
, file = "solution.csv"
, row.names=F
)
})
})
and a short analysis of your code:
The main reason geodatasetInput does not start at all is because it is a reactive() expression. reactive() is evaluated only when it is called by something else like renderTable() in the answer of @pops. If you want it to be executed by itself, it should be observe().
It might be a good idea to have input$generateButton in the beginning of your observe() expression.
In ui.R, you call a numeric input field filter1, but you try to obtain its value as input$BSL from server.R; the same is true for filter2.
As you want geodataSetInput to be triggered only on generateButton, all other input$ and reactive expressions withing geodataSetInput should be isolated with isolate(). On the other hand, there is no need to isolate write.csv because this particular function call does not involve any 'dynamic' parameters.
you would need to Render your the table you're subsetting, perhaps someone else can explain why you need this co-dependance. Below is the working example of the way I went to solve it. It will save the solution.csv in the working directory.
rm(list = ls())
library(shiny)
# You can change this directory
setwd("/Users/lukesingham/SOtestApp")
geodata <- read.csv("geodata.csv", header = TRUE, sep = ",",stringsAsFactors =FALSE)
ui = pageWithSidebar(
headerPanel('Min. working example - write a csv based on user input'),
sidebarPanel(
selectInput("filter1", "First selection:", choices = c("A", "B"),selected = "A"),
selectInput("filter2", "Second selection:", choices = c("C", "D"),selected = "C"),
br(),
p("Include actionButton to prevent write occuring before user finalises selection"),
actionButton("generateButton","Write Data")),mainPanel(tableOutput("test1"))
)
server = function(input, output) {
geodatasetInput <- reactive({
if(input$generateButton == 0){return()}
isolate({
input$generateButton
test_data <- geodata[geodata$BSL %in% as.character(input$filter1),]
test_data <- geodata[geodata$Position.Location %in% as.character(input$filter2),]
test_data <- test_data[,1:2]
test_data <- aggregate(. ~ Postcode, data=test_data, FUN=sum)
test_data
})
write.csv(test_data,"solution.csv",row.names=F)
})
output$test1 <- renderTable({geodatasetInput()})
}
runApp(list(ui = ui, server = server))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With