I'm trying to make a shinyapp for NBA play-by-play data which can subset the data based on which players are on or off the court for that play. The shiny app is functional, but I'm having trouble with the syntax of choosing when a player is ON the court.
The relevant columns of the base data I'm working looks like this:
pbp_shiny
# A tibble: 20 x 4
# Groups: team_final [1]
team_final play_number team_player description
<chr> <dbl> <chr> <chr>
1 DAL 462084 Delon Wright NA
2 DAL 462084 Tim Hardaway Jr. NA
3 DAL 462084 Maxi Kleber NA
4 DAL 462084 Willie Cauley-Stein NA
5 DAL 462084 Luka Doncic NA
6 DAL 462083 Delon Wright Cauley-Stein REBOUND (Off:1 Def:6)
7 DAL 462083 Tim Hardaway Jr. Cauley-Stein REBOUND (Off:1 Def:6)
8 DAL 462083 Maxi Kleber Cauley-Stein REBOUND (Off:1 Def:6)
9 DAL 462083 Willie Cauley-Stein Cauley-Stein REBOUND (Off:1 Def:6)
10 DAL 462083 Luka Doncic Cauley-Stein REBOUND (Off:1 Def:6)
11 DAL 462082 Delon Wright MISS Murray 28' 3PT Jump Shot
12 DAL 462082 Tim Hardaway Jr. MISS Murray 28' 3PT Jump Shot
13 DAL 462082 Maxi Kleber MISS Murray 28' 3PT Jump Shot
14 DAL 462082 Willie Cauley-Stein MISS Murray 28' 3PT Jump Shot
15 DAL 462082 Luka Doncic MISS Murray 28' 3PT Jump Shot
16 DAL 462081 Delon Wright Wright Bad Pass Turnover (P2.T11): Craig STEAL (1 STL)
17 DAL 462081 Tim Hardaway Jr. Wright Bad Pass Turnover (P2.T11): Craig STEAL (1 STL)
18 DAL 462081 Maxi Kleber Wright Bad Pass Turnover (P2.T11): Craig STEAL (1 STL)
19 DAL 462081 Willie Cauley-Stein Wright Bad Pass Turnover (P2.T11): Craig STEAL (1 STL)
20 DAL 462081 Luka Doncic Wright Bad Pass Turnover (P2.T11): Craig STEAL (1 STL)
There are always 5 players on the floor for a team in basketball. So, play_number
identifies which play it is, and team_player
shows each player on the floor during that play. I must keep the format like this for other reasons.
The widgets for choosing which players are ON or OFF the court are written as uiOutput
in the UI (the player options are dependent on which team is selected in another widget). On the server side, they look like this:
output$player_off <- renderUI({
selectizeInput(
"player_off",
"WITHOUT:",
choices = c(player_list$team_player[player_list$team_final==input$team_filter]),
multiple = TRUE
)
})
output$player_on <- renderUI({
selectizeInput(
"player_on",
"WITH:",
choices = c(player_list$team_player[player_list$team_final==input$team_filter]),
multiple = TRUE
)
})
and now here's the actual code I'm using to subset the data based on who is ON and OFF the court:
subset(pbp_shiny, ave(!(team_player %in% input$player_off), play_number, FUN = all) & ave(team_player %in% input$player_on, play_number, FUN = any))
I know the player_off
side is correct -- regardless of how many (even zero) players are chosen to be OFF, it will keep all play_number
which DO NOT include those players.
The player_on
side is where I'm struggling -- after adding it in, the shiny app only subsets correctly when EXACTLY one player is chosen to be on the court. If 0 or more than 1 are chosen, it subsets pbp_shiny
down to 0 observations. I understand why, since FUN = any
, but I'm struggling with a solution.