Loading...

Movies Scoring and Clustering

This example uses the filmtv_movies dataset to evaluate the quality of the movies and create clusters of similar movies. You can download the Jupyter notebook here.

The columns provided include:

  • year: Movie’s release year.

  • filmtv_id: Movie ID.

  • title: Movie title.

  • genre: Movie genre.

  • country: Movie’s country of origin.

  • description: Movie description.

  • notes: Information about the movie.

  • duration: Movie duration.

  • votes: Number of votes.

  • avg_vote: Average score.

  • director: Movie director.

  • actors: Actors in the movie.

We will follow the data science cycle (Data Exploration - Data Preparation - Data Modeling - Model Evaluation - Model Deployment) to solve this problem.

Initialization

This example uses the following version of VerticaPy:

import verticapy as vp

vp.__version__
Out[2]: '1.1.0'

Connect to Vertica. This example uses an existing connection called VerticaDSN. For details on how to create a connection, see the Connection tutorial. You can skip the below cell if you already have an established connection.

vp.connect("VerticaDSN")

Let’s create a new schema and assign the data to a vDataFrame object.

vp.drop("movies", method="schema")
vp.create_schema("movies")
filmtv_movies = vp.read_csv("movies.csv", schema = "movies")
filmtv_movies.head(5)

Let’s take a look at the first few entries in the dataset.

123
filmtv_id
Int
100%
...
Abc
Varchar(2232)
0%
Abc
Varchar(1052)
0%
124...
230...
364...
465...
5115...

Data Exploration and Preparation

One of the biggest challenges for any streaming platform is to find a good catalog of movies.

First, let’s explore the dataset.

filmtv_movies.describe(method = "categorical", unique = True)
...
top_percent
unique
"filmtv_id"...0.00253327.0
"title"...0.01950524.0
"year"...3.096111.0
"genre"...30.13727.0
"duration"...11.808279.0
"country"...41.1422394.0
"director"...0.13719146.0
"actors"...5.66350056.0
"avg_vote"...15.01989.0
"votes"...22.986588.0
"description"...99.458284.0
"notes"...99.93235.0

We can drop the description and notes columns since these fields are empty for most of our dataset.

filmtv_movies.drop(["description", "notes"])
123
filmtv_id
Int
100%
...
Abc
title
Varchar(486)
99%
123
votes
Int
100%
124...A... come assassino3
230...A Ghentar si muore facile2
364...A tutte le volanti1
465...Gas1
5115...Goodbye, My Lady3
6116...Ring of Bright Water1
7128...Lady Possessed1
8180...Rhino!2
9181...Die Flusspiraten vom Mississippi2
10188...Aida7
11201...Al Capone11
12205...Die Nackt und der Satan5
13207...Al di là della legge21
14208...All the Way Home7
15211...Checking Out2
16223...The Hanging Tree64
17224...Raintree County21
18231...Alfred the Great6
19232...Q Planes4
20234...The Wizard of Baghdad1

We have access to more than 50000 movies in 27 different genres. Let’s organize our list by their average rating.

filmtv_movies.sort({"avg_vote" : "desc"})
123
filmtv_id
Int
100%
...
Abc
Varchar(486)
99%
123
votes
Int
100%
176646...1
277950...1
386071...1
480205...1
579888...1
686266...1
7122810...1
8128665...1
986042...1
1084535...1
11139242...1
12121261...2
1386945...1
14141940...3
15138920...1
16134090...1
17145657...1
18129161...1
19146073...1
20139825...1

Since we want properly averaged scores, let’s just consider the top 10 movies that have at least 10 votes.

filmtv_movies.search(
    conditions = [filmtv_movies["votes"] > 10],
    order_by = {"avg_vote" : "desc" },
)
123
filmtv_id
Integer
100%
...
Abc
Varchar(486)
100%
123
votes
Integer
100%
125980...33
216567...58
329136...24
47042...427
57753...535
63831...477
75648...588
823395...325
927908...68
1016584...30
1112135...72
1210423...29
135580...789
1426035...31
1523112...125
1618173...148
1727984...18
1823023...50
1912730...514
2028382...17

We can see classic movies like The Godfather and Greed. Let’s smooth the avg_vote using a linear regression to make it more representative.

To create our model we could use the votes, the category, the duration, etc. but let’s go with the director and main actors.

We can extract the five main actors for each movie with regular expressions.

for i in range(1, 5):
    filmtv_movies2 = vp.read_csv("movies.csv")
    filmtv_movies2.regexp(
        column = "actors",
        method = "substr",
        pattern = '[^,]+',
        occurrence = i,
        name = "actor",
    )
    if i == 1:
        filmtv_movies = filmtv_movies2.copy()
    else:
        filmtv_movies = filmtv_movies.append(filmtv_movies2)
filmtv_movies["actor"].describe()

By aggregating the data, we can find the number of actors and the number of votes by actor. We can then normalize the data using the min-max method and quantify the notoriety of the actors.

import verticapy.sql.functions as fun

actors_stats = filmtv_movies.groupby(
    columns = ["actor"],
    expr = [
        fun.sum(filmtv_movies["votes"])._as("notoriety_actors"),
        fun.count(filmtv_movies["actors"])._as("castings_actors"),
    ],
)
actors_stats["actor"].dropna()
actors_stats["notoriety_actors"].normalize(method = "minmax")
Abc
actor
Varchar(2218)
100%
...
123
notoriety_actors
Float
100%
123
castings_actors
Integer
100%
1 Aladin Reibel...0.0008132560740064
2 Ann Miller...0.0816305784283834
3 Gwendolyn Laster...0.0007115990647561
4Andrew Scott...0.0014231981295113
5 Wu Nien-chen...0.01
6 Salvo Piparo...0.0010165700925081
7 Jay Rodan...0.0052861644810413
8 Maria Conchita Alonso...0.03944291958930619
9Arsinée Khanjian...0.0031513672867742
10 Emily Bett Rickards...0.0117922130730911
11 Joan Gardner...0.0008132560740064
12 Nick Hanauer...0.0002033140185021
13 Danielle De Metz...0.0018298261665143
14Lena Endre...0.0016265121480132
15 Leigh J. McCloskey...0.01
16 Clark Fyans...0.0001016570092511
17 Helgi Skúlason...0.0001016570092511
18 Dulcie Gray...0.0001016570092512
19Ravi Menon...0.01
20 Roderick Cook...0.01

Let’s look at the top ten actors by notoriety.

