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