在 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)
下面的 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)