Visualizing Netflix Data Using Python: Revealing Insights Into the World‘s Most Popular Streaming Service
Netflix has revolutionized the way we consume TV shows and movies. With over 220 million subscribers worldwide as of 2022, it‘s safe to say that the streaming giant has amassed a wealth of data on our viewing habits. In this post, we‘ll explore how to use Python to load, analyze and visualize a dataset of Netflix titles. We‘ll uncover insights into the content makeup of Netflix‘s catalog and discuss key considerations for creating compelling data visualizations.
Why Visualize Data?
In today‘s age of Big Data, we are inundated with massive amounts of information on a daily basis. Data visualization provides a way to make sense of it all by translating complex datasets into easily digestible visual representations. A well-crafted visualization can reveal patterns, outliers and trends in the data that may not be immediately apparent from looking at the raw numbers.
Visualizations are also highly effective for communicating insights to others. As the saying goes, "a picture is worth a thousand words" – the human brain processes visual information much faster than text. Compelling graphs, charts and plots can help get your point across and make your analysis more impactful and memorable.
The Netflix Dataset
For this analysis, we‘ll be working with a dataset of Netflix movies and TV shows available on Kaggle. The dataset contains metadata for over 8,800 titles as of 2021, including:
- Title name
- Director and cast information
- Release year and rating
- Duration (in minutes for movies, number of seasons for shows)
- Genre(s)
- Production country
To begin, let‘s load the data into a Pandas DataFrame and take a look:
import pandas as pd
netflix_df = pd.read_csv(‘netflix_titles.csv‘)
netflix_df.head()
| show_id | type | title | director | cast | country | date_added | release_year | rating | duration | listed_in | description |
|---|---|---|---|---|---|---|---|---|---|---|---|
| s1 | Movie | Dick Johnson Is Dead | Kirsten Johnson | NaN | United States | September 25, 2021 | 2020 | PG-13 | 90 min | Documentaries | As her father nears the end of his life, filmm… |
| s2 | TV Show | Blood & Water | NaN | Ama Qamata, Khosi Ngema, Gail Mabalane, Thaban… | South Africa | September 24, 2021 | 2021 | TV-MA | 2 Seasons | International TV Shows, TV Dramas, TV Mysteries | After crossing paths at a party, a Cape Town t… |
| s3 | TV Show | Ganglands | Julien Leclercq | Sami Bouajila, Tracy Gotoas, Samuel Jouy, Nabi… | NaN | September 24, 2021 | 2021 | TV-MA | 1 Season | Crime TV Shows, International TV Shows, TV Act… | To protect his family from a powerful drug lor… |
| s4 | TV Show | Jailbirds New Orleans | NaN | NaN | NaN | September 24, 2021 | 2021 | TV-MA | 1 Season | Docuseries, Reality TV | Feuds, flirtations and toilet talk go down amo… |
| s5 | TV Show | Kota Factory | NaN | Mayur More, Jitendra Kumar, Ranjan Raj, Alam K… | India | September 24, 2021 | 2021 | TV-MA | 2 Seasons | International TV Shows, Romantic TV Shows, TV … | In a city of coaching centers known to train I… |
We can see there are some missing values in the dataset, but overall it provides a good basis for analysis. Let‘s dive in and start visualizing!
Content Type Breakdown
First, let‘s look at the breakdown of Netflix‘s catalog between movies and TV shows over time. We can easily plot this using Matplotlib:
import matplotlib.pyplot as plt
netflix_df[‘year_added‘] = pd.to_datetime(netflix_df[‘date_added‘]).dt.year
content_type_counts = netflix_df.groupby([‘year_added‘, ‘type‘]).size().reset_index(name=‘count‘)
fig, ax = plt.subplots(figsize=(10, 6))
movies = ax.plot(content_type_counts[content_type_counts[‘type‘]==‘Movie‘][‘year_added‘],
content_type_counts[content_type_counts[‘type‘]==‘Movie‘][‘count‘],
color=‘#E50914‘, marker=‘o‘, linestyle=‘-‘, label=‘Movies‘)
shows = ax.plot(content_type_counts[content_type_counts[‘type‘]==‘TV Show‘][‘year_added‘],
content_type_counts[content_type_counts[‘type‘]==‘TV Show‘][‘count‘],
color=‘#221F1F‘, marker=‘o‘, linestyle=‘-‘, label=‘TV Shows‘)
ax.set(xlabel=‘Year‘, ylabel=‘Titles Added‘)
ax.legend()
fig.suptitle(‘Netflix Content Type by Year Added‘, fontsize=16)
plt.show()

This clearly shows that while Netflix started out with more movies in its catalog, in recent years TV shows have overtaken movies in terms of the amount of new content being added. This likely reflects the company‘s strategic shift to developing more original TV programming.
We can also leverage Seaborn to visually compare the total size of the movie vs. show catalog:
import seaborn as sns
type_counts = netflix_df.groupby(‘type‘).size()
type_props = type_counts / netflix_df.shape[0]
sns.set(font_scale=1.5)
colors = sns.color_palette([‘#E50914‘, ‘#221F1F‘])
pie, ax = plt.subplots(figsize=[10,8])
labels = type_props.keys()
plt.pie(x=type_props, autopct="%.1f%%", explode=[0.02]*2, labels=labels, pctdistance=0.9, colors=colors, textprops={‘fontsize‘: 14});
plt.title("Netflix Titles by Type", fontsize=16);

So in total, Netflix‘s catalog is close to a 70/30 split between movies and TV shows. The pie chart is an effective way to show the proportional breakdown.
Top Talent
Next let‘s examine the actors, actresses and directors with the most Netflix titles to their name. Since these are listed in string format in the dataset, we‘ll need to first parse them out to get a count by person:
from collections import defaultdict
cast_dict = defaultdict(int)
directors_dict = defaultdict(int)
for cast_str in netflix_df[‘cast‘].dropna():
for actor in cast_str.split(‘, ‘):
cast_dict[actor] += 1
for director in netflix_df[‘director‘].dropna():
directors_dict[director] += 1
top_cast = sorted(cast_dict.items(), key=lambda x: x[1], reverse=True)[:15]
top_cast_names, top_cast_counts = zip(*top_cast)
top_directors = sorted(directors_dict.items(), key=lambda x: x[1], reverse=True)[:10]
top_directors_names, top_directors_counts = zip(*top_directors)
fig, (ax1,ax2) = plt.subplots(1, 2, figsize=(20, 8))
sns.barplot(x=list(top_cast_counts), y=list(top_cast_names), palette="rocket", ax=ax1).set(title=‘Top Cast by Number of Titles‘, xlabel=‘Number of Titles‘)
sns.barplot(x=list(top_directors_counts), y=list(top_directors_names), palette="icefire", ax=ax2).set(title=‘Top Directors by Number of Titles‘, xlabel=‘Number of Titles‘)
plt.tight_layout()
plt.show()

Bollywood legend Anupam Kher takes the crown for the actor with the most Netflix titles, with Shah Rukh Khan and Naseeruddin Shah also making the Top 5. On the director side, American filmmakers like Rajiv Chilaka and Jay Karas lead the pack.
Having two subplots allows us to efficiently compare the cast vs. director counts side-by-side. The horizontal bar charts work well for displaying the rankings in descending order.
Yearly Content Additions and Removals
Let‘s dive deeper into how the size and composition of the Netflix catalog has changed over time:
add_remove_df = netflix_df.groupby([‘year_added‘, ‘type‘]).size().unstack().fillna(0)
add_remove_df[‘add_remove‘] = add_remove_df[‘Movie‘] - add_remove_df[‘TV Show‘]
fig, ax1 = plt.subplots(figsize=(10, 6))
ax1 = sns.lineplot(data=add_remove_df, x=add_remove_df.index, y=‘Movie‘, marker=‘o‘, sort=False, color=‘#e50914‘, label=‘Movies Added‘)
ax1 = sns.lineplot(data=add_remove_df, x=add_remove_df.index, y=‘TV Show‘, marker=‘o‘, sort=False, color=‘#221f1f‘, label=‘TV Shows Added‘)
ax2 = ax1.twinx()
ax2 = sns.lineplot(data=add_remove_df, x=add_remove_df.index, y=‘add_remove‘, color=‘#B20710‘, marker=‘d‘, sort=False, ax=ax2, label=‘Difference: Movies - Shows‘)
ax2.grid(False);
ax1.set(xlabel=‘Year‘, ylabel=‘Titles Added‘)
ax2.set_ylabel(‘Movies Added - Shows Added‘)
fig.suptitle(‘Netflix Yearly Additions‘, fontsize=16)
plt.show()

The twin y-axes plot illustrates the changing pace of movie vs. show additions over time. We can see that movie additions peaked earlier (in 2019), while show additions ramped up later and surged ahead in 2021.
The red line plot on the secondary y-axis shows the difference between movie and show additions each year, more clearly emphasizing the shift to TV content in recent years.
Regional Content Analysis
As Netflix has expanded globally, its catalog has become increasingly diverse. Let‘s compare the size and composition of the catalog across a few countries:
countries_df = pd.concat([netflix_df[‘country‘].str.split(‘, ‘, expand=True), netflix_df[‘type‘]], axis=1)
country_counts = countries_df.apply(pd.Series.value_counts).T.fillna(0).astype(int)
country_totals = country_counts.sum(axis=1)
selected_countries = country_totals.sort_values(ascending=False).index[:5]
fig, ax = plt.subplots(nrows=1, ncols=len(selected_countries), figsize=(20, 5))
fig.suptitle(‘Top Countries Content Comparison‘, size=16, y=1.05)
for i, country in enumerate(selected_countries):
country_data = country_counts.loc[country]
colors = sns.color_palette([‘#E50914‘, ‘#221F1F‘])
ax[i].pie(country_data, labels=[‘Movies‘, ‘TV Shows‘], autopct=‘%.0f%%‘, colors=colors, textprops={‘fontsize‘: 12})
ax[i].set_title(country, fontsize=14)
plt.tight_layout()
plt.show()

The United States dominates in total titles, which is unsurprising given Netflix‘s American origins. But India is a close second, reflecting the immense popularity of the platform in the Indian market. The UK, Canada and Spain round out the top 5 countries by catalog size.
Arranging pie charts in a row allows us to easily compare the movie/show composition across markets. We can see that the proportion of movies is higher in India compared to the other top countries.
Putting It All Together
Effective data visualizations require careful consideration of the overall visual design. When creating plots in Python, keep these tips in mind:
- Choose an appropriate plot type for the relationship you want to show (e.g., line plots for data over time, bar charts for counts/rankings, pie charts for proportions)
- Use color sparingly to draw attention to key data points. Stick to a core color palette to create a consistent look and feel.
- Add clear titles, axis labels and legends so that your plot can be interpreted on its own.
- Don‘t clutter your plot with unnecessary "chart junk." Keep it simple and let the data speak for itself.
- Order categories in a meaningful way, such as ranking from highest to lowest or sorting by another variable.
With a bit of practice, you‘ll develop an intuition for what works visually and what detracts from your message. Python plotting libraries like Matplotlib and Seaborn provide a robust set of tools for customizing your visualizations to make them publication-ready.
Conclusion
As this case study demonstrates, visualization is a powerful tool for exploring and finding meaning in datasets. With a few lines of Python code, we were able to uncover fascinating insights such as:
- The rapid growth of Netflix‘s TV show catalog compared to movies in recent years
- The most prolific actors and directors on Netflix across different genres and countries
- Regional differences in content preferences between major markets like the US and India
While we‘ve only scratched the surface, the same techniques can be applied to derive all kinds of insights from the Netflix data, such as analyzing show ratings, runtimes, release schedules and much more. And this is just one dataset – nearly every field from business to healthcare to sports is rife with interesting data visualizations waiting to be uncovered.
I encourage you to download the Netflix dataset (or find another dataset of interest) and start exploring it yourself using Python. The complete code for this analysis is available on my GitHub. If you‘re new to data visualization in Python, here are some great resources to get started:
- Seaborn tutorial
- Matplotlib tutorial
- Pandas visualization guide
- From Data to Viz: Find the graphic you need
Thanks for reading! Feel free to connect with me on LinkedIn or Twitter to discuss all things data visualization and Python. Happy plotting!