actors_stats.search(
    order_by = {
        "notoriety_actors" : "desc",
        "castings_actors" : "desc",
    },
).head(10)
Abc
actor
Varchar(2218)
100%
...
123
notoriety_actors
Numeric(36)
100%
123
castings_actors
Integer
100%
1Robert De Niro...1.057
2 Morgan Freeman...0.86144149639117652
3Clint Eastwood...0.85646030293788843
4Tom Cruise...0.82037206465385834
5Johnny Depp...0.81488258615431534
6Tom Hanks...0.77188167124123237
7 Samuel L. Jackson...0.74250279556775449
8Brad Pitt...0.7277625292263926
9Leonardo DiCaprio...0.71546203110704520
10Al Pacino...0.64836840500152540

As expected, we get a list of very popular actors like Robert De Niro, Morgan Freeman, and Clint Eastwood.

Let’s do the same for the directors.

director_stats = filmtv_movies.groupby(
    columns = ["director"],
    expr = [
        fun.sum(filmtv_movies["votes"])._as("notoriety_director"),
        fun.count(filmtv_movies["director"])._as("castings_director"),
    ],
)
director_stats["notoriety_director"].normalize(method = "minmax")
Abc
Varchar(1066)
99%
...
123
notoriety_director
Float
100%
123
castings_director
Integer
100%
1...0.04
2...0.0003466204506074
3...8.6655112652e-054
4...0.0014731369150784
5...0.04
6...0.0025996533795494
7...0.0028596187175048
8...0.04
9...0.0002599653379554
10...0.0033795493934148
11...0.04
12...0.00545927209705416
13...0.0003466204506074
14...0.04
15...0.00077989601386524
16...0.001039861351824
17...0.0001733102253034
18...8.6655112652e-054
19...0.00043327556325812
20...0.0006065857885624

Now let’s look at the top 10 movie directors.

director_stats.search(
    order_by = {
        "notoriety_director" : "desc",
        "castings_director" : "desc",
    },
).head(10)
Abc
director
Varchar(1066)
99%
...
123
notoriety_director
Numeric(36)
100%
123
castings_director
Integer
100%
1Steven Spielberg...1.0132
2Woody Allen...0.962045060658579192
3Clint Eastwood...0.893067590987868152
4Martin Scorsese...0.829289428076256140
5Alfred Hitchcock...0.753379549393414208
6Quentin Tarantino...0.68674176776429840
7Ridley Scott...0.655459272097054108
8Stanley Kubrick...0.64991334488734848
9Tim Burton...0.58821490467937672
10David Cronenberg...0.51343154246100584

Again, we get a list of popular directors like Steven Spielberg, Woody Allen, and Clint Eastwood.

Let’s join our notoriety metrics for actors and directors with the main dataset.

filmtv_movies_director = filmtv_movies.join(
    director_stats,
    on = {"director": "director"},
    how = "left",
    expr1 = ["*"],
    expr2 = [
        "notoriety_director",
        "castings_director",
    ],
)


filmtv_movies_director_actors = filmtv_movies_director.join(
    actors_stats,
    on = {"actor": "actor"},
    how = "left",
    expr1 = ["*"],
    expr2 = [
        "notoriety_actors",
        "castings_actors",
    ],
)

As we did many operation, it can be nice to save the vDataFrame as a table in the Vertica database.

vp.drop("filmtv_movies_director_actors", method = "table")
filmtv_movies_director_actors.to_db(
    name = "filmtv_movies_director_actors",
    relation_type = "table",
    inplace = True,
)

We can aggregate the data to get metrics on each movie.

filmtv_movies_complete = filmtv_movies_director_actors.groupby(
    columns = [
        "filmtv_id",
        "title",
        "year",
        "genre",
        "country",
        "avg_vote",
        "votes",
        "duration",
        "director",
        "notoriety_director",
        "castings_director",
    ],
    expr = [
        fun.sum(filmtv_movies_director_actors["notoriety_actors"])._as("notoriety_actors"),
        fun.sum(filmtv_movies_director_actors["castings_actors"])._as("castings_actors"),
    ],
)

Let’s compute some statistics on our dataset.

filmtv_movies_complete.describe(method = "all")
...
Abc
"country"
Varchar(208)
99%
Abc
"director"
Varchar(1066)
99%
dtype...varchar(208)varchar(1066)
percent...99.90499.884
count...5327653265
top...United StatesMario Mattòli
top_percent...41.1420.137
avg...11.499605826263214.9825213554867
stddev...6.365850632803287.95519700230993
min...43
approx_25%...612
approx_50%...1314
approx_75%...1316
max...104532
range...100529
empty...00

We can use the movie’s release year to get create three categories.

filmtv_movies_complete.case_when(
    "period",
    filmtv_movies_complete["year"] < 1990, "Old",
    filmtv_movies_complete["year"] >= 2000, "Recent", "90s",
)
123
filmtv_id
Integer
100%
...
Abc
Varchar(486)
99%
Abc
period
Varchar(6)
100%
135840...Old
246124...Recent
320158...Old
416557...90s
525485...Old
651429...Recent
752538...Recent
830731...Recent
9155325...Recent
1036664...Recent
1137288...Recent
1215595...Old
1332656...Recent
1434832...Recent
1574068...Recent
166529...Old
1720148...90s
181126...Old
1940519...90s
20142551...Recent

Now, let’s look at the countries that made the most movies.

filmtv_movies_complete.groupby(
    columns = ["country"],
    expr = ["COUNT(*)"]
).sort({"count" : "desc"}).head(10)
Abc
country
Varchar(208)
99%
123
COUNT
Integer
100%
1United States21940
2Italy9056
3France3040
4Great Britain2516
5Germany1697
6Japan1131
7Canada1053
8Spain562
9Italy, France403
10Hong Kong380

We can use this variable to create language groups.

# Language Discretization
Arabic_Middle_Est = [
    "Arab", "Iran", "Turkey", "Egypt", "Tunisia",
    "Lebanon", "Palestine", "Morocco", "Iraq",
    "Sudan", "Algeria", "Yemen", "Afghanistan",
    "Azerbaijan", "Kazakhstan", "Kyrgyzstan",
    "Kurdistan", "Syria", "Uzbekistan",
]


Chinese_Japan_Asian = [
    "Japan", "Hong Kong", "China", "South Korea",
    "Thailand", "Philippines", "Taiwan", "Indonesia",
    "Singapore", "Malaysia", "Vietnam", "Laos", "Cambodia",
    "Bhutan",
]


Indian = ["India", "Pakistan", "Nepal", "Sri Lanka", "Bangladesh",]

