<jupyter_start><jupyter_text>1 - Normalize the location field of Users dataset, splitting into city, region, country.<jupyter_code>users[['City', 'Region', 'Country' ]]= users['Location'].str.split(',', n = 2,expand=True )
#splitto la colonna location tramite .str.split e dividendola per la virgola 
#il 2 sta a significare: Limitare il numero di suddivisioni nell'output. 
#Se non viene fornito, il valore predefinito è -1, il che significa che non c'è limite.

users.head()<jupyter_output><empty_output><jupyter_text>2. For each book in the Books dataset, compute its average rating.<jupyter_code>merged_books = pd.merge(books, books_rating, on = 'ISBN', how = 'left').groupby(['Book-Title','ISBN'], as_index = False).agg(Average_rating=('Book-Rating','mean'))
#Sono stati uniti i dataset usando come vincolo d'integrità referenziale 'ISBN', dopo aver raggruppato per 'ISBN' e 'Book-Title' è stata calcolata la media del rating per ogni libro.
merged_books.head()<jupyter_output><empty_output><jupyter_text>3-For each book in the GoodBooks dataset, compute its average rating<jupyter_code>pd.set_option('display.max_columns', None)
#non tutte le colonne vengono mostrate essendo tante, in questo modo si può avere un quadro generale 
goodbooks.head(3)
goodbooks[['isbn','original_title','average_rating']]
#stampiamo le colonne che ci interessano
#non c'è bisogno di eseguire nessun calcolo o merge visto che la colonna di interesse è già presente nel dataset
#Seconda soluzione
goodbooks.groupby(['book_id'], as_index = False)[['average_rating']].mean()<jupyter_output><empty_output><jupyter_text>4-Merge together all rows sharing the same book title, author and publisher. We will call the resulting dataset "merged books". The books that have not been merged together will not appear in merged books.<jupyter_code>books2 = books.groupby(['Book-Title','Book-Author','Publisher'], as_index = False).count()
#raggruppo i libri che hanno lo stesso titolo, autorie e casa editrice contando
#anche quante volte si vi sono nel db 
books2.head(2)
merged_books = pd.DataFrame(books2[books2['ISBN']>=2])[['Book-Title', 'Book-Author','Publisher', 'ISBN']]
#da books2 prendo in considerazione chi ha avuto almeno 2 edizioni mostrando poi 
#solo le colonne di interesse 

merged_books.head()<jupyter_output><empty_output><jupyter_text>5. For each book in merged books compute its average rating.<jupyter_code>books_rating_avg = books_rating.groupby('ISBN', as_index = True).agg(avg_rating=('Book-Rating','mean'))
#raggruppo per ISBN e ne calcolo la media con la funzione di aggregazione 

books_rating_avg.head(2)
books_dubplicati = books[books.duplicated(subset =['Book-Title', 'Book-Author', 'Publisher'], keep = False)].sort_values(['Book-Title', 'Book-Author', 'Publisher'])
#uso la funzione duplicati per ottenere un risultato booleano e tenendo keep = false cosi facendo non eliminiamo i duplicati 
#vado poi a ordinare le colonne 
books_dubplicati[['ISBN','Book-Title']].head(6)

merged_books_rating = pd.merge(books_dubplicati,books_rating_avg, on =  'ISBN', how= 'left')
# mergio con una left join i risultati trovati sopra con la chiave ISBN


merged_books_rating[['ISBN','Book-Title','Book-Author','Publisher','avg_rating']]
#estraggo solo le colonne che mi interessa vedere<jupyter_output><empty_output><jupyter_text>6. For each book in merged books compute the minimum and maximum of the average ratings over all corresponding books in the books dataset.<jupyter_code>merged_books_rating_final_max = merged_books_rating.groupby(['Book-Title', 'Book-Author', 'Publisher'], as_index = False).agg({'avg_rating': ['min','max']}).round(2)
#raggruppo per titolo e aggrego ma deia raiting per valore massimo e minimo 

merged_books_rating_final_max.head(6)<jupyter_output><empty_output><jupyter_text>7 - For each book in goodbooks, compute the list of its authors. Assuming that the number of reviews with a text (column work_text_reviews_count)is split equally among all authors, find for each authors the total number of reviews with a text. We will call this quantity the shared number of reviews with a text<jupyter_code>goodbooks['autori_splitted'] = goodbooks['authors'].str.split(',')
#creo una nuova colonna splittando gli autori con la ',' come divisore creando una lista di autori per ogni riga
goodbooks[['authors','autori_splitted']].head(4)
goodbooks['shared_number_of_reviews_with_a_text'] = goodbooks['work_text_reviews_count'] / goodbooks['autori_splitted'].apply(len)
#E' stato calcolato il rapporto tra il numero di reviews e la lunghezza di ogni lista che rappresenta il numero di autori per ogni riga.
goodbooks[['autori_splitted','work_text_reviews_count', 'shared_number_of_reviews_with_a_text']].head(2)
goodbooks_exploded = goodbooks.explode('autori_splitted')
#Con il comando .explode abbiamo trasformato ogni elemento di un elenco in una riga, in modo che per ogni riga ci sia solo un autore.
goodbooks_exploded[['autori_splitted']].head(3)
goodbooks_exploded.groupby(['autori_splitted'], as_index=False).sum('shared_number_of_reviews_with_a_text')[['autori_splitted', 'shared_number_of_reviews_with_a_text']].round(2).head(3)
# raggruppo per autori e ne sommo le reviews<jupyter_output><empty_output><jupyter_text>8 - For each year of publication, determine the author that has the largest value of the shared number of reviews with a text.<jupyter_code>ex_8 = goodbooks_exploded.groupby(['original_publication_year', 'autori_splitted'], as_index=False)[['shared_number_of_reviews_with_a_text']].sum()
#Raggruppo per anni e autori e trovo la somma dei risultati ottenuti al punto precendente 
ex_8.head(4)
ex_8.rename(columns= {'shared_number_of_reviews_with_a_text':'somma_shared'}, inplace=True)
#cambio il nome alla colonna 

