igroffman commited on
Commit
ebaf56b
·
verified ·
1 Parent(s): e493d7c

Update app.R

Browse files
Files changed (1) hide show
  1. app.R +54 -37
app.R CHANGED
@@ -231,10 +231,13 @@ server <- function(input, output, session){
231
  have <- intersect(names(df), num_cols)
232
  df[have] <- lapply(df[have], function(x) suppressWarnings(as.numeric(x)))
233
 
234
- df <- df %>% distinct()
 
 
 
 
 
235
 
236
- processed_data(df)
237
- plot_data(df)
238
 
239
  if ("Pitcher" %in% names(df)) {
240
  choices <- sort(unique(df$Pitcher[!is.na(df$Pitcher)]))
@@ -272,14 +275,12 @@ server <- function(input, output, session){
272
  datatable(processed_data(), options=list(scrollX=TRUE, pageLength=10), filter="top")
273
  })
274
 
275
- # pitcher-specific reactive with stable row_key (per pitcher group)
276
- pitcher_df <- reactive({
277
- req(plot_data(), input$pitcher_select)
278
- plot_data() %>%
279
- filter(Pitcher == input$pitcher_select) %>%
280
- filter(!is.na(HorzBreak), !is.na(InducedVertBreak), !is.na(RelSpeed)) %>%
281
- mutate(row_key = row_number())
282
- })
283
 
284
  output$movement_plot <- renderPlotly({
285
  d <- pitcher_df()
@@ -297,8 +298,8 @@ output$movement_plot <- renderPlotly({
297
  ),
298
  hoverinfo = "text",
299
  key = ~row_key,
300
- color = ~factor(TaggedPitchType), # <-- data-driven
301
- colors = pitch_colors, # <-- your palette
302
  marker = list(size = 10)
303
  ) |>
304
  layout(
@@ -406,13 +407,26 @@ output$location_plot <- renderPlotly({
406
  )
407
  })
408
 
409
- # ---- Apply single-change from modal ----
410
- observeEvent(input$update_pitch, {
411
- info <- selected_pitch(); req(info)
412
- new_type <- input$modal_new_pitch_type; req(new_type)
413
- cur <- plot_data(); req("Pitcher" %in% names(cur))
414
- cur <- plot_data(); req("Pitcher" %in% names(cur))
415
- cur$TaggedPitchType <- as.character(cur$TaggedPitchType)
 
 
 
 
 
 
 
 
 
 
 
 
 
416
 
417
  # map row_key back to absolute index for this pitcher slice
418
  idx_pitcher <- which(cur$Pitcher == info$pitcher)
@@ -451,25 +465,28 @@ output$location_plot <- renderPlotly({
451
  paste(nrow(sel), "points selected:", paste(names(cnt), "(", cnt, ")", collapse=", "))
452
  })
453
 
454
- # bulk change
455
- observeEvent(input$apply_bulk_change, {
456
- req(input$selection_mode == "drag")
457
- keys <- selected_keys(); req(length(keys) > 0)
458
- new_type <- input$bulk_pitch_type; req(new_type)
459
-
460
- cur <- plot_data(); req("Pitcher" %in% names(cur))
461
- idx_pitcher <- which(cur$Pitcher == input$pitcher_select)
462
- valid_keys <- keys[keys > 0 & keys <= length(idx_pitcher)]
463
- abs_rows <- idx_pitcher[valid_keys]
464
- cur$TaggedPitchType[abs_rows] <- new_type
465
 
466
- plot_data(cur); processed_data(cur)
467
- selected_keys(integer(0))
468
- showNotification(paste("Updated", length(abs_rows), "pitches to", new_type),
469
- type="message", duration=3)
470
  cur <- plot_data(); req("Pitcher" %in% names(cur))
471
- cur$TaggedPitchType <- as.character(cur$TaggedPitchType)
472
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
473
 
474
  # click info small text
475
  output$click_info <- renderText({
 
231
  have <- intersect(names(df), num_cols)
232
  df[have] <- lapply(df[have], function(x) suppressWarnings(as.numeric(x)))
233
 
234
+ df <- df %>% distinct()
235
+
236
+ if (!".uid" %in% names(df)) df$.uid <- seq_len(nrow(df))
237
+
238
+ processed_data(df)
239
+ plot_data(df)
240
 
 
 
241
 
242
  if ("Pitcher" %in% names(df)) {
243
  choices <- sort(unique(df$Pitcher[!is.na(df$Pitcher)]))
 
275
  datatable(processed_data(), options=list(scrollX=TRUE, pageLength=10), filter="top")
276
  })
277
 
278
+ pitcher_df <- reactive({
279
+ req(plot_data(), input$pitcher_select)
280
+ plot_data() %>%
281
+ filter(Pitcher == input$pitcher_select) %>%
282
+ filter(!is.na(HorzBreak), !is.na(InducedVertBreak), !is.na(RelSpeed))
283
+ })
 
 
284
 
285
  output$movement_plot <- renderPlotly({
286
  d <- pitcher_df()
 
298
  ),
299
  hoverinfo = "text",
300
  key = ~row_key,
301
+ color = ~factor(TaggedPitchType),
302
+ colors = pitch_colors,
303
  marker = list(size = 10)
304
  ) |>
305
  layout(
 
407
  )
408
  })
409
 
410
+ observeEvent(input$update_pitch, {
411
+ info <- selected_pitch(); req(info)
412
+ new_type <- input$modal_new_pitch_type; req(new_type)
413
+
414
+ cur <- plot_data(); req("Pitcher" %in% names(cur))
415
+ cur$TaggedPitchType <- as.character(cur$TaggedPitchType) # ensure character
416
+
417
+ uid <- info$uid
418
+ hit_idx <- which(cur$.uid == uid)
419
+
420
+ if (length(hit_idx) == 1) {
421
+ cur$TaggedPitchType[hit_idx] <- new_type
422
+ plot_data(cur); processed_data(cur)
423
+ removeModal()
424
+ showNotification("Updated pitch tag.", type="message", duration=3)
425
+ selected_pitch(NULL)
426
+ } else {
427
+ showNotification("Could not map selection back to dataset.", type="error")
428
+ }
429
+ })
430
 
431
  # map row_key back to absolute index for this pitcher slice
432
  idx_pitcher <- which(cur$Pitcher == info$pitcher)
 
465
  paste(nrow(sel), "points selected:", paste(names(cnt), "(", cnt, ")", collapse=", "))
466
  })
467
 
468
+ observeEvent(input$apply_bulk_change, {
469
+ req(input$selection_mode == "drag")
470
+ keys <- selected_keys(); req(length(keys) > 0)
471
+ new_type <- input$bulk_pitch_type; req(new_type)
 
 
 
 
 
 
 
472
 
 
 
 
 
473
  cur <- plot_data(); req("Pitcher" %in% names(cur))
474
+ cur$TaggedPitchType <- as.character(cur$TaggedPitchType) # ensure character
475
+
476
+ # keys from plotly are .uid values
477
+ uids <- as.integer(keys)
478
+ hit_idx <- which(cur$.uid %in% uids & cur$Pitcher == input$pitcher_select)
479
+
480
+ if (length(hit_idx) == 0) {
481
+ showNotification("No matching rows found for bulk edit.", type="warning"); return()
482
+ }
483
+
484
+ cur$TaggedPitchType[hit_idx] <- new_type
485
+ plot_data(cur); processed_data(cur)
486
+ selected_keys(integer(0))
487
+ showNotification(paste("Updated", length(hit_idx), "pitches to", new_type),
488
+ type="message", duration=3)
489
+ })
490
 
491
  # click info small text
492
  output$click_info <- renderText({