1- import os
2- import gzip
3- import shutil
41import requests
2+ import asyncio , aiohttp
53import polars as pl
64from io import BytesIO
5+ from concurrent .futures import ThreadPoolExecutor , as_completed
6+
7+ import time
78
89def create_dataframe (url :str ):
910 """
@@ -21,6 +22,38 @@ def create_dataframe(url:str):
2122 null_values = "\\ N" )
2223 return df
2324
25+ async def fetch_url_async (session , url ):
26+ # Asynchronously function to fetch data from a given URL using aiohttp
27+ try :
28+ # Use 'session.get()' to make an asynchronous HTTP GET request
29+ async with session .get (url , timeout = 100 ) as response :
30+ response .raise_for_status ()
31+ # Return the JSON content of the response
32+ return await response .json ()
33+ except aiohttp .ClientError as e :
34+ return url , f"Error: { e } "
35+
36+ async def async_create_dataframe (* urls :str ):
37+
38+ # Create an aiohttp ClientSession for making asynchronous HTTP requests
39+ async with aiohttp .ClientSession () as session :
40+ # Cratea list of tasks, where each task is a call to 'fetch_data' with a specific URL
41+ tasks = [fetch_url_async (session , url ) for url in urls ]
42+ # Use 'asyncio.gather()' to run the tasks concurrently and gather their results
43+ results = await asyncio .gather (* tasks )
44+
45+ dfs = []
46+
47+ for result in results :
48+ df = pl .DataFrame (result )
49+ dfs .append (df )
50+
51+ for df in dfs :
52+ print (df )
53+
54+ return dfs
55+
56+
2457def filter_movie_dataframe (df :pl .DataFrame ):
2558 """
2659 Filters movie DataFrame
@@ -57,28 +90,65 @@ def lookup_people(crew_df:pl.DataFrame, lookup_df:pl.DataFrame, save_file:bool=F
5790 pl.DataFrame: DataFrame of writers and directors names with associated movie unique IDs
5891 """
5992
60- # Create a dictionary of unique identifiers and name of person
61- lookup_dict = dict (zip (lookup_df ['nconst' ], lookup_df ['primaryName' ]))
62- # Creating a list of crew unique IDs from the comma separated string
63- crew_df = crew_df .with_columns (
64- pl .col ("writers" ).str .split ("," ).alias ("writersList" ))
65- # Mapping crew names to crew unique IDs
66- crew_df = crew_df .with_columns (
67- pl .col ("writersList" ).list .eval (
68- pl .element ().map_elements (lambda x : lookup_dict .get (x , "\\ N" ), return_dtype = pl .Utf8 )
69- ).alias ("writerNames" )
70- )
71-
72- if (save_file == True ):
73- # If we want to save to a csv file, we need to convert the writerNames list to a string
74- crew_df = crew_df .with_columns (
75- pl .col ("writerNames" ).map_elements (lambda x : "," .join (map (str , x )), return_dtype = pl .Utf8 ).alias ("writers" )
76- )
77- # crew_df_save = crew_df.drop("writerNames")
78- crew_df .drop ("writerNames" ).write_csv ("crew_df_filtered.csv" )
79-
93+ # Create a list of writers from the string of writers
94+ crew_df = (crew_df .with_columns (
95+ pl .col ("writers" ).str .split ("," )
96+ ))
97+ # Create a list of directors from the string of writers
98+ crew_df = (crew_df .with_columns (
99+ pl .col ("directors" ).str .split ("," )
100+ ))
101+
102+ # Replacing unique IDs of writers and directors to names
103+ crew_df = map_names (crew_df , lookup_df , "writers" )
104+ crew_df = map_names (crew_df , lookup_df , "directors" )
105+
80106 return crew_df
107+
108+ def map_names (crew_df :pl .DataFrame , lookup_df :pl .DataFrame , list_to_map :str ):
109+ """
110+ Performs a mapping of the unique identifiers for the directors or writers to the name of the person
111+ Args:
112+ crew_df (pl.DataFrame): DataFrame of the crew to perform the mapping in
113+ lookup_df (pl.DataFrame): DataFrame containing lookup information for directors and writers
114+ list_to_map (str): The string of the column to map
115+ Returns:
116+ pl.DataFrame: DataFrame of containing a list of the names of the given crew category
117+ """
118+ if (list_to_map == "directors" ):
119+ alt_column = 'writers'
120+ else :
121+ alt_column = 'directors'
122+
123+ start_time = time .time ()
124+ mapped_df = (crew_df
125+ .lazy ()
126+ .explode (list_to_map )
127+ .join (
128+ lookup_df
129+ .lazy ()
130+ .select ('nconst' , 'primaryName' ),
131+ left_on = list_to_map ,
132+ right_on = 'nconst' ,
133+ how = 'left'
134+ )
135+ .group_by (['tconst' , alt_column ])
136+ .agg (
137+ pl .col (list_to_map ),
138+ pl .col ('primaryName' )
139+ )
140+ .drop (list_to_map )
141+ .rename ({'primaryName' :list_to_map })
142+ .sort ('tconst' )
143+ .collect (engine = 'gpu' )
144+ )
81145
146+ end_time = time .time ()
147+
148+ print (end_time - start_time )
149+
150+ return mapped_df
151+
82152def combine_dataframe (movie_df :pl .DataFrame , ratings_df :pl .DataFrame , crew_df :pl .DataFrame ):
83153 """
84154 Combines DataFrames into a single DataFrame using unique movie identifier
@@ -111,18 +181,21 @@ def data_preprocessing(title_basics_url:str, ratings_basics_url:str, crew_url, l
111181 # Filter movie DataFrame
112182 movie_df = filter_movie_dataframe (movie_df )
113183
114- if (os .path .exists ("sample_data/crew_df_filtered.csv" )):
115- # If crew has already been mapped, load file
116- crew_df = pl .read_csv ("sample_data/crew_df_filtered.csv" ) # Load Data
117- print ("crew_df 1: " , crew_df .head ())
118- else :
119- # Else map director and writer names
120- crew_df = create_dataframe (crew_url )
121- lookup_df = create_dataframe (lookup_url )
122- crew_df = lookup_people (crew_df , lookup_df )
123-
124- # Combine DataFrames into a single DataFrame for lookup and training
184+ crew_df = create_dataframe (crew_url )
185+ lookup_df = create_dataframe (lookup_url )
186+ crew_df = lookup_people (crew_df , lookup_df )
187+
188+ # if(os.path.exists("sample_data/crew_df_filtered.csv")):
189+ # # If crew has already been mapped, load file
190+ # crew_df = pl.read_csv("sample_data/crew_df_filtered.csv") # Load Data
191+ # print("crew_df 1: ", crew_df.head())
192+ # else:
193+ # # Else map director and writer names
194+ # crew_df = create_dataframe(crew_url)
195+ # lookup_df = create_dataframe(lookup_url)
196+ # crew_df = lookup_people(crew_df, lookup_df)
197+
198+ # Combine DataFrames into a single DataFrame for lookup and training
125199 combined_df = combine_dataframe (movie_df , ratings_df , crew_df )
126- return combined_df
127200
128201 return combined_df
0 commit comments