This file uses Madden 22 player ratings to create custom offensive and defensive power ratings. Subscribe to my Substack newsletter, Monte Carlo Football Picks, to learn more about the logic behind these calculations.
Load packages
library(tidyverse)
library(tidyquant)
Load files
madden22 <- read_csv("Week 07/inputs/madden_base.csv")
names <- read_csv("Week 07/inputs/names.csv", col_names = FALSE)
pos <- read_csv("Week 07/inputs/positions.csv")
Add position groups and full team names
madden <- madden22 %>%
left_join(names, by = c("Team" = "X1")) %>%
left_join(pos, by = "Position") %>%
select("Full Name", X2, Position, Pos_group, Archetype, Injured, Benched, Overall) %>%
rename(Name = "Full Name", Team = X2) %>%
filter(Team != "FA")
head(madden, 10)
Set weights for positions
olw <- 0.35
qbw <- 0.45
wrw <- 0.2
cbw <- 0.4
bzw <- 0.4
buw <- 0.2
Create groupings of players: OL, QB, WR, CB, Blitzer, DEF
#group and sort offensive linemen; return 5th best OL on each team
OL <- madden %>%
filter(Pos_group == "OL" & Injured == 0) %>%
group_by(Team) %>%
arrange(desc(Overall), .by_group = TRUE) %>%
slice(seq(0, 5, by = 5)) %>%
mutate(role = "OL", rating_group = "OFF", OA_wt = Overall * olw)
#return top QB on each team
QB <- madden %>%
filter(Position == "QB" & Injured == 0 & Benched == 0) %>%
group_by(Team) %>%
arrange(desc(Overall), .by_group = TRUE) %>%
slice(seq(1, n(), by = 5)) %>%
mutate(role = "QB", rating_group = "OFF", OA_wt = Overall * qbw) %>%
ungroup()
#return top Receiver (WR or TE) on each team
WR <- madden %>%
filter(Pos_group == "REC" & Injured == 0) %>%
group_by(Team) %>%
arrange(desc(Overall), .by_group = TRUE) %>%
slice(seq(1, n(), by = 25)) %>%
mutate(role = "WR", rating_group = "OFF", OA_wt = Overall * wrw)
#return top CB on each team
CB <- madden %>%
filter(Position == "CB" & Injured == 0) %>%
group_by(Team) %>%
arrange(desc(Overall), .by_group = TRUE) %>%
slice(seq(1, n(), by = 15)) %>%
mutate(role = "CB", rating_group = "DEF", OA_wt = Overall * cbw)
#return top pass rusher on each team
Blitz <- madden %>%
filter(Archetype == "DT_PowerRusher" | Archetype == "DT_SpeedRusher" | Archetype == "DE_SmallerSpeedRusher" |
Archetype == "DE_PowerRusher" | Archetype == "OLB_PowerRusher" | Archetype == "OLB_SpeedRusher") %>%
filter(Injured == 0) %>%
group_by(Team) %>%
arrange(desc(Overall), .by_group = TRUE) %>%
slice(seq(1, n(), by = 15)) %>%
mutate(role = "BZ", rating_group = "DEF", OA_wt = Overall * bzw)
#return 12th best defensive player
Scrub <- madden %>%
filter(Pos_group != "ST") %>%
filter(Pos_group != "OL") %>%
filter(Pos_group != "QB") %>%
filter(Pos_group != "RB") %>%
filter(Pos_group != "REC") %>%
filter(Injured == 0) %>%
group_by(Team) %>%
arrange(desc(Overall), .by_group = TRUE) %>%
slice(seq(12, n(), by = 100)) %>%
mutate(role = "BU", rating_group = "DEF", OA_wt = Overall * buw)
Combine and save dataset
talent <- bind_rows(OL, QB, CB,WR, Blitz, Scrub) %>%
arrange(desc(Team)) %>%
select(Name, Team, Position, role, rating_group, Overall, OA_wt)
head(talent, 10)
Sum OA_wt by team, Offense and Defense
off_ratings <- talent %>%
filter(rating_group == "OFF") %>%
group_by(Team) %>%
summarize(Rating = sum(OA_wt)) %>%
mutate(scaled = scale(Rating, center = TRUE, scale = TRUE)) %>%
mutate(off_rating = 25 + scaled * sd(Rating)) %>%
select(Team, off_rating)
def_ratings <- talent %>%
filter(rating_group == "DEF") %>%
group_by(Team) %>%
summarize(Rating = sum(OA_wt)) %>%
mutate(scaled = scale(Rating, center = TRUE, scale = TRUE)) %>%
mutate(def_rating = 50 - (25 + scaled * sd(Rating))) %>%
select(Team, def_rating)
talent_ratings <- full_join(off_ratings, def_ratings, by = "Team")
write.csv(x = talent_ratings, file = "Week 07/talent_ratings.csv")
talent_ratings
NA
LS0tDQp0aXRsZTogIlRhbGVudCBSYXRpbmdzOiAyMDIxIE5GTCBXZWVrIDA3Ig0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KDQpUaGlzIGZpbGUgdXNlcyBNYWRkZW4gMjIgcGxheWVyIHJhdGluZ3MgdG8gY3JlYXRlIGN1c3RvbSBvZmZlbnNpdmUgYW5kIGRlZmVuc2l2ZSBwb3dlciByYXRpbmdzLiBTdWJzY3JpYmUgdG8gbXkgU3Vic3RhY2sgbmV3c2xldHRlciwgW01vbnRlIENhcmxvIEZvb3RiYWxsIFBpY2tzXShodHRwczovL21jZnAuc3Vic3RhY2suY29tLyksIHRvIGxlYXJuIG1vcmUgYWJvdXQgdGhlIGxvZ2ljIGJlaGluZCB0aGVzZSBjYWxjdWxhdGlvbnMuDQoNCg0KDQpMb2FkIHBhY2thZ2VzDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHRpZHlxdWFudCkNCmBgYA0KDQpMb2FkIGZpbGVzDQpgYGB7cn0NCm1hZGRlbjIyIDwtIHJlYWRfY3N2KCJXZWVrIDA3L2lucHV0cy9tYWRkZW5fYmFzZS5jc3YiKQ0KbmFtZXMgPC0gcmVhZF9jc3YoIldlZWsgMDcvaW5wdXRzL25hbWVzLmNzdiIsIGNvbF9uYW1lcyA9IEZBTFNFKQ0KcG9zIDwtIHJlYWRfY3N2KCJXZWVrIDA3L2lucHV0cy9wb3NpdGlvbnMuY3N2IikNCmBgYA0KDQoNCg0KQWRkIHBvc2l0aW9uIGdyb3VwcyBhbmQgZnVsbCB0ZWFtIG5hbWVzDQpgYGB7cn0NCm1hZGRlbiA8LSBtYWRkZW4yMiAlPiUNCiAgbGVmdF9qb2luKG5hbWVzLCBieSA9IGMoIlRlYW0iID0gIlgxIikpICU+JQ0KICBsZWZ0X2pvaW4ocG9zLCBieSA9ICJQb3NpdGlvbiIpICU+JQ0KICBzZWxlY3QoIkZ1bGwgTmFtZSIsIFgyLCBQb3NpdGlvbiwgUG9zX2dyb3VwLCBBcmNoZXR5cGUsIEluanVyZWQsIEJlbmNoZWQsIE92ZXJhbGwpICU+JQ0KICByZW5hbWUoTmFtZSA9ICJGdWxsIE5hbWUiLCBUZWFtID0gWDIpICU+JQ0KICBmaWx0ZXIoVGVhbSAhPSAiRkEiKQ0KDQpoZWFkKG1hZGRlbiwgMTApDQpgYGANCg0KDQoNClNldCB3ZWlnaHRzIGZvciBwb3NpdGlvbnMNCmBgYHtyfQ0Kb2x3IDwtIDAuMzUNCnFidyA8LSAwLjQ1DQp3cncgPC0gMC4yDQoNCmNidyA8LSAwLjQNCmJ6dyA8LSAwLjQNCmJ1dyA8LSAwLjINCmBgYA0KDQoNCg0KQ3JlYXRlIGdyb3VwaW5ncyBvZiBwbGF5ZXJzOiBPTCwgUUIsIFdSLCBDQiwgQmxpdHplciwgREVGDQpgYGB7cn0NCiNncm91cCBhbmQgc29ydCBvZmZlbnNpdmUgbGluZW1lbjsgcmV0dXJuIDV0aCBiZXN0IE9MIG9uIGVhY2ggdGVhbQ0KT0wgPC0gbWFkZGVuICU+JQ0KICBmaWx0ZXIoUG9zX2dyb3VwID09ICJPTCIgJiBJbmp1cmVkID09IDApICU+JQ0KICBncm91cF9ieShUZWFtKSAlPiUNCiAgYXJyYW5nZShkZXNjKE92ZXJhbGwpLCAuYnlfZ3JvdXAgPSBUUlVFKSAgJT4lDQogIHNsaWNlKHNlcSgwLCA1LCBieSA9IDUpKSAlPiUNCiAgbXV0YXRlKHJvbGUgPSAiT0wiLCByYXRpbmdfZ3JvdXAgPSAiT0ZGIiwgT0Ffd3QgPSBPdmVyYWxsICogb2x3KQ0KICANCiNyZXR1cm4gdG9wIFFCIG9uIGVhY2ggdGVhbQ0KUUIgPC0gbWFkZGVuICU+JQ0KICBmaWx0ZXIoUG9zaXRpb24gPT0gIlFCIiAmIEluanVyZWQgPT0gMCAmIEJlbmNoZWQgPT0gMCkgJT4lDQogIGdyb3VwX2J5KFRlYW0pICU+JQ0KICBhcnJhbmdlKGRlc2MoT3ZlcmFsbCksIC5ieV9ncm91cCA9IFRSVUUpICU+JQ0KICBzbGljZShzZXEoMSwgbigpLCBieSA9IDUpKSAlPiUNCiAgbXV0YXRlKHJvbGUgPSAiUUIiLCByYXRpbmdfZ3JvdXAgPSAiT0ZGIiwgT0Ffd3QgPSBPdmVyYWxsICogcWJ3KSAlPiUNCiAgdW5ncm91cCgpDQogIA0KI3JldHVybiB0b3AgUmVjZWl2ZXIgKFdSIG9yIFRFKSBvbiBlYWNoIHRlYW0gDQpXUiA8LSBtYWRkZW4gJT4lDQogIGZpbHRlcihQb3NfZ3JvdXAgPT0gIlJFQyIgJiBJbmp1cmVkID09IDApICU+JQ0KICBncm91cF9ieShUZWFtKSAlPiUNCiAgYXJyYW5nZShkZXNjKE92ZXJhbGwpLCAuYnlfZ3JvdXAgPSBUUlVFKSAlPiUNCiAgc2xpY2Uoc2VxKDEsIG4oKSwgYnkgPSAyNSkpICU+JQ0KICBtdXRhdGUocm9sZSA9ICJXUiIsIHJhdGluZ19ncm91cCA9ICJPRkYiLCBPQV93dCA9IE92ZXJhbGwgKiB3cncpDQoNCiNyZXR1cm4gdG9wIENCIG9uIGVhY2ggdGVhbQ0KQ0IgPC0gbWFkZGVuICU+JQ0KICBmaWx0ZXIoUG9zaXRpb24gPT0gIkNCIiAmIEluanVyZWQgPT0gMCkgJT4lDQogIGdyb3VwX2J5KFRlYW0pICU+JQ0KICBhcnJhbmdlKGRlc2MoT3ZlcmFsbCksIC5ieV9ncm91cCA9IFRSVUUpICU+JQ0KICBzbGljZShzZXEoMSwgbigpLCBieSA9IDE1KSkgJT4lDQogIG11dGF0ZShyb2xlID0gIkNCIiwgcmF0aW5nX2dyb3VwID0gIkRFRiIsIE9BX3d0ID0gT3ZlcmFsbCAqIGNidykNCg0KI3JldHVybiB0b3AgcGFzcyBydXNoZXIgb24gZWFjaCB0ZWFtDQpCbGl0eiA8LSBtYWRkZW4gJT4lDQogIGZpbHRlcihBcmNoZXR5cGUgPT0gIkRUX1Bvd2VyUnVzaGVyIiB8IEFyY2hldHlwZSA9PSAiRFRfU3BlZWRSdXNoZXIiIHwgQXJjaGV0eXBlID09ICJERV9TbWFsbGVyU3BlZWRSdXNoZXIiIHwNCiAgICAgICAgICAgQXJjaGV0eXBlID09ICJERV9Qb3dlclJ1c2hlciIgfCBBcmNoZXR5cGUgPT0gIk9MQl9Qb3dlclJ1c2hlciIgfCBBcmNoZXR5cGUgPT0gIk9MQl9TcGVlZFJ1c2hlciIpICU+JQ0KICBmaWx0ZXIoSW5qdXJlZCA9PSAwKSAlPiUNCiAgZ3JvdXBfYnkoVGVhbSkgJT4lDQogIGFycmFuZ2UoZGVzYyhPdmVyYWxsKSwgLmJ5X2dyb3VwID0gVFJVRSkgJT4lDQogIHNsaWNlKHNlcSgxLCBuKCksIGJ5ID0gMTUpKSAlPiUNCiAgbXV0YXRlKHJvbGUgPSAiQloiLCByYXRpbmdfZ3JvdXAgPSAiREVGIiwgT0Ffd3QgPSBPdmVyYWxsICogYnp3KQ0KDQojcmV0dXJuIDEydGggYmVzdCBkZWZlbnNpdmUgcGxheWVyDQpTY3J1YiA8LSBtYWRkZW4gJT4lDQogIGZpbHRlcihQb3NfZ3JvdXAgIT0gIlNUIikgJT4lDQogIGZpbHRlcihQb3NfZ3JvdXAgIT0gIk9MIikgJT4lDQogIGZpbHRlcihQb3NfZ3JvdXAgIT0gIlFCIikgJT4lDQogIGZpbHRlcihQb3NfZ3JvdXAgIT0gIlJCIikgJT4lDQogIGZpbHRlcihQb3NfZ3JvdXAgIT0gIlJFQyIpICU+JQ0KICBmaWx0ZXIoSW5qdXJlZCA9PSAwKSAlPiUNCiAgZ3JvdXBfYnkoVGVhbSkgJT4lDQogIGFycmFuZ2UoZGVzYyhPdmVyYWxsKSwgLmJ5X2dyb3VwID0gVFJVRSkgJT4lDQogIHNsaWNlKHNlcSgxMiwgbigpLCBieSA9IDEwMCkpICU+JQ0KICBtdXRhdGUocm9sZSA9ICJCVSIsIHJhdGluZ19ncm91cCA9ICJERUYiLCBPQV93dCA9IE92ZXJhbGwgKiBidXcpDQpgYGANCg0KDQoNCkNvbWJpbmUgYW5kIHNhdmUgZGF0YXNldA0KYGBge3J9DQp0YWxlbnQgPC0gYmluZF9yb3dzKE9MLCBRQiwgQ0IsV1IsIEJsaXR6LCBTY3J1YikgJT4lDQogIGFycmFuZ2UoZGVzYyhUZWFtKSkgJT4lDQogIHNlbGVjdChOYW1lLCBUZWFtLCBQb3NpdGlvbiwgcm9sZSwgcmF0aW5nX2dyb3VwLCBPdmVyYWxsLCBPQV93dCkNCiAgDQpoZWFkKHRhbGVudCwgMTApDQpgYGANCg0KDQoNClN1bSBPQV93dCBieSB0ZWFtLCBPZmZlbnNlIGFuZCBEZWZlbnNlDQpgYGB7cn0NCm9mZl9yYXRpbmdzIDwtIHRhbGVudCAlPiUNCiAgZmlsdGVyKHJhdGluZ19ncm91cCA9PSAiT0ZGIikgJT4lDQogIGdyb3VwX2J5KFRlYW0pICU+JQ0KICBzdW1tYXJpemUoUmF0aW5nID0gc3VtKE9BX3d0KSkgJT4lDQogIG11dGF0ZShzY2FsZWQgPSBzY2FsZShSYXRpbmcsIGNlbnRlciA9IFRSVUUsIHNjYWxlID0gVFJVRSkpICU+JQ0KICBtdXRhdGUob2ZmX3JhdGluZyA9IDI1ICsgc2NhbGVkICogc2QoUmF0aW5nKSkgJT4lDQogIHNlbGVjdChUZWFtLCBvZmZfcmF0aW5nKQ0KDQpkZWZfcmF0aW5ncyA8LSB0YWxlbnQgJT4lDQogIGZpbHRlcihyYXRpbmdfZ3JvdXAgPT0gIkRFRiIpICU+JQ0KICBncm91cF9ieShUZWFtKSAlPiUNCiAgc3VtbWFyaXplKFJhdGluZyA9IHN1bShPQV93dCkpICU+JQ0KICBtdXRhdGUoc2NhbGVkID0gc2NhbGUoUmF0aW5nLCBjZW50ZXIgPSBUUlVFLCBzY2FsZSA9IFRSVUUpKSAlPiUNCiAgbXV0YXRlKGRlZl9yYXRpbmcgPSA1MCAtICgyNSArIHNjYWxlZCAqIHNkKFJhdGluZykpKSAlPiUNCiAgc2VsZWN0KFRlYW0sIGRlZl9yYXRpbmcpDQoNCnRhbGVudF9yYXRpbmdzIDwtIGZ1bGxfam9pbihvZmZfcmF0aW5ncywgZGVmX3JhdGluZ3MsIGJ5ID0gIlRlYW0iKQ0KDQp3cml0ZS5jc3YoeCA9IHRhbGVudF9yYXRpbmdzLCBmaWxlID0gIldlZWsgMDcvdGFsZW50X3JhdGluZ3MuY3N2IikNCg0KdGFsZW50X3JhdGluZ3MNCiAgDQpgYGANCg0K