Exemple #1
0
def _fix_clearances(actions: DataFrame) -> DataFrame:
    next_actions = actions.shift(-1)
    next_actions[-1:] = actions[-1:]
    clearance_idx = actions.type_id == spadlconfig.actiontypes.index(
        'clearance')
    actions.loc[clearance_idx,
                'end_x'] = next_actions[clearance_idx].start_x.values
    actions.loc[clearance_idx,
                'end_y'] = next_actions[clearance_idx].start_y.values

    return actions
Exemple #2
0
def _fix_direction_of_play(actions: DataFrame, home_team_id: int) -> DataFrame:
    away_idx = (actions.team_id != home_team_id).values
    for col in ['start_x', 'end_x']:
        actions.loc[
            away_idx,
            col] = spadlconfig.field_length - actions[away_idx][col].values
    for col in ['start_y', 'end_y']:
        actions.loc[
            away_idx,
            col] = spadlconfig.field_width - actions[away_idx][col].values

    return actions
Exemple #3
0
def _extra_from_fouls(actions: DataFrame) -> DataFrame:
    yellow = actions.result_id == _spadl.results.index('yellow_card')
    red = actions.result_id == _spadl.results.index('red_card')

    prev = actions[yellow | red]
    extra = pd.DataFrame()
    extra['game_id'] = prev.game_id
    extra['original_event_id'] = prev.original_event_id
    extra['period_id'] = prev.period_id
    extra['action_id'] = prev.action_id + 0.1
    extra['time_seconds'] = prev.time_seconds  # + nex.time_seconds) / 2
    extra['start_x'] = prev.end_x
    extra['start_y'] = prev.end_y
    extra['end_x'] = prev.end_x
    extra['end_y'] = prev.end_y
    extra['bodypart_id'] = prev.bodypart_id
    extra['result_id'] = -1
    extra['team_id'] = prev.team_id
    extra['player_id'] = prev.player_id

    ar = actiontypes
    extra['type_id'] = -1
    extra['type_id'] = extra.type_id.mask(yellow,
                                          ar.index('yellow_card')).mask(
                                              red, ar.index('red_card'))
    actions = pd.concat([actions, extra], ignore_index=True, sort=False)
    actions = actions.sort_values(['game_id', 'period_id',
                                   'action_id']).reset_index(drop=True)
    actions['action_id'] = range(len(actions))
    return actions
Exemple #4
0
def _extra_from_shots(actions: DataFrame) -> DataFrame:
    next_actions = actions.shift(-1)

    shotlike = ['shot', 'shot_freekick', 'shot_penalty']
    shot_ids = list(_spadl.actiontypes.index(ty) for ty in shotlike)

    samegame = actions.game_id == next_actions.game_id
    sameperiod = actions.period_id == next_actions.period_id

    shot = actions.type_id.isin(shot_ids)
    goal = shot & (actions.result_id == _spadl.results.index('success'))
    owngoal = shot & (actions.result_id == _spadl.results.index('owngoal'))
    next_corner_goalkick = next_actions.type_id.isin([
        actiontypes.index('corner_crossed'),
        actiontypes.index('corner_short'),
        actiontypes.index('goalkick'),
    ])
    out = shot & next_corner_goalkick & samegame & sameperiod

    extra_idx = goal | owngoal | out
    prev = actions[extra_idx]
    # nex = next_actions[extra_idx]

    extra = pd.DataFrame()
    extra['game_id'] = prev.game_id
    extra['original_event_id'] = prev.original_event_id
    extra['period_id'] = prev.period_id
    extra['action_id'] = prev.action_id + 0.1
    extra['time_seconds'] = prev.time_seconds  # + nex.time_seconds) / 2
    extra['start_x'] = prev.end_x
    extra['start_y'] = prev.end_y
    extra['end_x'] = prev.end_x
    extra['end_y'] = prev.end_y
    extra['bodypart_id'] = prev.bodypart_id
    extra['result_id'] = -1
    extra['team_id'] = prev.team_id
    extra['player_id'] = prev.player_id

    ar = actiontypes
    extra['type_id'] = -1
    extra['type_id'] = (extra.type_id.mask(goal, ar.index('goal')).mask(
        owngoal, ar.index('owngoal')).mask(out, ar.index('out')))
    actions = pd.concat([actions, extra], ignore_index=True, sort=False)
    actions = actions.sort_values(['game_id', 'period_id',
                                   'action_id']).reset_index(drop=True)
    actions['action_id'] = range(len(actions))
    return actions
