Nothing
cols <- c(
"pitch_type", "game_date", "release_speed",
"release_pos_x", "release_pos_z", "player_name",
"batter", "pitcher", "events", "description", "spin_dir",
"spin_rate_deprecated", "break_angle_deprecated",
"break_length_deprecated", "zone", "des", "game_type", "stand",
"p_throws", "home_team", "away_team", "type", "hit_location",
"bb_type", "balls", "strikes", "game_year", "pfx_x", "pfx_z",
"plate_x", "plate_z", "on_3b", "on_2b", "on_1b", "outs_when_up",
"inning", "inning_topbot", "hc_x", "hc_y", "tfs_deprecated",
"tfs_zulu_deprecated", "fielder_2", "umpire", "sv_id",
"vx0", "vy0", "vz0", "ax", "ay", "az", "sz_top", "sz_bot",
"hit_distance_sc", "launch_speed", "launch_angle", "effective_speed",
"release_spin_rate", "release_extension", "game_pk",
"fielder_3", "fielder_4",
"fielder_5", "fielder_6", "fielder_7", "fielder_8",
"fielder_9", "release_pos_y", "estimated_ba_using_speedangle",
"estimated_woba_using_speedangle", "woba_value",
"woba_denom", "babip_value", "iso_value", "launch_speed_angle",
"at_bat_number", "pitch_number", "pitch_name", "home_score",
"away_score", "bat_score", "fld_score", "post_away_score",
"post_home_score", "post_bat_score", "post_fld_score",
"if_fielding_alignment", "of_fielding_alignment",
"spin_axis", "delta_home_win_exp", "delta_run_exp", "bat_speed", "swing_length",
"miss_distance"
)
# Subset-direction assertion (including the newer bat_speed/swing_length
# columns) guards the length-tolerant column assignment that keeps
# statcast_search() from breaking when Baseball Savant adds columns
# (#337, #354, #371, #390).
test_that("Statcast Search", {
skip_statcast_test()
skip_on_cran()
x <- statcast_search(start_date = "2022-11-04",
end_date = "2022-11-06")
if (is.null(x) || !is.data.frame(x) || nrow(x) == 0) {
skip("No rows returned from Baseball Savant at test time")
}
expect_in(sort(cols), sort(colnames(x)))
expect_s3_class(x, "data.frame")
})
# Baseball Savant exports blank fields as empty strings. Numeric columns coerce
# to NA for free, but character columns (events, des, description, ...) used to
# keep "" -- which downstream helpers such as metrics_linear_weights_savant()
# do not treat as missing (#275). This is a pure, network-free parse test.
test_that("process_statcast_payload normalizes empty character fields to NA (#275)", {
testthat::skip_on_cran()
# csv_from_url() returns a data.table, so exercise that class here -- a plain
# data.frame would not catch class-specific indexing bugs.
payload <- data.table::as.data.table(as.data.frame(
matrix("", nrow = 2, ncol = length(cols), dimnames = list(NULL, cols)),
stringsAsFactors = FALSE
))
payload$game_date <- c("2022-06-01", "2022-06-01")
payload$events <- c("single", "") # blank PA outcome -> NA
payload$des <- c("", "Foul.") # blank description -> NA
payload$description <- c("hit_into_play", "foul")
# Input is a data.table (as from csv_from_url); convert the result to a plain
# data.frame only for convenient column-wise inspection below.
out <- as.data.frame(suppressWarnings(process_statcast_payload(payload)))
# Blank coerced to NA, real values preserved.
expect_true(is.na(out$events[2]))
expect_identical(out$events[1], "single")
expect_true(is.na(out$des[1]))
expect_identical(out$des[2], "Foul.")
# No character column should retain a whitespace-only value.
char_cols <- names(out)[vapply(out, is.character, logical(1))]
has_blank <- vapply(
out[char_cols],
function(x) any(!is.na(x) & trimws(x) == ""),
logical(1)
)
expect_false(any(has_blank))
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.