R/Shiny - 如何反应性地编写包含 actionButton 的 .csv?
R/Shiny - How to write a .csv reactively including a actionButton?
我正在尝试弄清楚如何根据最终用户所做的选择编写 .csv。所做的选择将 "geodata.csv" 子集并在应用程序文件夹中写入一个单独的 "solution.csv" 文件。
N.B. - 我创建了一个 github repo 来简化问题的解决。它包含 geodata.csv、ui.R 和 server.R,但还没有 solution.csv!
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
例如,根据用户选择 A
和 D
,解决方案文件应如下所示:
Postcode,HC
10,2
你需要渲染你的 table 你正在子集化,也许其他人可以解释为什么你需要这种相互依赖。下面是我去解决它的方式的工作示例。它将 solution.csv 保存在工作目录中。
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))
这是工作示例:
# 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
)
})
})
并对您的代码进行简短分析:
geodatasetInput
根本没有启动的主要原因是因为它是一个reactive()
表达式。 reactive()
只有在被@pops 的回答中的 renderTable()
之类的其他东西调用时才会被评估。如果想让它自己执行,应该是observe()
.
在 observe() 表达式的开头添加 input$generateButton
可能是个好主意。
在ui.R
中,你调用了一个数字输入字段filter1
,但你试图从server.R
获取它的值为input$BSL
; filter2
.
也是如此
因为您希望 geodataSetInput
仅在 generateButton
上触发,所有其他 input$
和包含 geodataSetInput
的反应式表达式应与 isolate()
。另一方面,不需要隔离 write.csv
因为这个特定的函数调用不涉及任何 'dynamic' 参数。
我正在尝试弄清楚如何根据最终用户所做的选择编写 .csv。所做的选择将 "geodata.csv" 子集并在应用程序文件夹中写入一个单独的 "solution.csv" 文件。
N.B. - 我创建了一个 github repo 来简化问题的解决。它包含 geodata.csv、ui.R 和 server.R,但还没有 solution.csv!
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
例如,根据用户选择 A
和 D
,解决方案文件应如下所示:
Postcode,HC
10,2
你需要渲染你的 table 你正在子集化,也许其他人可以解释为什么你需要这种相互依赖。下面是我去解决它的方式的工作示例。它将 solution.csv 保存在工作目录中。
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))
这是工作示例:
# 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
)
})
})
并对您的代码进行简短分析:
geodatasetInput
根本没有启动的主要原因是因为它是一个reactive()
表达式。reactive()
只有在被@pops 的回答中的renderTable()
之类的其他东西调用时才会被评估。如果想让它自己执行,应该是observe()
.在 observe() 表达式的开头添加
input$generateButton
可能是个好主意。在
ui.R
中,你调用了一个数字输入字段filter1
,但你试图从server.R
获取它的值为input$BSL
;filter2
. 也是如此
因为您希望
geodataSetInput
仅在generateButton
上触发,所有其他input$
和包含geodataSetInput
的反应式表达式应与isolate()
。另一方面,不需要隔离write.csv
因为这个特定的函数调用不涉及任何 'dynamic' 参数。