Exemple #5
0
    async def check_coros() -> None:
        good_df: DataFrame[Schema] = DataFrame({Schema.col1: [1]})
        bad_df: DataFrame[Schema] = DataFrame({"bad_schema": [1]})
        instance = SomeClass()
        for coro in [
                coroutine,
                instance.regular_coroutine,
                SomeClass.class_coroutine,
                instance.static_coroutine,
                SomeClass.static_coroutine,
                SomeClass.class_meta_coroutine,
                SomeClass.static_meta_coroutine,
                SomeClass.regular_meta_coroutine,
        ]:
            res = await coro(good_df)
            pd.testing.assert_frame_equal(good_df, res)

            with pytest.raises(errors.SchemaError):
                await coro(bad_df)
Exemple #6
0
def _add_dribbles(actions: DataFrame) -> DataFrame:
    next_actions = actions.shift(-1)

    same_team = actions.team_id == next_actions.team_id
    # not_clearance = actions.type_id != actiontypes.index("clearance")

    dx = actions.end_x - next_actions.start_x
    dy = actions.end_y - next_actions.start_y
    far_enough = dx**2 + dy**2 >= min_dribble_length**2
    not_too_far = dx**2 + dy**2 <= max_dribble_length**2

    dt = next_actions.time_seconds - actions.time_seconds
    same_phase = dt < max_dribble_duration
    same_period = actions.period_id == next_actions.period_id

    dribble_idx = same_team & far_enough & not_too_far & same_phase & same_period

    dribbles = pd.DataFrame()
    prev = actions[dribble_idx]
    nex = next_actions[dribble_idx]
    dribbles['game_id'] = nex.game_id
    dribbles['period_id'] = nex.period_id
    dribbles['action_id'] = prev.action_id + 0.1
    dribbles['time_seconds'] = (prev.time_seconds + nex.time_seconds) / 2
    if 'timestamp' in actions.columns:
        dribbles['timestamp'] = nex.timestamp
    dribbles['team_id'] = nex.team_id
    dribbles['player_id'] = nex.player_id
    dribbles['start_x'] = prev.end_x
    dribbles['start_y'] = prev.end_y
    dribbles['end_x'] = nex.start_x
    dribbles['end_y'] = nex.start_y
    dribbles['bodypart_id'] = spadlconfig.bodyparts.index('foot')
    dribbles['type_id'] = spadlconfig.actiontypes.index('dribble')
    dribbles['result_id'] = spadlconfig.results.index('success')

    actions = pd.concat([actions, dribbles], ignore_index=True, sort=False)
    actions = actions.sort_values(['game_id', 'period_id',
                                   'action_id']).reset_index(drop=True)
    actions['action_id'] = range(len(actions))
    return actions
Exemple #7
0
def test_check_types_method_args() -> None:
    """Test that @check_types works with positional and keyword args in methods,
    classmethods and staticmethods.
    """

    # pylint: disable=unused-argument,missing-class-docstring,too-few-public-methods,missing-function-docstring

    class SchemaIn1(SchemaModel):
        col1: Series[int]

        class Config:
            strict = True

    class SchemaIn2(SchemaModel):
        col2: Series[int]

        class Config:
            strict = True

    class SchemaOut(SchemaModel):
        col3: Series[int]

        class Config:
            strict = True

    in1: DataFrame[SchemaIn1] = DataFrame({SchemaIn1.col1: [1]})
    in2: DataFrame[SchemaIn2] = DataFrame({SchemaIn2.col2: [2]})
    out: DataFrame[SchemaOut] = DataFrame({SchemaOut.col3: [3]})

    class SomeClass:
        @check_types
        def regular_method(  # pylint: disable=no-self-use
            self,
            df1: DataFrame[SchemaIn1],
            df2: DataFrame[SchemaIn2],
        ) -> DataFrame[SchemaOut]:
            return out

        @classmethod
        @check_types
        def class_method(cls, df1: DataFrame[SchemaIn1],
                         df2: DataFrame[SchemaIn2]) -> DataFrame[SchemaOut]:
            return out

        @staticmethod
        @check_types
        def static_method(df1: DataFrame[SchemaIn1],
                          df2: DataFrame[SchemaIn2]) -> DataFrame[SchemaOut]:
            return out

    instance = SomeClass()

    pd.testing.assert_frame_equal(out,
                                  instance.regular_method(in1,
                                                          in2))  # Used to fail
    pd.testing.assert_frame_equal(out, instance.regular_method(in1, df2=in2))
    pd.testing.assert_frame_equal(out, instance.regular_method(df1=in1,
                                                               df2=in2))

    with pytest.raises(errors.SchemaError):
        instance.regular_method(in2, in1)  # Used to fail
    with pytest.raises(errors.SchemaError):
        instance.regular_method(in2, df2=in1)
    with pytest.raises(errors.SchemaError):
        instance.regular_method(df1=in2, df2=in1)

    pd.testing.assert_frame_equal(out, SomeClass.class_method(in1, in2))
    pd.testing.assert_frame_equal(out, SomeClass.class_method(in1, df2=in2))
    pd.testing.assert_frame_equal(out, SomeClass.class_method(df1=in1,
                                                              df2=in2))

    with pytest.raises(errors.SchemaError):
        instance.class_method(in2, in1)
    with pytest.raises(errors.SchemaError):
        instance.class_method(in2, df2=in1)
    with pytest.raises(errors.SchemaError):
        instance.class_method(df1=in2, df2=in1)

    pd.testing.assert_frame_equal(out, instance.static_method(in1, in2))
    pd.testing.assert_frame_equal(out, SomeClass.static_method(in1, in2))
    pd.testing.assert_frame_equal(out, instance.static_method(in1, df2=in2))
    pd.testing.assert_frame_equal(out, SomeClass.static_method(in1, df2=in2))
    pd.testing.assert_frame_equal(out, instance.static_method(df1=in1,
                                                              df2=in2))

    with pytest.raises(errors.SchemaError):
        instance.static_method(in2, in1)
    with pytest.raises(errors.SchemaError):
        instance.static_method(in2, df2=in1)
    with pytest.raises(errors.SchemaError):
        instance.static_method(df1=in2, df2=in1)
