【发布时间】:2020-10-28 04:04:41
【问题描述】:
我正在尝试与 R Shiny 一起玩耍并了解更多信息。我开发了一个反应式用户界面,但我对如何实现用户选择有点卡住。
我希望用户单击“添加文本框”按钮,从下拉菜单中选择一个变量/函数并将输入应用于该函数。为简单起见,我使用 TTR 包中的 SMA 和 WMA 以及 quantmod 来收集数据。
SMA 只接受一个输入 n,而 WMA 可以接受两个输入 n 和 weights。我设法使 Shiny 应用程序根据用户选择的选择做出反应,但我现在想将这些用户选择应用于数据。也就是说,我希望能够根据用户的功能选择和输入向表中添加新列。
预期的输出将能够得到一个带有额外列的表
MSFT.Open MSFT.High MSFT.Low MSFT.Close MSFT.Volume MSFT.Adjusted SMA.2, SMA.10, WMA.10
46.66 47.42 46.54 46.76 27913900.00 41.75 NA NA NA
46.37 46.73 46.25 46.33 39673900.00 41.36 NA NA NA
46.38 46.75 45.54 45.65 36447900.00 40.76 999 NA NA
45.98 46.46 45.49 46.23 29114100.00 41.28 999 NA NA
46.75 47.75 46.72 47.59 29645200.00 42.49 999 NA NA
(这里数据的head 将包含除 SMA.2 列之外的 NA)。我认为用户接口很好(如果我错了,请纠正我),我现在需要插入并应用到server 函数。
我希望用户可以根据需要添加任意数量的SMA 和WMA 函数(和列)。
R 代码:
downloadFinancialData <- function(symbol, start, end){
data <- getSymbols(Symbols = symbol, src = "yahoo", index.class = "POSIXct", from = start, to = end, auto.assign = FALSE)
# we can compute the returns and some other things inside this function so we can later plot for the user.
}
symbol = "MSFT"
start = "2018-01-01"
end = "2019-01-01"
data = downloadFinancialData(symbol = symbol, start = start, end = end)
n = 10
SMA(Cl(data), n = n)
WMA(Cl(data), n = n, wts = 1:n)
WMA(Cl(data), n = n, wts = rep(weights, times = nrow(data)))
闪亮的代码:
library(shiny)
library(quantmod)
dist <- c("SMA", "WMA")
add_box <- function(id){
ns <- NS(id)
tags$div(id = paste0("indicatorChoiceBox", id),
selectInput(inputId = ns("indicatorChoiceSelection"),
label = paste0("Variable ", id),
choices = dist),
conditionalPanel(
condition = "input.indicatorChoiceSelection=='SMA'",
ns = ns,
column(width = 3, numericInput(ns('nSMAPeriodSelection'), 'Number of Periods', value = '0'))
),
conditionalPanel(
condition = "input.indicatorChoiceSelection=='WMA'",
ns = ns,
column(width = 3, numericInput(ns('nWMAPeriodSelection'), 'Number of Periods', value = '0')),
column(width = 3, numericInput(ns('weightsWMAPeriodSelection'), 'Weights', value = '0'))
)
)
}
downloadFinancialData <- function(symbol, start, end){
data <- getSymbols(Symbols = symbol, src = "yahoo", index.class = "POSIXct", from = start, to = end, auto.assign = FALSE)
# we can compute the returns and some other things inside this function so we can later plot for the user.
}
#####################################################################################
ui <- shinyUI(fluidPage(
sidebarPanel(
# 1.a) Collect financial data:
wellPanel(
textInput(inputId = "symbolInput", label = "Symbol", value = "MSFT"),
dateRangeInput(inputId = "stockDateRange", label = "Dates", start = "2015-01-01", end = "2018-01-01")
),
actionButton("addIndicator", "Add Textbox"),
actionButton("rmIndicator", "Remove Textbox"),
textOutput("counter")
),
mainPanel(
tableOutput("stockData"),
column(width = 12, id = "column")
)
))
server <- shinyServer(function(input, output, session) {
###########################################
# 1.a) Process financial data:
stockData <- reactive({
symbol = input$symbolInput
start = input$stockDateRange[1]
end = input$stockDateRange[2]
data = downloadFinancialData(symbol = symbol, start = start, end = end)
# Modify data here depending on the users function selection and value input
})
output$stockData <- renderTable({
hd <- head(stockData())
tl <- tail(stockData())
out <- rbind(hd, tl)
})
###########################################
###########################################
# Track the number of input boxes to render
counter <- reactiveValues(n = 0)
# Track all user inputs
AllInputs <- reactive({
x <- reactiveValuesToList(input)
})
observeEvent(input$addIndicator, {
counter$n <- counter$n + 1
insertUI(selector = "#column",
where = "beforeEnd",
ui = add_box(counter$n)
)
})
observeEvent(input$rmIndicator, {
if (counter$n > 0) {
removeUI(selector = paste0("#indicatorChoiceBox", counter$n))
counter$n <- counter$n - 1
}
})
output$counter <- renderPrint(print(counter$n))
###########################################
})
shinyApp(ui, server)
【问题讨论】: