{"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":"Original notebook: https://www.kaggle.com/ryanholbrook/getting-started-with-mlb-player-digital-engagement","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"import gc\nimport sys\nimport warnings\nfrom joblib import Parallel, delayed\nfrom pathlib import Path\n\nimport ipywidgets as widgets\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split\nfrom statsmodels.tsa.deterministic import (CalendarFourier,\n                                           CalendarSeasonality,\n                                           CalendarTimeTrend,\n                                           DeterministicProcess)\n\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import Dataset\nimport lightgbm as lgbm\nimport xgboost as xgb\n\nfrom skopt import dummy_minimize\n\nwarnings.simplefilter(\"ignore\")\n\n# Set Matplotlib defaults\nplt.style.use(\"seaborn-whitegrid\")\nplt.rc(\"figure\", autolayout=True, figsize=(11, 5))\nplt.rc(\n    \"axes\",\n    labelweight=\"bold\",\n    labelsize=\"large\",\n    titleweight=\"bold\",\n    titlesize=14,\n    titlepad=10,\n)\nplot_params = dict(\n    color=\"0.75\",\n    style=\".-\",\n    markeredgecolor=\"0.25\",\n    markerfacecolor=\"0.25\",\n    legend=False,\n)\n","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:28:40.120535Z","iopub.execute_input":"2021-07-07T20:28:40.120915Z","iopub.status.idle":"2021-07-07T20:28:43.511519Z","shell.execute_reply.started":"2021-07-07T20:28:40.120837Z","shell.execute_reply":"2021-07-07T20:28:43.510641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Helper function to unpack json found in daily data\ndef unpack_json(json_str):\n    return pd.DataFrame() if pd.isna(json_str) else pd.read_json(json_str)\n\n\ndef unpack_data(data, dfs=None, n_jobs=-1):\n    if dfs is not None:\n        data = data.loc[:, dfs]\n    unnested_dfs = {}\n    for name, column in data.iteritems():\n        daily_dfs = Parallel(n_jobs=n_jobs)(\n            delayed(unpack_json)(item) for date, item in column.iteritems())\n        df = pd.concat(daily_dfs)\n        unnested_dfs[name] = df\n    return unnested_dfs","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:28:43.512799Z","iopub.execute_input":"2021-07-07T20:28:43.513062Z","iopub.status.idle":"2021-07-07T20:28:43.520203Z","shell.execute_reply.started":"2021-07-07T20:28:43.513036Z","shell.execute_reply":"2021-07-07T20:28:43.519283Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = Path('../input/mlb-player-digital-engagement-forecasting/')\n\ndf_names = ['seasons', 'teams', 'players', 'awards']\n\nfor name in df_names:\n    globals()[name] = pd.read_csv(data_dir / f\"{name}.csv\")\n\nkaggle_data_tabs = widgets.Tab()\n# Add Output widgets for each pandas DF as tabs' children\nkaggle_data_tabs.children = list([widgets.Output() for df_name in df_names])\n\nfor index in range(0, len(df_names)):\n    # Rename tab bar titles to df names\n    kaggle_data_tabs.set_title(index, df_names[index])\n    \n    # Display corresponding table output for this tab name\n    with kaggle_data_tabs.children[index]:\n        display(eval(df_names[index]))\n\ndisplay(kaggle_data_tabs)","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:28:43.521942Z","iopub.execute_input":"2021-07-07T20:28:43.522239Z","iopub.status.idle":"2021-07-07T20:28:43.759211Z","shell.execute_reply.started":"2021-07-07T20:28:43.522213Z","shell.execute_reply":"2021-07-07T20:28:43.758181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n# Define dataframes to load from training set\ndfs = [\n    'nextDayPlayerEngagement',  # targets\n    'playerBoxScores',  # features\n    # Other dataframes available for features:\n    # 'games',\n    # 'rosters',\n    # 'teamBoxScores',\n    # 'transactions',\n    # 'standings',\n    # 'awards',\n    # 'events',\n    # 'playerTwitterFollowers',\n    # 'teamTwitterFollowers',\n]\n\n# Read training data\ntraining = pd.read_csv(\n    data_dir / 'train.csv',\n    usecols=['date'] + dfs,\n)\n\n# Convert training data date field to datetime type\ntraining['date'] = pd.to_datetime(training['date'], format=\"%Y%m%d\")\ntraining = training.set_index('date').to_period('D')\nprint(training)","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:50:07.621891Z","iopub.execute_input":"2021-07-07T20:50:07.622917Z","iopub.status.idle":"2021-07-07T20:50:55.067053Z","shell.execute_reply.started":"2021-07-07T20:50:07.622862Z","shell.execute_reply":"2021-07-07T20:50:55.065751Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%time\n# Unpack nested dataframes and store in dictionary `training_dfs`\ntraining_dfs = unpack_data(training, dfs=dfs)\nprint('\\n', training_dfs.keys())","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:29:49.792106Z","iopub.execute_input":"2021-07-07T20:29:49.792716Z","iopub.status.idle":"2021-07-07T20:30:14.035170Z","shell.execute_reply.started":"2021-07-07T20:29:49.792656Z","shell.execute_reply":"2021-07-07T20:30:14.034011Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Players in the test set. We'll filter our data for only this set of players\npids_test = players.playerId.loc[\n    players.playerForTestSetAndFuturePreds.fillna(False)\n].astype(str)\n\n# Name of target columns\ntargets = [\"target1\", \"target2\", \"target3\", \"target4\"]\n\n\ndef make_playerBoxScores(dfs: dict, features):\n    X = dfs['playerBoxScores'].copy()\n    X = X[['gameDate', 'playerId'] + features]\n    # Set dtypes\n    X = X.astype({name: np.float32 for name in features})\n    X = X.astype({'playerId': str})\n    # Create date index\n    X = X.rename(columns={'gameDate': 'date'})\n    X['date'] = pd.PeriodIndex(X.date, freq='D')\n    # Aggregate multiple games per day by summing\n    X = X.groupby(['date', 'playerId'], as_index=False).sum()\n    return X\n\n\ndef make_targets(training_dfs: dict):\n    Y = training_dfs['nextDayPlayerEngagement'].copy()\n    # Set dtypes\n    Y = Y.astype({name: np.float32 for name in targets})\n    Y = Y.astype({'playerId': str})\n    # Match target dates to feature dates and create date index\n    Y = Y.rename(columns={'engagementMetricsDate': 'date'})\n    Y['date'] = pd.to_datetime(Y['date'])\n    Y = Y.set_index('date').to_period('D')\n    Y.index = Y.index - 1\n    return Y.reset_index()\n\n\ndef join_datasets(dfs):\n    dfs = [x.pivot(index='date', columns='playerId') for x in dfs]\n    df = pd.concat(dfs, axis=1).stack().reset_index('playerId')\n    return df\n\n\ndef make_training_data(training_dfs: dict,\n                       features,\n                       targets,\n                       fourier=4,\n                       test_size=30):\n    # Process dataframes\n    X = make_playerBoxScores(training_dfs, features)\n    Y = make_targets(training_dfs)\n    # Merge for processing\n    df = join_datasets([X, Y])\n    # Filter for players in test set\n    df = df.loc[df.playerId.isin(pids_test), :]\n    # Convert from long to wide format\n    df = df.pivot(columns=\"playerId\")\n    # Restore features and targets\n    X = df.loc(axis=1)[features, :]\n    Y = df.loc(axis=1)[targets, :]\n    # Fill missing values in features\n    X.fillna(-1, inplace=True)\n    # Create temporal features\n    fourier_terms = CalendarFourier(freq='A', order=fourier)\n    deterministic = DeterministicProcess(\n        index=X.index,\n        order=0,\n        seasonal=False,  # set to True for weekly seasonality\n        additional_terms=[fourier_terms],\n    )\n    X = pd.concat([X, deterministic.in_sample()], axis=1)\n    # Create train / validation splits\n    X_train, X_valid, y_train, y_valid = train_test_split(\n        X,\n        Y,\n        test_size=test_size,\n        shuffle=False,\n    )\n    return X_train, X_valid, y_train, y_valid, deterministic","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:14.036754Z","iopub.execute_input":"2021-07-07T20:30:14.037350Z","iopub.status.idle":"2021-07-07T20:30:14.059020Z","shell.execute_reply.started":"2021-07-07T20:30:14.037306Z","shell.execute_reply":"2021-07-07T20:30:14.058010Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\n# Columns to select from playerBoxScores, all numeric\nfeatures = [\n    \"hits\",\n    \"strikeOuts\",\n    \"homeRuns\",\n    \"runsScored\",\n    \"stolenBases\",\n    \"strikeOutsPitching\",\n    \"inningsPitched\",\n    \"strikes\",\n    \"flyOuts\",\n    \"groundOuts\",\n    \"errors\",\n]\n\n# Number of days to use for the validation set\ntest_size = 30\n\nX_train, X_valid, y_train, y_valid, deterministic = make_training_data(\n    training_dfs, \n    features=features, \n    targets=targets,\n    fourier=4,  # number of Fourier pairs describing annual seasonality\n    test_size=test_size,\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:14.060439Z","iopub.execute_input":"2021-07-07T20:30:14.060852Z","iopub.status.idle":"2021-07-07T20:30:40.403983Z","shell.execute_reply.started":"2021-07-07T20:30:14.060809Z","shell.execute_reply":"2021-07-07T20:30:40.402904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train\n","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:40.406325Z","iopub.execute_input":"2021-07-07T20:30:40.406641Z","iopub.status.idle":"2021-07-07T20:30:40.464219Z","shell.execute_reply.started":"2021-07-07T20:30:40.406609Z","shell.execute_reply":"2021-07-07T20:30:40.463103Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def MLB_Train_Dataset(Dataset):\n    def __init__(self, x, y):\n        self.features = x\n        self.labels   = y\n        \n    def __len__(self):\n        return x.size\n    \n    def __getitem__(self, idx):\n        return (self.features.iloc[idx, :], self.labels.iloc[idx])","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:40.466349Z","iopub.execute_input":"2021-07-07T20:30:40.466827Z","iopub.status.idle":"2021-07-07T20:30:40.472894Z","shell.execute_reply.started":"2021-07-07T20:30:40.466783Z","shell.execute_reply":"2021-07-07T20:30:40.471824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(X_train.columns)\n","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:40.474638Z","iopub.execute_input":"2021-07-07T20:30:40.475099Z","iopub.status.idle":"2021-07-07T20:30:40.491280Z","shell.execute_reply.started":"2021-07-07T20:30:40.475056Z","shell.execute_reply":"2021-07-07T20:30:40.489855Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_train['target1']","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:40.492550Z","iopub.execute_input":"2021-07-07T20:30:40.492859Z","iopub.status.idle":"2021-07-07T20:30:40.546120Z","shell.execute_reply.started":"2021-07-07T20:30:40.492831Z","shell.execute_reply":"2021-07-07T20:30:40.544830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lgbm_params = \\\n{\n    'random_state': 42,\n    'objective': 'regression'\n}\n\nlgbm_train = pd.concat([X_train, X_valid])\nlgbm_labels = pd.concat([y_train, y_valid])\n\n#print(lgbm_train.columns)\n#print(lgbm_labels.columns)\n\nlgbm_labels1 = lgbm_labels['target1']\nlgbm_labels2 = lgbm_labels['target2']\nlgbm_labels3 = lgbm_labels['target3']\nlgbm_labels4 = lgbm_labels['target4']\n\n#lgbm_dataset  = lgbm.Dataset(lgbm_train, label=lgbm_labels)\nlgbm_dataset1 = lgbm.Dataset(lgbm_train, label=lgbm_labels1)\nlgbm_dataset2 = lgbm.Dataset(lgbm_train, label=lgbm_labels2)\nlgbm_dataset3 = lgbm.Dataset(lgbm_train, label=lgbm_labels3)\nlgbm_dataset4 = lgbm.Dataset(lgbm_train, label=lgbm_labels4)\n\nmodel1 = lgbm.train(lgbm_params, lgbm_dataset1)\nmodel2 = lgbm.train(lgbm_params, lgbm_dataset2)\nmodel3 = lgbm.train(lgbm_params, lgbm_dataset3)\nmodel4 = lgbm.train(lgbm_params, lgbm_dataset4)\n","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:40.549779Z","iopub.execute_input":"2021-07-07T20:30:40.550141Z","iopub.status.idle":"2021-07-07T20:30:40.923801Z","shell.execute_reply.started":"2021-07-07T20:30:40.550106Z","shell.execute_reply":"2021-07-07T20:30:40.921834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:40.924728Z","iopub.status.idle":"2021-07-07T20:30:40.925139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lgbm_labels","metadata":{"execution":{"iopub.status.busy":"2021-07-07T20:30:40.926369Z","iopub.status.idle":"2021-07-07T20:30:40.926817Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}