我正在构建我的第一个 Shiny 应用程序,目的是创建一个抵押计算器和可调整的摊销计划。我可以使用 runApp() 获得以下代码来呈现,但它不起作用(即,不输出任何值,也不显示图形)。此外,它会在 RStudio 的控制台中生成以下错误:
“.getReactiveEnvironment()$currentContext() 中的错误:如果没有活动的反应上下文,则不允许操作。(您试图做一些只能从反应表达式或观察者内部完成的事情。)”
对于背景,我正在运行:Win 7, 64-bit OS | R v3.1.1 | RStudio v0.98.944
并尝试实现此处定义的过程但没有运气: R R Shiny 中的 Shiny Tutorial Error - Numeric Input without Selectors
用户界面
library(shiny)
shinyUI(
pageWithSidebar(
headerPanel(
h1('Amoritization Simulator for Home Mortgages'),
windowTitle = "Amoritization Simulator"
),
sidebarPanel(
h3('Mortgage Information'),
h4('Purchase Price'),
p('Enter the total sale price of the home'),
textInput('price', "Sale Price ($USD)", value = ""),
h4('Percent Down Payment'),
p('Use the slider to select the percent of the purchase price you
intend to pay as a down payment at the time of purchase'),
sliderInput('per.down', "% Down Payment", value = 20, min = 0, max = 30, step = 1),
h4('Interest Rate (APR)'),
p('Use the slider to select the interest rate of the loan expressed
as an Annual Percentage Rate (APR)'),
sliderInput('apr', "APR", value = 4, min = 0, max = 8, step = 0.125),
h4('Term Length (Years)'),
p('Use the buttons to define the term of the loan'),
radioButtons('term', "Loan Term (Years)", choices = c(15, 30), selected = 30),
submitButton('Calculate')
),
mainPanel(
h3('Payment and Amoritization Simulation'),
p('Use this tool to determine your monthly mortgage payment,
how much interest you will owe over the life of the loan, and how
you can reduce that amount with additional payment'),
h4('Monthly Payment (Principal and Interest)'),
p('This is the amount (in $USD) you would pay each month for a
mortgage under the terms you defined'),
verbatimTextOutput("base.monthly.payment"),
h4('Total Interest Over Life of Loan'),
p('If paying just that amount per month, this is the total amount
in $USD you will spend on interest for that loan'),
verbatimTextOutput("base.total.interest"),
h4('Additional Principal Simulation'),
p('One way to reduce the interest expense is to pay more principal
each month. Use the slider below to select an additional amount to
include with your payment and see the reduction in interest expense
for the life of the loan.'),
sliderInput('add', "Additional Principal ($USD)", value = 250, min = 0, max = 1000, step = 25),
p('Interest costs saved with this additional principal (in $USD)'),
verbatimTextOutput("savings"),
p('You will also pay the loan off the loan this many months early'),
verbatimTextOutput("early"),
plotOutput('plot')
)
)
)
服务器.R
library(shiny)
library(ggplot2)
library(scales)
shinyServer(
function(input, output) {
## determine baseline payment and interest total
price <- reactive({as.numeric(input$price)})
per.down <- reactive({input$per.down / 100})
int <- reactive({input$apr / 1200})
n <- reactive({input$term * 12})
base.monthly.payment <- (int() * price() * (1 - per.down()) * ((1 + int())^n())) / (((1 + int())^n()) - 1)
output$base.monthly.payment <- renderPrint({base.monthly.payment})
base.total.interest <- (base.monthly.payment * n()) - (price() * (1 - per.down()))
output$base.total.interest <- renderPrint({base.total.interest})
## create dataframe to populate with increments of additional payment
schedule <- data.frame(matrix(data = NA, nrow = 41, ncol = 6,
dimnames = list(1:41, c("add", "add.n",
"prin", "add.total.interest",
"savings", "early"))))
## initialize 'for' loop to populate possible amoritization totals
c <- 1
for (i in seq(0, 1000, 25)) {
schedule$add[c] <- i
schedule$add.n[c] <- log(((base.monthly.payment + i) / int()) / (((base.monthly.payment + i) / int()) - (price() * (1 - per.down())))) / log(1 + int())
schedule$prin[c] <- round(price() * (1 - per.down()), digits = 2)
schedule$add.total.interest[c] <- round(((base.monthly.payment + i) * schedule$add.n[c]) - schedule$prin[c], digits = 2)
schedule$savings[c] <- round(base.total.interest - schedule$add.total.interest[c], digits = 2)
schedule$early[c] <- round(n() - schedule$add.n[c], digits = 0)
c <- c + 1
}
add <- reactive({input$add})
output$savings <- renderPrint({schedule$savings[which(schedule$add == add())]})
output$early <- renderPrint({schedule$early[which(schedule$add == add())]})
## create data.frame suitable for plotting
graph.data <- data.frame(matrix(data = NA, nrow = 82, ncol = 3,
dimnames = list(1:82, c("add", "amount", "type"))))
c <- 1
for (i in seq(0, 1000, 25)) {
graph.data$add[c] <- i
graph.data$add[c + 1] <- i
graph.data$amount[c] <- schedule$prin[which(schedule$add == i)]
graph.data$amount[c + 1] <- schedule$add.total.interest[which(schedule$add == i)]
graph.data$type[c] <- "Principal"
graph.data$type[c + 1] <- "Interest"
c <- c + 2
}
## create plot of amoritization with line for additional principal amount
output$plot <- renderPlot({
ggplot(graph.data, aes(x = add, y = amount), color = type)
+ geom_area(aes(fill = type), position = 'stack', alpha = 0.75)
+ geom_vline(xintercept = add(), color="black", linetype = "longdash", size = 1)
+ labs(x = "Additional Principal/Month", y = "Total Cost")
+ scale_fill_manual(values=c("firebrick3", "dodgerblue3"), name = "Payment Component")
+ theme(axis.title.x = element_text(face = "bold", vjust = -0.7, size = 16),
axis.title.y = element_text(face = "bold", vjust = 2, size = 16),
axis.text.x = element_text(size = 14),
axis.text.y = element_text(size = 14),
panel.margin = unit(c(5, 5, 5, 5), "mm"),
plot.margin = unit(c(5, 5, 5, 5), "mm"),
panel.background = element_blank(),
panel.grid.major.y = element_line(colour = "gray"),
panel.grid.minor.y = element_line(colour = "gray86"),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank())
+ scale_x_continuous(labels = dollar)
+ scale_y_continuous(labels = dollar)
})
})
提前感谢您的帮助!