BurntSushi / nflgame

An API to retrieve and read NFL Game Center JSON data. It can work with real-time data, which can be used for fantasy football.
http://pdoc.burntsushi.net/nflgame
The Unlicense
1.27k stars 413 forks source link

How to detect blocked punts recovered for a TD #330

Open ToddAtWSU opened 7 years ago

ToddAtWSU commented 7 years ago

So I am trying to see how many "defensive" touchdowns a team has and I have the following block in a for-loop:

` numDefTDs = 0 for play in nflgame.combine_plays(week).filter(defense_frec_tds=True):

play.team shows the offense that gave up the TD

                    # so if play.team is the same as game.away, our defense got the fum rec td
                    if play.team == game.away:
                        numDefTDs += 1
                for play in nflgame.combine_plays(week).filter(defense_int_tds=True):
                    # play.team shows the offense that gave up the TD
                    # so if play.team is the same as game.away, our defense got the int td
                    if play.team == game.away:
                        numDefTDs += 1
                for play in nflgame.combine_plays(week).filter(kickret_tds=True):
                    # play.team shows the offense that gave up the TD
                    # so if play.team is the same as game.away, our defense got the kick ret td
                    if play.team == game.away:
                        numDefTDs += 1
                for play in nflgame.combine_plays(week).filter(puntret_tds=True):
                    # play.team shows the offense that gave up the TD
                    # so if play.team is the same as game.away, our defense got the punt ret td
                    if play.team == game.away:
                        numDefTDs += 1`

So I am gathering INT and fumble recovery TDs plus punt and kickoff returns and this has worked fine for the past couple years. But in the Pittsburgh/Cleveland game, Pittsburgh blocked a punt and recovered it for a TD. Is there a stat to show this? Thanks!

ochawkeye commented 7 years ago
import nflgame

games = nflgame.games(2017, 1, kind='REG')
plays = nflgame.combine_plays(games).filter(defense_puntblk__ge=1, touchdown__ge=1)
for play in plays:
    print play
(CLE, CLE 16, Q1, 4 and 19) (12:44) B.Colquitt punt is BLOCKED by T.Matakevich, Center-C.Hughlett, RECOVERED by PIT-A.Chickillo at CLE -8. TOUCHDOWN.

Looks like there were two punt blocks for touchdown last season.

import nflgame

games = nflgame.games(2016, kind='REG')
plays = nflgame.combine_plays(games).filter(defense_puntblk__ge=1, touchdown__ge=1)
for play in plays:
    print play
(PIT, PIT 33, Q4, 4 and 8) (13:44) (Punt formation) J.Berry punt is BLOCKED by J.Allen, Center-G.Warren, RECOVERED by BAL-C.Moore at PIT 14. C.Moore for 14 yards, TOUCHDOWN.
(NYJ, NYJ 41, Q3, 4 and 12) (10:37) L.Edwards punt is BLOCKED by W.Aikens, Center-T.Purdum, RECOVERED by MIA-W.Aikens at NYJ 11. W.Aikens for 11 yards, TOUCHDOWN. Penalty on NYJ, Illegal Formation, declined.
ToddAtWSU commented 7 years ago

Edit: Nevermind, figured out my bug. Thanks, this works perfectly!!

ochawkeye commented 7 years ago

I want to amend my original answer a bit. By doing .filter(defense_puntblk__ge=1, touchdown__ge=1) you will indeed catch plays that included both a punt block & a touchdown. But those could technically include plays where the punting team had their kick blocked, ended up recovering, and taking all the way for a touchdown...I don't know if such a play would even be legal, but we can do better.

import nflgame
games = nflgame.games(year=2014, kind='REG')

plays = nflgame.combine_plays(games).filter(defense_puntblk=True, touchdown=True)
print len([p for p in plays])  # 10

plays = nflgame.combine_plays(games).filter(defense_puntblk=True, defense_tds=True)
print len([p for p in plays])  # 10

plays = nflgame.combine_plays(games).filter(defense_puntblk=True, touchdown=True, defense_tds=False)
print len([p for p in plays])  # 0

Okay, so how do I get that Pittsburgh got the TD in this?