ex_8.groupby('original_publication_year').max()
#per ogni anno trovo il valore massimo<jupyter_output><empty_output><jupyter_text>9 - Assuming that there are no errors in the ISBN fields,find the books in both datasets,and compute the difference of average rating according to the ratings and the goodratings datasets<jupyter_code>avg_books = pd.merge(books, books_rating, on = 'ISBN', how = 'left').groupby(['Book-Title','ISBN'], as_index = False).agg(Average_rating=('Book-Rating','mean'))
#Sono stati uniti i dataset usando come vincolo d'integrità referenziale 'ISBN', dopo aver raggruppato per 'ISBN' e 'Book-Title' è stata calcolata la media del rating per ogni libro.
avg_books.head(3)
books_both_datasets = pd.merge(avg_books, goodbooks, left_on='ISBN', right_on='isbn')
#faccio un merge tra 'books' e 'good_books' per ottenere tutti i libri che compaiono in entrambi i dataset

del books_both_datasets['isbn']
books_both_datasets.rename(columns={'average_rating': 'Goodbook_Average_Rating'}, inplace=True)
# elimino una delle due colonne superflua e rinomino average_rating in Goodbook_Average_Rating

books_both_datasets['Differenza'] = books_both_datasets['Goodbook_Average_Rating'] - books_both_datasets['Average_rating']
#Calcolo la differenza fra i due punteggi.
books_both_datasets[['ISBN', 'Book-Title','Goodbook_Average_Rating','Average_rating', 'Differenza']].head(3)<jupyter_output><empty_output><jupyter_text>10 - Split the users dataset according to the age. One dataset contains the users with unknown age, one with age 0-14, one with age 15-24, one with age 25-34, and so on.<jupyter_code>users['age_group'] = pd.cut(x = users['Age'], bins = [0, 14, 24, 34, 44, 54, 64, 74, 84,94,100,1000], labels=['0-14','15-24','25-34','35-44','45-54','55-64','65-74','75-84','85-94','95-100','over']) 
# usando la funzine pd.cut e' possibile convertire l'eta in gruppi di eta' 
# per bins si intendono i bordi che vogliamo porre 
# per LABELS Specifica le etichette per i bin restituiti
users['age_group']
is_null = users[users['age_group'].isnull()]
#creo un dataset con età mancante 
is_null[['age_group']].head(5)
u_0_14 = users[users['age_group']== '0-14'] 
u_14_24 = users[users['age_group']== '14-24'] 
u_25_34 = users[users['age_group']== '25-34'] 
u_35_44 = users[users['age_group']== '35-44'] 
u_45_54 = users[users['age_group']== '45-54'] 
u_55_64 = users[users['age_group']== '55-64'] 
u_65_74 = users[users['age_group']== '65-74'] 
u_75_84 = users[users['age_group']== '75-84'] 
u_85_94 = users[users['age_group']== '85-94'] 
u_95_100 = users[users['age_group']== '95-100'] 
over_users = users[users['age_group']=='over']
over_users
#i Vari dataset divisi per età
# la richiesta era di splittare il dataset nelle diverse classi di eta'<jupyter_output><empty_output><jupyter_text>11 - Find the books that appear only in the goodbooks datasets.<jupyter_code>ex_11 = goodbooks[goodbooks['isbn'].isin(books['ISBN'])==False]
#uso una condizione booleana e la do per falsa prendendo cosi tutti i libri che vi sono in goodbooks
# e scartando quelli che non trovo il books

ex_11[['isbn','original_title']].head(10)<jupyter_output><empty_output><jupyter_text>12. Assuming that each pair (author, title) identifies a book, for each book find the number of times it appears in the books dataset. Which books appear the most times?<jupyter_code>count = books.groupby(['Book-Author','Book-Title']).count().sort_values(by='ISBN',ascending=False)
#Ho raggruppato per prima l'autore e il titolo e poi usato la funzione count per contare le righe di ogni 'ISBN' ordinnando
#poi in modo decrescente 

count.head(1)
# per vedere quale era il libro più ridondande bastava stampare solo la prima riga visto che era state ordinate<jupyter_output><empty_output><jupyter_text>13. Find the author with the highest average rating according to the goodbooks datasets.<jupyter_code>goodbooks['average_rating'].max()
# trovo il valore massimo dell'average_rating
goodbooks[goodbooks['average_rating']==4.61][['authors','original_title','average_rating']]
#trovato il valore e raggruppato per autori trovo la riga corrispondente stampando autori,titolo e media
#oppure 
goodbooks.iloc[goodbooks['average_rating'].idxmax()][['authors', 'average_rating']]<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11564151131492374, 'fraction_numerical': 0.02123417406041272, 'mean_word_length': 7.064308681672026, 'pattern_counts': {'":': 0, '<': 53, '<?xml version=': 0, '>': 54, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '657442', 'license': 'Unlicense', 'n_tokens_mistral': 3511, 'n_tokens_neox': 3361, 'n_words': 984, 'path': 'Progetto.ipynb', 'repo_name': 'GioCorna97/Progetto_CS', 'size': '10031'}