Hebrew = ["Israel",]

Spanish_Portuguese = [
    "Spain", "Portugal", "Mexico", "Brasil", "Chile",
    "Argentina", "Colombia", "Cuba", "Venezuela", "Peru",
    "Uruguay", "Dominican Republic", "Ecuador", "Guatemala",
    "Costa Rica", "Paraguay", "Bolivia",
]


English = [
    "United States", "England", "Great Britain", "Ireland",
    "Australia", "New Zealand", "South Africa",
]


French = ["France", "Canada", "Belgium", "Switzerland", "Luxembourg",]

Italian = ["Italy",]

German_North_Europe = [
    "German", "Austria", "Holland", "Netherlands", "Denmark",
    "Norway", "Iceland", "Finland", "Sweden", "Greenland",
]


Russian_Est_Europe = ["Russia", "Soviet Union", "Yugoslavia", "Czechoslovakia", "Poland", "Bulgaria", "Croatia", "Czech Republic", "Serbia", "Ukraine", "Slovenia", "Lithuania", "Latvia", "Estonia", "Bosnia and Herzegovina", "Georgia"]

Grec_Balkan = [
    "Greece", "Macedonia", "Cyprus", "Romania", "Armenia", "Hungary",
    "Albania", "Malta",
]

# Creation of the new feature
filmtv_movies_complete.case_when('language_area',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(Arabic_Middle_Est))), 'Arabic_Middle_Est',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(Chinese_Japan_Asian))), 'Chinese_Japan_Asian',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(Indian))), 'Indian',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(Hebrew))), 'Hebrew',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(Spanish_Portuguese))), 'Spanish_Portuguese',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(English))), 'English',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(French))), 'French',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(Italian))), 'Italian',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(German_North_Europe))), 'German_North_Europe',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(Russian_Est_Europe))), 'Russian_Est_Europe',
        vp.StringSQL("REGEXP_LIKE(Country, '{}')".format("|".join(Grec_Balkan))), 'Grec_Balkan',
        'Others')
123
filmtv_id
Integer
100%
...
Abc
period
Varchar(6)
100%
Abc
language_area
Varchar(19)
100%
159122...OldFrench
2161519...RecentEnglish
3144169...RecentIndian
440108...RecentItalian
534236...OldEnglish
636000...OldItalian
728139...OldEnglish
876652...OldFrench
972927...RecentFrench
1057435...OldGerman_North_Europe
1116451...90sFrench
1213626...90sEnglish
134142...OldEnglish
1436589...RecentItalian
1546277...RecentItalian
1632982...OldGerman_North_Europe
1717698...OldEnglish
1831352...OldItalian
19173623...RecentEnglish
2037082...90sEnglish

We can do the same for the genres.

filmtv_movies_complete.case_when(
        'Category',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Drama|Noir')"), 'Drama',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Comedy|Grotesque')"), 'Comedy',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Fantasy|Super-hero')"), 'Fantasy',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Romantic|Sperimental|Mélo')"), 'Romantic',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Thriller|Crime|Gangster')"), 'Thriller',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Action|Western|War|Spy')"), 'Action',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Adventure')"), 'Adventure',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Animation')"), 'Animation',
        vp.StringSQL("REGEXP_LIKE(Genre, 'Horror')"), 'Horror',
        'Others'
)
123
filmtv_id
Integer
100%
...
Abc
Varchar(486)
99%
Abc
Category
Varchar(9)
100%
112170...Comedy
24116...Comedy
32425...Comedy
476988...Drama
540681...Romantic
67304...Comedy
783180...Drama
818604...Drama
920985...Horror
1035916...Drama
116334...Comedy
1251477...Thriller
1379558...Others
1412213...Drama
1514673...Comedy
1618262...Drama
175539...Thriller
1837969...Drama
1916214...Drama
2070767...Drama

Since we’re more concerned with the Category at this point, we can drop genre.

filmtv_movies_complete.drop(columns = ["genre"])

Let’s look at the missing values.

filmtv_movies_complete.count_percent()
...
count
percent
"filmtv_id"...53327.0100.0
"avg_vote"...53327.0100.0
"votes"...53327.0100.0
"duration"...53327.0100.0
"period"...53327.0100.0
"language_area"...53327.0100.0
"Category"...53327.0100.0
"title"...53325.099.996
"year"...53317.099.981
"country"...53276.099.904
"director"...53265.099.884
"notoriety_director"...53265.099.884
"castings_director"...53265.099.884
"notoriety_actors"...50307.094.337
"castings_actors"...50307.094.337

Let’s impute the missing values for notoriety_actors and castings_actors using different techniques.

We can then drop the few remaining missing values.

filmtv_movies_complete["notoriety_actors"].fillna(
    method = "median",
    by = [
        "director",
        "Category",
    ],
)
filmtv_movies_complete["castings_actors"].fillna(
    method = "median",
    by = [
        "director",
        "Category",
    ],
)
filmtv_movies_complete.dropna()
123
filmtv_id
Integer
100%
...
Abc
language_area
Varchar(19)
100%
Abc
Category
Varchar(9)
100%
113022...EnglishAction
229250...EnglishAction
341127...Chinese_Japan_AsianAction
414741...EnglishAction
516763...EnglishAction
6157253...Chinese_Japan_AsianAction
7132848...Chinese_Japan_AsianAction
812439...EnglishAction
94294...EnglishAction
1062803...EnglishAction
1147005...EnglishAction
1276088...OthersAction
1366736...EnglishAction
14157811...EnglishAction
159703...EnglishAction
16121219...EnglishAction
1728616...EnglishAction
1814515...Spanish_PortugueseAction
197397...ItalianAction
2027217...ItalianAction

Before we export the data, we should normalize the numerical columns to get the dummies of the different categories.

filmtv_movies_complete.normalize(
    method = "minmax",
    columns = [
        "votes",
        "duration",
        "notoriety_director",
        "castings_director",
        "notoriety_actors",
        "castings_actors",
    ],
)

Out[17]: 
None  filmtv_id    ...          language_area    Category  
1         13134    ...                Italian      Action  
2         43946    ...     Spanish_Portuguese      Action  
3         57083    ...     Spanish_Portuguese      Action  
4          3760    ...                Italian      Action  
5         58321    ...                 French      Action  
6         17252    ...                Italian      Action  
7          5058    ...                Italian      Action  
8          7345    ...                Italian      Action  
9         24945    ...                English      Action  
10         4783    ...                English      Action  
11         3427    ...                English      Action  
12        37026    ...                English      Action  
13       170419    ...                English      Action  
14       149103    ...    Chinese_Japan_Asian      Action  
15        56496    ...                English      Action  
16        26778    ...                English      Action  
17        34351    ...                English      Action  
18        35451    ...                English      Action  
19        11606    ...                English      Action  
20         5323    ...                English      Action  
...         ...    ...                    ...         ...  
Rows: 1-20 of 50831 | Columns: 4

