Kaggle competition: PUBG Finish Placement Prediction (Kernels Only)
<SOS> metric: MAE Kaggle data source: pubg-finish-placement-prediction-(kernels-only)<feature_engineering>
import gc
import sys
import numpy as np
import pandas as pd
all['FamSize'] = all.apply(lambda s: 1+s['SibSp']+s['Parch'], axis = 1)
 all['isAlone'] = all.apply(lambda s: 1 if s['FamSize'] == 1 else 0, axis = 1 )<count_values>
def df_footprint_reduce(df, skip_obj=False, skip_int=False, skip_float=False, print_comparison=True):

 if print_comparison:
print(f"Dataframe size before shrinking column types into smallest possible: {round(( sys.getsizeof(df)/1024/1024),4)} MB")
 for column in df.columns:
if(skip_obj is False)and(str(df[column].dtype)[:6] == 'object'):
num_unique_values = len(df[column].unique())
 num_total_values = len(df[column])
 if num_unique_values / num_total_values < 0.5:
df.loc[:,column] = df[column].astype('category')
 else:
df.loc[:,column] = df[column]
elif(skip_int is False)and(str(df[column].dtype)[:3] == 'int'):
if df[column].min() > np.iinfo(np.int8 ).min and df[column].max() < np.iinfo(np.int8 ).max:
df[column] = df[column].astype(np.int8)
 elif df[column].min() > np.iinfo(np.int16 ).min and df[column].max() < np.iinfo(np.int16 ).max:
df[column] = df[column].astype(np.int16)
 elif df[column].min() > np.iinfo(np.int32 ).min and df[column].max() < np.iinfo(np.int32 ).max:
df[column] = df[column].astype(np.int32)
 elif(skip_float is False)and(str(df[column].dtype)[:5] == 'float'):
if df[column].min() > np.finfo(np.float16 ).min and df[column].max() < np.finfo(np.float16 ).max:
df[column] = df[column].astype(np.float16)
 elif df[column].min() > np.finfo(np.float32 ).min and df[column].max() < np.finfo(np.float32 ).max:
df[column] = df[column].astype(np.float32)
 if print_comparison:
print(f"Dataframe size after shrinking column types into smallest possible: {round(( sys.getsizeof(df)/1024/1024),4)} MB")
 return df
ticket_counts = all['Ticket'].value_counts()
all['GrSize'] = all.apply(lambda s: ticket_counts.loc[s['Ticket']], axis=1)
 all['Cabin'].fillna('U',inplace=True)
 all['hasCabin'] = all.apply(lambda s: 0 if s['Cabin'] == 'U' else 1,axis = 1 )<feature_engineering>
def feature_engineering(df,is_train=True):
if is_train:
df = df[df['maxPlace'] > 1].copy()
target = 'winPlacePerc'
print('Grouping similar match types together')
 df.loc[(df['matchType'] == 'solo'), 'matchType'] = 1
df.loc[(df['matchType'] == 'normal-solo'), 'matchType'] = 1
df.loc[(df['matchType'] == 'solo-fpp'), 'matchType'] = 1
df.loc[(df['matchType'] == 'normal-solo-fpp'), 'matchType'] = 1
df.loc[(df['matchType'] == 'duo'), 'matchType'] = 2
df.loc[(df['matchType'] == 'normal-duo'), 'matchType'] = 2
df.loc[(df['matchType'] == 'duo-fpp'), 'matchType'] = 2
df.loc[(df['matchType'] == 'normal-duo-fpp'), 'matchType'] = 2
df.loc[(df['matchType'] == 'squad'), 'matchType'] = 3
df.loc[(df['matchType'] == 'normal-squad'), 'matchType'] = 3
df.loc[(df['matchType'] == 'squad-fpp'), 'matchType'] = 3
df.loc[(df['matchType'] == 'normal-squad-fpp'), 'matchType'] = 3
df.loc[(df['matchType'] == 'flaretpp'), 'matchType'] = 0
df.loc[(df['matchType'] == 'flarefpp'), 'matchType'] = 0
df.loc[(df['matchType'] == 'crashtpp'), 'matchType'] = 0
df.loc[(df['matchType'] == 'crashfpp'), 'matchType'] = 0
df.loc[(df['rankPoints'] < 0), 'rankPoints'] = 0
print('Adding new features using existing ones')
 df['headshotrate'] = df['kills']/df['headshotKills']
df['killStreakrate'] = df['killStreaks']/df['kills']
df['healthitems'] = df['heals'] + df['boosts']
df['totalDistance'] = df['rideDistance'] + df["walkDistance"] + df["swimDistance"]
df['killPlace_over_maxPlace'] = df['killPlace'] / df['maxPlace']
df['headshotKills_over_kills'] = df['headshotKills'] / df['kills']
df['distance_over_weapons'] = df['totalDistance'] / df['weaponsAcquired']
df['walkDistance_over_heals'] = df['walkDistance'] / df['heals']
df['walkDistance_over_kills'] = df['walkDistance'] / df['kills']
df['killsPerWalkDistance'] = df['kills'] / df['walkDistance']
df['skill'] = df['headshotKills'] + df['roadKills']
print('Adding normalized features')
 df['playersJoined'] = df.groupby('matchId')['matchId'].transform('count')
 gc.collect()
df['killsNorm'] = df['kills']*(( 100-df['playersJoined'])/100 + 1)
 df['damageDealtNorm'] = df['damageDealt']*(( 100-df['playersJoined'])/100 + 1)
 df['maxPlaceNorm'] = df['maxPlace']*(( 100-df['playersJoined'])/100 + 1)
 df['matchDurationNorm'] = df['matchDuration']*(( 100-df['playersJoined'])/100 + 1)
 df['headshotKillsNorm'] = df['headshotKills']*(( 100-df['playersJoined'])/100 + 1)
 df['killPlaceNorm'] = df['killPlace']*(( 100-df['playersJoined'])/100 + 1)
 df['killPointsNorm'] = df['killPoints']*(( 100-df['playersJoined'])/100 + 1)
 df['killStreaksNorm'] = df['killStreaks']*(( 100-df['playersJoined'])/100 + 1)
 df['longestKillNorm'] = df['longestKill']*(( 100-df['playersJoined'])/100 + 1)
 df['roadKillsNorm'] = df['roadKills']*(( 100-df['playersJoined'])/100 + 1)
 df['teamKillsNorm'] = df['teamKills']*(( 100-df['playersJoined'])/100 + 1)
 df['damageDealtNorm'] = df['damageDealt']*(( 100-df['playersJoined'])/100 + 1)
 df['DBNOsNorm'] = df['DBNOs']*(( 100-df['playersJoined'])/100 + 1)
 df['revivesNorm'] = df['revives']*(( 100-df['playersJoined'])/100 + 1)
 df = df_null_cleaner(df,fill_with=0)
 features = list(df.columns)
 features.remove("Id")
 features.remove("matchId")
 features.remove("groupId")
 features.remove("matchType")
 features.remove("maxPlace")
 y = pd.DataFrame()
if is_train:
print('Preparing target variable')
 y = df.groupby(['matchId','groupId'])[target].agg('mean')
 gc.collect()
features.remove(target)
 print('Aggregating means')
 means_features = list(df.columns)
 means_features.remove("Id")
 means_features.remove("matchId")
 means_features.remove("groupId")
 means_features.remove("matchType")
 means_features.remove("maxPlace")
 means_features.remove("playersJoined")
 means_features.remove("matchDuration")
 means_features.remove("numGroups")
 means_features.remove("teamKillsNorm")
 if is_train:
means_features.remove(target)
 agg = df.groupby(['matchId','groupId'])[means_features].agg('mean')
 gc.collect()
