下面是我的闪亮应用程序中使用的代码的演示 - 它包含了我的完整应用程序的所有重要元素,最重要的是,我的问题被重现。
我闪亮的应用程序的一个重要部分是,只有当另一个窗口小部件设置为某个值时,才会显示某些窗口小部件。在这种情况下,shotchart.input是主窗口小部件,然后只有在shotchart.input设置为特定值时才会出现playerseason.input和teamgame.input窗口小部件。在我的UI中,我在uiOutput()函数中传递了这些第二和第三个小部件。
在我的服务器中,我也为这两个小部件中的每一个都有了renderUI函数。这些小部件的下拉选项取决于对我的主数据帧的某些过滤(不是在我的示例中,而是在我的主应用程序中),因此在服务器中创建这些小部件非常重要。
我的问题如下 - 当我启动应用程序时,暂时存在“非字符参数”错误。然后,当我将第一个小部件的值更改为Shot Marker Graph(团队游戏)时,我得到另一个分秒错误,这次“结果必须长度为20,而不是0”。
我认为这是因为,在我的renderPlotly()函数中,我有这样的代码行:
fname <- strsplit(input$player.id, split = ' ')[[1]][1]
和其他小部件
this.t2 <- input$team.id
all.pbp <- all.pbp %>% filter(team == this.t2)
依赖于反应输入参数输入$ player.id并输入$ team.id。我的想法是这些输入参数需要大约1秒来获取值,因此在启动应用程序和切换主窗口小部件时会很快发生这些错误。
从用户体验的角度来看,这些错误看起来很糟糕,更重要的是,让我觉得我在这里没有正确使用renderUI和uiOutput。任何关于如何摆脱这些分裂错误消息/更好的编码实践的想法将不胜感激。谢谢!
以下应用程序:
# Pre-Processing
all.pbp <- structure(list(team = c("BOS", "CLE", "BOS", "CLE", "BOS", "BOS",
"CLE", "CLE", "BOS", "CLE", "BOS", "CLE", "BOS", "CLE", "BOS",
"BOS", "CLE", "BOS", "BOS", "BOS"), lastname = c("Irving", "Rose",
"Hayward", "Love", "Tatum", "Horford", "Crowder", "Wade", "Brown",
"Rose", "Hayward", "Rose", "Irving", "Wade", "Irving", "Brown",
"Crowder", "Horford", "Brown", "Brown"), firstname = c("Kyrie",
"Derrick", "Gordon", "Kevin", "Jayson", "Al", "Jae", "Dwyane",
"Jaylen", "Derrick", "Gordon", "Derrick", "Kyrie", "Dwyane",
"Kyrie", "Jaylen", "Jae", "Al", "Jaylen", "Jaylen"), yloc = c(789L,
55L, 751L, 134L, 866L, 699L, 107L, 86L, 883L, 62L, 798L, 296L,
858L, 66L, 768L, 873L, 309L, 667L, 748L, 876L), xloc = c(251L,
232L, 464L, 119L, 240L, 203L, 467L, 133L, 261L, 245L, 259L, 346L,
257L, 398L, 141L, 248L, 197L, 133L, 468L, 255L)), .Names = c("team",
"lastname", "firstname", "yloc", "xloc"), class = "data.frame", row.names = c(NA, 20L))
shotchart.types <- c('Shot Marker Graph (Player-Season)', 'Shot Marker Graph (Team-Game)')
names(shotchart.types) <- shotchart.types
# The UI
ui <- fluidPage(fluidRow(
column(width = 3, align = 'center',
h3('Chart Type'), hr(),
# create permanent input for shot chart type (should be 5 options)
selectInput(inputId = 'shotchart.input', label = 'Select Shot Chart Type:', multiple = FALSE,
choices = shotchart.types, selected = 'Shot Marker Graph (Player-Season)'),
uiOutput('playerseason.input'),
uiOutput('teamgame.input')
),
# 2.C Launch the Chart
# ===-===-===-===-===-===
column(width = 8, align = 'left',
plotlyOutput("shotplot")
)
)
)
# The Server
server <- shinyServer(function(input, output) {
# 3.A widgets whose appearance is conditional on another widget value
# ===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===
# select player for player-season graph
output$playerseason.input <- renderUI({
if(input$shotchart.input == 'Shot Marker Graph (Player-Season)') {
all.players <- unique(paste(all.pbp$firstname, all.pbp$lastname))
names(all.players) <- all.players
selectInput(inputId = 'player.id', label = 'Select Player:', multiple = FALSE,
choices = all.players, selected = 'Kyrie Irving')
} else{
return(NULL)
}
})
# select team for team-game graph
output$teamgame.input <- renderUI({
if(input$shotchart.input == 'Shot Marker Graph (Team-Game)') {
all.teams <- unique(all.pbp$team)
names(all.teams) <- all.teams
selectInput(inputId = 'team.id', label = 'Select Team:', multiple = FALSE,
choices = all.teams, selected = 'BOS')
} else{
return(NULL)
}
})
# 3.B The Plot
# ===-===-===-===
output$shotplot <- renderPlotly({
# first plot, based on chart type widget
if(input$shotchart.input == 'Shot Marker Graph (Player-Season)') {
fname <- strsplit(input$player.id, split = ' ')[[1]][1]
lname <- strsplit(input$player.id, split = ' ')[[1]][2]
all.pbp <- all.pbp %>% filter(firstname == fname, lastname == lname)
print(fname);
print(lname);
print(all.pbp);
plot_ly(all.pbp) %>%
add_trace(x = ~xloc, y = ~yloc, type = 'scatter', mode = 'markers')
}
# second plot, also based on chart type widget
else if(input$shotchart.input == 'Shot Marker Graph (Team-Game)') {
this.t2 <- input$team.id
all.pbp <- all.pbp %>% filter(team == this.t2)
plot_ly(all.pbp) %>%
add_trace(x = ~xloc, y = ~yloc, type = 'scatter', mode = 'markers')
}
})
})
shinyApp(ui, server)
答案 0 :(得分:1)
嗨,这些问题来自输入字段的动态呈现。它们不是在第一次计算图表时启动的。但是一旦启动,情节就会重新计算,一切正常。
Shiny具有函数req
只是为了这个目的,你可以测试一个变量是否真实,即有一个值。如果不是,则使用静音警告取消计算。以下是它如何适用于您的情况。我刚刚在两个地方添加了req()
,它运行正常。
server <- shinyServer(function(input, output) {
# 3.A widgets whose appearance is conditional on another widget value
# ===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===-===
# select player for player-season graph
output$playerseason.input <- renderUI({
if(input$shotchart.input == 'Shot Marker Graph (Player-Season)') {
all.players <- unique(paste(all.pbp$firstname, all.pbp$lastname))
names(all.players) <- all.players
selectInput(inputId = 'player.id', label = 'Select Player:', multiple = FALSE,
choices = all.players, selected = 'Kyrie Irving')
} else{
return(NULL)
}
})
# select team for team-game graph
output$teamgame.input <- renderUI({
if(input$shotchart.input == 'Shot Marker Graph (Team-Game)') {
all.teams <- unique(all.pbp$team)
names(all.teams) <- all.teams
selectInput(inputId = 'team.id', label = 'Select Team:', multiple = FALSE,
choices = all.teams, selected = 'BOS')
} else{
return(NULL)
}
})
# 3.B The Plot
# ===-===-===-===
output$shotplot <- renderPlotly({
# first plot, based on chart type widget
if(input$shotchart.input == 'Shot Marker Graph (Player-Season)') {
req(input$player.id)
fname <- strsplit(input$player.id, split = ' ')[[1]][1]
lname <- strsplit(input$player.id, split = ' ')[[1]][2]
all.pbp <- all.pbp %>% filter(firstname == fname, lastname == lname)
print(fname);
print(lname);
print(all.pbp);
plot_ly(all.pbp) %>%
add_trace(x = ~xloc, y = ~yloc, type = 'scatter', mode = 'markers')
}
# second plot, also based on chart type widget
else if(input$shotchart.input == 'Shot Marker Graph (Team-Game)') {
req(input$team.id)
this.t2 <- input$team.id
all.pbp <- all.pbp %>% filter(team == this.t2)
plot_ly(all.pbp) %>%
add_trace(x = ~xloc, y = ~yloc, type = 'scatter', mode = 'markers')
}
})
})