重新启动 R Shiny 应用程序或查询时如何保存已编辑的数据框并重新加载它?

How to save an edited dataframe and load it back when restarting an R Shiny app or query?

我正在使用查询在 R shiny 中构建报告,然后将结果存储在数据框中。

data1 <- dbGetQuery(q_r,sql)

然后我使用此数据框动态创建新列(这些列在我查询的 table 中不存在,因为我只有读取权限,无法写回数据库)

data1['R/Y/G'] <- " "

data1['R'] <- " "

data1['Y'] <- " "

data1['G'] <- " "

data1['tcolor'] <- " "

然后我保存到本地的rds文件

saveRDS(data1, 'data.rds')

然后我创建一个editable数据table(https://yihui.shinyapps.io/DT-edit/),编辑完成后保存回同一个rds文件

问题是,每当查询重新运行时,使用 R 创建的列的值('R/Y/G'、'R'、'Y'、'G' 和 'tcolor') 失去所有价值。我如何确保即使在查询重新运行后,使用 R('R/Y/G'、'R'、'Y'、'G' 和 'tcolor') 创建的列仍保留它们的价值观?我使用多个文件吗?

这是代码的其余部分:

dt_output = function(title, id) {
  fluidRow(column(
    12, h1(paste0(title)),
    hr(), DTOutput(id)
  ))
}

render_dt = function(data, editable = 'cell', server = TRUE, ...) {
  renderDT(data,selection = 'none', server = server, editable = editable, ...)
}

ui = fluidPage(
  downloadButton("mcp_csv", "Download as CSV", class="but"),
  
  dt_output('Report', 'x9')
)

server = function(input, output, session) {
  d1 = readRDS('data.rds')
  d9 = d1
  
  rv <- reactiveValues()
  observe({
    rv$d9 <- d9
  })
  
  dt_d9=datatable(isolate(d9), editable = 'cell', rownames = FALSE, extensions = 'Buttons', options = list(dom = 'Bfrtip', buttons = I('colvis'))) %>% formatStyle(
    'R/Y/G', 'tcolor',
    backgroundColor = styleEqual(c(0,1,2), c('green', 'yellow', 'red')),fontWeight = 'bold'
  )
  
  output$x9 = render_dt(dt_d9)
  
  proxy = dataTableProxy('x9')
  observe({
    DT::replaceData(proxy, rv$d9, rownames = FALSE, resetPaging = FALSE)
  })
  
  observeEvent(input$x9_cell_edit, {
    rv$d9 <<- editData(rv$d9, input$x9_cell_edit, 'x9', rownames = FALSE)
    d9 <- rv$d9
    d9$tcolor <- ifelse(d9$R > 2500000, 2,
                        ifelse(d9$Y > 2000000 & d9$Y <= 2500000, 1,
                               ifelse(d9$G <= 2000000, 0)))
    rv$d9 <<- d9
    saveRDS(d9, 'data.rds')
    
  })

谢谢

这是因为您先将 data1 table 保存为空列,然后在编辑 table 后将其覆盖。重新启动应用程序时,您再次保存带有空列的 data1,覆盖之前保存的 table(带有编辑的列)。

如果您需要显示从sql查询中获得的列和查询后创建的新列,您需要保存两个数据帧并将它们组合起来以在呈现的DT中显示它们。

首先,在查询后立即保存sql查询的结果。

data1 <- dbGetQuery(q_r,sql)
saveRDS(data1, 'data_query.rds')

然后您必须使用服务器中添加的空列创建组合数据框。如果数据框已经被编辑和保存,我们还可以通过检查应用程序文件夹中是否存在已保存的文件来检索数据: 替换为:

d1 = readRDS('data.rds') 
d9 = d1

通过这个:

  if(!file.exists("data.rds")){
    d9 = data1
    d9['R/Y/G'] <- NA
    d9['R'] <- NA
    d9['Y'] <- NA
    d9['G'] <- NA
    d9['tcolor'] <- NA
  }
  else{
    cmp <- readRDS("data.rds")
    d9 = cbind(data1, cmp[,(ncol(cmp)-4):ncol(cmp)])
  }

̀d9 现在是您使用 renderDT() 显示并可以编辑的组合数据框。如您的代码 (saveRDS(d9, 'data.rds')) 中所述,在编辑后保存此数据框。

再次启动应用程序时,如果文件夹中已存在 data.rds 文件,则它包含来自 data1 的所有列(来自先前的查询) 和附加列(R、Y、G...)。所以我们必须 cbind 使用新查询创建的新 data1 和保存的 data.rds 文件的最后 5 列(即只有附加列).