In [49]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt 
import warnings
import seaborn as sns

from sklearn import tree
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans

#To ignore warnings
warnings.filterwarnings("ignore")
In [50]:
#Find where the dataset is being stored and load it
file_path = r"C:OneDrive/Year 3/AI and Machine Learning/online_gaming_behavior_dataset.csv"
data=pd.read_csv(file_path)
In [51]:
#Print dataset to see if it has loaded correctly
print(data)
       PlayerID  Age  Gender Location   GameGenre  PlayTimeHours  \
0          9000   43    Male    Other    Strategy      16.271119   
1          9001   29  Female      USA    Strategy       5.525961   
2          9002   22  Female      USA      Sports       8.223755   
3          9003   35    Male      USA      Action       5.265351   
4          9004   33    Male   Europe      Action      15.531945   
...         ...  ...     ...      ...         ...            ...   
40029     49029   32    Male      USA    Strategy      20.619662   
40030     49030   44  Female    Other  Simulation      13.539280   
40031     49031   15  Female      USA         RPG       0.240057   
40032     49032   34    Male      USA      Sports      14.017818   
40033     49033   19    Male      USA      Sports      10.083804   

       InGamePurchases GameDifficulty  SessionsPerWeek  \
0                    0         Medium                6   
1                    0         Medium                5   
2                    0           Easy               16   
3                    1           Easy                9   
4                    0         Medium                2   
...                ...            ...              ...   
40029                0           Easy                4   
40030                0           Hard               19   
40031                1           Easy               10   
40032                1         Medium                3   
40033                0           Easy               13   

       AvgSessionDurationMinutes  PlayerLevel  AchievementsUnlocked  \
0                            108           79                    25   
1                            144           11                    10   
2                            142           35                    41   
3                             85           57                    47   
4                            131           95                    37   
...                          ...          ...                   ...   
40029                         75           85                    14   
40030                        114           71                    27   
40031                        176           29                     1   
40032                        128           70                    10   
40033                         84           72                    39   

      EngagementLevel  
0              Medium  
1              Medium  
2                High  
3              Medium  
4              Medium  
...               ...  
40029          Medium  
40030            High  
40031            High  
40032          Medium  
40033          Medium  

[40034 rows x 13 columns]
In [52]:
#Dropping the unique ID column and the in game purchases comlumn
data=data.drop(['PlayerID', 'InGamePurchases'], axis=1)
In [53]:
# Creating numerical columns
num_cols=['Age', 'PlayTimeHours', 'SessionsPerWeek', 'AvgSessionDurationMinutes', 'PlayerLevel', 'AchievementsUnlocked'] 

# Creating categorical variables 
cat_cols= ['Gender', 'Location', 'GameGenre', 'GameDifficulty', 'EngagementLevel']
In [54]:
# Checking summary statistics
data[num_cols].describe().T
Out[54]:
count mean std min 25% 50% 75% max
Age 40034.0 31.992531 10.043227 15.000000 23.000000 32.000000 41.000000 49.000000
PlayTimeHours 40034.0 12.024365 6.914638 0.000115 6.067501 12.008002 17.963831 23.999592
SessionsPerWeek 40034.0 9.471774 5.763667 0.000000 4.000000 9.000000 14.000000 19.000000
AvgSessionDurationMinutes 40034.0 94.792252 49.011375 10.000000 52.000000 95.000000 137.000000 179.000000
PlayerLevel 40034.0 49.655568 28.588379 1.000000 25.000000 49.000000 74.000000 99.000000
AchievementsUnlocked 40034.0 24.526477 14.430726 0.000000 12.000000 25.000000 37.000000 49.000000
In [55]:
# Creating histograms
data[num_cols].hist(figsize=(10,10))
plt.show()
No description has been provided for this image
In [56]:
# Printing the % sub categories of each category
for i in cat_cols:
    print(data[i].value_counts (normalize=True))
    print('*'*40)
