In_Class activty 9: Choosing among different players.

Suppose you are the General Manager of a baseball team, and you are selecting two players for your team. You have a budget of $10,500,000, and you have the choice between the following players: Player Name OBP SLG Salary Yandy Diaz 0.403 0.511 $8,000,000 Joey Meneses 0.320 0.366 $723,600 Jose Abreu 0.292 0.358 $19,500,000 Ryan Noda 0.384 0.400 $720,000 Nate Lowe 0.365 0.426 $4,050,000

Given your budget and the player statistics, which two players would you select?

Goal: pick two palyers maximizing combined offensive production (OPS = OBP + SLG) subject to total salary <= $10,500,000

install.packages("dplyr")
trying URL 'http://rspm/default/__linux__/noble/latest/src/contrib/dplyr_1.2.1.tar.gz'
Content type 'application/x-gzip' length 1528942 bytes (1.5 MB)
==================================================
downloaded 1.5 MB


The downloaded source packages are in
    ‘/tmp/Rtmp0CHNGl/downloaded_packages’
library(dplyr)
# Build the player pool from the assignment table
players <- data.frame(
  name   = c("Yandy Diaz", "Joey Meneses", "Jose Abreu", "Ryan Noda", "Nate Lowe"),
  OBP    = c(0.403, 0.320, 0.292, 0.384, 0.365),
  SLG    = c(0.511, 0.366, 0.358, 0.400, 0.426),
  salary = c(8000000, 723600, 19500000, 720000, 4050000)
)
# OPS is the standard sabermetric summary of a hitter's offensive value
players$OPS <- players$OBP + players$SLG

budget <- 10500000
# Enumerate every 2-player combination, then filter by the budget constraint
combos <- as.data.frame(t(combn(nrow(players), 2)))
names(combos) <- c("i", "j")

combos <- combos %>%
  mutate(
    player1     = players$name[i],
    player2     = players$name[j],
    total_salary = players$salary[i] + players$salary[j],
    total_OPS    = players$OPS[i]    + players$OPS[j]
  ) %>%
  filter(total_salary <= budget) %>%           # keep only affordable pairs
  arrange(desc(total_OPS)) %>%                 # rank by combined production
  select(player1, player2, total_salary, total_OPS)

combos

The two players that we would select based on the budget are: Yandy Diaz and Ryan Noda because this two maximizes combine offensive production (OPS = 1.698) while staying within the $10.5M budget at a total cost of $8.72M.