agg_rank = agg.groupby('matchId')[means_features].rank(pct=True ).reset_index()
gc.collect()
if is_train:
X = agg.reset_index() [['matchId','groupId']]
else:
X = df[['matchId','groupId']]
X = X.merge(agg.reset_index() , suffixes=["", ""], how='left', on=['matchId', 'groupId'])
 X = X.merge(agg_rank, suffixes=["_mean", "_mean_rank"], how='left', on=['matchId', 'groupId'])
 del agg, agg_rank
gc.collect()
print('Aggregating maxes')
 maxes_features = list(df.columns)
 maxes_features.remove("Id")
 maxes_features.remove("matchId")
 maxes_features.remove("groupId")
 maxes_features.remove("matchType")
 maxes_features.remove("DBNOsNorm")
 maxes_features.remove("damageDealtNorm")
 maxes_features.remove("headshotKillsNorm")
 maxes_features.remove("killPlaceNorm")
 maxes_features.remove("killPlace_over_maxPlace")
 maxes_features.remove("killPointsNorm")
 maxes_features.remove("killStreaksNorm")
 maxes_features.remove("killsNorm")
 maxes_features.remove("longestKillNorm")
 maxes_features.remove("matchDurationNorm")
 maxes_features.remove("matchDuration")
 maxes_features.remove("maxPlaceNorm")
 maxes_features.remove("maxPlace")
 maxes_features.remove("numGroups")
 maxes_features.remove("playersJoined")
 maxes_features.remove("revivesNorm")
 maxes_features.remove("roadKillsNorm")
 maxes_features.remove("teamKillsNorm")
 if is_train:
maxes_features.remove(target)
 agg = df.groupby(['matchId','groupId'])[maxes_features].agg('max')
 gc.collect()
agg_rank = agg.groupby('matchId')[maxes_features].rank(pct=True ).reset_index()
gc.collect()
X = X.merge(agg.reset_index() , suffixes=["", ""], how='left', on=['matchId', 'groupId'])
 X = X.merge(agg_rank, suffixes=["_max", "_max_rank"], how='left', on=['matchId', 'groupId'])
 del agg, agg_rank
gc.collect()
print('Aggregating mins')
 mins_features = list(df.columns)
 mins_features.remove("Id")
 mins_features.remove("matchId")
 mins_features.remove("groupId")
 mins_features.remove("matchType")
 mins_features.remove("DBNOsNorm")
 mins_features.remove("damageDealtNorm")
 mins_features.remove("headshotKillsNorm")
 mins_features.remove("killPlaceNorm")
 mins_features.remove("killPlace_over_maxPlace")
 mins_features.remove("killPointsNorm")
 mins_features.remove("killStreaksNorm")
 mins_features.remove("killsNorm")
 mins_features.remove("longestKillNorm")
 mins_features.remove("matchDurationNorm")
 mins_features.remove("matchDuration")
 mins_features.remove("maxPlaceNorm")
 mins_features.remove("maxPlace")
 mins_features.remove("numGroups")
 mins_features.remove("playersJoined")
 mins_features.remove("revivesNorm")
 mins_features.remove("roadKillsNorm")
 mins_features.remove("teamKillsNorm")
 if is_train:
mins_features.remove(target)
 agg = df.groupby(['matchId','groupId'])[mins_features].agg('min')
 gc.collect()
agg_rank = agg.groupby('matchId')[mins_features].rank(pct=True ).reset_index()
gc.collect()
X = X.merge(agg.reset_index() , suffixes=["", ""], how='left', on=['matchId', 'groupId'])
 X = X.merge(agg_rank, suffixes=["_min", "_min_rank"], how='left', on=['matchId', 'groupId'])
 del agg, agg_rank
gc.collect()
print('Aggregating group sizes')
 agg = df.groupby(['matchId','groupId'] ).size().reset_index(name='group_size')
 gc.collect()
X = X.merge(agg, how='left', on=['matchId', 'groupId'])
 print('Aggregating match means')
 agg = df.groupby(['matchId'])[features].agg('mean' ).reset_index()
