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==