Gender
Male      0.598466
Female    0.401534
Name: proportion, dtype: float64
****************************************
Location
USA       0.399660
Europe    0.299845
Asia      0.202203
Other     0.098291
Name: proportion, dtype: float64
****************************************
GameGenre
Sports        0.201029
Action        0.200804
Strategy      0.200130
Simulation    0.199406
RPG           0.198631
Name: proportion, dtype: float64
****************************************
GameDifficulty
Easy      0.49995
Medium    0.30002
Hard      0.20003
Name: proportion, dtype: float64
****************************************
EngagementLevel
Medium    0.483939
High      0.258181
Low       0.257881
Name: proportion, dtype: float64
****************************************
In [57]:
for i in cat_cols:
    if i!='EngagementLevel':
         (pd.crosstab(data[i],data['EngagementLevel'],normalize='index')*100).plot(kind='bar',figsize=(8,4),stacked=False)
         plt.ylabel('Percentage Engegement Level')
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
In [58]:
# Mean of numerical variables grouped by Engagement Level
data.groupby(['EngagementLevel'])[num_cols].mean()
Out[58]:
Age PlayTimeHours SessionsPerWeek AvgSessionDurationMinutes PlayerLevel AchievementsUnlocked
EngagementLevel
High 31.920085 12.069238 14.254547 131.921827 50.823723 25.095975
Low 31.896939 12.104915 4.530511 66.882119 46.101414 22.661565
Medium 32.082120 11.957503 9.553267 89.856405 50.926293 25.216424
In [59]:
# Plotting the correlation between numerical variables
plt.figure(figsize=(15,8))
sns.heatmap(data[num_cols].corr(), annot=True, fmt='0.2f', cmap='YlOrRd')
Out[59]:
<Axes: >
No description has been provided for this image
In [60]:
#convert text catagories to numerical so the prediction algorithms can read it
data['Gender'] = data['Gender'].map({'M':0, 'F':1})
data['Location'] = data['Location'].astype('category').cat.codes
data['GameGenre'] = data['GameGenre'].astype('category').cat.codes
In [61]:
#Selecting the features for prediction
features=['Age','Location', 'GameGenre', 'PlayTimeHours', 'SessionsPerWeek', 'AvgSessionDurationMinutes', 'PlayerLevel', 'AchievementsUnlocked']
In [62]:
#Using the prediction features and selecting the target variable
X=data[features]
Y=data['EngagementLevel']
In [63]:
#Splitting the dataset into testing and traning sets (70/30 split)
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.3, random_state=109) #Random state ensures repeatability
In [64]:
#Creating and traing the decision tree model
dtree=DecisionTreeClassifier(max_depth=5) #Max depth set to five for easy readability/faster loading times when testing
dtree=dtree.fit(X_train, Y_train)
In [65]:
#Using the trained DT model to make predictions on the testing dataset
dt_pred = dtree.predict(X_test)

#Calculating and printing the DT preformance metrics
print("DT Accuracy:", accuracy_score(Y_test, dt_pred))
print("DT Precision:", precision_score(Y_test, dt_pred, average='weighted'))
print("DT Recall:", recall_score(Y_test, dt_pred, average='weighted'))
print("DT F1 Score:", f1_score(Y_test, dt_pred, average='weighted'))

#Calculating the DT AUC-ROC score
dt_prob = dtree.predict_proba(X_test)
dt_auc = roc_auc_score(Y_test, dt_prob, multi_class='ovr')
print("DT AUC-ROC:", dt_auc)
DT Accuracy: 0.857547248355674
DT Precision: 0.8596886322695013
DT Recall: 0.857547248355674
DT F1 Score: 0.856660642337442
DT AUC-ROC: 0.9225327673135123
In [66]:
#Creating a standard scaler so that all data is on a similar scale
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
In [67]:
#Creating SVM model with a linear kernal (uses straight line boundaries) 
svm_model = SVC(kernel='linear', probability=True)   
svm_model.fit(X_train_scaled, Y_train)
Out[67]:
SVC(kernel='linear', probability=True)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
SVC(kernel='linear', probability=True)
In [68]:
#Predicting engagement level using trained SVM model
svm_pred = svm_model.predict(X_test_scaled)
In [69]:
#Printing SVM preformance metrics
print("SVM Accuracy:", accuracy_score(Y_test, svm_pred))
print("SVM Precision:", precision_score(Y_test, svm_pred, average='weighted'))
print("SVM Recall:", recall_score(Y_test, svm_pred, average='weighted'))
print("SVM F1 Score:", f1_score(Y_test, svm_pred, average='weighted'))