for elem in ["category", "period", "language_area"]:
    filmtv_movies_complete[elem].get_dummies(drop_first = True)

We can export the results to our Vertica database.

filmtv_movies_complete.to_db(
    name = "filmtv_movies_complete",
    relation_type = "table",
    inplace = True,
)
filmtv_movies_complete.to_db(
    name = "filmtv_movies_mco",
    relation_type = "view",
    db_filter = "votes > 0.02",
)

Machine Learning : Adjusting the Films Rates

Let’s create a model to evaluate an unbiased score for each different movie.

from verticapy.machine_learning.vertica.linear_model import LinearRegression

predictors = filmtv_movies_complete.get_columns(
    exclude_columns = [
        "avg_vote",
        "period",
        "director",
        "language_area",
        "title",
        "year",
        "country",
        "Category",
    ],
)


vp.drop("filmtv_movies_lr") # If model name already exists
Out[21]: True

model = LinearRegression(
    "filmtv_movies_lr",
    max_iter = 1000,
    solver = "BFGS",
)


model.fit("filmtv_movies_mco", predictors, "avg_vote")


=======
details
=======
            predictor            |coefficient|std_err | t_value |p_value 
---------------------------------+-----------+--------+---------+--------
            Intercept            |  5.51752  | 0.06811|81.01187 | 0.00000
            filmtv_id            |  0.00000  | 0.00000| 2.12608 | 0.03352
              votes              |  5.51964  | 0.13995|39.43918 | 0.00000
            duration             | 14.38180  | 2.01767| 7.12792 | 0.00000
       notoriety_director        | -0.00375  | 0.08850|-0.04239 | 0.96619
        castings_director        |  0.19043  | 0.06989| 2.72457 | 0.00645
        notoriety_actors         | -1.12558  | 0.10928|-10.29957| 0.00000
         castings_actors         |  0.06521  | 0.11143| 0.58525 | 0.55840
         category_action         | -0.21055  | 0.04275|-4.92542 | 0.00000
       category_adventure        | -0.28171  | 0.06659|-4.23056 | 0.00002
       category_animation        |  0.71959  | 0.23813| 3.02187 | 0.00252
         category_comedy         | -0.15443  | 0.03590|-4.30178 | 0.00002
         category_drama          |  0.51295  | 0.03578|14.33749 | 0.00000
        category_fantasy         | -0.41598  | 0.04860|-8.55911 | 0.00000
         category_horror         | -0.40973  | 0.04744|-8.63595 | 0.00000
         category_others         |  0.56428  | 0.05551|10.16458 | 0.00000
        category_romantic        |  0.17602  | 0.08426| 2.08914 | 0.03672
           period_90s            |  0.51808  | 0.03137|16.51406 | 0.00000
           period_old            |  1.26392  | 0.02943|42.94980 | 0.00000
 language_area_arabic_middle_est |  0.23921  | 0.13128| 1.82214 | 0.06846
language_area_chinese_japan_asian|  0.58808  | 0.07456| 7.88786 | 0.00000
      language_area_english      | -0.22049  | 0.05702|-3.86668 | 0.00011
      language_area_french       |  0.09483  | 0.06345| 1.49469 | 0.13503
language_area_german_north_europe|  0.24511  | 0.08050| 3.04491 | 0.00233
    language_area_grec_balkan    |  0.61652  | 0.36109| 1.70739 | 0.08778
      language_area_hebrew       |  0.43149  | 0.49329| 0.87472 | 0.38175
      language_area_indian       |  0.11994  | 0.75991| 0.15784 | 0.87459
      language_area_italian      | -0.78387  | 0.05999|-13.06757| 0.00000
      language_area_others       |  0.00000  | 0.91351| 0.00000 | 1.00000
language_area_russian_est_europe |  0.58483  | 0.12646| 4.62450 | 0.00000


==============
regularization
==============
type| lambda 
----+--------
none| 1.00000


===========
call_string
===========
linear_reg('public.filmtv_movies_lr', 'filmtv_movies_mco', '"avg_vote"', '"filmtv_id", "votes", "duration", "notoriety_director", "castings_director", "notoriety_actors", "castings_actors", "Category_Action", "Category_Adventure", "Category_Animation", "Category_Comedy", "Category_Drama", "Category_Fantasy", "Category_Horror", "Category_Others", "Category_Romantic", "period_90s", "period_Old", "language_area_Arabic_Middle_Est", "language_area_Chinese_Japan_Asian", "language_area_English", "language_area_French", "language_area_German_North_Europe", "language_area_Grec_Balkan", "language_area_Hebrew", "language_area_Indian", "language_area_Italian", "language_area_Others", "language_area_Russian_Est_Europe"'
USING PARAMETERS optimizer='bfgs', epsilon=1e-06, max_iterations=1000, regularization='none', lambda=1, alpha=0.5, fit_intercept=true)

===============
Additional Info
===============
       Name       |Value
------------------+-----
 iteration_count  | 28  
rejected_row_count|  0  
accepted_row_count|10307
model.report()
value
explained_variance0.464651819821462
max_error4.90691407293243
median_absolute_error0.593429116536077
mean_absolute_error0.715710573929926
mean_squared_error0.832067099504979
root_mean_squared_error0.912177120687084
r20.464651819812942
r2_adj0.463141155492087
aic-1834.5053132193
bic-1617.64412628404

The model is good. Let’s add it in our vDataFrame.

model.predict(
    filmtv_movies_complete,
    name = "unbiased_vote",
)
123
filmtv_id
Int
100%
...
Abc
title
Varchar(486)
100%
123
unbiased_vote
Float(22)
100%
118...Diner6.52335043317847
261...The Appaloosa6.46961868237301
3116...Ring of Bright Water6.4620963698666
4172...The Hostage Tower6.51076490336608
5173...The Pawnshop6.36489185260189
6187...Ai vostri ordini, signora...6.06268700597543
7188...Aida6.69087133291048
8196...It Nearly Wasn't Christmas6.45844725319076
9210...Above Suspicion6.6391005059926
10218...Dallas: The Early Years6.85725736623595
11224...Raintree County7.42478326783083
12226...Alcune signore perbene5.88526099157838
13233...Nightwing6.39474949339561
14234...The Wizard of Baghdad6.36906694852514
15235...Alibi7.70518977148171
16238...Her Alibi6.78324730504166
17241...Alice Doesn't Live Here Anymore7.55842968143407
18245...Alien terror6.24929132432935
19250...Run for Cover6.65040062858399
20255...All'ultimo sangue5.9667196793943