gc.collect()
X = X.merge(agg, suffixes=["", "_match_mean"], how='left', on=['matchId'])
 print('Aggregating match sizes')
 agg = df.groupby(['matchId'] ).size().reset_index(name='match_size')
 gc.collect()
X = X.merge(agg, how='left', on=['matchId'])
 del df, agg
gc.collect()
X.drop(columns = ['matchId',
'groupId'
], axis=1, inplace=True)
 gc.collect()
if is_train:
return X, y
return X
all['Fname'] = all.Name.str.extract('^ (.+?),', expand=False)
 Pas_wSib = []
all_x_0 = all[(all['SibSp'] > 0)&(all['Parch'] == 0)]
name_counts_SibSp = all_x_0['Fname'].value_counts()
for label, value in name_counts_SibSp.items() :
entries = all_x_0[all_x_0['Fname'] == label]
if(entries.shape[0] > 1 and(not(entries['Title'] == 'Mrs' ).any())) or \ 
(entries.shape[0] == 1 and entries['Title'].values[0] == 'Mrs'):
Pas_wSib.extend(entries['PassengerId'].values.tolist())
 else:
Pas_wSib.extend(\
entries[(entries['Title'] == 'Miss')|(entries['GrSize'] == 1)]['PassengerId'].values.tolist())
 Mrs_wPar = []
all_x_y = all[all['Parch'] > 0]
name_counts_Parch = all_x_y['Fname'].value_counts()
for label, value in name_counts_Parch.items() :
entries = all_x_y[all_x_y['Fname'] == label]
if entries.shape[0] == 1:
if entries['Title'].values[0] == 'Mrs' and entries['Age'].values[0] <= 30:
Mrs_wPar.extend(entries['PassengerId'].values.tolist())
 def get_features(row):
features = pd.Series(0, index = ['wSib','wSp','wCh','wPar'])
 if row['PassengerId'] in Pas_wSib:
features['wSib'] = 1
else:
if(row['SibSp'] != 0)&(row['Parch'] == 0):
features['wSp'] = 1
else:
if(( row['Title']=='Mrs')&(not row['PassengerId'] in Mrs_wPar)) | \ 
(( row['Title']=='Mr')&(not row['PassengerId'] == 680)& 
(((row['Pclass']==1)&(row['Age']>=30)) | 
(( row['Pclass']==2)&(row['Age']>=25)) | 
(( row['Pclass']==3)&(row['Age']>=20)))) :
features['wCh'] = 1
else:
features['wPar'] = 1
return features
all[['wSib','wSp','wCh','wPar']] = all.apply(lambda s: get_features(s)if s['isAlone'] == 0 else [0,0,0,0], axis = 1 )<drop_column>
X_train = pd.read_csv('.. /input/train_V2.csv', engine='c' )
all = all.drop(['Fname','Name','Cabin','Ticket','Fare','SibSp','Parch'], axis = 1 )<groupby>
X_train = df_footprint_reduce(X_train, skip_obj=True)
 gc.collect()
all[all['Pclass'] == 1].groupby(['Title','isAlone','wSib','wSp','wCh','wPar'])['Survived'].agg(['count','size','mean'] )<groupby>
X_train, y_train = feature_engineering(X_train, True)
 gc.collect()
all[(all['Pclass'] == 1)&(all['Title'] == 'Mr')].groupby(['hasCabin','isAlone','wSib','wSp','wCh','wPar'])['Survived'].agg(['count','size','mean'] )<groupby>
X_train = df_footprint_reduce(X_train, skip_obj=True)
 gc.collect()
all[all['Pclass'] == 2].groupby(['Title','isAlone','wSib','wSp','wCh','wPar'])['Survived'].agg(['count','size','mean'] )<groupby>
from sklearn.model_selection import train_test_split, GridSearchCV
all[all['Pclass'] == 3].groupby(['Title','isAlone','wSib','wSp','wCh','wPar'])['Survived'].agg(['count','size','mean'] )<groupby>
X_train, X_validation, y_train, y_validation = train_test_split(X_train,
y_train,
test_size=0.2)
 gc.collect()
