This page was generated from getting_started/use_case_2_netflix_kevin_bacon.ipynb.

Use Case Tutorial 2: Kevin Bacon(s) of 2019

This is a tutorial on how to find the most well-connected Netflix cast member of 2019.

Bacon’s Law is a concept claiming that most people in the Hollywood film industry can be linked through their film roles to Kevin Bacon within six steps.

We’ll go over how to find out who are the centers of the the Netflix film world, similar to how Bacon is the center of the Hollywood film industry.

Well use a Kaggle dataset containing all the TV shows and movies on Netflix as of 2019. The dataset can be found here.

Preprocess Data

The raw data is in a tabular format with columns for movies, cast members, directors, release dates, countries of release, etc.

We’ll want to put it in a graph-friendly format. In particular, we’ll want to convert it to an edge list format.

First, we’ll import some necessary libraries.


import pandas as pd
import numpy as np
import networkx as nx
import metagraph as mg
from collections import Counter
from typing import Union

Let’s take a look at the raw data provided.


RAW_DATA_CSV = './data/kevin_bacon/netflix_titles.csv' # https://www.kaggle.com/shivamb/netflix-shows
raw_data_df = pd.read_csv(RAW_DATA_CSV)
raw_data_df.head()

show_id type title director cast country date_added release_year rating duration listed_in description
0 81145628 Movie Norm of the North: King Sized Adventure Richard Finn, Tim Maltby Alan Marriott, Andrew Toth, Brian Dobson, Cole... United States, India, South Korea, China September 9, 2019 2019 TV-PG 90 min Children & Family Movies, Comedies Before planning an awesome wedding for his gra...
1 80117401 Movie Jandino: Whatever it Takes NaN Jandino Asporaat United Kingdom September 9, 2016 2016 TV-MA 94 min Stand-Up Comedy Jandino Asporaat riffs on the challenges of ra...
2 70234439 TV Show Transformers Prime NaN Peter Cullen, Sumalee Montano, Frank Welker, J... United States September 8, 2018 2013 TV-Y7-FV 1 Season Kids' TV With the help of three human allies, the Autob...
3 80058654 TV Show Transformers: Robots in Disguise NaN Will Friedle, Darren Criss, Constance Zimmer, ... United States September 8, 2018 2016 TV-Y7 1 Season Kids' TV When a prison ship crash unleashes hundreds of...
4 80125979 Movie #realityhigh Fernando Lebrija Nesta Cooper, Kate Walsh, John Michael Higgins... United States September 8, 2017 2017 TV-14 99 min Comedies When nerdy high schooler Dani finally attracts...

We’ll only consider movies since multiple cast members can work on the same TV show but may not ever see each other on set.

We’ll also only consider U.S. movies since cast members from different countries often do not work together.

We’ll necessarily need to remove any rows with missing data as well.


movies_df = raw_data_df[raw_data_df['type']=='Movie'].drop(columns=['type']).dropna()
movies_df = movies_df[movies_df.country.str.contains('United States')]
movies_df.head()

show_id title director cast country date_added release_year rating duration listed_in description
0 81145628 Norm of the North: King Sized Adventure Richard Finn, Tim Maltby Alan Marriott, Andrew Toth, Brian Dobson, Cole... United States, India, South Korea, China September 9, 2019 2019 TV-PG 90 min Children & Family Movies, Comedies Before planning an awesome wedding for his gra...
4 80125979 #realityhigh Fernando Lebrija Nesta Cooper, Kate Walsh, John Michael Higgins... United States September 8, 2017 2017 TV-14 99 min Comedies When nerdy high schooler Dani finally attracts...
6 70304989 Automata Gabe Ibáñez Antonio Banderas, Dylan McDermott, Melanie Gri... Bulgaria, United States, Spain, Canada September 8, 2017 2014 R 110 min International Movies, Sci-Fi & Fantasy, Thrillers In a dystopian future, an insurance adjuster f...
9 70304990 Good People Henrik Ruben Genz James Franco, Kate Hudson, Tom Wilkinson, Omar... United States, United Kingdom, Denmark, Sweden September 8, 2017 2014 R 90 min Action & Adventure, Thrillers A struggling couple can't believe their luck w...
11 70299204 Kidnapping Mr. Heineken Daniel Alfredson Jim Sturgess, Sam Worthington, Ryan Kwanten, A... Netherlands, Belgium, United Kingdom, United S... September 8, 2017 2015 R 95 min Action & Adventure, Dramas, International Movies When beer magnate Alfred "Freddy" Heineken is ...

All the cast members for a movie are in the same cell.

To have the data in an edge list format, we’ll need to use Pandas to reformat the data to have rows where each cast member cell contains exactly one cast member. This will mean that a movie will have multiple rows (one for each cast member).