#Calulating the SVM AUC-ROC score
svm_prob = svm_model.predict_proba(X_test_scaled)
svm_auc = roc_auc_score(Y_test, svm_prob, multi_class='ovr')
print("SVM AUC-ROC:", svm_auc)
SVM Accuracy: 0.8308217467321621
SVM Precision: 0.8312654920537748
SVM Recall: 0.8308217467321621
SVM F1 Score: 0.829470880450099
SVM AUC-ROC: 0.9178585491097667
In [70]:
#Plotting DT 
plt.figure(figsize=(12, 8))
tree.plot_tree(dtree,feature_names=features, filled=True, rounded=True, max_depth=7)
Out[70]:
[Text(0.5, 0.9166666666666666, 'SessionsPerWeek <= 2.5\ngini = 0.633\nsamples = 28023\nvalue = [7282.0, 7207.0, 13534.0]'),
 Text(0.25, 0.75, 'SessionsPerWeek <= 1.5\ngini = 0.273\nsamples = 4166\nvalue = [141, 3511, 514]'),
 Text(0.375, 0.8333333333333333, 'True  '),
 Text(0.125, 0.5833333333333334, 'AchievementsUnlocked <= 46.5\ngini = 0.141\nsamples = 2766\nvalue = [97.0, 2559.0, 110.0]'),
 Text(0.0625, 0.4166666666666667, 'PlayerLevel <= 90.5\ngini = 0.13\nsamples = 2592\nvalue = [89, 2414, 89]'),
 Text(0.03125, 0.25, 'PlayerLevel <= 2.5\ngini = 0.119\nsamples = 2381\nvalue = [80, 2232, 69]'),
 Text(0.015625, 0.08333333333333333, 'gini = 0.304\nsamples = 40\nvalue = [4, 33, 3]'),
 Text(0.046875, 0.08333333333333333, 'gini = 0.116\nsamples = 2341\nvalue = [76, 2199, 66]'),
 Text(0.09375, 0.25, 'AvgSessionDurationMinutes <= 137.5\ngini = 0.245\nsamples = 211\nvalue = [9, 182, 20]'),
 Text(0.078125, 0.08333333333333333, 'gini = 0.167\nsamples = 167\nvalue = [9, 152, 6]'),
 Text(0.109375, 0.08333333333333333, 'gini = 0.434\nsamples = 44\nvalue = [0.0, 30.0, 14.0]'),
 Text(0.1875, 0.4166666666666667, 'PlayerLevel <= 68.0\ngini = 0.289\nsamples = 174\nvalue = [8, 145, 21]'),
 Text(0.15625, 0.25, 'AvgSessionDurationMinutes <= 154.5\ngini = 0.176\nsamples = 127\nvalue = [6, 115, 6]'),
 Text(0.140625, 0.08333333333333333, 'gini = 0.136\nsamples = 111\nvalue = [6, 103, 2]'),
 Text(0.171875, 0.08333333333333333, 'gini = 0.375\nsamples = 16\nvalue = [0, 12, 4]'),
 Text(0.21875, 0.25, 'AvgSessionDurationMinutes <= 118.5\ngini = 0.489\nsamples = 47\nvalue = [2, 30, 15]'),
 Text(0.203125, 0.08333333333333333, 'gini = 0.291\nsamples = 30\nvalue = [2, 25, 3]'),
 Text(0.234375, 0.08333333333333333, 'gini = 0.415\nsamples = 17\nvalue = [0, 5, 12]'),
 Text(0.375, 0.5833333333333334, 'AvgSessionDurationMinutes <= 123.5\ngini = 0.453\nsamples = 1400\nvalue = [44.0, 952.0, 404.0]'),
 Text(0.3125, 0.4166666666666667, 'AchievementsUnlocked <= 37.5\ngini = 0.264\nsamples = 911\nvalue = [32, 774, 105]'),
 Text(0.28125, 0.25, 'AvgSessionDurationMinutes <= 118.5\ngini = 0.172\nsamples = 702\nvalue = [25, 637, 40]'),
 Text(0.265625, 0.08333333333333333, 'gini = 0.152\nsamples = 666\nvalue = [21.0, 612.0, 33.0]'),
 Text(0.296875, 0.08333333333333333, 'gini = 0.468\nsamples = 36\nvalue = [4, 25, 7]'),
 Text(0.34375, 0.25, 'PlayerLevel <= 60.0\ngini = 0.472\nsamples = 209\nvalue = [7, 137, 65]'),
 Text(0.328125, 0.08333333333333333, 'gini = 0.198\nsamples = 120\nvalue = [4, 107, 9]'),
 Text(0.359375, 0.08333333333333333, 'gini = 0.489\nsamples = 89\nvalue = [3, 30, 56]'),
 Text(0.4375, 0.4166666666666667, 'AchievementsUnlocked <= 13.5\ngini = 0.493\nsamples = 489\nvalue = [12, 178, 299]'),
 Text(0.40625, 0.25, 'AvgSessionDurationMinutes <= 168.5\ngini = 0.416\nsamples = 138\nvalue = [5, 100, 33]'),
 Text(0.390625, 0.08333333333333333, 'gini = 0.246\nsamples = 109\nvalue = [5, 94, 10]'),
 Text(0.421875, 0.08333333333333333, 'gini = 0.328\nsamples = 29\nvalue = [0, 6, 23]'),
 Text(0.46875, 0.25, 'PlayerLevel <= 32.5\ngini = 0.376\nsamples = 351\nvalue = [7, 78, 266]'),
 Text(0.453125, 0.08333333333333333, 'gini = 0.478\nsamples = 96\nvalue = [0, 58, 38]'),
 Text(0.484375, 0.08333333333333333, 'gini = 0.194\nsamples = 255\nvalue = [7, 20, 228]'),
 Text(0.75, 0.75, 'AvgSessionDurationMinutes <= 93.5\ngini = 0.589\nsamples = 23857\nvalue = [7141.0, 3696.0, 13020.0]'),
 Text(0.625, 0.8333333333333333, '  False'),
 Text(0.625, 0.5833333333333334, 'AvgSessionDurationMinutes <= 23.5\ngini = 0.499\nsamples = 11788\nvalue = [883.0, 3280.0, 7625.0]'),
 Text(0.5625, 0.4166666666666667, 'SessionsPerWeek <= 15.5\ngini = 0.394\nsamples = 1939\nvalue = [72, 1449, 418]'),
 Text(0.53125, 0.25, 'AchievementsUnlocked <= 33.5\ngini = 0.277\nsamples = 1485\nvalue = [51, 1248, 186]'),
 Text(0.515625, 0.08333333333333333, 'gini = 0.172\nsamples = 995\nvalue = [35, 903, 57]'),
 Text(0.546875, 0.08333333333333333, 'gini = 0.434\nsamples = 490\nvalue = [16, 345, 129]'),
 Text(0.59375, 0.25, 'AvgSessionDurationMinutes <= 17.5\ngini = 0.541\nsamples = 454\nvalue = [21, 201, 232]'),
 Text(0.578125, 0.08333333333333333, 'gini = 0.466\nsamples = 259\nvalue = [10, 173, 76]'),
 Text(0.609375, 0.08333333333333333, 'gini = 0.336\nsamples = 195\nvalue = [11.0, 28.0, 156.0]'),
 Text(0.6875, 0.4166666666666667, 'SessionsPerWeek <= 5.5\ngini = 0.423\nsamples = 9849\nvalue = [811, 1831, 7207]'),
 Text(0.65625, 0.25, 'AvgSessionDurationMinutes <= 62.5\ngini = 0.503\nsamples = 1813\nvalue = [61, 1095, 657]'),
 Text(0.640625, 0.08333333333333333, 'gini = 0.349\nsamples = 1021\nvalue = [38, 803, 180]'),
 Text(0.671875, 0.08333333333333333, 'gini = 0.5\nsamples = 792\nvalue = [23, 292, 477]'),
 Text(0.71875, 0.25, 'AvgSessionDurationMinutes <= 76.5\ngini = 0.319\nsamples = 8036\nvalue = [750, 736, 6550]'),
 Text(0.703125, 0.08333333333333333, 'gini = 0.267\nsamples = 6065\nvalue = [252, 668, 5145]'),
 Text(0.734375, 0.08333333333333333, 'gini = 0.427\nsamples = 1971\nvalue = [498, 68, 1405]'),
 Text(0.875, 0.5833333333333334, 'SessionsPerWeek <= 9.5\ngini = 0.53\nsamples = 12069\nvalue = [6258, 416, 5395]'),
 Text(0.8125, 0.4166666666666667, 'SessionsPerWeek <= 8.5\ngini = 0.23\nsamples = 4985\nvalue = [434, 203, 4348]'),
 Text(0.78125, 0.25, 'SessionsPerWeek <= 7.5\ngini = 0.173\nsamples = 4290\nvalue = [214, 186, 3890]'),
 Text(0.765625, 0.08333333333333333, 'gini = 0.148\nsamples = 3606\nvalue = [126.0, 157.0, 3323.0]'),
 Text(0.796875, 0.08333333333333333, 'gini = 0.294\nsamples = 684\nvalue = [88, 29, 567]'),
 Text(0.84375, 0.25, 'AvgSessionDurationMinutes <= 150.5\ngini = 0.465\nsamples = 695\nvalue = [220.0, 17.0, 458.0]'),
 Text(0.828125, 0.08333333333333333, 'gini = 0.202\nsamples = 477\nvalue = [40, 13, 424]'),
 Text(0.859375, 0.08333333333333333, 'gini = 0.294\nsamples = 218\nvalue = [180, 4, 34]'),
 Text(0.9375, 0.4166666666666667, 'SessionsPerWeek <= 12.5\ngini = 0.301\nsamples = 7084\nvalue = [5824, 213, 1047]'),
 Text(0.90625, 0.25, 'AvgSessionDurationMinutes <= 125.5\ngini = 0.494\nsamples = 2145\nvalue = [1323, 64, 758]'),
 Text(0.890625, 0.08333333333333333, 'gini = 0.348\nsamples = 801\nvalue = [137, 33, 631]'),
 Text(0.921875, 0.08333333333333333, 'gini = 0.212\nsamples = 1344\nvalue = [1186, 31, 127]'),
 Text(0.96875, 0.25, 'AvgSessionDurationMinutes <= 101.5\ngini = 0.165\nsamples = 4939\nvalue = [4501, 149, 289]'),
 Text(0.953125, 0.08333333333333333, 'gini = 0.401\nsamples = 454\nvalue = [337, 20, 97]'),
 Text(0.984375, 0.08333333333333333, 'gini = 0.135\nsamples = 4485\nvalue = [4164, 129, 192]')]
