r - 如何使用上传文件中的 DT 和 Shiny 编辑表格?
问题描述
我依靠在这里找到的代码块来创建一个闪亮的应用程序来上传表格,编辑表格,然后下载表格。我已经设法编辑了一个已经加载到内存(iris)中的表,但是如何编辑要在 Shiny 中上传的表?.
我已经尝试了上面链接中的代码并验证它是否有效。我也尝试了下面的代码,这也有效。我无法实现的是将数据框x
转换为分配给上传文件的反应对象,并x
相应地编辑所有引用。
# This code works, but lacks a fileinput object
# and needs to be amended for a reactive dataframe...
library(shiny)
library(DT)
shinyApp(
ui = fluidPage(
fluidRow(
# ~~ add fileInput("file1", "Choose file") here ~~
downloadButton("download")
),
fluidRow(
DT::dataTableOutput('x1')
)
),
server = function(input, output, session) {
# Do I make x reactive?
x = iris
x$Date = Sys.time() + seq_len(nrow(x))
output$x1 = DT::renderDataTable(x, selection = 'none', rownames = FALSE, edit = TRUE)
proxy = dataTableProxy('x1')
observeEvent(input$x1_cell_edit, {
info = input$x1_cell_edit
str(info)
i = info$row
j = info$col + 1
v = info$value
x[i, j] <<- DT:::coerceValue(v, x[i, j])
replaceData(proxy, x, resetPaging = FALSE, rownames = FALSE)
})
output$download <- downloadHandler("example.csv",
content = function(file){
write.csv(x, file)
},
contentType = "text/csv")
}
)
以前对此的尝试已经引发了错误,主要与没有活动的反应性上下文的情况下不允许的操作有关。
下面的代码显示了我想要实现的目标,但会引发错误: “缺少参数“expr”,没有默认值”
library(shiny)
library(DT)
shinyApp(
ui = fluidPage(
fluidRow(
fileInput("upload", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
downloadButton("download")
),
fluidRow(
DT::dataTableOutput('x1')
)
),
server = function(input, output, session) {
#x = iris
# In this edited example x is now a reactive expression, dependent on input$upload
x <- eventReactive({
# input$file1 will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$upload)
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch(
{
x <- read.csv(input$upload$datapath,
header = TRUE,
sep = ",",
stringsAsFactors = TRUE,
row.names = NULL)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
}
)
})
#x$Date = Sys.time() + seq_len(nrow(x))
output$x1 = DT::renderDataTable(x(), selection = 'none', rownames = FALSE, edit = TRUE)
proxy = dataTableProxy('x1')
observeEvent(input$x1_cell_edit, {
info = input$x1_cell_edit
str(info)
i = info$row
j = info$col + 1
v = info$value
x()[[i, j]] <<- DT:::coerceValue(v, x()[[i, j]])
newdf <- x()
replaceData(proxy, newdf, resetPaging = FALSE, rownames = FALSE)
})
output$download <- downloadHandler("example.csv",
content = function(file){
write.csv(x(), file)
},
contentType = "text/csv")
}
)
解决方案
感谢 Stephane,以及从这个相关问题中得到的启发,我想我有了答案。
关键是使用 reactiveValues 作为 DT:::coerceValue 不喜欢反应式表达式的解决方法。我已经包含了一个逐字文本输出来说明在您编辑数据表后对表的存储更改。下载按钮也允许您下载已编辑的表格。
library(shiny)
library(DT)
shinyApp(
ui = fluidPage(
fluidRow(
fileInput("upload", "Choose CSV File",
multiple = FALSE,
accept = c("text/csv",
"text/comma-separated-values,text/plain",
".csv")),
downloadButton("download")
),
fluidRow(
DT::dataTableOutput('x1'),
verbatimTextOutput("print")
)
),
server = function(input, output, session) {
# In this edited example x is now a reactive expression, dependent on input$upload
# Key to the solution is the use of reactiveValues, stored as vals
vals <- reactiveValues(x = NULL)
observe({
# input$upload will be NULL initially. After the user selects
# and uploads a file, head of that data file by default,
# or all rows if selected, will be shown.
req(input$upload)
# when reading semicolon separated files,
# having a comma separator causes `read.csv` to error
tryCatch(
{
x <- read.csv(input$upload$datapath,
header = TRUE,
sep = ",",
stringsAsFactors = TRUE,
row.names = NULL)
},
error = function(e) {
# return a safeError if a parsing error occurs
stop(safeError(e))
}
)
# Reactive values updated from x
vals$x <- x
})
output$print <- renderPrint({
vals$x
})
output$x1 = DT::renderDataTable(vals$x, selection = 'none', rownames = FALSE, edit = TRUE)
proxy = dataTableProxy('x1')
observeEvent(input$x1_cell_edit, {
info = input$x1_cell_edit
str(info)
i = info$row
j = info$col + 1
v = info$value
# Below is the crucial spot where the reactive value is used where a reactive expression cannot be used
vals$x[i, j] <<- DT:::coerceValue(v, vals$x[i, j])
replaceData(proxy, vals$x, resetPaging = FALSE, rownames = FALSE)
})
output$download <- downloadHandler("example.csv",
content = function(file){
write.csv(vals$x, file, row.names = F)
},
contentType = "text/csv")
}
)
推荐阅读
- postgresql - Spring Boot 2.2 中的 r2dbc-postgresql 0.8.0.RC1 无法正常工作
- javascript - discord.js 如何修复未定义的变量
- odoo - Odoo:如何删除销售订单中的笔记本页面
- python - Windows 上 Python 3.6 subprocess.run() 中的 7z 命令
- eclipse - 在 Eclipse 中:找不到或加载主类 org.testng.remote.RemoteTestNG
- r - 在闪亮/ flexdashboards中,如何通过multiple = TRUE的输入更改列的值?
- javascript - CPF 巴西 Jquery JS 验证
- google-apps-script - 如何在 onEdit 触发器上执行 copyTo 后附加时间戳?
- c - 第二个“ ch = getchar(); ”有什么意义
- bash - zsh 中有哪些特殊的美元符号变量?