I'm having trouble deciphering your code in that format, but aren't you already determining the defensive team in most every line in your OP (ie. # play.team shows the offense that gave up the TD # so if play.team is the same as game.away, our defense got the fum rec td)? Ignoring all that, here is one way you could do it.

def defense_on_field(play):
    if play.home:  # play.home == True if home team has the ball
        return play.drive.game.away
    return play.drive.game.home

I'm curious how using the .filter(defense_tds=True) compares to your big loop...

import nflgame

def defense_on_field(play):
    if play.home:  # play.home == True if home team has the ball
        return play.drive.game.away
    return play.drive.game.home

games = nflgame.games(year=2017, week=1, kind='REG')
plays = nflgame.combine_plays(games).filter(defense_tds=True)

for play in plays:
    print 'Defense:', defense_on_field(play), 'in play:', play
Defense: PIT in play: (CLE, CLE 16, Q1, 4 and 19) (12:44) B.Colquitt punt is BLOCKED by T.Matakevich, Center-C.Hughlett, RECOVERED by PIT-A.Chickillo at CLE -8. TOUCHDOWN.
Defense: ARI in play: (DET, ARI 21, Q1, 2 and 5) (11:29) (Shotgun) M.Stafford pass short middle intended for G.Tate INTERCEPTED by J.Bethel at ARI 18. J.Bethel for 82 yards, TOUCHDOWN.
Defense: DET in play: (ARI, ARI 25, Q4, 1 and 10) (4:13) (Shotgun) C.Palmer pass short middle intended for A.Ellington INTERCEPTED by M.Killebrew [A.Robinson] at ARI 35. M.Killebrew for 35 yards, TOUCHDOWN.
Defense: JAX in play: (HOU, JAX 37, Q2, 2 and 16) (1:00) (Shotgun) T.Savage sacked at JAX 47 for -10 yards (Y.Ngakoue). FUMBLES (Y.Ngakoue), RECOVERED by JAX-D.Fowler at JAX 47. D.Fowler for 53 yards, TOUCHDOWN.
Defense: WAS in play: (PHI, PHI 20, Q2, 2 and 10) (8:39) (Shotgun) C.Wentz pass short right intended for D.Sproles INTERCEPTED by R.Kerrigan (S.McGee) [S.McGee] at PHI 24. R.Kerrigan for 24 yards, TOUCHDOWN.
Defense: PHI in play: (WAS, WAS 32, Q4, 2 and 3) (1:38) (No Huddle, Shotgun) K.Cousins sacked at WAS 24 for -8 yards (B.Graham). FUMBLES (B.Graham) [B.Graham], RECOVERED by PHI-F.Cox at WAS 20. F.Cox for 20 yards, TOUCHDOWN. The Replay Official reviewed the fumble ruling, and the play was Upheld. The ruling on the field stands.
Defense: LA in play: (IND, IND 25, Q1, 3 and 10) (11:21) (Shotgun) S.Tolzien pass short left intended for T.Hilton INTERCEPTED by T.Johnson [M.Brockers] at IND 39. T.Johnson for 39 yards, TOUCHDOWN.
Defense: LA in play: (IND, IND 25, Q3, 1 and 10) (7:23) (Shotgun) S.Tolzien pass short left intended for T.Hilton INTERCEPTED by L.Joyner at IND 29. L.Joyner for 29 yards, TOUCHDOWN.
[Finished in 1.6s]
ToddAtWSU commented 7 years ago

So you're saying I can just filter by "defense_tds" and I don't have to look for all the possible Defensive TDs? Is there also a Special Teams TD or do I still need to look for kickoff returns and punt returns? Where do you see all the options you can filter plays by? Thanks again!

ochawkeye commented 7 years ago

The wiki has a table with stat types though in truth I probably end up stumbling upon much of what I use by random inspection.

For example, in the initial code I posted to your question, printing dir(play) tells me a lot about what does and doesn't apply to that particular play.

import nflgame
games = nflgame.games(year=2017, week=1, kind='REG')

plays = nflgame.combine_plays(games).filter(defense_puntblk=True, touchdown=True)
for play in plays:
    print play
print '-'*25
print dir(play)
(CLE, CLE 16, Q1, 4 and 19) (12:44) B.Colquitt punt is BLOCKED by T.Matakevich, Center-C.Hughlett, RECOVERED by PIT-A.Chickillo at CLE -8. TOUCHDOWN.
-------------------------
['_Play__players', '__class__', '__delattr__', '__dict__', '__doc__', '__eq__', '__format__', '__getattr__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_stats', 'data', 'defense_misc_tds', 'defense_misc_yds', 'defense_puntblk', 'defense_tds', 'desc', 'down', 'drive', 'events', 'has_player', 'home', 'note', 'players', 'playid', 'punting_blk', 'team', 'time', 'touchdown', 'yardline', 'yards_togo']

Looking at that, I noticed the defense_tds which is probably a closer stat to what you were looking for vs. just generic touchdown.

ToddAtWSU commented 7 years ago

Cool, I will look into this a little more tonight. Thanks for your help!