No description has been provided for this image
In [71]:
#Example prediction for a single player (column numbers are interchangable)
single_player = pd.DataFrame([[27, 200, 2, 9, 120, 4, 1, 12]], columns=features)
print(dtree.predict(single_player))
['Low']
In [72]:
#Selecting two data columns to compare when clustering
subset = data[['SessionsPerWeek', 'PlayTimeHours']]
In [73]:
#Standardising chosen features to be on the same scale
KMscaler = StandardScaler()
cluster_scaled = KMscaler.fit_transform(subset)
In [74]:
#Graph limited to 500 plots so avoid overcorwding
player_sample = data.sample(n=500, random_state=42) #Random state ensures the same 500 records are picked

#Jitter added to spread out plots
x = player_sample['SessionsPerWeek'] + np.random.normal(0, 0.5, size=player_sample.shape[0])
y = player_sample['PlayTimeHours'] + np.random.normal(0, 0.2, size=player_sample.shape[0])
In [75]:
#Creating scatter plot comparing the Sessions played x Hours played
plt.figure(figsize=(8,6))
plt.scatter(x, y)
plt.xlabel('Sessions Per Week')
plt.ylabel('Play Time Hours')
plt.title('Player Behaviour Scatter Plot')
plt.show()
No description has been provided for this image
In [76]:
#Clustering example 
km1 = KMeans(n_clusters=3) #Creating a k means model with three clusters
km1.fit(cluster_scaled)
Out[76]:
KMeans(n_clusters=3)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KMeans(n_clusters=3)
In [77]:
#Getting and adding the cluster labels for each player to the dataset 
labels1 = km1.labels_
data['player_segment'] = km1.labels_
In [78]:
#Max sample plots set to 500
player_sample_1 = data.sample(n=500, random_state=42)