Since a score can’t be greater than 10 or less than 0, we need to adjust the unbiased_vote.

filmtv_movies_complete["unbiased_vote"] = fun.case_when(
    filmtv_movies_complete["unbiased_vote"] > 10, 10,
    filmtv_movies_complete["unbiased_vote"] < 0, 0,
    filmtv_movies_complete["unbiased_vote"],
)

Let’s look at the top movies.

filmtv_movies_complete.search(
    usecols = [
        "filmtv_id",
        "title",
        "year",
        "country",
        "avg_vote",
        "unbiased_vote",
        "votes",
        "duration",
        "director",
        "notoriety_director",
        "castings_director",
        "notoriety_actors",
        "castings_actors",
        "period",
        "language_area",
    ],
    order_by = {
        "unbiased_vote" : "desc",
        "avg_vote" : "desc",
    },
).head(10)
123
filmtv_id
Integer
100%
...
Abc
period
Varchar(6)
100%
Abc
language_area
Varchar(19)
100%
15580...OldEnglish
227984...90sGerman_North_Europe
317065...OldEnglish
41963...OldEnglish
56476...OldEnglish
64991...OldEnglish
77025...OldEnglish
812849...90sEnglish
927983...OldGerman_North_Europe
101152...OldEnglish

Great, our results are more consistent. Psycho, Pulp Fiction, and The Godfather are among the top movies.

Machine Learning : Creating Movie Clusters

Since KMeans clustering is sensitive to unnormalized data, let’s normalize our new predictors.

filmtv_movies_complete["unbiased_vote"].normalize(method = "minmax")
123
filmtv_id
Int
100%
...
Abc
Varchar(486)
100%
123
unbiased_vote
Float
100%
130...0.29204883188871
241...0.567574841850368
358...0.445403875628512
491...0.403384664509852
5125...0.45102875011258
6136...0.384611253670232
7180...0.379759309324951
8181...0.471966137135568
9186...0.436677749985097
10193...0.415990552650199
11194...0.283165231465175
12198...0.31023899390153
13202...0.505342966160913
14203...0.38045294583808
15207...0.306872195545759
16208...0.523419969586664
17214...0.436874173972948
18217...0.356571540814665
19223...0.424933002280405
20229...0.528059407347737

Let’s compute the elbow() curve to find a suitable number of clusters.

predictors = filmtv_movies_complete.get_columns(
    exclude_columns = [
        "avg_vote",
        "period",
        "director",
        "language_area",
        "title",
        "year",
        "country",
        "Category",
        "filmtv_id",
    ],
)


from verticapy.machine_learning.model_selection import elbow

import verticapy

verticapy.set_option("plotting_lib", "plotly") # to switch plotting graphics to plotly

elbow_chart = elbow(
    filmtv_movies_complete,
    predictors,
    n_cluster = (1, 60),
    show = True
)

elbow_chart

By looking at the elbow curve, we can choose 15 clusters. Let’s create a KMeans model.

from verticapy.machine_learning.vertica.cluster import KMeans

model_kmeans = KMeans(n_cluster = 15)

model_kmeans.fit(filmtv_movies_complete, predictors)


=======
centers
=======
 votes  |duration|notoriety_director|castings_director|notoriety_actors|castings_actors|category_action|category_adventure|category_animation|category_comedy|category_drama|category_fantasy|category_horror|category_others|category_romantic|period_90s|period_old|language_area_arabic_middle_est|language_area_chinese_japan_asian|language_area_english|language_area_french|language_area_german_north_europe|language_area_grec_balkan|language_area_hebrew|language_area_indian|language_area_italian|language_area_others|language_area_russian_est_europe|unbiased_vote
