以下是要求。
1)我需要浏览并上传一个excel文件(带有包readxl
),用于获得一些我需要在闪亮窗口中显示为不同表输出的计算
2)手动编辑上传文件中的一些数据,它应自动反映在显示的结果中
3)我们应该能够下载编辑过的文件。
到目前为止我写过。我在输入数据中有列ID,曝光和频率。对于每个ID,我需要使用相应的曝光和频率来计算变量。我需要使用ID(这是唯一的)手动编辑频率和曝光。我添加了一个"更新"按钮。但改变不是永久性的。一旦我再次点击更新按钮,它就会返回
library(shiny)
ui = fluidPage(
titlePanel("HEllo world"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose xlsx file',
accept = c(".xlsx")),
actionButton("go", "update"),
numericInput('NewVal', 'Enter new Frequency',NULL),
numericInput('NewExp', 'Enter new Exposure',NULL)),
mainPanel(
textInput('ID', 'Enter ID'),
dataTableOutput('contents')
)))
server = function(input,output){
ef <- eventReactive(input$go, {
infile <- input$file1
if(is.null(infile))
return(NULL)
file.rename(infile$datapath,paste(infile$datapath, ".xlsx", sep=""))
data<-read_excel(paste(infile$datapath, ".xlsx", sep=""), 1)
if(input$ID!="" && input$go>0){
for( i in 1:nrow(data)){
if( input$ID == data$'ID'[i]){
if(!is.na(input$NewVal)){
data$' Frequency'[i] <- input$NewVal
}
if(!is.na(input$NewExp)){
data$'Exposure'[i] <- input$NewExp
}
}}}
data
}, ignoreNULL = FALSE)
output$contents <- renderDataTable({ef()})}
shinyApp(ui,server)
更新!:根据一个答案,我对代码进行了一些更改。新代码似乎运行正常。以下是适用于可能需要相同问题帮助的人的工作代码。
ui = fluidPage(
titlePanel("HEllo world"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose xlsx file',
accept = c(".xlsx")),
actionButton("go", "update"),
numericInput('NewVal', 'Enter new Frequency',NULL),
numericInput('NewExp', 'Enter new Exposure',NULL)),
mainPanel(
textInput('ID', 'Enter ID'),
tableOutput('contents')
)))
server = function(input,output){
# Reactive value to save input data frame for use elsewhere
original <- reactiveValues()
observeEvent(input$file1, {
theFile <- input$file1
if(is.null(theFile)) {
return(NULL)}
**file.rename(theFile$datapath,paste(theFile$datapath, ".xlsx", sep=""))**
original$oldData <- read_excel(paste(theFile$datapath, ".xlsx", sep = ""), 1)
})
observeEvent(input$go, {
original$newData <- original$oldData
if(input$ID !="") {
for( i in 1:nrow(original$oldData)){
if( input$ID == original$oldData$'ID'[i]){
if(!is.na(input$NewVal)){
original$newData$'Frequency'[i] <- input$NewVal
}
if(!is.na(input$NewExp)){
original$newData$'Exposure'[i] <- input$NewExp
}
}
}
**original$oldData<-original$newData** }
})
output$contents <- renderTable({
if(!is.null(original$newData)) {
original$newData}
else {
original$oldData}
})
}
shinyApp(ui = ui, server = server)
答案 0 :(得分:0)
有些评论似乎在正确的轨道上发生了什么。可以使用几种解决方案,但我会分享对我来说最直观的方法。另外,我只会更改服务器功能。
server = function(input,output){
# Reactive value to save input data frame for use elsewhere
original <- reactiveValues()
observeEvent(input$file1, {
theFile <- input$file1
if(is.null(theFile)) {return(NULL)}
original$oldData <- read_excel(paste(theFile$datapath, ".xlsx", sep = ""), 1)
})
observeEvent(input$goButton2, {
original$newData <- original$oldData
if(input$ID !="") {
for( i in 1:nrow(data)){
if( input$ID == dat$'ID'[i]){
if(!is.na(input$NewVal)){
original$newData$' Frequency'[i] <- input$NewVal
}
if(!is.na(input$NewExp)){
original$newData$'Exposure'[i] <- input$NewExp
}
}
}
}
})
output$contents <- renderDataTable({
if(!is.null(original$newData)) {original$newData}
else {original$oldData}
})
}
在单击go按钮之前,这不会更改表格输出。我没有完全测试它,因为我没有你的数据,但我相信这应该让你在最小的轨道上正确...我喜欢观察陈述,因为它们会引起副作用,看起来更开放比eventReactives或函数。
这仅对初始问题有帮助,即在输出中进行正确的更改并继续显示。如果这样可行,则添加下载功能应该相当容易,该功能会在文件更新时保存文件。
更新1
下面的代码应该按照您希望的方式执行。我添加了两种不同的功能来保存新数据框。注释掉的代码会在按下更新按钮时自动保存数据。没有注释的代码会创建一个用于下载数据的下载按钮。我还添加了一条基于频率和曝光计算新值的线。在数据集中将此列命名为Value
。希望这可以帮助!
#### Example app for Exchange answer
library(shiny)
library(readxl)
ui = fluidPage(
titlePanel("HEllo world"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose xlsx file',
accept = c(".xlsx")),
actionButton("go", "update"),
numericInput('NewVal', 'Enter new Frequency',NULL),
numericInput('NewExp', 'Enter new Exposure',NULL),
# Download button (goes with download handler below)
# Use if desire is to save at press of button
downloadButton("save", "Download")
),
mainPanel(
textInput('ID', 'Enter ID'),
dataTableOutput('contents')
)
)
)
server = function(input,output){
# Reactive value to save input data frame for use elsewhere
original <- reactiveValues()
observeEvent(input$file1, {
theFile <- input$file1
if(is.null(theFile)) {
original$oldData <- NULL
} else {
original$oldData <- read_excel(theFile$datapath, 1)
}
})
observeEvent(input$go, {
original$newData <- original$oldData
if(input$ID !="") {
for(i in 1:nrow(original$oldData)){
if(input$ID == original$oldData$'ID'[i]){
if(!is.na(input$NewVal)){
original$newData$'Frequency'[i] <- input$NewVal
}
if(!is.na(input$NewExp)){
original$newData$'Exposure'[i] <- input$NewExp
}
### Make sure a column in your data set is named Value for this
# Calculate a new column
original$newData$'Value'[i] <- (original$newData$'Exposure'[i]*
original$newData$'Frequency'[i])
}
}
original$oldData<-original$newData
}
### Use this to automatically save table when update is clicked
# write.csv(original$newData,
# file = #Desired Pathname,
# row.names = FALSE)
})
output$contents <- renderDataTable({
if(!is.null(original$newData)) {
original$newData}
else {
original$oldData
}
})
### Use this code below if desired saving is through download button
# Server code for download button
output$save <- downloadHandler(
filename = function() {
paste0("newData - ", Sys.Date(), ".csv")
},
content = function(con) {
if (!is.null(original$newData)) {
dataSave <- original$newData
} else {
dataSave <- original$oldData
}
con <- ## Desired save location... could just use `getwd()` to
# save to working directory
write.csv(dataSave, con)
}
)
}
shinyApp(ui = ui, server = server)