{"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":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\nimport datetime\nimport json\nimport os\n\nimport datatable as dt\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom sklearn.base import BaseEstimator, TransformerMixin\n\nimport mlb\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-06-17T12:32:14.267517Z","iopub.execute_input":"2021-06-17T12:32:14.268122Z","iopub.status.idle":"2021-06-17T12:32:14.585116Z","shell.execute_reply.started":"2021-06-17T12:32:14.267983Z","shell.execute_reply":"2021-06-17T12:32:14.584277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.options.display.float_format = '{:.2f}'.format","metadata":{"execution":{"iopub.status.busy":"2021-06-17T12:32:14.586888Z","iopub.execute_input":"2021-06-17T12:32:14.587206Z","iopub.status.idle":"2021-06-17T12:32:14.59088Z","shell.execute_reply.started":"2021-06-17T12:32:14.587176Z","shell.execute_reply":"2021-06-17T12:32:14.590109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def unpack_json(json_like: str) -> pd.DataFrame:\n    '''Convert json value into dataframe.\n    \n    Parameters\n    ----------\n    json_like: str\n        Json-format string\n    \n    Return\n    ------\n    converted: pd.DataFrame\n        If `json_like` is not a json-format string, return blank dataframe.e \n    '''\n    try:\n        unpacked = pd.DataFrame(json.loads(json_like))\n    except json.JSONDecodeError:\n        unpacked = pd.DataFrame()\n    return unpacked","metadata":{"execution":{"iopub.status.busy":"2021-06-17T12:32:14.591999Z","iopub.execute_input":"2021-06-17T12:32:14.592269Z","iopub.status.idle":"2021-06-17T12:32:14.601747Z","shell.execute_reply.started":"2021-06-17T12:32:14.592244Z","shell.execute_reply":"2021-06-17T12:32:14.60094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Predictor(BaseEstimator, TransformerMixin):\n    \n    def __init__(self, train_path):\n        self.train_path = train_path\n        self.timeseries = self.load_timeseries_engagement()\n\n    def load_timeseries_engagement(self) -> pd.DataFrame:\n        train = dt.fread(self.train_path).to_pandas()\n        timeseries = pd.concat(train.nextDayPlayerEngagement.apply(unpack_json).tolist())\n        timeseries['engagementMetricsDate'] = pd.to_datetime(timeseries['engagementMetricsDate'])\n        timeseries['date'] = timeseries.engagementMetricsDate + datetime.timedelta(days=-1)\n        return timeseries\n    \n    def get_timeseries_engagement(self, copy=True):\n        return self.timeseries.copy() if copy else self.timeseries\n    \n    def fit(self, X=None, y=None):\n        return self\n\n    def predict(self, X: pd.DataFrame) -> pd.DataFrame:\n        return X.date_playerId.apply(self.predict_by_row)\n        \n    def predict_by_row(self, date_playerId: str) -> pd.Series:\n        date = date_playerId.split('_')[0]\n        date = '-'.join([str(date)[:4], str(date)[4:6], str(date)[6:]])  # to YYYY-MM-DD format\n        player_id = int(date_playerId.split('_')[1])\n        timeseries = self.get_timeseries_engagement()\n        if player_id in timeseries.playerId.values:  # Find player's engagement data\n            player_timeseries = timeseries[timeseries.playerId == player_id]\n            player_history = player_timeseries[player_timeseries.date < date].sort_values('date')\n            if player_history.shape[0] > 0:  # Find historical data\n                latest = player_history.iloc[-1]\n                return pd.Series({'date': latest.date,\n                                  'playerId': latest.playerId,\n                                  'target1': latest.target1,\n                                  'target2': latest.target2,\n                                  'target3': latest.target3,\n                                  'target4': latest.target4})\n            else:  # Go to future...\n                nearest = player_timeseries.sort_values('date').iloc[0]\n                return pd.Series({'date': nearest.date,\n                                  'playerId': nearest.playerId,\n                                  'target1': nearest.target1,\n                                  'target2': nearest.target2,\n                                  'target3': nearest.target3,\n                                  'target4': nearest.target4})\n        else:  # That player is not seen in training set\n            all_player_history = timeseries[timeseries.date < date]\n            if all_player_history.shape[0] > 0:\n                mean_by_date = all_player_history \\\n                              .groupby('date') \\\n                              [['target1', 'target2', 'target3', 'target4']] \\\n                              .mean() \\\n                              .sort_index() \\\n                              .reset_index()\n                latest = mean_by_date.iloc[0]\n                return pd.Series({'date': latest.date,\n                                  'playerId': np.nan,\n                                  'target1': latest.target1,\n                                  'target2': latest.target2,\n                                  'target3': latest.target3,\n                                  'target4': latest.target4})\n            else:\n                return pd.Series({'date': np.nan,\n                                  'playerId': np.nan,\n                                  'target1': timeseries.target1.median(),\n                                  'target2': timeseries.target2.median(),\n                                  'target3': timeseries.target3.median(),\n                                  'target4': timeseries.target4.median()})\n            \n            ","metadata":{"execution":{"iopub.status.busy":"2021-06-17T12:32:14.602946Z","iopub.execute_input":"2021-06-17T12:32:14.603333Z","iopub.status.idle":"2021-06-17T12:32:14.620936Z","shell.execute_reply.started":"2021-06-17T12:32:14.603296Z","shell.execute_reply":"2021-06-17T12:32:14.620347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\npredictor = Predictor(train_path='/kaggle/input/mlb-player-digital-engagement-forecasting/train.csv')","metadata":{"execution":{"iopub.status.busy":"2021-06-17T12:32:14.621934Z","iopub.execute_input":"2021-06-17T12:32:14.622174Z","iopub.status.idle":"2021-06-17T12:32:52.665971Z","shell.execute_reply.started":"2021-06-17T12:32:14.622152Z","shell.execute_reply":"2021-06-17T12:32:52.664977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nenv = mlb.make_env() # initialize the environment\niter_test = env.iter_test() # iterator which loops over each date in test set\nfor i, (test_df, sample_prediction_df) in enumerate(iter_test):\n    prediction = predictor.predict(sample_prediction_df.copy())\n    sample_prediction_df['target1'] = prediction['target1']\n    sample_prediction_df['target2'] = prediction['target2']\n    sample_prediction_df['target3'] = prediction['target3']\n    sample_prediction_df['target4'] = prediction['target4']\n    env.predict(sample_prediction_df)","metadata":{"execution":{"iopub.status.busy":"2021-06-17T12:32:52.667164Z","iopub.execute_input":"2021-06-17T12:32:52.66743Z","iopub.status.idle":"2021-06-17T12:38:31.956115Z","shell.execute_reply.started":"2021-06-17T12:32:52.667404Z","shell.execute_reply":"2021-06-17T12:38:31.955006Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}