--------+--------+------------------+-----------------+----------------+---------------+---------------+------------------+------------------+---------------+--------------+----------------+---------------+---------------+-----------------+----------+----------+-------------------------------+---------------------------------+---------------------+--------------------+---------------------------------+-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------------------+-------------
 0.02401| 0.01194|      0.03978     |     0.15038     |     0.09444    |    0.16525    |    0.00000    |      0.00000     |      0.00000     |    0.00000    |    1.00000   |     0.00000    |    0.00000    |    0.00000    |     0.00000     |  0.00000 |  0.50763 |            0.00000            |             0.00000             |       1.00000       |       0.00000      |             0.00000             |         0.00000         |       0.00000      |       0.00000      |       0.00000       |       0.00000      |             0.00000            |   0.43309   
 0.00858| 0.01166|      0.01794     |     0.11109     |     0.03326    |    0.10935    |    0.03584    |      0.05341     |      0.00000     |    0.17569    |    0.40759   |     0.03022    |    0.01546    |    0.07379    |     0.02389     |  1.00000 |  0.00000 |            0.03584            |             0.00000             |       0.00000       |       0.52565      |             0.24666             |         0.00984         |       0.00773      |       0.00703      |       0.00000       |       0.00281      |             0.03162            |   0.41116   
 0.01289| 0.01199|      0.01909     |     0.09990     |     0.02979    |    0.08323    |    0.00000    |      0.00000     |      0.00000     |    0.00000    |    1.00000   |     0.00000    |    0.00000    |    0.00000    |     0.00000     |  0.00000 |  0.35719 |            0.05760            |             0.00000             |       0.00000       |       0.41001      |             0.20949             |         0.02053         |       0.01734      |       0.02193      |       0.00000       |       0.00319      |             0.07634            |   0.46971   
 0.01239| 0.01270|      0.02101     |     0.10500     |     0.01925    |    0.05126    |    0.25757    |      0.01101     |      0.02006     |    0.08769    |    0.40936   |     0.03539    |    0.06567    |    0.04090    |     0.01573     |  0.11797 |  0.26268 |            0.00000            |             1.00000             |       0.00000       |       0.00000      |             0.00000             |         0.00000         |       0.00000      |       0.00000      |       0.00000       |       0.00000      |             0.00000            |   0.47079   
 0.02216| 0.01126|      0.02191     |     0.09544     |     0.07413    |    0.14450    |    0.56585    |      0.01392     |      0.00611     |    0.00000    |    0.00000   |     0.03938    |    0.03530    |    0.00000    |     0.06042     |  0.00000 |  0.20536 |            0.00950            |             0.00000             |       0.37237       |       0.41650      |             0.02885             |         0.00373         |       0.00407      |       0.00849      |       0.00000       |       0.00068      |             0.01969            |   0.29080   
 0.01272| 0.01213|      0.02960     |     0.11964     |     0.04669    |    0.08920    |    0.00000    |      0.00000     |      0.00000     |    0.00000    |    0.00000   |     0.00000    |    0.00000    |    1.00000    |     0.00000     |  0.06007 |  0.33815 |            0.01001            |             0.00000             |       0.69855       |       0.12977      |             0.06155             |         0.00260         |       0.00445      |       0.00742      |       0.00000       |       0.00000      |             0.02262            |   0.42967   
 0.01807| 0.01166|      0.02911     |     0.15185     |     0.06133    |    0.15909    |    0.00000    |      0.00000     |      0.00000     |    0.00000    |    1.00000   |     0.00000    |    0.00000    |    0.00000    |     0.00000     |  0.13502 |  0.46180 |            0.00000            |             0.00000             |       0.00000       |       0.00000      |             0.00000             |         0.00000         |       0.00000      |       0.00000      |       1.00000       |       0.00000      |             0.00000            |   0.33768   
 0.02620| 0.01079|      0.03110     |     0.08541     |     0.11019    |    0.14938    |    0.00000    |      0.00000     |      0.00000     |    1.00000    |    0.00000   |     0.00000    |    0.00000    |    0.00000    |     0.00000     |  0.32602 |  0.00000 |            0.00000            |             0.00000             |       1.00000       |       0.00000      |             0.00000             |         0.00000         |       0.00000      |       0.00000      |       0.00000       |       0.00000      |             0.00000            |   0.23033   
 0.01905| 0.01062|      0.04448     |     0.19751     |     0.07223    |    0.18512    |    0.26673    |      0.00000     |      0.00105     |    0.41475    |    0.00000   |     0.08200    |    0.00000    |    0.00000    |     0.05057     |  0.00000 |  1.00000 |            0.00035            |             0.00000             |       0.98068       |       0.00000      |             0.00000             |         0.00035         |       0.00035      |       0.00053      |       0.00000       |       0.00000      |             0.00439            |   0.42304   
 0.01284| 0.01123|      0.02515     |     0.17570     |     0.05849    |    0.16641    |    0.00000    |      1.00000     |      0.00000     |    0.00000    |    0.00000   |     0.00000    |    0.00000    |    0.00000    |     0.00000     |  0.00000 |  0.80716 |            0.00635            |             0.01386             |       0.61663       |       0.06755      |             0.05196             |         0.00000         |       0.00000      |       0.00173      |       0.16917       |       0.00000      |             0.00866            |   0.35211   
 0.01071| 0.01076|      0.01753     |     0.10238     |     0.03244    |    0.11043    |    0.00000    |      0.00000     |      0.00000     |    0.81455    |    0.00000   |     0.01130    |    0.00000    |    0.00000    |     0.08654     |  0.02649 |  0.32427 |            0.01307            |             0.00000             |       0.00000       |       0.42035      |             0.38114             |         0.00954         |       0.00530      |       0.01519      |       0.00000       |       0.00106      |             0.03568            |   0.34972   
 0.02610| 0.00974|      0.02624     |     0.08535     |     0.03899    |    0.08871    |    0.00000    |      0.00000     |      0.00000     |    0.00000    |    0.00000   |     0.00000    |    1.00000    |    0.00000    |     0.00000     |  0.09292 |  0.33923 |            0.00295            |             0.00000             |       0.86382       |       0.02852      |             0.02606             |         0.00049         |       0.00147      |       0.00049      |       0.00000       |       0.00000      |             0.00590            |   0.25918   
 0.02558| 0.01076|      0.05363     |     0.23229     |     0.09521    |    0.22780    |    0.11786    |      0.00000     |      0.00120     |    0.73644    |    0.00000   |     0.01608    |    0.03409    |    0.00000    |     0.02472     |  0.07945 |  0.69731 |            0.00000            |             0.00000             |       0.00000       |       0.00000      |             0.00000             |         0.00000         |       0.00000      |       0.00000      |       1.00000       |       0.00000      |             0.00000            |   0.26919   
 0.02767| 0.01131|      0.03195     |     0.11679     |     0.09455    |    0.15817    |    0.09468    |      0.04117     |      0.01346     |    0.00000    |    0.25222   |     0.12967    |    0.00000    |    0.00000    |     0.05272     |  0.63949 |  0.00000 |            0.00000            |             0.00000             |       1.00000       |       0.00000      |             0.00000             |         0.00000         |       0.00000      |       0.00000      |       0.00000       |       0.00000      |             0.00000            |   0.30163   
 0.00767| 0.01014|      0.02353     |     0.14004     |     0.03620    |    0.10252    |    0.03605    |      0.02300     |      0.00186     |    0.00000    |    0.00000   |     0.03170    |    0.06339    |    0.65817    |     0.04164     |  0.14419 |  0.23928 |            0.00000            |             0.00000             |       0.00000       |       0.00000      |             0.00000             |         0.00000         |       0.00000      |       0.00000      |       1.00000       |       0.00000      |             0.00000            |   0.25045   


=======
metrics
=======
Evaluation metrics:
     Total Sum of Squares: 90981.961
     Within-Cluster Sum of Squares: 
         Cluster 0: 1804.1096
         Cluster 1: 1683.224
         Cluster 2: 4389.6354
         Cluster 3: 2641.5329
         Cluster 4: 3456.3598
         Cluster 5: 2094.1254
         Cluster 6: 1137.5742
         Cluster 7: 1023.545
         Cluster 8: 3776.4604
         Cluster 9: 1292.4825
         Cluster 10: 3107.2247
         Cluster 11: 1094.8659
         Cluster 12: 3243.3793
         Cluster 13: 4990.8449
         Cluster 14: 1270.5356
     Total Within-Cluster Sum of Squares: 37005.9
     Between-Cluster Sum of Squares: 53976.062
     Between-Cluster SS / Total SS: 59.33%
 Number of iterations performed: 13
 Converged: True
 Call:
kmeans('"public"."_verticapy_tmp_kmeans_v_mldb_28c2847697b411efa8720242ac120002_"', '"public"."_verticapy_tmp_view_v_mldb_290e88ee97b411efa8720242ac120002_"', '"votes", "duration", "notoriety_director", "castings_director", "notoriety_actors", "castings_actors", "Category_Action", "Category_Adventure", "Category_Animation", "Category_Comedy", "Category_Drama", "Category_Fantasy", "Category_Horror", "Category_Others", "Category_Romantic", "period_90s", "period_Old", "language_area_Arabic_Middle_Est", "language_area_Chinese_Japan_Asian", "language_area_English", "language_area_French", "language_area_German_North_Europe", "language_area_Grec_Balkan", "language_area_Hebrew", "language_area_Indian", "language_area_Italian", "language_area_Others", "language_area_Russian_Est_Europe", "unbiased_vote"', 15
USING PARAMETERS max_iterations=300, epsilon=0.0001, init_method='kmeanspp', distance_method='euclidean')

model_kmeans.clusters_
Out[33]: 
array([[2.40097190e-02, 1.19415685e-02, 3.97783770e-02, 1.50382525e-01,
        9.44354082e-02, 1.65254559e-01, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        5.07630079e-01, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        4.33085941e-01],
       [8.57562347e-03, 1.16567782e-02, 1.79420537e-02, 1.11091591e-01,
        3.32620188e-02, 1.09354113e-01, 3.58397751e-02, 5.34082923e-02,
        0.00000000e+00, 1.75685172e-01, 4.07589599e-01, 3.02178496e-02,
        1.54602952e-02, 7.37877723e-02, 2.38931834e-02, 1.00000000e+00,
        0.00000000e+00, 3.58397751e-02, 0.00000000e+00, 0.00000000e+00,
        5.25650035e-01, 2.46661982e-01, 9.83836964e-03, 7.73014758e-03,
        7.02740689e-03, 0.00000000e+00, 2.81096275e-03, 3.16233310e-02,
        4.11156837e-01],
       [1.28913047e-02, 1.19905299e-02, 1.90860433e-02, 9.98964631e-02,
        2.97902715e-02, 8.32320486e-02, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        3.57185569e-01, 5.76041459e-02, 0.00000000e+00, 0.00000000e+00,
        4.10005980e-01, 2.09487742e-01, 2.05301973e-02, 1.73410405e-02,
        2.19254535e-02, 0.00000000e+00, 3.18915687e-03, 7.63404425e-02,
        4.69714107e-01],
       [1.23909703e-02, 1.26960553e-02, 2.10070326e-02, 1.04999563e-01,
        1.92463846e-02, 5.12589476e-02, 2.57569799e-01, 1.10106174e-02,
        2.00550531e-02, 8.76917027e-02, 4.09359025e-01, 3.53912702e-02,
        6.56704680e-02, 4.08965788e-02, 1.57294534e-02, 1.17970901e-01,
        2.62681872e-01, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        4.70789177e-01],
       [2.21597268e-02, 1.12584407e-02, 2.19139779e-02, 9.54401448e-02,
        7.41257382e-02, 1.44497573e-01, 5.65852003e-01, 1.39171758e-02,
        6.10997963e-03, 0.00000000e+00, 0.00000000e+00, 3.93754243e-02,
        3.53021045e-02, 0.00000000e+00, 6.04209097e-02, 0.00000000e+00,
        2.05363204e-01, 9.50441276e-03, 0.00000000e+00, 3.72369314e-01,
        4.16496945e-01, 2.88526816e-02, 3.73387644e-03, 4.07331976e-03,
        8.48608282e-03, 0.00000000e+00, 6.78886626e-04, 1.96877122e-02,
        2.90803425e-01],
       [1.27204766e-02, 1.21343477e-02, 2.96001270e-02, 1.19644255e-01,
        4.66885433e-02, 8.92031246e-02, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 6.00667408e-02,
        3.38153504e-01, 1.00111235e-02, 0.00000000e+00, 6.98553949e-01,
        1.29773823e-01, 6.15498702e-02, 2.59547646e-03, 4.44938821e-03,
        7.41564702e-03, 0.00000000e+00, 0.00000000e+00, 2.26177234e-02,
        4.29669456e-01],
       [1.80666501e-02, 1.16551518e-02, 2.91064822e-02, 1.51853253e-01,
        6.13294181e-02, 1.59094787e-01, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 1.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.35022693e-01,
        4.61800303e-01, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        3.37678646e-01],
       [2.62007978e-02, 1.07855817e-02, 3.10964618e-02, 8.54097947e-02,
        1.10186296e-01, 1.49376517e-01, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 3.26023001e-01,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        2.30328328e-01],
       [1.90504336e-02, 1.06163167e-02, 4.44819029e-02, 1.97512438e-01,
        7.22325313e-02, 1.85121496e-01, 2.66725198e-01, 0.00000000e+00,
        1.05355575e-03, 4.14749781e-01, 0.00000000e+00, 8.20017559e-02,
        0.00000000e+00, 0.00000000e+00, 5.05706760e-02, 0.00000000e+00,
        1.00000000e+00, 3.51185250e-04, 0.00000000e+00, 9.80684811e-01,
        0.00000000e+00, 0.00000000e+00, 3.51185250e-04, 3.51185250e-04,
        5.26777875e-04, 0.00000000e+00, 0.00000000e+00, 4.38981563e-03,
        4.23044105e-01],
       [1.28448835e-02, 1.12284699e-02, 2.51507959e-02, 1.75696048e-01,
        5.84885263e-02, 1.66409818e-01, 0.00000000e+00, 1.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        8.07159353e-01, 6.35103926e-03, 1.38568129e-02, 6.16628176e-01,
        6.75519630e-02, 5.19630485e-02, 0.00000000e+00, 0.00000000e+00,
        1.73210162e-03, 1.69168591e-01, 0.00000000e+00, 8.66050808e-03,
        3.52106400e-01],
       [1.07132597e-02, 1.07617814e-02, 1.75266164e-02, 1.02383335e-01,
        3.24447787e-02, 1.10430173e-01, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 8.14553161e-01, 0.00000000e+00, 1.13034264e-02,
        0.00000000e+00, 0.00000000e+00, 8.65418580e-02, 2.64924055e-02,
        3.24267043e-01, 1.30695867e-02, 0.00000000e+00, 0.00000000e+00,
        4.20346167e-01, 3.81137407e-01, 9.53726598e-03, 5.29848110e-03,
        1.51889792e-02, 0.00000000e+00, 1.05969622e-03, 3.56764394e-02,
        3.49718470e-01],
       [2.61017252e-02, 9.73760949e-03, 2.62411619e-02, 8.53545286e-02,
        3.89904358e-02, 8.87136721e-02, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        1.00000000e+00, 0.00000000e+00, 0.00000000e+00, 9.29203540e-02,
        3.39233038e-01, 2.94985251e-03, 0.00000000e+00, 8.63815143e-01,
        2.85152409e-02, 2.60570305e-02, 4.91642085e-04, 1.47492625e-03,
        4.91642085e-04, 0.00000000e+00, 0.00000000e+00, 5.89970501e-03,
        2.59177459e-01],
       [2.55755909e-02, 1.07599964e-02, 5.36283448e-02, 2.32287166e-01,
        9.52092857e-02, 2.27804118e-01, 1.17858857e-01, 0.00000000e+00,
        1.20019203e-03, 7.36437830e-01, 0.00000000e+00, 1.60825732e-02,
        3.40854537e-02, 0.00000000e+00, 2.47239558e-02, 7.94527124e-02,
        6.97311570e-01, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        2.69189068e-01],
       [2.76742140e-02, 1.13052879e-02, 3.19522069e-02, 1.16793329e-01,
        9.45470724e-02, 1.58170323e-01, 9.46801773e-02, 4.11652945e-02,
        1.34578847e-02, 0.00000000e+00, 2.52216593e-01, 1.29670678e-01,
        0.00000000e+00, 0.00000000e+00, 5.27232426e-02, 6.39487017e-01,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        3.01628264e-01],
       [7.67285168e-03, 1.01415464e-02, 2.35289366e-02, 1.40036945e-01,
        3.61956948e-02, 1.02518961e-01, 3.60472343e-02, 2.29956495e-02,
        1.86451212e-03, 0.00000000e+00, 0.00000000e+00, 3.16967060e-02,
        6.33934121e-02, 6.58172778e-01, 4.16407707e-02, 1.44188937e-01,
        2.39279055e-01, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        0.00000000e+00, 1.00000000e+00, 0.00000000e+00, 0.00000000e+00,
        2.50446768e-01]])