def expand_dataframe_list_values_for_column(df: pd.DataFrame, column_name: Union[str, int]) -> pd.DataFrame:
    return df.apply(lambda x: pd.Series(x[column_name].split(', ')), axis=1) \
                  .stack() \
                  .reset_index(level=1, drop=True) \
                  .to_frame(column_name) \
                  .join(df.drop(columns=[column_name]))

movies_df = expand_dataframe_list_values_for_column(movies_df, 'cast')

movies_df.head()

cast show_id title director country date_added release_year rating duration listed_in description
0 Alan Marriott 81145628 Norm of the North: King Sized Adventure Richard Finn, Tim Maltby United States, India, South Korea, China September 9, 2019 2019 TV-PG 90 min Children & Family Movies, Comedies Before planning an awesome wedding for his gra...
0 Andrew Toth 81145628 Norm of the North: King Sized Adventure Richard Finn, Tim Maltby United States, India, South Korea, China September 9, 2019 2019 TV-PG 90 min Children & Family Movies, Comedies Before planning an awesome wedding for his gra...
0 Brian Dobson 81145628 Norm of the North: King Sized Adventure Richard Finn, Tim Maltby United States, India, South Korea, China September 9, 2019 2019 TV-PG 90 min Children & Family Movies, Comedies Before planning an awesome wedding for his gra...
0 Cole Howard 81145628 Norm of the North: King Sized Adventure Richard Finn, Tim Maltby United States, India, South Korea, China September 9, 2019 2019 TV-PG 90 min Children & Family Movies, Comedies Before planning an awesome wedding for his gra...
0 Jennifer Cameron 81145628 Norm of the North: King Sized Adventure Richard Finn, Tim Maltby United States, India, South Korea, China September 9, 2019 2019 TV-PG 90 min Children & Family Movies, Comedies Before planning an awesome wedding for his gra...

One thing to note is that there might be some movies, e.g. autobiographies, who have names that overlap with those of the actors.


movies_df[movies_df.title.isin(movies_df.cast)].head()

cast show_id title director country date_added release_year rating duration listed_in description
1383 Jimi Hendrix 653673 Jimi Hendrix Joe Boyd United States November 1, 2019 1973 R 102 min Documentaries, Music & Musicals Jimi Hendrix's family, friends, and fellow mus...
1383 Eric Clapton 653673 Jimi Hendrix Joe Boyd United States November 1, 2019 1973 R 102 min Documentaries, Music & Musicals Jimi Hendrix's family, friends, and fellow mus...
1383 Billy Cox 653673 Jimi Hendrix Joe Boyd United States November 1, 2019 1973 R 102 min Documentaries, Music & Musicals Jimi Hendrix's family, friends, and fellow mus...
1969 Benji 296682 Benji Joe Camp United States March 6, 2018 1974 G 86 min Children & Family Movies, Classic Movies After lovable abandoned mutt Benji is adopted ...
1969 Deborah Walley 296682 Benji Joe Camp United States March 6, 2018 1974 G 86 min Children & Family Movies, Classic Movies After lovable abandoned mutt Benji is adopted ...

Let’s make sure that the names of movies and actors don’t overlap so that we don’t have any problems with name collisions. We’ll accomplish this by assigning actor IDs and movie IDs (which do not overlap).


actors = movies_df.cast.unique()
movies = movies_df.title.unique()

actor_id_to_actor = actors
actor_to_id = dict(map(reversed, enumerate(actors)))

movie_id_to_movie = dict(((len(actors)+relative_movie_id, movie) for relative_movie_id, movie in enumerate(movies)))
movie_to_id = {movie: movie_id for movie_id, movie in movie_id_to_movie.items()}

movies_df['actor_id'] = movies_df.cast.map(lambda actor: actor_to_id[actor])
movies_df['movie_id'] = movies_df.title.map(lambda movie: movie_to_id[movie])

assert len(set(movies_df.actor_id).intersection(movies_df.movie_id)) == 0

Now that we have the data in an edgelist format (where edges connect cast members to movies) we want to put the data into a graph format. Since actors and movies are disjoint, we’ll create a bipartite graph.


nx_actor_to_movie_graph = nx.from_pandas_edgelist(movies_df, 'actor_id', 'movie_id')

actor_ids = list(actor_to_id.values())
movie_ids = list(movie_to_id.values())

actor_id_to_movie_id_graph = mg.wrappers.BipartiteGraph.NetworkXBipartiteGraph(nx_actor_to_movie_graph, [actor_ids, movie_ids])