all[(all['Pclass'] == 3)&(all['Title'] != 'Mr')].groupby(['Title','FamSize'])['Survived'].agg(['count','size','mean'] )<groupby>
import lightgbm as lgb
all[(all['Pclass'] == 3)&(all['Title'] != 'Mr')].groupby(['Title','FamSizeBin','isAlone','wSib','wSp','wCh','wPar'])['Survived'].agg(['count','size','mean'] )<categorify>
parameters = { 'objective': 'regression_l1',
'learning_rate': 0.01
}
def get_survived_1(row):
if row['Pclass'] in [1,2]:
if row['Title'] == 'Mr':
survived = 0
else:
survived = 1
else:
if row['Title'] == 'Mr' or row['FamSizeBin'] == 1:
survived = 0
else:
survived = 1
return survived<save_to_csv>
def find_best_hyperparameters(model):
gridParams = {
'learning_rate' : [0.1, 0.01 , 0.05],
'n_estimators ' : [1000, 10000, 20000],
'bagging_fraction' : [0.5, 0.6 ,0.7],
'feature_fraction' : [0.5, 0.6 ,0.7],
'num_leaves' : [31, 80, 140]
}
grid = GridSearchCV(model,
gridParams,
verbose=5,
cv=3)
 grid.fit(X_train, y_train)
 print('Best parameters: %s' % grid.best_params_)
 print('Accuracy: %.2f' % grid.best_score_)
 return
X_train = all.iloc[:891,:]
X_test = all.iloc[891:,:]
y_train = all.iloc[:891,:]['Survived']
y_train_hat = X_train.apply(lambda s: get_survived_1(s), axis = 1)
 predictions = pd.DataFrame({'PassengerId': test['PassengerId'], 'Survived': 0})
 predictions['Survived'] = X_test.apply(lambda s: get_survived_1(s), axis = 1)
 predictions.to_csv('submission-1.csv', index=False)
 score = metrics.accuracy_score(y_train_hat, y_train)
 print('Train Accuracy: {}'.format(score))<groupby>
X_train = lgb.Dataset(X_train, label=y_train)
 X_validation = lgb.Dataset(X_validation, label=y_validation)
 gc.collect()
all[(all['Pclass'] == 3)&(all['Title'] != 'Mr')&(all['FamSizeBin'] == 0)].groupby(['Title','Embarked'])['Survived'].agg(['count','size','mean'] )<define_variables>
%%time
model = lgb.train(parameters,
X_train,
num_boost_round = 40000,
valid_sets=[X_validation,X_train] )
def get_survived_2(row):
if row['Pclass'] in [1,2]:
if row['Title'] == 'Mr':
survived = 0
else:
survived = 1
else:
if row['Title'] == 'Mr' or row['FamSizeBin'] == 1 or(row['Title'] == 'Miss' and row['Embarked'] == 'S'):
survived = 0
else:
survived = 1
return survived<save_to_csv>
print('The mean absolute error of model on validation set is:', model.best_score['valid_0']['l1'] )
y_train_hat = X_train.apply(lambda s: get_survived_2(s), axis = 1)
 predictions['Survived'] = X_test.apply(lambda s: get_survived_2(s), axis = 1)
 predictions.to_csv('submission-2.csv', index=False)
 score = metrics.accuracy_score(y_train_hat, y_train)
 print('Train Accuracy: {}'.format(score))<groupby>
import matplotlib.pyplot as plt
import seaborn as sns
all[(all['Pclass'] == 3)&(all['Title'] == 'Miss')&(all['FamSizeBin'] == 0)].groupby(['Title','wPar','Embarked'])['Survived'].agg(['count','size','mean'] )<categorify>
feature_imp[feature_imp['Value']==0]
def get_survived_3(row):
if row['Pclass'] in [1,2]:
if row['Title'] == 'Mr':
survived = 0
else:
survived = 1
else:
if row['Title'] == 'Mr' or row['FamSizeBin'] == 1 or \ 
(row['Title'] == 'Miss' and row['Embarked'] == 'S' and row['wPar'] == 0):
survived = 0
else:
survived = 1
return survived<save_to_csv>
del X_train, X_validation, y_train, y_validation, feature_imp
gc.collect()
y_train_hat = X_train.apply(lambda s: get_survived_3(s), axis = 1)
 predictions['Survived'] = X_test.apply(lambda s: get_survived_3(s), axis = 1)
 predictions.to_csv('submission-3.csv', index=False)
 score = metrics.accuracy_score(y_train_hat, y_train)
 print('Train Accuracy: {}'.format(score))<categorify>