Let’s add the clusters in the vDataFrame.

model_kmeans.predict(
    filmtv_movies_complete,
    name = "movies_cluster",
)
123
filmtv_id
Int
100%
...
123
unbiased_vote
Float
100%
123
movies_cluster
Integer
100%
118...0.398848550002788
261...0.3895577315619898
3116...0.3882570399093949
4172...0.396672371659158
5173...0.3714492957359198
6187...0.3191947103214412
7188...0.42781478023196114
8196...0.3876260669744688
9210...0.4188630273816758
10218...0.456584779413778
11224...0.5547163316733360
12226...0.2885157753951566
13233...0.37661201452930311
14234...0.3721712163436488
15235...0.6032017406909852
16238...0.4437876151479438
17241...0.577825285791470
18245...0.3514606762746218
19250...0.4208169444936528
20255...0.30260089020302512

Let’s look at the different clusters.

filmtv_movies_complete.search(
    filmtv_movies_complete["movies_cluster"] == 0,
    usecols=[
        "avg_vote",
        "period",
        "director",
        "language_area",
        "title",
        "year",
        "country",
        "Category",
    ]
)
123
avg_vote
Numeric(8)
100%
...
Abc
period
Varchar(6)
100%
Abc
Category
Varchar(9)
100%
16.3...OldDrama
27.8...OldDrama
37.5...OldDrama
47.4...OldDrama
56.0...OldDrama
64.0...OldDrama
75.1...OldDrama
88.0...OldDrama
97.1...OldDrama
106.0...OldDrama
117.9...OldDrama
127.0...OldDrama
135.3...OldDrama
147.5...OldDrama
156.9...OldDrama
166.9...OldDrama
173.5...OldDrama
187.0...OldDrama
195.8...OldDrama
207.6...OldDrama
filmtv_movies_complete.search(
    filmtv_movies_complete["movies_cluster"] == 1,
    usecols=[
        "avg_vote",
        "period",
        "director",
        "language_area",
        "title",
        "year",
        "country",
        "Category",
    ],
)
123
avg_vote
Numeric(8)
100%
...
Abc
period
Varchar(6)
100%
Abc
Category
Varchar(9)
100%
18.0...90sDrama
26.5...90sDrama
35.7...90sAdventure
44.5...90sComedy
55.9...90sComedy
66.0...90sDrama
74.8...90sComedy
88.3...90sComedy
96.3...90sDrama
106.0...90sThriller
117.8...90sDrama
128.0...90sDrama
137.1...90sDrama
148.4...90sDrama
155.4...90sDrama
168.0...90sDrama
174.0...90sComedy
186.0...90sFantasy
198.0...90sAdventure
205.8...90sDrama
filmtv_movies_complete.search(
    filmtv_movies_complete["movies_cluster"] == 2,
    usecols=[
        "avg_vote",
        "period",
        "director",
        "language_area",
        "title",
        "year",
        "country",
        "Category",
    ],
)
123
avg_vote
Numeric(8)
100%
...
Abc
period
Varchar(6)
100%
Abc
Category
Varchar(9)
100%
14.0...OldDrama
24.0...OldDrama
38.1...OldDrama
44.8...OldDrama
57.1...OldDrama
69.0...OldDrama
73.5...OldDrama
87.7...OldDrama
97.1...OldDrama
106.2...OldDrama
117.7...OldDrama
126.0...OldDrama
136.9...OldDrama
146.0...OldDrama
155.2...OldDrama
165.8...OldDrama
176.0...OldDrama
187.1...OldDrama
198.0...OldDrama
206.0...OldDrama
filmtv_movies_complete.search(
    filmtv_movies_complete["movies_cluster"] == 3,
    usecols=[
        "avg_vote",
        "period",
        "director",
        "language_area",
        "title",
        "year",
        "country",
        "Category",
    ],
)
123
avg_vote
Numeric(8)
100%
...
Abc
period
Varchar(6)
100%
Abc
Category
Varchar(9)
100%
17.0...90sAction
27.4...OldDrama
34.8...OldAction
46.5...90sAction
57.8...OldFantasy
63.0...OldAction
77.9...90sAction
87.4...90sDrama
94.8...OldAction
106.0...90sAction
117.7...90sDrama
127.6...OldOthers
136.9...90sDrama
144.0...90sAdventure
157.4...OldAction
164.7...90sAction
178.0...90sAction
186.0...OldComedy
198.3...OldDrama
207.4...90sDrama

Each cluster consists of similar movies. These clusters can be used to give movie recommendations or help streaming platforms group movies together.

Conclusion

We’ve solved our problem in a Pandas-like way, all without ever loading data into memory!