# Pretty-print salaries for the final table
knitr::kable(
  combos,
  col.names = c("Player 1", "Player 2", "Total Salary", "Total OPS"),
  format.args = list(big.mark = ",", scientific = FALSE),
  caption = "Affordable 2-player combinations ranked by combined OPS"
)
Affordable 2-player combinations ranked by combined OPS
Player 1 Player 2 Total Salary Total OPS
Yandy Diaz Ryan Noda 8,720,000 1.698
Yandy Diaz Joey Meneses 8,723,600 1.600
Ryan Noda Nate Lowe 4,770,000 1.575
Joey Meneses Nate Lowe 4,773,600 1.477
Joey Meneses Ryan Noda 1,443,600 1.470
LS0tCnRpdGxlOiAiQ2hvb3NpbmcgYW1vbmcgZGlmZmVyZW50IHBsYXllcnMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCiMjIEluX0NsYXNzIGFjdGl2dHkgOTogQ2hvb3NpbmcgYW1vbmcgZGlmZmVyZW50IHBsYXllcnMuCgpTdXBwb3NlIHlvdSBhcmUgdGhlIEdlbmVyYWwgTWFuYWdlciBvZiBhIGJhc2ViYWxsIHRlYW0sIGFuZCB5b3UgYXJlIHNlbGVjdGluZyB0d28gcGxheWVycyBmb3IgeW91ciB0ZWFtLiBZb3UgaGF2ZSBhIGJ1ZGdldCBvZiAkMTAsNTAwLDAwMCwgYW5kIHlvdSBoYXZlIHRoZSBjaG9pY2UgYmV0d2VlbiB0aGUgZm9sbG93aW5nIHBsYXllcnM6ClBsYXllciBOYW1lICAgICBPQlAgICAgIFNMRyAgICAgU2FsYXJ5CllhbmR5IERpYXogICAgICAwLjQwMyAgIDAuNTExICAgJDgsMDAwLDAwMApKb2V5IE1lbmVzZXMgICAgMC4zMjAgICAwLjM2NiAgICQ3MjMsNjAwCkpvc2UgQWJyZXUgICAgICAwLjI5MiAgIDAuMzU4ICAgJDE5LDUwMCwwMDAKUnlhbiBOb2RhICAgICAgIDAuMzg0ICAgMC40MDAgICAkNzIwLDAwMApOYXRlIExvd2UgICAgICAgMC4zNjUgICAwLjQyNiAgICQ0LDA1MCwwMDAKCgpHaXZlbiB5b3VyIGJ1ZGdldCBhbmQgdGhlIHBsYXllciBzdGF0aXN0aWNzLCB3aGljaCB0d28gcGxheWVycyB3b3VsZCB5b3Ugc2VsZWN0PwoKR29hbDogcGljayB0d28gcGFseWVycyBtYXhpbWl6aW5nIGNvbWJpbmVkIG9mZmVuc2l2ZSBwcm9kdWN0aW9uIChPUFMgPSBPQlAgKyBTTEcpCiAgc3ViamVjdCB0byB0b3RhbCBzYWxhcnkgPD0gJDEwLDUwMCwwMDAKCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCJkcGx5ciIpCmBgYAoKYGBge3J9CmxpYnJhcnkoZHBseXIpCmBgYAoKCmBgYHtyfQojIEJ1aWxkIHRoZSBwbGF5ZXIgcG9vbCBmcm9tIHRoZSBhc3NpZ25tZW50IHRhYmxlCnBsYXllcnMgPC0gZGF0YS5mcmFtZSgKICBuYW1lICAgPSBjKCJZYW5keSBEaWF6IiwgIkpvZXkgTWVuZXNlcyIsICJKb3NlIEFicmV1IiwgIlJ5YW4gTm9kYSIsICJOYXRlIExvd2UiKSwKICBPQlAgICAgPSBjKDAuNDAzLCAwLjMyMCwgMC4yOTIsIDAuMzg0LCAwLjM2NSksCiAgU0xHICAgID0gYygwLjUxMSwgMC4zNjYsIDAuMzU4LCAwLjQwMCwgMC40MjYpLAogIHNhbGFyeSA9IGMoODAwMDAwMCwgNzIzNjAwLCAxOTUwMDAwMCwgNzIwMDAwLCA0MDUwMDAwKQopCmBgYAoKYGBge3J9CiMgT1BTIGlzIHRoZSBzdGFuZGFyZCBzYWJlcm1ldHJpYyBzdW1tYXJ5IG9mIGEgaGl0dGVyJ3Mgb2ZmZW5zaXZlIHZhbHVlCnBsYXllcnMkT1BTIDwtIHBsYXllcnMkT0JQICsgcGxheWVycyRTTEcKCmJ1ZGdldCA8LSAxMDUwMDAwMAoKYGBgCgpgYGB7cn0KIyBFbnVtZXJhdGUgZXZlcnkgMi1wbGF5ZXIgY29tYmluYXRpb24sIHRoZW4gZmlsdGVyIGJ5IHRoZSBidWRnZXQgY29uc3RyYWludApjb21ib3MgPC0gYXMuZGF0YS5mcmFtZSh0KGNvbWJuKG5yb3cocGxheWVycyksIDIpKSkKbmFtZXMoY29tYm9zKSA8LSBjKCJpIiwgImoiKQoKY29tYm9zIDwtIGNvbWJvcyAlPiUKICBtdXRhdGUoCiAgICBwbGF5ZXIxICAgICA9IHBsYXllcnMkbmFtZVtpXSwKICAgIHBsYXllcjIgICAgID0gcGxheWVycyRuYW1lW2pdLAogICAgdG90YWxfc2FsYXJ5ID0gcGxheWVycyRzYWxhcnlbaV0gKyBwbGF5ZXJzJHNhbGFyeVtqXSwKICAgIHRvdGFsX09QUyAgICA9IHBsYXllcnMkT1BTW2ldICAgICsgcGxheWVycyRPUFNbal0KICApICU+JQogIGZpbHRlcih0b3RhbF9zYWxhcnkgPD0gYnVkZ2V0KSAlPiUgICAgICAgICAgICMga2VlcCBvbmx5IGFmZm9yZGFibGUgcGFpcnMKICBhcnJhbmdlKGRlc2ModG90YWxfT1BTKSkgJT4lICAgICAgICAgICAgICAgICAjIHJhbmsgYnkgY29tYmluZWQgcHJvZHVjdGlvbgogIHNlbGVjdChwbGF5ZXIxLCBwbGF5ZXIyLCB0b3RhbF9zYWxhcnksIHRvdGFsX09QUykKCmNvbWJvcwpgYGAKClRoZSB0d28gcGxheWVycyB0aGF0IHdlIHdvdWxkIHNlbGVjdCBiYXNlZCBvbiB0aGUgYnVkZ2V0IGFyZTogWWFuZHkgRGlheiBhbmQgUnlhbiBOb2RhIGJlY2F1c2UgdGhpcyB0d28gbWF4aW1pemVzIGNvbWJpbmUgb2ZmZW5zaXZlIHByb2R1Y3Rpb24gKE9QUyA9IDEuNjk4KSB3aGlsZSBzdGF5aW5nIHdpdGhpbiB0aGUgJDEwLjVNIGJ1ZGdldCBhdCBhIHRvdGFsIGNvc3Qgb2YgJDguNzJNLiAKCmBgYHtyfQojIFByZXR0eS1wcmludCBzYWxhcmllcyBmb3IgdGhlIGZpbmFsIHRhYmxlCmtuaXRyOjprYWJsZSgKICBjb21ib3MsCiAgY29sLm5hbWVzID0gYygiUGxheWVyIDEiLCAiUGxheWVyIDIiLCAiVG90YWwgU2FsYXJ5IiwgIlRvdGFsIE9QUyIpLAogIGZvcm1hdC5hcmdzID0gbGlzdChiaWcubWFyayA9ICIsIiwgc2NpZW50aWZpYyA9IEZBTFNFKSwKICBjYXB0aW9uID0gIkFmZm9yZGFibGUgMi1wbGF5ZXIgY29tYmluYXRpb25zIHJhbmtlZCBieSBjb21iaW5lZCBPUFMiCikKYGBgCg==