Movie Ratings dataset
Users rating fictional films from 0.5 to 5 stars: build your first recommendation system.
About this dataset
Star ratings given by users to a catalogue of 120 fictional films, with each film's genre and release year and the time of the rating. The film titles are invented, and the catalogue is the same in every download (film M001 is always the same film), so results are comparable between files.
It is shaped like the famous public rating datasets but small enough for a laptop, which makes it a good place to build a first recommender: popularity baselines, user–item matrices and collaborative filtering.
Good for practising: Recommender systems, Pivot / matrix ops, Collaborative filtering, SQL aggregates.
What's built into the data
The rows are random, but they follow rules, so there is something real to find. These are the patterns to look for:
- Each user has two favourite genres, mostly watches those, and rates them higher.
- Some users are generous raters and some are harsh, so normalising by user helps.
- A few films are far more popular than the rest (a long tail), and some films are simply better liked than others.
- A few users rate a lot, most rate a little, as on real platforms.
- No user rates the same film twice.
Columns
| Column | Type | Description |
|---|---|---|
rating_id | ID (number) | Row number, in time order. |
user_id | Category | Fictional user. |
movie_id | Category | Film code (stable across downloads). |
movie_title | Category | Invented film title. |
genre | Category | Main genre. |
release_year | Whole number | Year of release. |
rating | Decimal | 0.5 to 5.0 in half-star steps. |
rated_at | Date & time | When the rating was given. |
Preview: the first 8 rows
A sample with seed 2026. Your download will have different values but the same columns and patterns.
| rating_id | user_id | movie_id | movie_title | genre | release_year | rating | rated_at |
|---|---|---|---|---|---|---|---|
| 1 | U0011 | M118 | Crimson Compass | Romance | 2004 | 4.0 | 2024-05-20 22:32 |
| 2 | U0014 | M118 | Crimson Compass | Romance | 2004 | 3.5 | 2024-10-19 00:57 |
| 3 | U0019 | M118 | Crimson Compass | Romance | 2004 | 2.0 | 2024-11-25 22:35 |
| 4 | U0017 | M084 | Hidden Garden | Thriller | 2007 | 5.0 | 2024-12-02 22:54 |
| 5 | U0014 | M070 | Hidden Harbour | Thriller | 2008 | 3.0 | 2025-04-22 03:40 |
| 6 | U0005 | M007 | Midnight Lantern | Family | 2007 | 2.0 | 2025-05-12 03:21 |
| 7 | U0019 | M018 | Golden Lantern | Action | 2015 | 0.5 | 2025-05-30 13:11 |
| 8 | U0012 | M090 | Quiet Signal | Action | 2006 | 2.5 | 2025-12-17 04:19 |
Practice exercises
- Find the 10 best-rated films with at least 20 ratings. Why does the minimum matter?
- Pivot into a user × film matrix. How empty (sparse) is it?
- Recommend films for one user by finding the users most similar to them (cosine similarity).
- Work out each user's favourite genre from their ratings and compare it with what they watch most.
- Hold back each user's latest rating, predict it, and measure your error (RMSE).
Stuck on one? Each exercise uses ideas from the lessons below, and trying it with the messy option on turns it into a cleaning exercise as well.
Load it straight into Python
You don't have to download first. Pandas can read the link directly, in Jupyter, Google Colab or a script. Keep the seed so you get the same data every time you run the notebook:
import pandas as pd
url = "https://beeprotonai.info/resources/datasets/movie-ratings/download/?rows=1000&seed=42"
df = pd.read_csv(url, parse_dates=["rated_at"])
df.head()
For SQL practice, download the SQL format and run it against an empty database, for example sqlite3 practice.db < movie-ratings-1000-rows-seed42.sql or mysql -u root -p practice < movie-ratings-1000-rows-seed42.sql (use your file's name). It creates a table called movie_ratings and fills it.
About the data
Everything in this file is invented. Names are random pairings of common first names and surnames, email addresses use example.com (reserved for examples, so it can never reach anyone), and phone numbers start with +91 00, which no real Indian mobile number does. Any resemblance to a real person or business is coincidence. Dates run from 1 April 2024 to 31 March 2026 unless a column says otherwise. Use it freely for learning, teaching and projects, including commercial ones, with no attribution required (CC0).
Lessons that go with it
More datasets
Two years of orders from a fictional chain of Indian sweet shops, with Diwali …
Employee & Attrition RecordsAn HR file of employees with salary, satisfaction, overtime and whether they left: built …
Student Exam ResultsMarks in five subjects with attendance and study hours, plus totals, percentage, result and …
Customer List (CRM)Customer records with contact details, segment, orders and spend: ideal for cleaning, deduplication and …
Stock Register (Inventory)Monthly stock register for five warehouses: opening, received, issued, closing, reorder level and value.
Website Traffic (Analytics)Daily sessions, users, bounce rate and conversions by page, traffic source and device.