I ran the below code and below I provide screenshots below of what happens:
- The first image shows the user successfully adding 2 additional interpolation scenarios; all OK.
- The second image shows what happens when a user deletes the Scenario 2 that was input above, by clicking the [x] in the Scenario 2 input matrix column header. See the error message that pops up for the plot.
- The third image shows the results of the user clicking on the [x] for the empty "Scenario 3" in the preceding image; the input matrix and plot re-render correctly. All OK again.
I'm trying to automate the elimination of the empty columns so the user doesn't need to go through the additional deletion step noted in #3 above.
The code I'm using in attempt to do this is:
# Remove any empty matrix columns
empty_columns <- sapply(tmpMatrix, function(x) all(is.na(x) | x == ""))
tmpMatrix[, !empty_columns]
But the problem is, it is looking for complete empty columns to remove. I need to modify it so it looks for empty columns ignoring any column header. The second image below shows this type of column I'm targeting: column header "Scenario 3", but all cells beneath it are empty.
Does anyone know how to eliminate empty columns ignoring the header?
Note that if I comment out the empty_columns <-
section I highlight above, this problem goes away, but a new problem arises when deleting Scenario 2: Scenario 3 becomes the second scenario as it should, but its column header remains "Scenario 3" when it should become "Scenario 2"!
Code:
library(shiny)
library(shinyMatrix)
library(dplyr)
library(ggplot2)
interpol <- function(a, b) { # a = periods, b = matrix inputs
c <- rep(NA, a)
c[1] <- b[1]
c[a] <- b[2]
c <- approx(seq_along(c)[!is.na(c)], c[!is.na(c)], seq_along(c))$y # << interpolates
return(c)
}
ui <- fluidPage(
sliderInput('periods','Periods to interpolate:',min=2,max=10,value=10),
matrixInput(
"myMatrixInput",
label = "Values to interpolate paired under each scenario heading:",
value = matrix(c(1, 5), 1, 2, dimnames = list(NULL, c("Scenario 1", "NULL"))),
cols = list(extend = TRUE, delta = 2, names = TRUE, delete = TRUE, multiheader = TRUE),
rows = list(extend = FALSE, delta = 1, names = FALSE, delete = FALSE),
class = "numeric"),
plotOutput("plot")
)
server <- function(input, output, session) {
sanitizedMat <- reactiveVal()
observeEvent(input$myMatrixInput, {
if(any(colnames(input$myMatrixInput) == "")){
tmpMatrix <- input$myMatrixInput
# Assign column header names
colnames(tmpMatrix) <- paste("Scenario", trunc(1:ncol(input$myMatrixInput)/2+1))
# Remove any empty matrix columns
empty_columns <- sapply(tmpMatrix, function(x) all(is.na(x) | x == ""))
tmpMatrix[, !empty_columns]
updateMatrixInput(session, inputId = "myMatrixInput", value = tmpMatrix)
}
else {sanitizedMat(na.omit(input$myMatrixInput))}
})
plotData <- reactive({
lapply(seq_len(ncol(sanitizedMat())/2),
function(i){
tibble(
Scenario = colnames(sanitizedMat())[i*2-1],
X = 1:input$periods,
Y = interpol(input$periods, sanitizedMat()[1,(i*2-1):(i*2)])
)
}) %>% bind_rows()
})
output$plot <- renderPlot({
plotData() %>% ggplot() + geom_line(aes(
x = X,
y = Y,
colour = as.factor(Scenario)
))
})
}
shinyApp(ui, server)