{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Introduction","metadata":{}},{"cell_type":"markdown","source":"Here, I would like to provide some of the insights I obtained through the competition.  \nI hope it will be of some help to you.  \n\nThe points of my analysis are as follows.  \n* Use lag features: Useful for explaining short-term trends  \n* Use MSE(Mean Squared Error): Suitable for explaining the \"Peaks(outliers)\" scattered in the data, compared to MAE.  ","metadata":{}},{"cell_type":"markdown","source":"### Import libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\n\nfrom pathlib import Path\nfrom sklearn.metrics import mean_absolute_error, mean_squared_error\n\nimport lightgbm as lgbm\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nsns.set(font_scale=1.3)\n\nimport pickle\nimport gc\nimport os\n\npd.set_option(\"display.max_columns\", 1000)\npd.set_option('display.max_rows', 1000)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:39:49.572704Z","iopub.execute_input":"2021-07-31T23:39:49.573065Z","iopub.status.idle":"2021-07-31T23:39:49.580073Z","shell.execute_reply.started":"2021-07-31T23:39:49.573035Z","shell.execute_reply":"2021-07-31T23:39:49.578875Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Settings","metadata":{}},{"cell_type":"code","source":"BASE_DIR = Path('../input/mlb-player-digital-engagement-forecasting')\nTRAIN_DIR = Path('../input/mlb-datasets')","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:39:49.582028Z","iopub.execute_input":"2021-07-31T23:39:49.582477Z","iopub.status.idle":"2021-07-31T23:39:49.602408Z","shell.execute_reply.started":"2021-07-31T23:39:49.582434Z","shell.execute_reply":"2021-07-31T23:39:49.601330Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Tools","metadata":{}},{"cell_type":"code","source":"# Memory reduction function\ndef reduce_mem_usage(df, verbose=True):\n    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']\n    start_mem = df.memory_usage().sum() / 1024**2\n    for col in df.columns:\n        col_type = df[col].dtypes\n        if col_type in numerics:\n            c_min = df[col].min()\n            c_max = df[col].max()\n            if str(col_type)[:3] == 'int':\n                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:\n                    df[col] = df[col].astype(np.int8)\n                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:\n                    df[col] = df[col].astype(np.int16)\n                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:\n                    df[col] = df[col].astype(np.int32)\n                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:\n                    df[col] = df[col].astype(np.int64)\n            else:\n                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:\n                    df[col] = df[col].astype(np.float16)\n                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:\n                    df[col] = df[col].astype(np.float32)\n                else:\n                    df[col] = df[col].astype(np.float64)\n    end_mem = df.memory_usage().sum() / 1024 ** 2\n    if verbose: print('Mem. usage decreased to {:5.2f} Mb ({:.1f}% reduction)'.format(end_mem, 100 * (start_mem - end_mem) / start_mem))\n    return df","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:39:49.604263Z","iopub.execute_input":"2021-07-31T23:39:49.604766Z","iopub.status.idle":"2021-07-31T23:39:49.620811Z","shell.execute_reply.started":"2021-07-31T23:39:49.604720Z","shell.execute_reply":"2021-07-31T23:39:49.619789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Columns","metadata":{}},{"cell_type":"code","source":"targets_cols = ['playerId', 'target1', 'target2', 'target3', 'target4', 'date']\nteams_cols = ['id','leagueId', 'divisionId']\nplayers_cols = ['playerId', 'primaryPositionName']\nrosters_cols = ['playerId', 'teamId', 'status', 'date']\nscores_cols = ['playerId', 'battingOrder', 'gamesPlayedBatting', 'flyOuts',\n       'groundOuts', 'runsScored', 'doubles', 'triples', 'homeRuns',\n       'strikeOuts', 'baseOnBalls', 'intentionalWalks', 'hits', 'hitByPitch',\n       'atBats', 'caughtStealing', 'stolenBases', 'groundIntoDoublePlay',\n       'groundIntoTriplePlay', 'plateAppearances', 'totalBases', 'rbi',\n       'leftOnBase', 'sacBunts', 'sacFlies', 'catchersInterference',\n       'pickoffs', 'gamesPlayedPitching', 'gamesStartedPitching',\n       'completeGamesPitching', 'shutoutsPitching', 'winsPitching',\n       'lossesPitching', 'flyOutsPitching', 'airOutsPitching',\n       'groundOutsPitching', 'runsPitching', 'doublesPitching',\n       'triplesPitching', 'homeRunsPitching', 'strikeOutsPitching',\n       'baseOnBallsPitching', 'intentionalWalksPitching', 'hitsPitching',\n       'hitByPitchPitching', 'atBatsPitching', 'caughtStealingPitching',\n       'stolenBasesPitching', 'inningsPitched', 'saveOpportunities',\n       'earnedRuns', 'battersFaced', 'outsPitching', 'pitchesThrown', 'balls',\n       'strikes', 'hitBatsmen', 'balks', 'wildPitches', 'pickoffsPitching',\n       'rbiPitching', 'gamesFinishedPitching', 'inheritedRunners',\n       'inheritedRunnersScored', 'catchersInterferencePitching',\n       'sacBuntsPitching', 'sacFliesPitching', 'saves', 'holds', 'blownSaves',\n       'assists', 'putOuts', 'errors', 'chances', 'date']\nawards_cols = ['date', 'playerId', 'awardId']\nplayerTwitterFollowers_cols = ['playerId', 'numberOfFollowers', 'date']\nteamTwitterFollowers_cols = ['teamId', 'numberOfFollowers', 'date']\nstandings_cols = ['teamId', 'wins', 'losses', 'lastTenWins', 'lastTenLosses', 'date']\n\n# lag features\nlag_cols =  ['lag_t' + str(i) + '_tgt' + str(j) for i in range(1, 4) for j in range(1, 5)] + \\\n            ['roll_mean_t' + str(i) + '_tgt' + str(j) for i in [7, 28] for j in range(1, 5)] + \\\n            ['roll_min_t' + str(i) + '_tgt' + str(j) for i in [7, 28] for j in range(1, 5)] + \\\n            ['roll_max_t' + str(i) + '_tgt' + str(j) for i in [7, 28] for j in range(1, 5)]\n\n# date features\ndate_cols = ['year', 'month', 'week', 'day', 'dayofweek']\n\n# statistics\nstats_cols = ['playerId', \n              'target1_mean', 'target1_max', 'target1_min', \n              'target2_mean', 'target2_max', 'target2_min', \n              'target3_mean', 'target3_max', 'target3_min',\n              'target4_mean', 'target4_max', 'target4_min']\n\nfeature_cols = [\n       'label_playerId', 'label_primaryPositionName', 'label_teamId', 'label_status', \n       'battingOrder', 'gamesPlayedBatting', 'flyOuts',\n       'groundOuts', 'runsScored', 'doubles', 'homeRuns',\n       'strikeOuts', 'baseOnBalls', 'intentionalWalks', 'hits', 'hitByPitch',\n       'atBats', 'caughtStealing', 'stolenBases', 'groundIntoDoublePlay',\n       'groundIntoTriplePlay', 'plateAppearances', 'totalBases', 'rbi',\n       'leftOnBase', 'sacBunts', 'sacFlies', 'catchersInterference',\n       'pickoffs', 'gamesPlayedPitching', 'gamesStartedPitching',\n       'completeGamesPitching', 'shutoutsPitching', 'winsPitching',\n       'lossesPitching', 'flyOutsPitching', 'airOutsPitching',\n       'groundOutsPitching', 'runsPitching', 'doublesPitching',\n       'triplesPitching', 'homeRunsPitching', 'strikeOutsPitching',\n       'baseOnBallsPitching', 'intentionalWalksPitching', 'hitsPitching',\n       'hitByPitchPitching', 'atBatsPitching', 'caughtStealingPitching',\n       'stolenBasesPitching', 'inningsPitched', 'saveOpportunities',\n       'earnedRuns', 'battersFaced', 'outsPitching', 'pitchesThrown', 'balls',\n       'strikes', 'hitBatsmen', 'balks', 'wildPitches', 'pickoffsPitching',\n       'rbiPitching', 'gamesFinishedPitching', 'inheritedRunners',\n       'inheritedRunnersScored', 'catchersInterferencePitching',\n       'sacBuntsPitching', 'sacFliesPitching', 'saves', 'holds', 'blownSaves',\n       'assists', 'putOuts', 'errors', 'chances', 'awardId_count', 'playernumberOfFollowers',               \n       'teamnumberOfFollowers', 'label_leagueId', 'label_divisionId', 'wins', 'losses', \n       'lastTenWins', 'lastTenLosses'\n    ] + stats_cols[1:] + lag_cols + date_cols","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:39:49.622694Z","iopub.execute_input":"2021-07-31T23:39:49.623310Z","iopub.status.idle":"2021-07-31T23:39:49.646701Z","shell.execute_reply.started":"2021-07-31T23:39:49.623268Z","shell.execute_reply":"2021-07-31T23:39:49.645683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Read csv data","metadata":{}},{"cell_type":"code","source":"players = pd.read_csv(BASE_DIR / 'players.csv', usecols=players_cols)\nplayers = reduce_mem_usage(players)\n\nteams = pd.read_csv(BASE_DIR / 'teams.csv')\nteams = teams.rename(columns = {'id':'teamId'})\nteams = reduce_mem_usage(teams)\n\nrosters = pd.read_csv(TRAIN_DIR / 'rosters.csv', usecols=rosters_cols)\nrosters = reduce_mem_usage(rosters)\n\ntargets = pd.read_csv(TRAIN_DIR / 'nextDayPlayerEngagement.csv', usecols=targets_cols)\ntargets = reduce_mem_usage(targets)\n\nscores = pd.read_csv(TRAIN_DIR / 'playerBoxScores.csv', usecols = scores_cols)\nscores = scores.groupby(['playerId', 'date']).sum().reset_index()\nscores = reduce_mem_usage(scores)\n\nawards = pd.read_csv(TRAIN_DIR / 'awards.csv', usecols=awards_cols)\nawards_count = awards[['playerId', 'awardId']].groupby('playerId').count().reset_index()\nawards_count = awards_count.rename(columns = {'awardId':'awardId_count'})\nawards_count = reduce_mem_usage(awards_count)\n\nplayerTwitterFollowers = pd.read_csv(TRAIN_DIR / 'playerTwitterFollowers.csv', usecols=playerTwitterFollowers_cols)\nplayerTwitterFollowers[\"year\"] = pd.to_datetime(playerTwitterFollowers['date'], format='%Y%m%d').dt.year\nplayerTwitterFollowers[\"month\"] = pd.to_datetime(playerTwitterFollowers['date'], format='%Y%m%d').dt.month\nplayerTwitterFollowers = playerTwitterFollowers.drop('date', axis=1)\nplayerTwitterFollowers = playerTwitterFollowers.groupby(['playerId', 'year', 'month']).sum().reset_index()\nplayerTwitterFollowers = playerTwitterFollowers.rename(columns = {'numberOfFollowers':'playernumberOfFollowers'})\nplayerTwitterFollowers = reduce_mem_usage(playerTwitterFollowers)\n\nteamTwitterFollowers = pd.read_csv(TRAIN_DIR / 'teamTwitterFollowers.csv', usecols=teamTwitterFollowers_cols)\nteamTwitterFollowers[\"year\"] = pd.to_datetime(teamTwitterFollowers['date'], format='%Y%m%d').dt.year\nteamTwitterFollowers[\"month\"] = pd.to_datetime(teamTwitterFollowers['date'], format='%Y%m%d').dt.month\nteamTwitterFollowers = teamTwitterFollowers.drop('date', axis=1)\nteamTwitterFollowers = teamTwitterFollowers.groupby(['teamId', 'year', 'month']).sum().reset_index()\nteamTwitterFollowers = teamTwitterFollowers.rename(columns = {'numberOfFollowers':'teamnumberOfFollowers'})\nteamTwitterFollowers = reduce_mem_usage(teamTwitterFollowers)\n\nstandings = pd.read_csv(TRAIN_DIR / 'standings.csv', usecols=standings_cols)\nstandings = reduce_mem_usage(standings)\n\nstats = pd.read_csv(TRAIN_DIR / 'player_target_stats.csv', usecols=stats_cols)\nstats = reduce_mem_usage(stats)\n\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:39:49.831789Z","iopub.execute_input":"2021-07-31T23:39:49.832391Z","iopub.status.idle":"2021-07-31T23:39:57.885765Z","shell.execute_reply.started":"2021-07-31T23:39:49.832348Z","shell.execute_reply":"2021-07-31T23:39:57.884985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Merge data","metadata":{}},{"cell_type":"code","source":"train = targets[targets_cols].merge(players[players_cols], on=['playerId'], how='left')\ntrain['year'] = pd.to_datetime(train['date'], format='%Y%m%d').dt.year\ntrain['month'] = pd.to_datetime(train['date'], format='%Y%m%d').dt.month\ntrain = train.merge(rosters, on=['playerId', 'date'], how='left')\ntrain = train.merge(scores, on=['playerId', 'date'], how='left')\ntrain = train.merge(stats, on=['playerId'], how='left')\ntrain = train.merge(teams, on='teamId', how='left')\ntrain = train.merge(awards_count, on='playerId', how='left')\ntrain['awardId_count'] = train['awardId_count'].fillna(0)\ntrain = train.merge(playerTwitterFollowers, how='left', on=['playerId', 'year', 'month'])\ntrain = train.merge(teamTwitterFollowers, how = 'left', on=['teamId', 'year', 'month'])\ntrain = train.merge(standings, how='left', on = ['teamId', 'date'])\ntrain = train.drop(['year', 'month'], axis=1)\n\n# label encoding\nplayer2num = {c: i for i, c in enumerate(train['playerId'].unique())}\nposition2num = {c: i for i, c in enumerate(train['primaryPositionName'].unique())}\nteamid2num = {c: i for i, c in enumerate(train['teamId'].unique())}\nstatus2num = {c: i for i, c in enumerate(train['status'].unique())}\nleagueId2num = {c: i for i, c in enumerate(train['leagueId'].unique())}\ndivisionId2num = {c: i for i, c in enumerate(train['divisionId'].unique())}\n\ntrain['label_playerId'] = train['playerId'].map(player2num)\ntrain['label_primaryPositionName'] = train['primaryPositionName'].map(position2num)\ntrain['label_teamId'] = train['teamId'].map(teamid2num)\ntrain['label_status'] = train['status'].map(status2num)\ntrain['label_leagueId'] = train['leagueId'].map(leagueId2num)\ntrain['label_divisionId'] = train['divisionId'].map(divisionId2num)\n\ntrain[\"date\"] = pd.to_datetime(train['date'], format='%Y%m%d')\n\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:39:57.887117Z","iopub.execute_input":"2021-07-31T23:39:57.887626Z","iopub.status.idle":"2021-07-31T23:40:25.796864Z","shell.execute_reply.started":"2021-07-31T23:39:57.887595Z","shell.execute_reply":"2021-07-31T23:40:25.796134Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Simple EDA - Trend of TGT value (Each playerId) ","metadata":{}},{"cell_type":"markdown","source":"First, let's check the trend of the target in each player as a simple analysis.","metadata":{}},{"cell_type":"markdown","source":"### Target 1","metadata":{}},{"cell_type":"markdown","source":"* It seems that the engagement tends to be more active during the regular season. (See the upper graph)  \n* Engagement from March to July 2020 has decreased compared to the normal year.  \n  This is apparently due to the late start of the season, which is caused by COVID-19.  \n* Peaks are scattered in the data. It seems difficult to predict this peak...  ","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(nrows=2, figsize=(25,10))\nfor i in [0, 5, 12, 18, 21]:\n    ax[0].plot(train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"date\"], \n              train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"target1\"], \n              label=train[\"playerId\"].loc[i])\n    ax[1].plot(train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"date\"], \n          train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"target1\"], \n          label=train[\"playerId\"].loc[i])\n\n# Expanded regular season period\nax[1].set_xlim(np.array(('2019-03-01', '2019-10-01'),  dtype='datetime64'))\nax[0].set_ylim([0,100])\nax[1].set_ylim([0,100])\nax[0].legend()","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:40:25.798465Z","iopub.execute_input":"2021-07-31T23:40:25.798964Z","iopub.status.idle":"2021-07-31T23:40:27.198818Z","shell.execute_reply.started":"2021-07-31T23:40:25.798931Z","shell.execute_reply":"2021-07-31T23:40:27.197671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Target2","metadata":{}},{"cell_type":"markdown","source":"* It seems that the trend fluctuations appear to be more stable than Target1.  ","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(nrows=2, figsize=(25,10))\nfor i in [0, 5, 12, 18, 21]:\n    ax[0].plot(train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"date\"], \n              train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"target2\"], \n              label=train[\"playerId\"].loc[i])\n    ax[1].plot(train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"date\"], \n          train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"target2\"], \n          label=train[\"playerId\"].loc[i])\n\n# Expanded regular season period\nax[1].set_xlim(np.array(('2019-03-01', '2019-10-01'),  dtype='datetime64'))\nax[0].set_ylim([0,100])\nax[1].set_ylim([0,100])\nax[0].legend()","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:40:27.200414Z","iopub.execute_input":"2021-07-31T23:40:27.200723Z","iopub.status.idle":"2021-07-31T23:40:28.435501Z","shell.execute_reply.started":"2021-07-31T23:40:27.200693Z","shell.execute_reply":"2021-07-31T23:40:28.434440Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Target3","metadata":{}},{"cell_type":"markdown","source":"* There are drastic changes in the data, similar to Target1.  ","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(nrows=2, figsize=(25,10))\nfor i in [0, 5, 12, 18, 21]:\n    ax[0].plot(train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"date\"], \n              train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"target3\"], \n              label=train[\"playerId\"].loc[i])\n    ax[1].plot(train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"date\"], \n          train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"target3\"], \n          label=train[\"playerId\"].loc[i])\n\n# Expanded regular season period\nax[1].set_xlim(np.array(('2019-03-01', '2019-10-01'),  dtype='datetime64'))\nax[0].set_ylim([0,100])\nax[1].set_ylim([0,100])\nax[0].legend()","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:40:28.437085Z","iopub.execute_input":"2021-07-31T23:40:28.437452Z","iopub.status.idle":"2021-07-31T23:40:29.633673Z","shell.execute_reply.started":"2021-07-31T23:40:28.437421Z","shell.execute_reply":"2021-07-31T23:40:29.632407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Target4","metadata":{}},{"cell_type":"markdown","source":"* The value is low and stable as a whole. It's relatively similar to target2?","metadata":{}},{"cell_type":"code","source":"fig, ax = plt.subplots(nrows=2, figsize=(25,10))\nfor i in [0, 5, 12, 18, 21]:\n    ax[0].plot(train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"date\"], \n              train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"target4\"], \n              label=train[\"playerId\"].loc[i])\n    ax[1].plot(train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"date\"], \n          train[train[\"playerId\"] == train[\"playerId\"].loc[i]][\"target4\"], \n          label=train[\"playerId\"].loc[i])\n\n# Expanded regular season period\nax[1].set_xlim(np.array(('2019-03-01', '2019-10-01'),  dtype='datetime64'))\nax[0].set_ylim([0,100])\nax[1].set_ylim([0,100])\nax[0].legend()","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:40:29.635040Z","iopub.execute_input":"2021-07-31T23:40:29.635370Z","iopub.status.idle":"2021-07-31T23:40:30.803392Z","shell.execute_reply.started":"2021-07-31T23:40:29.635338Z","shell.execute_reply":"2021-07-31T23:40:30.802421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As a first impression, target1 and 3 are relatively similar, and target2 and 4 are.  \nTarget 1 and 3 have relatively short-term violent fluctuations, and targets 2 and 4 have medium or long-term relatively gradual fluctuations.","metadata":{}},{"cell_type":"markdown","source":"Looking at the trends above, I remembered the competition I had participated in before.  \n[M5-forecast](https://www.kaggle.com/c/m5-forecasting-accuracy)  \n\nIn this competition, the \"lag features\" were very useful, and I was able to make good inferences by using it. (61st/5558)  \nTherefore, I believed that the Lag statistic would also be useful information in this competition as well.  ","metadata":{}},{"cell_type":"markdown","source":"## Make \"lag features\"","metadata":{}},{"cell_type":"markdown","source":"Here is a function that generates lag features.  \nIn addition to simple lag information, the rolling method is used to calculate the average, maximum, and minimum values for the past few days.  \n(In the actual competition, we used additional lag features. For simplicity, I will omit it here.)  ","metadata":{}},{"cell_type":"code","source":"def make_features(df, shift=1):\n    \n    for i in range(1, 5):\n        # lag features\n        df['lag_t1_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift))\n        df['lag_t2_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift+1))\n        df['lag_t3_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift+2))\n        \n        # use rolling methods to caululate statistics \n        df['roll_mean_t7_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift).rolling(7).mean())\n        df['roll_mean_t28_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift).rolling(28).mean())\n        df['roll_max_t7_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift).rolling(7).max())\n        df['roll_max_t28_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift).rolling(28).max())\n        df['roll_min_t7_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift).rolling(7).min())\n        df['roll_min_t28_tgt' + str(i)] = df.groupby(['playerId'])['target' + str(i)].transform(lambda x: x.shift(shift).rolling(28).min())\n        \n    # time features\n    df['date'] = pd.to_datetime(df['date'], format='%Y%m%d')\n    df['year'] = df['date'].dt.year\n    df['month'] = df['date'].dt.month\n    df['week'] = df['date'].dt.week\n    df['day'] = df['date'].dt.day\n    df['dayofweek'] = df['date'].dt.dayofweek\n\n    return df","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:40:30.804881Z","iopub.execute_input":"2021-07-31T23:40:30.805189Z","iopub.status.idle":"2021-07-31T23:40:30.821835Z","shell.execute_reply.started":"2021-07-31T23:40:30.805159Z","shell.execute_reply":"2021-07-31T23:40:30.820357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Confirmation of correlation between each feature and Target","metadata":{}},{"cell_type":"markdown","source":"Next, let's check the correlation between each feature and the target.  \n\n* Given features (in training data)  \n* stats (long-term trends of each target)  \n* lag features (relatively short-term trends of each target)   ","metadata":{}},{"cell_type":"code","source":"# given features\ncorr = train[scores_cols + standings_cols + targets_cols + \n            [\"playernumberOfFollowers\", \"teamnumberOfFollowers\", \"awardId_count\"]].corr().\\\n            drop([\"target1\", 'target2', 'target3', 'target4', 'playerId', 'teamId'], axis=0)\ncorr = corr.loc[:, [\"target1\", 'target2', 'target3', 'target4']]\n\n# stats\ncorr_static = train[stats_cols + targets_cols].corr().\\\n              drop([\"target1\", 'target2', 'target3', 'target4', 'playerId'], axis=0)\ncorr_static = corr_static.loc[:, [\"target1\", 'target2', 'target3', 'target4']]","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:40:30.825345Z","iopub.execute_input":"2021-07-31T23:40:30.825748Z","iopub.status.idle":"2021-07-31T23:41:05.150988Z","shell.execute_reply.started":"2021-07-31T23:40:30.825713Z","shell.execute_reply":"2021-07-31T23:41:05.149758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Given features","metadata":{}},{"cell_type":"markdown","source":"* Most of the features appear to have little correlation with the target.  \n\n##### Target1  \n* \"homeruns\", \"totalbases\", \"rbi\" have a relatively high correlation with Target1.  \n  It's not hard to imagine that the reaction of SNS will increase at once when you hit a home run, a long hit, or a RBI.  \n  In Japan, my hometown, when Shohei Ohtani hit a home run, SNS was very exciting! lol  \n  The \"peaks\" of the target1 may be related to such a sudden rise in reaction.  \n  \n##### Target2 / 4\n* \"numberOfFollowers\" has a relatively high correlation with Target2 / 4.  \n  Based on this fact, target2 / 4 may be related to social networking interactions between fans and players/teams.  \n  Since mutual exchanges on SNS always occur regardless of whether or not there is a match, it is understandable that the trend is stable over the long term.  \n    \n##### Target3\n* There is a slight correlation with the features related to the details of the game content, such as \"strikes\", \"winspitching\", flyOutsPitching\", and so on.  \n  Therefore, it may have something to do with the engagements related to the content of the match.  ","metadata":{}},{"cell_type":"code","source":"sns.set(font_scale=1)\nfig=plt.figure(figsize=(15, 25))\nsns.heatmap(corr, vmax=0.4, vmin=-0.4, annot=True, cmap='coolwarm')","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:41:05.153433Z","iopub.execute_input":"2021-07-31T23:41:05.153730Z","iopub.status.idle":"2021-07-31T23:41:08.856083Z","shell.execute_reply.started":"2021-07-31T23:41:05.153702Z","shell.execute_reply":"2021-07-31T23:41:08.855296Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Stats","metadata":{}},{"cell_type":"markdown","source":"* Stats are relatively strongly correlated with all targets.  \n* In particular, targets 2 and 4 have a high correlation.  \n  This is thought to be due to the long-term stable characteristics of targets 2 and 4.  ","metadata":{}},{"cell_type":"code","source":"sns.set(font_scale=1)\nfig=plt.figure(figsize=(15, 7))\nsns.heatmap(corr_static, vmax=0.4, vmin=-0.4, annot=True, cmap='coolwarm')","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:41:08.857333Z","iopub.execute_input":"2021-07-31T23:41:08.857597Z","iopub.status.idle":"2021-07-31T23:41:09.544870Z","shell.execute_reply.started":"2021-07-31T23:41:08.857572Z","shell.execute_reply":"2021-07-31T23:41:09.543756Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Lag features","metadata":{}},{"cell_type":"markdown","source":"First, let's look at the lag features for delay of 1-day.  \n\n* \"lag_tx\": Each target value (x days ago). For example, If the base date is 5/1, \"lag_t1\" is the value at 4/30.  \n  Looking at the heatmap, you can see that lag_t1 and each Target show a very high correlation.(lag_t1_tgt4 and target4: 0.7!!)  \n  To put it simply, it is natural to think that the reactions of the previous and next days are similar.  \n  Therefore, if the information of the previous day is known, lag_t1 is a very powerful feature.  \n  (In the competition, for the estimate of 8/1, the target information of 7/31 should be used as the lag feature.)  \n* Other features, such as rolling features, are also useful to estimate.  ","metadata":{}},{"cell_type":"code","source":"train = make_features(train, 1)\n\ncorr_lag = train[lag_cols + targets_cols].corr().\\\n           drop([\"target1\", 'target2', 'target3', 'target4', 'playerId'], axis=0)\ncorr_lag = corr_lag.loc[:, [\"target1\", 'target2', 'target3', 'target4']]","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:41:09.546069Z","iopub.execute_input":"2021-07-31T23:41:09.546368Z","iopub.status.idle":"2021-07-31T23:42:32.441818Z","shell.execute_reply.started":"2021-07-31T23:41:09.546341Z","shell.execute_reply":"2021-07-31T23:42:32.440741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.set(font_scale=1)\nfig=plt.figure(figsize=(15, 20))\nsns.heatmap(corr_lag, vmax=0.4, vmin=-0.4, annot=True, cmap='coolwarm')","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:42:32.442967Z","iopub.execute_input":"2021-07-31T23:42:32.443272Z","iopub.status.idle":"2021-07-31T23:42:33.898499Z","shell.execute_reply.started":"2021-07-31T23:42:32.443242Z","shell.execute_reply":"2021-07-31T23:42:33.897701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Next, let's look at the lag features for delay of 7-day.  \n\nHere, it means that lag_t1 is the information of 7(=1+6) days ago, and lag_t2 is the information of 8(=2+6) days ago.  \n\n* Not surprisingly, the information of 7-days ago cannot be as useful as the information of 1-day ago.  \n  Nonetheless, it shows a high correlation, especially in Targets 2 and 4.  \n* Like stats, short-term statistics calculated by rolling method are especially useful for targets 2 and 4.  ","metadata":{}},{"cell_type":"code","source":"train = make_features(train, 7)\n\ncorr_lag = train[lag_cols + targets_cols].corr().\\\n           drop([\"target1\", 'target2', 'target3', 'target4', 'playerId'], axis=0)\ncorr_lag = corr_lag.loc[:, [\"target1\", 'target2', 'target3', 'target4']]","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:42:33.899432Z","iopub.execute_input":"2021-07-31T23:42:33.899687Z","iopub.status.idle":"2021-07-31T23:43:40.500915Z","shell.execute_reply.started":"2021-07-31T23:42:33.899663Z","shell.execute_reply":"2021-07-31T23:43:40.498316Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sns.set(font_scale=1)\nfig=plt.figure(figsize=(15, 20))\nsns.heatmap(corr_lag, vmax=0.4, vmin=-0.4, annot=True, cmap='coolwarm')","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:40.502529Z","iopub.status.idle":"2021-07-31T23:43:40.503110Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Confirm feature importance (use LightGBM)","metadata":{}},{"cell_type":"markdown","source":"Finally, let's check the importance of each feature using LightGBM.  \n\nThe model generation function is shown below.  ","metadata":{}},{"cell_type":"code","source":"def train_lgbm(train_X, train_y, valid_X, valid_y, params: dict=None):\n    pred = np.zeros(len(valid_y), dtype=np.float32)\n    lgb_train = lgbm.Dataset(train_X, train_y)\n    lgb_valid = lgbm.Dataset(valid_X, valid_y, reference=lgb_train)\n    model = lgbm.train(\n        params, lgb_train, valid_sets=lgb_valid,\n        verbose_eval=50,\n                       )\n\n    pred = model.predict(valid_X)\n    score = mean_absolute_error(pred, valid_y)\n    print('MAE:', score)\n    \n    if valid_y[valid_y > 10].shape[0] != 0:\n        score_over10 = mean_absolute_error(pred[valid_y > 10], valid_y[valid_y > 10])\n        print('MAE for TGT values higher than 10:', score_over10)\n\n    lgbm.plot_importance(model, figsize=(10, 30), importance_type=\"gain\")\n    plt.show()\n    \n    return pred, model, score","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:43.776422Z","iopub.execute_input":"2021-07-31T23:43:43.776782Z","iopub.status.idle":"2021-07-31T23:43:43.785577Z","shell.execute_reply.started":"2021-07-31T23:43:43.776749Z","shell.execute_reply":"2021-07-31T23:43:43.784334Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In the competition, submissions are evaluated on the mean-absolute error(MAE).  \nBut in this analysis, I will use mean-squared error(MSE) for objective function.  \n\nI think what you are most interested in is what causes the \"peaks(outliers)\".  \nSince MSE imposes strong penalties on outliers, I thought that it would be possible to create a model that emphasizes peaks by using MSE.  ","metadata":{}},{"cell_type":"code","source":"# Minimal adjustment so as not to disturb the competition\n\nparams = {'objective': 'mse', \n          'metric': 'l2', \n          'lambda_l1': 3.0, \n          'early_stopping_round': 50,\n          'random_state': 63,\n          'learning_rate': 0.1}","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:45.534903Z","iopub.execute_input":"2021-07-31T23:43:45.535293Z","iopub.status.idle":"2021-07-31T23:43:45.540020Z","shell.execute_reply.started":"2021-07-31T23:43:45.535260Z","shell.execute_reply":"2021-07-31T23:43:45.539014Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Here, we use the lag statistic based on 7 days ago.","metadata":{}},{"cell_type":"code","source":"train = make_features(train, shift=7)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:40.507339Z","iopub.status.idle":"2021-07-31T23:43:40.507771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# use only regular season's data \ntrain_idx = ((train['date'] >= \"2018-03-01\") & (train['date'] < \"2018-10-01\")) |\\\n            ((train['date'] >= \"2019-03-01\") & (train['date'] < \"2019-10-01\")) |\\\n            ((train['date'] >= \"2020-07-23\") & (train['date'] < \"2020-10-01\")) |\\\n            ((train['date'] >= \"2021-03-01\") & (train['date'] < \"2021-06-19\"))\nvalid_idx = (train['date'] >= \"2021-06-19\") & (train['date'] < \"2021-07-19\")\n\ntrain_X = train.loc[train_idx].reset_index(drop=True)[feature_cols]\ntrain_y = train.loc[train_idx].reset_index(drop=True)[['target1', 'target2', 'target3', 'target4']]\nvalid_X = train.loc[valid_idx].reset_index(drop=True)[feature_cols]\nvalid_y = train.loc[valid_idx].reset_index(drop=True)[['target1', 'target2', 'target3', 'target4']]\n\nidx_pitcher_t = (train_X['label_primaryPositionName'] == 0)\nidx_pitcher_v = (valid_X['label_primaryPositionName'] == 0)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:54.001108Z","iopub.execute_input":"2021-07-31T23:43:54.001491Z","iopub.status.idle":"2021-07-31T23:43:58.152527Z","shell.execute_reply.started":"2021-07-31T23:43:54.001461Z","shell.execute_reply":"2021-07-31T23:43:58.151570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Many of the pre-given statistics are thought to be divided into those related to \"pitchers\" and those related to \"batters\".  \nTherefore, we decided to check the importance of the features separately for the pitcher and the batter.  ","metadata":{}},{"cell_type":"markdown","source":"### Pitcher","metadata":{}},{"cell_type":"markdown","source":"#### Target1\n* The most important feature was calculated to be \"inningsPitched\".  \n  Certainly, high engagement is reasonable for a good pitcher who can throw long innings. \n  In addition, the pitcher that can strike out a lot is also attractive, so it is understandable that \"StrikeOutsPitching\" is quite important.\n* Surprisingly, \"homeruns\" are very important for pitcher(Needless to say for batters).  \n  Certainly, pitchers rarely hit home runs, and it's no wonder that engagement increases at that time.","metadata":{}},{"cell_type":"code","source":"print(\"==========target1-pitcher==========\")\npred_1, model_1, score_1 = train_lgbm(\n    train_X[idx_pitcher_t], train_y['target1'][idx_pitcher_t],\n    valid_X[idx_pitcher_v], valid_y['target1'][idx_pitcher_v],\n    params\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:58.154010Z","iopub.execute_input":"2021-07-31T23:43:58.154302Z","iopub.status.idle":"2021-07-31T23:44:12.910683Z","shell.execute_reply.started":"2021-07-31T23:43:58.154275Z","shell.execute_reply":"2021-07-31T23:44:12.909909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Target2\n* Most of the top rankings are due to lag features, and as mentioned above, target2 is associated with relatively medium/long-term trends.  \n* \"label_status\" is ranked third.  \n  For example, a player who is out of order is less likely to be picked up on Twitter of the team, so the status seems to be important.  ","metadata":{}},{"cell_type":"code","source":"print(\"==========target2-pitcher==========\")\npred_2, model_2, score_2 = train_lgbm(\n    train_X[idx_pitcher_t], train_y['target2'][idx_pitcher_t],\n    valid_X[idx_pitcher_v], valid_y['target2'][idx_pitcher_v],\n    params\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:40.511620Z","iopub.status.idle":"2021-07-31T23:43:40.512050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Target3\n* Features related to match information are judged to be important(e.g. \"gamesStartedPitching, gamesFinishedPitching\").  \n* \"teamnumberOfFollowers\" is also judged to be important.  \n  Given this fact, I suppose that the team is disseminating match information via SNS and engaging the fans' reactions to it as target3.  ","metadata":{}},{"cell_type":"code","source":"print(\"==========target3-pitcher==========\")\npred_3, model_3, score_3 = train_lgbm(\n    train_X[idx_pitcher_t], train_y['target3'][idx_pitcher_t],\n    valid_X[idx_pitcher_v], valid_y['target3'][idx_pitcher_v],\n    params\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:40.513070Z","iopub.status.idle":"2021-07-31T23:43:40.513552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Target4\n* Like target2, the main features are medium/long-term informations.","metadata":{}},{"cell_type":"code","source":"print(\"==========target4-pitcher==========\")\npred_4, model_4, score_4 = train_lgbm(\n    train_X[idx_pitcher_t], train_y['target4'][idx_pitcher_t],\n    valid_X[idx_pitcher_v], valid_y['target4'][idx_pitcher_v],\n    params\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:40.515164Z","iopub.status.idle":"2021-07-31T23:43:40.515618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Batter","metadata":{}},{"cell_type":"markdown","source":"#### Target1\n* The most important feature was \"homeruns\".  \n  It is no exaggeration to say that the peak of target1 shows the excitement when hitting a home run!  \n* \"rbi\" is also important. It is easy to imagine that SNS will be exciting even when adding points.  ","metadata":{}},{"cell_type":"code","source":"print(\"==========target1-nonpitcher==========\")\npred_1, model_1, score_1 = train_lgbm(\n    train_X[~idx_pitcher_t], train_y['target1'][~idx_pitcher_t],\n    valid_X[~idx_pitcher_v], valid_y['target1'][~idx_pitcher_v],\n    params\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:44:12.912156Z","iopub.execute_input":"2021-07-31T23:44:12.912635Z","iopub.status.idle":"2021-07-31T23:44:23.694079Z","shell.execute_reply.started":"2021-07-31T23:44:12.912602Z","shell.execute_reply":"2021-07-31T23:44:23.693317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Target2\n* As with the discussion of the pitcher section, long-term trends are emphasized.","metadata":{}},{"cell_type":"code","source":"print(\"==========target2-nonpitcher==========\")\npred_2, model_2, score_2 = train_lgbm(\n    train_X[~idx_pitcher_t], train_y['target2'][~idx_pitcher_t],\n    valid_X[~idx_pitcher_v], valid_y['target2'][~idx_pitcher_v],\n    params\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:40.517969Z","iopub.status.idle":"2021-07-31T23:43:40.518427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Target3\n* Long-term information is important, but features related to match information such as home runs and rbi are also important.","metadata":{}},{"cell_type":"code","source":"print(\"==========target3-nonpitcher==========\")\npred_3, model_3, score_3 = train_lgbm(\n    train_X[~idx_pitcher_t], train_y['target3'][~idx_pitcher_t],\n    valid_X[~idx_pitcher_v], valid_y['target3'][~idx_pitcher_v],\n    params\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:40.519339Z","iopub.status.idle":"2021-07-31T23:43:40.519765Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Target4\n* Like target2, the main features are medium/long-term informations.","metadata":{}},{"cell_type":"code","source":"print(\"==========target4-nonpitcher==========\")\npred_4, model_4, score_4 = train_lgbm(\n    train_X[~idx_pitcher_t], train_y['target4'][~idx_pitcher_t],\n    valid_X[~idx_pitcher_v], valid_y['target4'][~idx_pitcher_v],\n    params\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:43:40.520855Z","iopub.status.idle":"2021-07-31T23:43:40.521314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### (FYI) MSE vs MAE","metadata":{}},{"cell_type":"markdown","source":"Create MAE model to compare with the MSE prediction.","metadata":{}},{"cell_type":"code","source":"# Minimal adjustment so as not to disturb the competition\n\nparams_mae = {'objective': 'mae', \n              'metric': 'l1', \n              'lambda_l1': 3.0, \n              'early_stopping_round': 50,\n              'random_state': 63,\n              'learning_rate': 0.1}","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:44:23.695418Z","iopub.execute_input":"2021-07-31T23:44:23.695821Z","iopub.status.idle":"2021-07-31T23:44:23.699725Z","shell.execute_reply.started":"2021-07-31T23:44:23.695792Z","shell.execute_reply":"2021-07-31T23:44:23.698784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"==========target1-nonpitcher==========\")\npred_1_mae, model_1_mae, score_1_mae = train_lgbm(\n    train_X[~idx_pitcher_t], train_y['target1'][~idx_pitcher_t],\n    valid_X[~idx_pitcher_v], valid_y['target1'][~idx_pitcher_v],\n    params_mae\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:44:23.700781Z","iopub.execute_input":"2021-07-31T23:44:23.701189Z","iopub.status.idle":"2021-07-31T23:44:40.766987Z","shell.execute_reply.started":"2021-07-31T23:44:23.701162Z","shell.execute_reply":"2021-07-31T23:44:40.765975Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Looking at the graph, we can see that MSE is more sensitive to high values = peaks (whether the predicted values are correct or not).  \nMAE does not place much emphasis on outliers, making it insensitive to peaks.  \nFor this reason, I thought that MSE was suitable for explaining the peak.","metadata":{}},{"cell_type":"code","source":"fig = plt.figure(figsize=(25, 6))\nplt.plot(pred_1, label=\"mse\")\nplt.plot(pred_1_mae, label=\"mae\")\nplt.legend(loc='upper right', fontsize=26)","metadata":{"execution":{"iopub.status.busy":"2021-07-31T23:45:40.032423Z","iopub.execute_input":"2021-07-31T23:45:40.032935Z","iopub.status.idle":"2021-07-31T23:45:40.573607Z","shell.execute_reply.started":"2021-07-31T23:45:40.032890Z","shell.execute_reply":"2021-07-31T23:45:40.571707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Summary","metadata":{}},{"cell_type":"markdown","source":"I provided some of the insights I obtained through the competition.  \nI think that I was able to perform an effective analysis for each Target and the peaks, by using \"lag features\" and \"mse\".  \n\nI hope you find this analysis useful.  \nThank you!  ","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}