如何在闪亮的编辑单元格上对 DT 进行子集化

How to subset DT with edited cells on shiny

我正在尝试从闪亮的 DT 输出中获取子集数据table,其中我编辑了一些单元格。 不需要编辑原始数据table,只需渲染编辑后的值。 这就是我闪亮的 UI 的样子:

第一个DT为源数据 第二个是用第一个的选定行制作的 下面三行是加权平均值;加权标准差;和第二个数据的总和 table.

我制作了第二个 DT edi 的“Poids”table,我想提取一个编辑过的 DT(以及其他)DT2 也在其上进行我的 3 计算。

我的代码有一部分:

 
 
x2<-reactive({
  sel <- input$x1_rows_selected
  if(length(valdureT())){
    valdureT()[sel, ]
  }
 
})
 
 
 
 
 
output$x2 = DT::renderDataTable(x2(), rownames = FALSE,editable = list(
  target = 'cell', disable = list(columns = c(1:9))),
  extensions = c ('RowGroup'),
  options = list(rowGroup = list(dataSrc = 2), order = list(c(4 , 'asc'))),
  selection = 'none'
)
 
x3<-reactive({
  sel <- input$x2_rows_all
  if(length(x2())){
    x2()[sel, ]
  }
 
})
 
 
 
M<-reactive({M <- x3()$"Dureté Moyenne"
M<-as.numeric(M)})
 
S<-reactive({S<- x3()$"Ecart Type Dureté"
S<-as.numeric(S)})
 
N<-reactive({N<- x3()$Poids
N<-as.numeric(N)
})
 
dureTmoymoy<- reactive({paste("Dureté Moyenne des batchs séléctionnés : ",{weighted.mean(M(), N())}," kg")})
 
sdmoy<- reactive({paste("Ecart Type des batchs selectionnés : ",{sqrt(weighted.mean(S()^2 + M()^2, N()) - weighted.mean(M(), N())^2)}," kg")})
 
poidsselect<- reactive({paste("Poids des batchs selectionnés :", {sum(N())}," kg")})
 
output$dureTmoymoy<-renderText({dureTmoymoy()})
 
output$sdmoy<-renderText({sdmoy()}) 
 
output$poidsselect<-renderText({poidsselect()}) 
 

如您所见,我使用输入 $x2_rows_all 创建了 x3 对象(预期的 DT2 (x2) 并编辑了行),但这不起作用。

这可能吗?

以虹膜数据为例####

好的抱歉,这里有一个虹膜数据的例子。

我制作了第一列(萼片长度)editable;萼片长度对我的加权平均值有影响。

如何在我编辑萼片长度列时使我的 3 条机器人线反应?

library(shiny)
 
# Define UI for application that draws a histogram
ui <- fluidPage(
 
    wellPanel(
        fluidRow(
            column(12,h2("iris head" , align = "center"), DT::dataTableOutput('x1')),
            column(12,h2("row selected on iris head" , align = "center"), DT::dataTableOutput('x2'))
        ),
        h2("3 calculation about 2nd DT with edited cells"),
        h3(textOutput("dureTmoymoy", inline = TRUE)),
        h3(textOutput("sdmoy", inline = TRUE)),
        h3(textOutput("poidsselect", inline = TRUE)),
       
        
    )
)
 
# Define server logic required to draw a histogram
server <- function(input, output) {
 
    headiris<- reactive({
    headiris<-head(iris)
    headiris<-as.data.frame(headiris)
    })
   
    output$x1 = DT::renderDataTable(headiris())
   
    
    x2<-reactive({
        sel <- input$x1_rows_selected
        if(length(headiris())){
            headiris()[sel, ]
        }
       
    })
   
    
    
    
    
    output$x2 = DT::renderDataTable(x2(), rownames = FALSE,editable = list(
        target = 'cell', disable = list(columns = c(1:6))),
                selection = 'none'
    )
   
    x3<-reactive({
        sel <- input$x2_rows_all
        if(length(x2())){
            x2()[sel, ]
        }
       
    })
   
 
   
    M<-reactive({M <- x3()$"Petal.Length"
    M<-as.numeric(M)})
   
    S<-reactive({S<- x3()$"Sepal.Width"
    S<-as.numeric(S)})
   
    N<-reactive({N<- x3()$"Sepal.Length"
    N<-as.numeric(N)
    })
   
    dureTmoymoy<- reactive({paste("petal lenght weighted mean ",{weighted.mean(M(), N())}," kg")})
   
    sdmoy<- reactive({paste("sepal width weighted mean (SD) ",{sqrt(weighted.mean(S()^2 + M()^2, N()) - weighted.mean(M(), N())^2)}," kg")})
   
    poidsselect<- reactive({paste("Sepal lenght sum  :", {sum(N())}," kg")})
   
    output$dureTmoymoy<-renderText({dureTmoymoy()})
   
    output$sdmoy<-renderText({sdmoy()}) 
    
    output$poidsselect<-renderText({poidsselect()}) 
    
    
    
    
    
}
 