test_x = pd.read_csv('.. /input/test_V2.csv', engine='c' )
all['Sex'] = all['Sex'].map({'male': 0, 'female': 1} ).astype(int)
 all['Embarked'].fillna(all['Embarked'].value_counts().index[0], inplace=True)
 all_dummies = pd.get_dummies(all, columns = ['Title','Pclass','Embarked'],\
prefix=['Title','Pclass','Embarked'], drop_first = True)
 all_dummies = all_dummies.drop(['PassengerId','Survived'], axis = 1 )<data_type_conversions>
test_x = df_footprint_reduce(test_x, skip_obj=True)
 gc.collect()
all_dummies_i = pd.DataFrame(data=KNN(k=3, verbose = False ).fit_transform(all_dummies ).astype(int),
columns=all_dummies.columns, index=all_dummies.index )<categorify>
test_x = feature_engineering(test_x, False)
 gc.collect()
all_dummies_i['isAlwSib'] = all_dummies_i.apply(lambda s: 1 if(s['isAlone'] == 1)|(s['wSib'] == 1)else 0 ,axis = 1)
 all_dummies_i = all_dummies_i.drop(['isAlone','wSib','Sex','GrSize'], axis = 1 )<prepare_x_and_y>
pred_test = model.predict(test_x, num_iteration=model.best_iteration)
 del test_x
gc.collect()
X_train = all_dummies_i.iloc[:891,:]
X_test = all_dummies_i.iloc[891:,:]<normalization>
test_set = pd.read_csv('.. /input/test_V2.csv', engine='c' )
<choose_model_class><EOS> 
submission = pd.read_csv(".. /input/sample_submission_V2.csv")
 submission['winPlacePerc'] = pred_test
submission.loc[submission.winPlacePerc < 0, "winPlacePerc"] = 0
submission.loc[submission.winPlacePerc > 1, "winPlacePerc"] = 1
submission = submission.merge(test_set[["Id", "matchId", "groupId", "maxPlace", "numGroups"]], on="Id", how="left")
 submission_group = submission.groupby(["matchId", "groupId"] ).first().reset_index()
submission_group["rank"] = submission_group.groupby(["matchId"])["winPlacePerc"].rank()
submission_group = submission_group.merge(
 submission_group.groupby("matchId")["rank"].max().to_frame("max_rank" ).reset_index() ,
on="matchId", how="left")
 submission_group["adjusted_perc"] =(submission_group["rank"] - 1)/(submission_group["numGroups"] - 1)
 submission = submission.merge(submission_group[["adjusted_perc", "matchId", "groupId"]], on=["matchId", "groupId"], how="left")
 submission["winPlacePerc"] = submission["adjusted_perc"]
submission.loc[submission.maxPlace == 0, "winPlacePerc"] = 0
submission.loc[submission.maxPlace == 1, "winPlacePerc"] = 1
subset = submission.loc[submission.maxPlace > 1]
gap = 1.0 /(subset.maxPlace.values - 1)
 new_perc = np.around(subset.winPlacePerc.values / gap)* gap
submission.loc[submission.maxPlace > 1, "winPlacePerc"] = new_perc
submission.loc[(submission.maxPlace > 1)&(submission.numGroups == 1), "winPlacePerc"] = 0
assert submission["winPlacePerc"].isnull().sum() == 0
submission[["Id", "winPlacePerc"]].to_csv("submission.csv", index=False )