Exemple #8
0
def _extra_from_passes(actions: DataFrame) -> DataFrame:
    next_actions = actions.shift(-1)
    same_team = actions.team_id == next_actions.team_id

    passlike = [
        'pass',
        'cross',
        'throw_in',
        'freekick_short',
        'freekick_crossed',
        'corner_crossed',
        'corner_short',
        'clearance',
        'goalkick',
    ]
    pass_ids = list(_spadl.actiontypes.index(ty) for ty in passlike)

    interceptionlike = [
        'interception',
        'tackle',
        'keeper_punch',
        'keeper_save',
        'keeper_claim',
        'keeper_pick_up',
    ]
    interception_ids = list(
        _spadl.actiontypes.index(ty) for ty in interceptionlike)

    samegame = actions.game_id == next_actions.game_id
    sameperiod = actions.period_id == next_actions.period_id
    # samephase = next_actions.time_seconds - actions.time_seconds < max_pass_duration
    extra_idx = (
        actions.type_id.isin(pass_ids)
        & samegame
        & sameperiod  # & samephase
        & ~next_actions.type_id.isin(interception_ids))

    prev = actions[extra_idx]
    nex = next_actions[extra_idx]

    extra = pd.DataFrame()
    extra['game_id'] = prev.game_id
    extra['original_event_id'] = prev.original_event_id
    extra['period_id'] = prev.period_id
    extra['action_id'] = prev.action_id + 0.1
    extra['time_seconds'] = (prev.time_seconds + nex.time_seconds) / 2
    extra['start_x'] = prev.end_x
    extra['start_y'] = prev.end_y
    extra['end_x'] = prev.end_x
    extra['end_y'] = prev.end_y
    extra['bodypart_id'] = bodyparts.index('foot')
    extra['result_id'] = -1

    offside = prev.result_id == _spadl.results.index('offside')
    out = ((nex.type_id == actiontypes.index('goalkick')) &
           (~same_team)) | (nex.type_id == actiontypes.index('throw_in'))
    ar = actiontypes
    extra['type_id'] = -1
    extra['type_id'] = (extra.type_id.mask(
        same_team,
        ar.index('receival')).mask(~same_team, ar.index('interception')).mask(
            out, ar.index('out')).mask(offside, ar.index('offside')))
    is_interception = extra['type_id'] == ar.index('interception')
    extra['team_id'] = prev.team_id.mask(is_interception, nex.team_id)
    extra['player_id'] = nex.player_id.mask(out | offside, prev.player_id)

    actions = pd.concat([actions, extra], ignore_index=True, sort=False)
    actions = actions.sort_values(['game_id', 'period_id',
                                   'action_id']).reset_index(drop=True)
    actions['action_id'] = range(len(actions))
    return actions