# Run the application
shinyApp(ui = ui, server = server)

潜在的问题是 table 中编辑的数据没有写回用于生成 table 的 reactive/data 对象 x2。所以你必须添加逻辑来读出编辑的数据。我通过将用于呈现 table 和选定行的数据存储为 reactiveValues 对象 dat$x2 来解决此问题。然后我添加了 2 observeEvent:

  • 一个监听所选行的编辑
  • 一个监听选择行的变化。但是,作为我使用 input$x1_cell_clicked 的事件,因为 input$x1_rows_selected 不会在最后选定的行被取消选择并且根本没有选择任何行时触发。此外,它包含仅添加新行但不覆盖之前选择的行的逻辑,因为否则可能的编辑将丢失
library(shiny)
library(dplyr)

# Define UI for application that draws a histogram
ui <- fluidPage(
  
  wellPanel(
    fluidRow(
      column(12,h2("iris head" , align = "center"), DT::dataTableOutput('x1')),
      column(12,h2("row selected on iris head" , align = "center"), DT::dataTableOutput('x2'))
    ),
    h2("3 calculation about 2nd DT with edited cells"),
    h3(textOutput("dureTmoymoy", inline = TRUE)),
    h3(textOutput("sdmoy", inline = TRUE)),
    h3(textOutput("poidsselect", inline = TRUE)),
    
    
  )
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  
  headiris<- reactive({
    headiris<-head(iris)
    headiris<-as.data.frame(headiris)
  })
  
  output$x1 = DT::renderDataTable(headiris())
  
  output$x2 = DT::renderDataTable({
    req(dat$x2)
    DT::datatable(dat$x2[, colnames(dat$x2) != "selected_row"], rownames = FALSE,editable = list(
    target = 'cell', disable = list(columns = c(1:6))),
    selection = 'none')
  })
  
  # define the data as reactive value
  dat <- reactiveValues()
  
  # listen for changes which rows are selected
  observeEvent(input$x1_cell_clicked, {
    print(input$x1_rows_selected)
    if (is.null(dat$x2)) {
      new_data <- cbind(selected_row = input$x1_rows_selected, headiris()[input$x1_rows_selected, ])
      dat$x2 <- new_data
    } else {
      old_rows <- dat$x2
      old_row_numbers <- dat$x2$selected_row
      # rows to add
      new_row_number <- setdiff(input$x1_rows_selected, old_row_numbers)
      if (length(new_row_number) != 0) {
      new_row <- cbind(selected_row = new_row_number, headiris()[new_row_number, ])
      new_data <- rbind(old_rows, new_row)
      new_data <- new_data %>% 
        arrange(selected_row)
      }
      # rows to delete
      delete_row_numbers <- setdiff(old_row_numbers, input$x1_rows_selected)
      if (length(delete_row_numbers) != 0) {
        new_data <- dat$x2 %>% 
          filter(selected_row %in% input$x1_rows_selected)
      }
      dat$x2 <- new_data
    }
  })
  
  # update edited data
  observeEvent(input$x2_cell_edit, {
    data_table <- dat$x2
    data_table[input$x2_cell_edit$row, "Sepal.Length"] <- as.numeric(input$x2_cell_edit$value)
    dat$x2 <- data_table
  })
  
  
  
  M<-reactive({M <- dat$x2$"Petal.Length"
  M<-as.numeric(M)})
  
  S<-reactive({S<- dat$x2$"Sepal.Width"
  S<-as.numeric(S)})
  
  N<-reactive({N<- dat$x2$"Sepal.Length"
  N<-as.numeric(N)
  })
  
  dureTmoymoy<- reactive({paste("petal lenght weighted mean ",{weighted.mean(M(), N())}," kg")})
  
  sdmoy<- reactive({paste("sepal width weighted mean (SD) ",{sqrt(weighted.mean(S()^2 + M()^2, N()) - weighted.mean(M(), N())^2)}," kg")})
  
  poidsselect<- reactive({paste("Sepal lenght sum  :", {sum(N())}," kg")})
  
  output$dureTmoymoy<-renderText({dureTmoymoy()})
  
  output$sdmoy<-renderText({sdmoy()}) 
  
  output$poidsselect<-renderText({poidsselect()}) 
  
  
  
  
  
}

# Run the application
shinyApp(ui = ui, server = server)