¿Cómo modificar la cadena de reactividad para que el último objeto modificado controle otros objetos encadenados?
[Nueva nota 1: código resuelto final publicado en la parte inferior que refleja la solución de ismirsehregal del 03-Dic-2021 y algunos ajustes menores marcados como “ADDED” y “MODIFIED”. ADD se refiere a la solución del problema que encontré cuando se eliminan filas de la matriz 1 después de que se hayan agregado valores a la matriz 2 (como se comenta a continuación), y “MODIFIED” es para hacer que las cabeceras de columna para las matrices 1 y 2 sean iguales (no tenía sentido que tuvieran cabeceras de columnas diferentes).]
Al ejecutar el código a continuación, me gustaría que el último objeto modificado en la cadena de reactividad “controle” o “domine” otros objetos en esa cadena de reactividad. En este código, los objetos reactivos en cadena son “matrix1” y “matrix2”. Las entradas de matrix1 fluyen hacia matrix2, y las entradas a las primeras 2 columnas de matrix2 fluyen hacia matrix1. Como está redactado, las entradas en matrix2 tienen prioridad sobre las entradas en matrix1. Quisiera que cualquiera de las matrices que haya recibido la entrada más reciente tenga prioridad sobre la otra matriz. ¿Puede alguien ayudarme con esto?
Las imágenes al final ayudan a ilustrar.
He intentado usar “isolate()” y otras cosas para tratar de hacer que esto funcione como quiero, pero también he tenido el problema de que las matrices quedan atrapadas en un ciclo en el que los valores rebotan entre las 2 matrices. Todavía no tengo una comprensión completa de “isolate()”.
Código:
library(dplyr)
library(ggplot2)
library(shiny)
library(shinyMatrix)
sumMat <- function(x){return(rep(sum(x,na.rm = TRUE), 10))}
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
matrixInput("matrix1",
label = "Matrix 1 (scenario 1):",
value = matrix(c(60,5),ncol=2,dimnames=list(NULL,c("X","Y"))),
rows = list(extend = TRUE, delete = TRUE),
class = "numeric"),
actionButton(inputId = "showMat2", "Add scenarios"),br(),br(),
),
mainPanel(plotOutput("plot"))
)
)
server <- function(input, output, session){
observeEvent(input$matrix1, {
tmpMat1 <- input$matrix1
if(any(rownames(input$matrix1) == "")){rownames(tmpMat1) <- paste("Row", seq_len(nrow(input$matrix1))) }
isolate(updateMatrixInput(session, inputId = "matrix1", value = tmpMat1))
})
observeEvent(input$showMat2,{
showModal(
modalDialog(
matrixInput("matrix2",
label = "Matrix 2:",
value = input$matrix1,
rows = list(extend = TRUE, delete = TRUE),
cols = list(extend = TRUE, delta = 2, delete = TRUE, multiheader = TRUE),
class = "numeric"),
footer = tagList(modalButton("Close"))
))
observeEvent(input$matrix2, {
tmpMat2 <- input$matrix2
rownames(tmpMat2) <- paste("Row", seq_len(nrow(input$matrix2)))
colnames(tmpMat2) <- paste("Scenario",rep(1:ncol(tmpMat2),each=2,length.out=ncol(tmpMat2)))
isolate(updateMatrixInput(session, inputId = "matrix2", value = tmpMat2))
isolate(updateMatrixInput(session, inputId = "matrix1", value = tmpMat2[,1:2]))
})
})
plotData <- reactive({
tryCatch(
lapply(seq_len(ncol(input$matrix1)/2),
function(i){
tibble(
Scenario= colnames(input$matrix1)[i*2-1],X=seq_len(10),
Y=sumMat(input$matrix1[,(i*2-1):(i*2), drop = FALSE])
)
}) %>% bind_rows(),
error = function(e) NULL
)
})
output$plot <- renderPlot({
plotData() %>% ggplot() +
geom_line(aes(x = X, y = Y, colour = as.factor(Scenario))) +
theme(legend.title=element_blank())
})
}
shinyApp(ui, server)
[Nueva nota 1: código resuelto final a continuación]
“`R
sumMat <- function(x) {return(rep(sum(x, na.rm = TRUE), 10))}
ui <- fluidPage(sidebarLayout(
sidebarPanel(
matrixInput(
“matrix1”,
label = “Matrix 1:”, # MODIFIED HEADER
value = matrix(c(60,5),ncol=2,dimnames=list(NULL,rep(“Scenario 1”,2))), # MODIFIED HEADER
rows = list(extend = TRUE, delete = TRUE),
cols = list(multiheader = TRUE), # ADD
class = “numeric”
),
actionButton(inputId = “showMat2”, “Add scenarios”),br(),br(),
),
mainPanel(plotOutput(“plot”))
))
server <- function(input, output, session) {
currentMat <- reactiveVal(isolate(input$matrix1))
observeEvent(input$matrix1, {
tmpMat1 <- input$matrix1
if(any(rownames(input$matrix1)==””)){rownames(tmpMat1)<-paste(“Row”,seq_len(nrow(input$matrix1)))}
updateMatrixInput(session, inputId = “matrix1”, value = tmpMat1)
tmpMat2 <- currentMat()
if(nrow(tmpMat1) > nrow(tmpMat2)){tmpMat2 <- rbind(tmpMat2, rep(NA, ncol(tmpMat2)))}
# ADDED
if(nrow(tmpMat2) > nrow(tmpMat1)){tmpMat1 <- rbind(tmpMat1, rep(NA, ncol(tmpMat1)))}
currentMat(cbind(tmpMat1[drop=FALSE], tmpMat2[,-1:-2,drop=FALSE]))
})
observeEvent(input$showMat2, {
showModal(modalDialog(
matrixInput(
“matrix2”,
label = “Matrix 2:”,
value = currentMat(),
rows = list(extend = TRUE, delete = TRUE),
cols = list(extend = TRUE,delta = 2,delete = TRUE,multiheader = TRUE),
class = “numeric”
),
footer = tagList(modalButton(“Close”))
))
})
observeEvent(input$matrix2, {
tmpMat2 <- input$matrix2
rownames(tmpMat2) <- paste(“Row”, seq_len(nrow(input$matrix2)))
colnames(tmpMat2) <-
paste(“Scenario”, rep(1:ncol(tmpMat2),each = 2,length.out = ncol(tmpMat2)))
currentMat(tmpMat2)
updateMatrixInput(session, inputId = “matrix2”, value = tmpMat2)
updateMatrixInput(session, inputId = “matrix1”, value = tmpMat2[, 1:2, drop = FALSE])
})
plotData <- reactive({
tryCatch(
lapply(seq_len(ncol(input$matrix1) / 2),
function(i) {
tibble(
Scenario = colnames(input$matrix1)[i * 2 - 1],
X = seq_len(10),
Y = sumMat(input$matrix1[, (i * 2 - 1):(i * 2), drop = FALSE])
)
}) %>% bind_rows(),
error = function(e)
NULL
)
davy.ai
El objetivo de esta tarea es modificar el código dado de tal manera que sea la última matriz introducida la que tenga prioridad sobre la otra matriz. En el código original, las entradas en matrix2 tenían prioridad sobre las entradas en matrix1.
La solución a esto requiere la creación de un objeto
reactiveVal
que contenga el estado actual de ambas matrices. EstereactiveVal
actúa como un contenedor de estado actual para ambas matrices. Cada vez que ocurre un evento de entrada en matrix1 o matrix2, ambas matrices se actualizan en base a estereactiveVal
de estado actual. Específicamente, cuando ocurre un evento de entrada en matrix1, se fusiona el estado actual de matrix2 con matrix1 y se establece como el nuevo estado en el objetoreactiveVal
de estado actual. De manera similar, cuando ocurre un evento de entrada en matrix2, se actualiza el objetoreactiveVal
de estado actual con el nuevo estado de matrix2.A continuación se muestra el código final resuelto que resuelve el problema:
Nótese que este código todavía está estructurado con el código original de tener
matrix2
como un diálogo modal, dondematrix2
es una copia exacta dematrix1
. Esto puede ser mejorado aún más, pero la solución actual se centra en abordar el problema principal, que es dejar que la última entrada de matriz modificada domine la otra matriz de entrada.