#Adding jitter for better visuals
player_sample_1['SessionsPerWeek_jitter'] = player_sample_1['SessionsPerWeek'] + np.random.normal(0, 0.2, size=player_sample_1.shape[0])
player_sample_1['PlayTimeHours_jitter'] = player_sample_1['PlayTimeHours'] + np.random.normal(0, 0.5, size=player_sample_1.shape[0])
In [79]:
#Plotting Scatterplot for first clustering example
plt.figure(figsize=(8,6))
sns.scatterplot(x='SessionsPerWeek_jitter', y='PlayTimeHours_jitter', hue='player_segment', palette='Set1', data=player_sample_1)
plt.xlabel('Sessions per Week')
plt.ylabel('Play Time Hours')
plt.title('KMeans Player Behaviour')
plt.legend(title='Cluster Groups')
plt.show()
No description has been provided for this image
In [80]:
#Clustering example 2 
subset_2 = data[['PlayerLevel', 'PlayTimeHours']]
In [81]:
#Standardising chosen features
cluster_scaled_2 = StandardScaler().fit_transform(subset_2)
In [82]:
#Creating second k means model with three clusters
km2 = KMeans(n_clusters=3)
km2.fit(cluster_scaled_2)
Out[82]:
KMeans(n_clusters=3)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KMeans(n_clusters=3)
In [83]:
#Store the newcluster labels in the dataset
data['player_segment_2'] = km2.labels_
In [85]:
#Second player sample, limited to 500 plots so the graph is readable 
player_sample_2 = data.sample(n=500, random_state=42)

