在 R 中,为什么 运行 这个函数时我得到的维数不正确?

In R, why am I getting incorrect number of dimensions when running this function?

下面的 MWE 代码按原样呈现 运行。但是,当我注释掉当前未注释的自定义 interpol() 函数,并取消注释已注释掉的较长 interpol() 函数时,我收到“维数不正确”错误。当 2 个函数的输出在结构(我认为)方面非常相似时。 运行 宁第二个 interpol() 时如何消除此错误?

第二个较长的 interpol() 函数不应像第一个那样在这个缩减的 MWE 中进行插值(它在完全部署时会做其他事情,包括但不限于插值):在默认情况下它应该在周期 1 中绘制 5,之后绘制 0。如果用户输入 3 和 5,它应该在前 3 个周期绘制 5,之后绘制 0。

当我 运行 R studio 控制台中的 2 个函数时,我得到了下图中显示的内容。第一张图片用于较短的 interpol() (它进行插值),第二张图片用于较长的 interpol() 函数(尚未准备好在此 MWE 中进行插值)。所以两者都可以在 R Studio 控制台中正常工作,但第二个会使应用程序崩溃!

MWE 代码:

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)
}

# interpol <- function(a, b) { # [a] = modeled periods, [b] = matrix inputs
#   c <- b
#   c[,1][c[,1] > a] <- a
#   d <- diff(c[,1, drop = FALSE])
#   d[d <= 0] <- NA
#   d <- c(1,d)
#   c <- cbind(c,d)
#   c <- na.omit(c)
#   c <- c[,-c(3),drop=FALSE]
#   e <- rep(NA, a)
#   e[c[,1]] <- c[,2]
#   e[seq_len(min(c[,1])-1)] <- e[min(c[,1])]
#   if(max(c[,1]) < a){e[seq(max(c[,1]) + 1, a, 1)] <- 0}
#   e <- approx(seq_along(e)[!is.na(e)], e[!is.na(e)], seq_along(e))$y # interpolates
#  return(e)
# }

ui <- fluidPage(
  sliderInput('periods', 'Periods to interpolate:', min=2, max=10, value=10),
  matrixInput(
    "myMatrixInput",
    label = "Values to interpolate:",
    value =  matrix(c(2, 5), 1, 2),
    cols = list(names = FALSE),
    rows = list(names = FALSE),
    class = "numeric"),
  plotOutput("plot")
)

server <- function(input, output, session) {
  
  observeEvent(input$myMatrixInput, {
    tmpMatrix <- input$myMatrixInput
    # isolate( # isolate update to prevent infinite loop
      updateMatrixInput(session, inputId = "myMatrixInput", value = tmpMatrix)
    # )
  })
  
    plotData <- reactive({
    tibble(
      X = seq_len(input$periods),
      Y = interpol(input$periods, input$myMatrixInput[1,1:2])
    )
  })
  
  output$plot <- renderPlot({
    req(plotData())
    plotData() %>% ggplot() + geom_line(aes(
      x = X,
      y = Y
      ))  
    })
}

shinyApp(ui, server)

更短的 interpol() 函数:

更长的interpol()函数:

请参阅下面解析的功能代码。关键修复是将 drop = FALSE 添加到每个 rawr 评论的矩阵索引。增强功能的其他更改包括添加 lapply()“循环”以创建动态矩阵索引以反映每个用户输入 expands/contracts 的矩阵,以及隔离 updateMatrixInput() 函数。

interpol <- function(a, b) {
  
  # [a] = modeled periods, [b] = matrix inputs
  c <- b
  
  # Assign < of modeled periods [a] and max periods per matrix [b] left-col to matrix [c]
  c[,1][c[,1] > a] <- a
  
  # Ensure matrix [b] left-column period inputs are in increasing order
  d <- diff(c[,1, drop = FALSE])
  d[d <= 0] <- NA
  d <- c(1,d)
  c <- cbind(c,d)
  c <- na.omit(c)
  c <- c[,-c(3),drop=FALSE]
  
  ### Interpolate [b] matrix right-col variables###
  e <- rep(NA, a)
  
  # Places each [b] matrix right-col variable in position indicated by its left-col period
  e[c[,1]] <- c[,2]
  
  # If 1st period in [b] matrix left-col > 1, applies its right-col variable to all periods <= [b] matrix 1st period
  e[seq_len(min(c[,1])-1)] <- e[min(c[,1])]
  
  # Applies 0 to all periods after max period in [b] matrix left-col up to period [a]
  if(max(c[,1]) < a){e[seq(max(c[,1]) + 1, a, 1)] <- 0}
  
  # Interpolates
  e <- approx(seq_along(e)[!is.na(e)], e[!is.na(e)], seq_along(e))$y
  ### End interpolation ###
  return(e)
}

ui <- fluidPage(
  sliderInput('periods', 'Modeled periods:', min=1, max=10, value=10),
  matrixInput(
    "myMatrixInput",
    label = "Period (X) to apply variable (Y) are paired under each scenario heading:",
    value =  matrix(c(1, 5), 1, 2, dimnames = list(NULL, rep("Scenario 1", 2))),
    cols = list(extend = TRUE, delta = 2, names = TRUE, delete = TRUE, multiheader = TRUE),
    rows = list(extend = TRUE, delta = 1, names = TRUE, delete = TRUE),
    class = "numeric"),
  plotOutput("plot")
)

server <- function(input, output, session) {
  
  observeEvent(input$myMatrixInput, {
    if(any(colnames(input$myMatrixInput) == "")){
      tmpMatrix <- input$myMatrixInput
      colnames(tmpMatrix) <- paste("Scenario",rep(1:ncol(tmpMatrix),each=2,length.out=ncol(tmpMatrix)))
      isolate(updateMatrixInput(session, inputId = "myMatrixInput", value = tmpMatrix))
      }
    input$myMatrixInput
  })
  
  plotData <- reactive({
    tryCatch(
      lapply(seq_len(ncol(input$myMatrixInput)/2), # column counter to set matrix index as it expands
         function(i){
             tibble(
               Scenario = colnames(input$myMatrixInput)[i*2-1],
               X = seq_len(input$periods),
               Y = interpol(input$periods,input$myMatrixInput[,(i*2-1):(i*2), drop = FALSE])
             )
          }) %>% bind_rows(),
      error = function(e) NULL
    )
  })
  
  output$plot <- renderPlot({
    req(plotData())
    plotData() %>% ggplot() + 
      geom_line(aes(
        x = X,
        y = Y,
        colour = as.factor(Scenario)
      )) +
      theme(legend.title=element_blank())
  })
  
}

shinyApp(ui, server)