Note that the above graph is a bipartite graph of cast members and movies. Since we want a graph where the edges connect actors who’ve worked together on a movie, we’ll use bipartite graph projection to generate an actor-to-actor graph.


actor_partition_label = 0
actor_id_to_actor_id_graph = mg.algos.bipartite.graph_projection(actor_id_to_movie_id_graph, actor_partition_label)

The actor partition label is 0 because the actors are the 0th element of [actor_ids, movie_ids] that was passed into the bipartite graph initializer, i.e. mg.wrappers.BipartiteGraph.NetworkXBipartiteGraph.

Find The Kevin Bacon(s)

We’re going to find the Kevin Bacons.

We’ll refer to the maximum number of hops a cast member needs to reach all other cast members as the Kevin Bacon distance.

We’ll refer to the cast members who have the smallest Kevin Bacon distance the Kevin Bacons.

To find the Kevin Bacons, we’ll first have to find all the connected components (since we don’t exactly have a Kevin Bacon if our graph is disconnected).


cc_node_label_mapping = r.algos.clustering.connected_components(actor_id_to_actor_id_graph)

Let’s take a look at the connected component results.


type(cc_node_label_mapping)

dict

list(cc_node_label_mapping.items())[:10]

[(0, 0),
 (1, 0),
 (2, 0),
 (3, 0),
 (4, 0),
 (5, 0),
 (6, 0),
 (7, 0),
 (8, 0),
 (9, 0)]

len(set(cc_node_label_mapping.values())) # number of connected components

249

It looks like we have 249 connected components. Since we can’t find the Kevin Bacon of a disconnected graph, let’s find the Kevin Bacon of the largest connected component.


label_counts = Counter()
for label in cc_node_label_mapping.values():
    label_counts[label] += 1
largest_cc_label, _ = max(label_counts.items(), key = lambda pair: pair[1])
largest_cc_node_set = {node for node, label in cc_node_label_mapping.items() if label == largest_cc_label}
largest_cc_subgraph = mg.algos.subgraph.extract_subgraph(actor_id_to_actor_id_graph, largest_cc_node_set)

We now need to find each actor’s Kevin Bacon distance.

Our graph is currently a NetworkX graph.


type(largest_cc_subgraph)

metagraph.plugins.networkx.types.NetworkXGraph

NetworkX represents graphs using hash tables, which can be slow due to spatial locality issues. We can use a Scipy graph, which represents graphs via sparse adjacency matrices, to achieve better spatial locality and faster runtime performance.


largest_cc_subgraph = largest_cc_subgraph.translate("ScipyGraph")

In order to compute each actor’s Kevin Bacon distance, we’ll need to find the shortest path lengths between every pair of actors.


largest_cc_subgraph = mg.algos.util.graph.assign_uniform_weight(largest_cc_subgraph, 1.0)
_, lengths_graph = mg.algos.traversal.all_pairs_shortest_paths(largest_cc_subgraph)

lengths_graph is a fully connected graph where each edge weight between two nodes represents the length in the original graph between the two nodes. We can calculate the Kevin Bacon distance of an actor ID node by taking the max over all the node’s edges.


actor_id_to_kevin_bacon_distance = mg.algos.util.graph.aggregate_edges(lengths_graph, np.maximum, 0, True, True)

Once we have all the Kevin Bacon distances from every cast member, we can find the smallest Kevin Bacon distance.


min_kevin_bacon_dist = mg.algos.util.nodemap.reduce(actor_id_to_kevin_bacon_distance, np.minimum)
min_kevin_bacon_dist

6

From here, we can determine the Kevin Bacon(s)!

We’ll do this by finding all the actors who have a Kevin Bacon distance equal to min_kevin_bacon_dist.


kevin_bacon_ids = mg.algos.util.nodemap.filter(actor_id_to_kevin_bacon_distance, lambda distance: distance == min_kevin_bacon_dist)
kevin_bacons = [actor_id_to_actor[actor_id] for actor_id in kevin_bacon_ids.value]
kevin_bacons[:10]

['John Michael Higgins',
 'Robert Forster',
 'Jim Sturgess',
 'Sam Worthington',
 'Ryan Kwanten',
 'Anthony Hopkins',
 'Ben Kingsley',
 'Nicolas Cage',
 'Lindsay Burdge',
 'Jason Sudeikis']

Let’s see what fraction of the largest connected component in the Netflix 2019 film industry the Kevin Bacons make up.


len(kevin_bacons)

295

len(largest_cc_node_set)

7824

len(kevin_bacons) / len(largest_cc_node_set)

0.037704498977505115

It turns out that 3.8% of Netflix’s largest connected component are Kevin Bacons. It seems that being a Kevin Bacon in the Netflix film world is not as rare as one might initially believe!