#Adding jitter so simliar plots don't overlap
player_sample_2['PlayerLevel_jitter'] = player_sample_2['PlayerLevel'] + np.random.normal(0, 0.2, size=player_sample_2.shape[0])
player_sample_2['PlayTimeHours_jitter'] = player_sample_2['PlayTimeHours'] + np.random.normal(0, 0.5, size=player_sample_2.shape[0])
In [86]:
#Plotting second scattergraph for clustering exmaple 2
plt.figure(figsize=(8,6))
sns.scatterplot(x='PlayerLevel_jitter', y='PlayTimeHours_jitter', hue='player_segment_2', palette='Set1', data=player_sample_2)
plt.xlabel('Player Level')
plt.ylabel('Play Time Hours')
plt.title('K-Means Player Segments by Level & Hours Played')
plt.legend(title='Cluster')
plt.show()
No description has been provided for this image
In [87]:
#Creating an empty list to store values
WCSS = []
silhouette_scores = []

#Setting range of clusters to try
K = range(2, 9) #silhouette score cannot run k=1

#Creating loop that will keep looping through the set range 
for i in K:
    model = KMeans(n_clusters=i, init='k-means++', max_iter=300, n_init=10, random_state=42)
    model.fit(cluster_scaled) #Fitting the k means model to the scaled data
    WCSS.append(model.inertia_)
    
    #Calculating silhouette scor 
    score = silhouette_score(cluster_scaled, model.labels_)
    silhouette_scores.append(score)
In [88]:
#Plotting the 'Elbow Method' graph
plt.plot(K, WCSS)
plt.xlabel('Number of clusters (k)')
plt.ylabel('WCSS')
plt.show()
No description has been provided for this image
In [89]:
#Plotting the silhouette score graph
plt.figure(figsize=(8,5))
plt.plot(K, silhouette_scores, marker='o')
plt.xlabel('Number of clusters')
plt.ylabel('Silhouette Score')
plt.title('Silhouette Score vs Number of Clusters')
plt.show()
No description has been provided for this image
In [ ]:
#Printing the column heading of the dataset
print(data.columns)
In [ ]: