File size: 21,430 Bytes
c9ed1ce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f318c6f
c9ed1ce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
all_stopwords=['sugl', 'up', 'stetti', 'lei', 'vi', 'ti', 'avait', 'on', 'you', 'tutto', 'nos', 'ayantes', 'seront', 'avions', 'sta', 'farà', 'sulle', 'ad', 'soyez', 'own', 'étant', 'tutti', 'avevamo', 'its', 'son', 'facesse', 'en', 'nostro', 'farete', 'essendo', 'those', 'tua', "aren't", 'votre', 'avete', 'aveva', "don't", 'had', 'dagli', 'aren', 'again', 'queste', 'auras', 'avevo', 'sto', 'off', 'tra', 'stando', 'li', 'avesti', 'sia', 'between', 'fai', 'stiate', 'furono', 'once', 'nella', 'hai', 'ebbero', 'tu', 'avez', 'du', 'mais', 'eurent', 'eravate', 've', 't', 'facemmo', 'étants', 'sommes', 'stavate', 'y', 'be', 'degli', 'sarebbero', 'serons', 'eût', 'mie', 'siano', 'ayants', 'dalle', 'negl', 'avranno', 'mi', 'facevamo', 'having', 'farebbero', 'hadn', 'avresti', 'under', 'quante', 'fossimo', "she's", 'stanno', 'dagl', 'her', 'as', 'était', 'avec', 'until', 'ai', 'same', 'siate', 'been', 'avons', 'fummo', 'sera', 'eravamo', 'are', 'soyons', "didn't", 'con', 'sarei', 'dai', 'o', 'after', 'an', 'qu', 'ton', 'why', 'most', 'm', 'eûtes', 'fûmes', 'needn', 'of', 'dello', 'more', 'there', 'le', 'aveste', 'stessi', 'abbiano', 'starebbero', 'facesti', 'him', 'll', 'aurait', 'e', 'êtes', 'aviez', 'stettero', 'me', 'facendo', 'la', 'della', 'qui', 'vostro', 'fareste', 'étante', 'sono', 'dallo', 'agli', 'fosse', 'aient', 'erano', 'staranno', "needn't", 'few', 'dalla', 'tuoi', 'vostra', 'sarete', 'stavano', 'here', 'seraient', 'à', 'ayante', 'aurions', 'eut', 'stette', 'a', 'at', 'nel', 'te', "that'll", 'fût', 'avevi', 'just', 'who', 'toi', 'nell', 'than', 'ne', 'questa', 'sarò', 'eue', 'dov', 'haven', 'avuto', 'vostri', 'seriez', 'coi', 'themselves', 'aurez', 'or', 'abbiamo', 'eûmes', "haven't", "shouldn't", 'sont', 'fosti', 'each', 'eus', 'saremmo', 'not', 'auraient', 'doesn', 'au', 'about', 'no', "weren't", 'aurons', 'da', 'herself', "couldn't", 'the', 'mes', 'est', 'stareste', 'both', 'quanta', 'de', 'seras', 'ho', 'what', 'stia', 'weren', 'she', 'avremmo', 'les', 'avrà', 'siete', 'faremo', 'any', 'yourself', 'avais', 'out', 'sullo', 'des', 'si', 'étées', 'fussent', 'eussiez', 'so', 'che', 'abbia', 'que', 'lo', 'nor', 'abbiate', 'étée', 'farei', 'suoi', 'quella', 'has', 'only', 'contro', 'ours', 'myself', 'faccia', 'does', 'stessero', 'avremo', 'in', 'mia', 'avrebbe', 'while', 'which', 'wasn', "mightn't", 'saremo', 'ci', "doesn't", 'su', 'nous', 'fûtes', 'aie', 'suo', 'l', 'but', 'dans', 'fus', 'del', 'fusses', 'shan', 'un', 'j', 'other', 'avuti', 'avrete', 'col', 'avessimo', 'notre', 'gli', 'soit', 'dall', 'mightn', 'ain', 'it', 'did', 'faranno', 'se', 'facessero', 'et', 'non', 'starà', 'do', 'eri', 'am', 'into', 'sui', 'mustn', "mustn't", 'fusse', 'uno', 'sa', 'di', "you've", 'été', 'furent', 'eues', 'nostri', 'he', 'delle', 'è', 'for', 'auriez', 'anche', 'farebbe', 'itself', 'faremmo', 'vous', 'aura', 'étions', 'soient', 'if', 'chi', 'facessimo', 'miei', 'hanno', 'allo', 'sull', 'nelle', 'perché', 'facevo', 'sulla', 'tue', 'facessi', 'such', 'theirs', 'and', 'serez', 'eusses', 'facciano', 'sul', 'facciate', 'have', 'hasn', 'fu', 'should', 'was', 'sua', 'avrebbero', 'that', 'étais', 'nello', 'cui', 'stessimo', 'alle', 'dove', 'below', 'over', "should've", 'is', 'aux', 'serai', 'staremmo', 'pas', 'quanto', 'avevano', 'vos', 'ait', 'avute', 'al', 'avrai', 'per', 'faceva', 'faccio', 'noi', 'during', 'yours', 'étés', 'foste', 'siamo', 'against', 'faceste', 'auront', 'hers', 'fanno', 'io', 'then', 'staresti', 'fussions', "you'll", 'une', 'being', 'tes', 'this', "you'd", 'quanti', 'when', 'più', 'starai', 'through', 'didn', 'avaient', 'eu', 'steste', 'where', 'come', 'them', 'aies', 'couldn', "you're", 'faresti', 'i', 'facevate', "shan't", 'feci', 'with', 'questo', 'stai', 'saresti', 'stesse', 'my', 'era', 'fece', 'shouldn', 'avrò', 'fui', 'starei', 'can', 'starebbe', "isn't", 'leur', 'ta', 'fossero', 'sei', 'they', 'ebbi', 'stiano', "wasn't", 'avreste', 'ce', 'ayez', 'serais', 'yourselves', 'avesse', 'ed', 'sarà', "hadn't", 'je', 'eux', 'don', 'questi', 'stavi', 'stesti', 're', 'himself', 'es', 'stava', 'saranno', 'avevate', 'by', 'fossi', 'farò', 'their', 'all', 'fecero', 'stavo', 'nei', 'sarai', 'sue', 'because', 'elle', 'fut', 'degl', 'down', 'suis', 'avessero', 'dal', 'how', 'will', 'were', 'étaient', 'avuta', 'stavamo', 'ayant', 'eussions', 'voi', 'negli', "it's", 'wouldn', 'ils', 'n', 'too', 'serait', 'serions', 'ebbe', 'some', 'stiamo', 'staremo', 'stemmo', 'your', 'dei', 'ha', 'avendo', 'lui', 'starete', 'ont', 'dell', 'avessi', 'ces', 'mio', 'ourselves', 'very', 'tuo', 'quello', 'from', 'il', "wouldn't", 'sur', 'sois', 'fussiez', 'now', 'won', 'further', 'eusse', 'loro', 'quelli', 'we', 'c', 'these', 'ou', 'ayons', 'our', 'quale', 'sarebbe', 'agl', 'to', 'above', 'facevi', 'doing', 'alla', 's', 'pour', 'd', 'isn', 'par', 'ero', 'avemmo', 'sareste', 'facciamo', 'starò', 'before', 'his', 'ses', 'aurai', 'una', 'avrei', 'farai', 'nostra', 'quelle', 'sugli', 'facevano', 'eussent', 'aurais', 'whom', "hasn't", 'nostre', 'même', "won't", 'mon', 'vostre', 'moi', 'ma', 'étiez', 'étantes']



import streamlit as st
import scattertext as stx
from scattertext import CorpusFromPandas
from scattertext.WhitespaceNLP import whitespace_nlp
import pandas as pd
import nltk
from nltk.tokenize import word_tokenize
#from nltk.corpus import stopwords
import plotly.express as px
from sklearn.feature_extraction.text import TfidfVectorizer
import matplotlib.pyplot as plt



################
#download function
import requests
import time
import pandas as pd
import urllib.parse
import datetime

from io import StringIO


def download_steam_api(app_id):
	# Imposta il cursore iniziale
	cursor = '*'


	# Lista per raccogliere tutte le recensioni
	reviews_data = []


	while True:
    	# Parametri per la richiesta API
        params = { 'filter': 'recent','language': 'all','review_type': 'all','purchase_type': 'all','num_per_page': 100,'cursor': cursor,'json': 1}

    	# Genera la query string
    	query_string = urllib.parse.urlencode(params)
    	request_url = f'https://store.steampowered.com/appreviews/{app_id}?{query_string}'

    	print(f"Effettuo richiesta a: {request_url}")
    	st.write(f"Effettuo richiesta a: {request_url}")

    	# Effettua la richiesta
    	response = requests.get(request_url)

    	# Se la richiesta non va a buon fine, interrompi
    	if response.status_code != 200:
        	print("Errore nella richiesta:", response.status_code)
        	break

    	# Converte la risposta in JSON
    	data = response.json()

    	# Se non ci sono recensioni, esce dal ciclo
    	if not data.get('reviews') or len(data['reviews']) == 0:
        	print("Nessuna recensione trovata, fine ciclo.")
        	break


    	# Aggiorna il cursore per la prossima pagina
    	cursor = data.get('cursor')


    	# Processa ogni recensione
    	for review in data['reviews']:
        	# Conversione del timestamp in data formattata
        	timestamp = review.get('timestamp_created')
        	review_date = datetime.datetime.fromtimestamp(timestamp).strftime('%Y.%m.%d %H:%M') if timestamp else ''


        	# Costruisce il dizionario dei dati della recensione
        	reviews_data.append({
            	'Review ID': review.get('recommendationid'),
            	'Language': review.get('language'),
            	'Date Posted': review_date,  # già convertito in formato "YYYY.MM.DD HH:MM" precedentemente
            	'Timestamp Updated': datetime.datetime.fromtimestamp(review.get('timestamp_updated')).strftime("%Y-%m-%d %H:%M:%S") if review.get('timestamp_updated') else '',
            	'Recommended': '1' if review.get('voted_up') else '0',
            	'Steam Purchase': '1' if review.get('steam_purchase') else '0',
            	'Weighted Vote Score': review.get('weighted_vote_score'),
            	'Votes Up': review.get('votes_up'),
            	'Votes Funny': review.get('votes_funny'),
            	'Comment Count': review.get('comment_count'),
            	'Received For Free': '1' if review.get('received_for_free') else '0',
            	'Written During Early Access': '1' if review.get('written_during_early_access') else '0',
            	'Primarily Steam Deck': '1' if review.get('primarily_steam_deck') else '0',
            	'Review Text': review.get('review'),
            	# Informazioni sull'autore
            	'Author SteamID': review.get('author', {}).get('steamid'),
            	'Num Games Owned': review.get('author', {}).get('num_games_owned'),
            	'Num Reviews': review.get('author', {}).get('num_reviews'),
            	'Playtime Forever': review.get('author', {}).get('playtime_forever'),
            	'Playtime Last Two Weeks': review.get('author', {}).get('playtime_last_two_weeks'),
            	'Playtime At Review': review.get('author', {}).get('playtime_at_review'),
            	'Last Played': datetime.datetime.fromtimestamp(review.get('author', {}).get('last_played')).strftime("%Y-%m-%d %H:%M:%S") if review.get('author', {}).get('last_played') else ''
        	})


    	# (Facoltativo) Attende un attimo per non sovraccaricare l'endpoint
    	time.sleep(1)


	# Crea un DataFrame dai dati raccolti
	df_reviews = pd.DataFrame(reviews_data)

	return df_reviews


# Funzione per la tokenizzazione usando nltk e rimuovere le stopwords
def clean_text(text):
	# Tokenizza il testo usando nltk
	tokens = word_tokenize(str(text).lower())
    
	# Rimuovi le stopwords dal testo
	filtered_tokens = [word for word in tokens if word not in all_stopwords]
    
	return ' '.join(filtered_tokens)

############################################# Interfaccia

# Interfaccia Streamlit
st.title("Steam Review Dashboard")

# Carica o scarica le recensioni
app_id = st.text_input("Inserisci l'App ID di Steam (può impiegare alcuni minuti):", "")

if st.button("Scarica Recensioni"):
	if app_id:
    	df = download_steam_api(app_id)
    	st.write("Recensioni scaricate con successo!")
    	#st.write(df.head())  # Mostra le prime righe per il controllo
	else:
    	st.error("Inserisci un App ID valido.")

# Carica un file CSV
uploaded_file = st.file_uploader("Carica un file CSV", type=["csv"])

if uploaded_file is not None:
	df = pd.read_csv(uploaded_file)
	#st.write("Prime righe del file caricato:", df.head())

# Mostra un'opzione per scaricare il DataFrame
def download_csv(df):
	csv = df.to_csv(index=False)
	st.download_button(
    	label="Scarica il CSV",
    	data=csv,
    	file_name="steam_reviews.csv",
    	mime="text/csv"
	)

# Pulsante per scaricare il CSV
if 'df' in locals():
	download_csv(df)



    
##############à Messaggio

	# Calcola il volume totale di recensioni
	volume = len(df)

	# Calcola il numero di recensioni raccomandate (1) e non raccomandate (0)
	totpos = df['Recommended'].astype(int).sum()  # Assumendo che 1 = raccomandato
	totneg = volume - totpos  # Il resto sono non raccomandate

	# Calcola la percentuale di recensioni raccomandate e non raccomandate
	percentpos = (totpos / volume) * 100
	percentneg = (totneg / volume) * 100

	# Trova le date minime e massime
	mindate = df['Date Posted'].min()
	maxdate = df['Date Posted'].max()

	# Calcola il numero di recensioni per lingua
	lingua_counts = df['Language'].value_counts()
	primalingua = lingua_counts.index[0] if len(lingua_counts) > 0 else "N/D"
	totperclingua1 = lingua_counts.iloc[0] if len(lingua_counts) > 0 else 0
	secondalingua = lingua_counts.index[1] if len(lingua_counts) > 1 else "N/D"
	totperclingua2 = lingua_counts.iloc[1] if len(lingua_counts) > 1 else 0
	terzalingua = lingua_counts.index[2] if len(lingua_counts) > 2 else "N/D"
	totperclingua3 = lingua_counts.iloc[2] if len(lingua_counts) > 2 else 0

	# Format della frase
	message = (f"Per il file caricato ho trovato {volume} recensioni, "
           	f"di cui il {percentpos:.2f}% raccomandate e il {percentneg:.2f}% non raccomandate, "
           	f"comprese tra {mindate} e {maxdate}, principalmente in {primalingua} ({totperclingua1}), "
           	f"{secondalingua} ({totperclingua2}) e {terzalingua} ({totperclingua3}).")
    
	# Visualizza la frase
	st.write(message)

    
    
################àà Filtro iniziale

	df['Review Text'] = df['Review Text'].apply(lambda x: clean_text(x))
	# Visualizza le prime righe del DataFrame
 
    
    
	# Filtro per lingua (di default "english" o "Tutti" per nessun filtro)
	language_filter = st.selectbox("Seleziona la lingua o tutte le lingue", ['Tutti'] + df['Language'].unique().tolist(), index=0)
	if language_filter != 'Tutti':
    	df_filtered = df[df['Language'] == language_filter]
	else:
    	df_filtered = df  # Nessun filtro sulla lingua

#### Plot dataframe

	# Ordina inizialmente per "Votes Up"
	df_sorted = df_filtered.sort_values(by='Votes Up', ascending=False)

	# Permetti all'utente di scegliere il criterio di ordinamento
	sort_by = st.selectbox(
    	"Scegli la colonna per ordinare",
    	['Votes Up', 'Votes Funny', 'Comment Count', 'Num Games Owned'],
    	index=0
	)

	# Ordina il DataFrame in base alla scelta dell'utente
	df_sorted = df_sorted.sort_values(by=sort_by, ascending=False)

	# Mostra un selettore per quante righe visualizzare
	num_rows = st.slider("Seleziona il numero di righe da visualizzare", min_value=5, max_value=50, value=5)

	col_plot_sort = ['Review Text','Recommended','Date Posted','Language','Votes Up', 'Votes Funny', 'Comment Count', 'Num Games Owned','Last Played']
	# Visualizza le prime righe del DataFrame ordinato e filtrato
	st.write(f"Prime {num_rows} righe del file caricato (ordinate per {sort_by}):", df_sorted[col_plot_sort].head(num_rows))

   	 
##### **Pie Chart per la distribuzione delle recensioni (Raccomandato vs Non Raccomandato)**
	st.subheader("Distribuzione delle Recensioni per Raccomandazione")
	fig_pie = px.pie(df_filtered, names='Recommended', title='Distribuzione Raccomandazione delle Recensioni')
	st.plotly_chart(fig_pie)

##### **Serie Temporale delle recensioni**
	st.subheader("Serie Temporale delle Recensioni")
	df_filtered['Date Posted'] = pd.to_datetime(df_filtered['Date Posted'], errors='coerce')  # Assicurati che la colonna 'Date Posted' sia di tipo datetime
	df_filtered['Date'] = df_filtered['Date Posted'].dt.date  # Estrai solo la data (senza l'ora)

	# Seleziona la granularità (giorno, mese, anno)
	time_granularity = st.selectbox("Seleziona la granularità della serie temporale", ["Giorno", "Mese", "Anno"])

	# Aggrega le recensioni in base alla granularità scelta
	if time_granularity == "Giorno":
    	df_time_series = df_filtered.groupby('Date').size().reset_index(name='Recensioni')
	elif time_granularity == "Mese":
    	df_filtered['Month'] = df_filtered['Date Posted'].dt.to_period('M')
    	df_filtered['Month'] = df_filtered['Month'].astype(str)  # Converte Period in stringa
    	df_time_series = df_filtered.groupby('Month').size().reset_index(name='Recensioni')
	else:
    	df_filtered['Year'] = df_filtered['Date Posted'].dt.year
    	df_time_series = df_filtered.groupby('Year').size().reset_index(name='Recensioni')

	# Selezione per split Recommended vs Non Recommended
	split_by_recommended = st.radio("Vuoi suddividere la serie temporale per Raccomandazione?", ('No', 'Sì'))

	if split_by_recommended == 'Sì':
    	df_recommended = df_filtered[df_filtered['Recommended'] == 1]
    	df_not_recommended = df_filtered[df_filtered['Recommended'] == 0]

    	# Aggrega separatamente per "Recommended" e "Not Recommended"
    	if time_granularity == "Giorno":
        	df_recommended_ts = df_recommended.groupby('Date').size().reset_index(name='Recensioni')
        	df_not_recommended_ts = df_not_recommended.groupby('Date').size().reset_index(name='Recensioni')
    	elif time_granularity == "Mese":
        	df_recommended_ts = df_recommended.groupby('Month').size().reset_index(name='Recensioni')
        	df_not_recommended_ts = df_not_recommended.groupby('Month').size().reset_index(name='Recensioni')
    	else:
        	df_recommended_ts = df_recommended.groupby('Year').size().reset_index(name='Recensioni')
        	df_not_recommended_ts = df_not_recommended.groupby('Year').size().reset_index(name='Recensioni')

    	# Crea i grafici separati per Recommended e Not Recommended
    	fig_recommended = px.line(df_recommended_ts, x=df_recommended_ts.columns[0], y='Recensioni', title='Recensioni Raccomandate nel Tempo')
    	fig_not_recommended = px.line(df_not_recommended_ts, x=df_not_recommended_ts.columns[0], y='Recensioni', title='Recensioni Non Raccomandate nel Tempo')

    	st.plotly_chart(fig_recommended)
    	st.plotly_chart(fig_not_recommended)
	else:
    	# Mostra la serie temporale aggregata per tutti
    	fig_time_series = px.line(df_time_series, x=df_time_series.columns[0], y='Recensioni', title='Numero di Recensioni nel Tempo')
    	st.plotly_chart(fig_time_series)

##################################################################################
   	 
   	 
	# **Generazione dei barplot per le parole più frequenti**
	st.subheader("Le 20 Parole più Frequenti nelle Recensioni")

	# Impostazione dell'utente per decidere quante parole visualizzare
	n_words = st.slider("Seleziona il numero di parole da visualizzare", min_value=5, max_value=50, value=20)
   
	def counter_words(df_counter,n_words):
   	 
    	df_counter['Review Text'] = df_counter['Review Text'].astype(str)
   	 
    	# Filtro delle recensioni raccomandate (1) e non raccomandate (0)
    	df_counter['Recommended'] = df_counter['Recommended'].astype(str)  # Converte in stringa
    	df_recommended 	= df_counter[df_counter['Recommended'] == '1']
    	df_not_recommended = df_counter[df_counter['Recommended'] == '0']


    	# Funzione per estrarre le parole più frequenti usando TfidfVectorizer
    	def get_most_common_words(text_data, n):
        	# Usa TfidfVectorizer per tokenizzare e contare le parole
        	#vectorizer = TfidfVectorizer(stop_words='english', max_features=n)
        	vectorizer = TfidfVectorizer(stop_words='english', max_features=n)
        	X = vectorizer.fit_transform(text_data)
        	word_freq = dict(zip(vectorizer.get_feature_names_out(), X.toarray().sum(axis=0)))
        	return word_freq

    	# Estrai il testo delle recensioni
    	text_recommended = df_recommended['Review Text'].dropna()
    	text_not_recommended = df_not_recommended['Review Text'].dropna()

    	print(text_recommended)
    	print(text_not_recommended)
   	 
    	# Ottieni le parole più frequenti
    	recommended_word_freq = get_most_common_words(text_recommended, n_words)
    	not_recommended_word_freq = get_most_common_words(text_not_recommended, n_words)

    	# Ordina le parole in ordine decrescente di frequenza
    	recommended_word_freq = dict(sorted(recommended_word_freq.items(), key=lambda item: item[1], reverse=True))
    	not_recommended_word_freq = dict(sorted(not_recommended_word_freq.items(), key=lambda item: item[1], reverse=True))
   	 
    	return recommended_word_freq,not_recommended_word_freq
    
	recommended_word_freq,not_recommended_word_freq = counter_words(df_filtered,n_words)

	# Crea i plot delle parole più frequenti
	fig, axes = plt.subplots(1, 2, figsize=(12, 6))

	# Parole più frequenti per recensioni raccomandate (1)
	ax = axes[0]
	ax.bar(recommended_word_freq.keys(), recommended_word_freq.values())
	ax.set_title("Parole più frequenti (Raccomandate)")
	ax.set_xticklabels(recommended_word_freq.keys(), rotation=90, ha='center')  # Etichette verticali

	# Parole più frequenti per recensioni non raccomandate (0)
	ax = axes[1]
	ax.bar(not_recommended_word_freq.keys(), not_recommended_word_freq.values())
	ax.set_title("Parole più frequenti (Non Raccomandate)")
	ax.set_xticklabels(not_recommended_word_freq.keys(), rotation=90, ha='center')  # Etichette verticali

	# Mostra il grafico
	st.pyplot(fig)
    

##################################################################################

	# **Generazione di scattertext**
	st.subheader("Analisi dei Termini più Frequente con Scattertext")
	st.write('Se dovesse dare errore prova a selezionare una lingua')
    
	def scatter_text(df_scat):
    
    	# Converte 'Recommended' in stringhe per garantire la compatibilità con scattertext
    	df_scat['Recommended'] = df_scat['Recommended'].astype(str)  # Converte in stringa

   	 
   	 
    	df_scat = df_scat[df_scat['Recommended'].isin(['0', '1'])]

    	df_scat['Review Text'] = df_scat['Review Text'].fillna('').astype(str)
    	df_scat = df_scat.dropna(subset=['Review Text', 'Recommended'])


   	 
    	# Crea un Corpus usando scattertext con la funzione custom di tokenizzazione
    	corpus = CorpusFromPandas(df_scat, category_col='Recommended', text_col='Review Text',
                              	nlp=whitespace_nlp).build()

    	# Usa scattertext per generare l'explorer
    	html = stx.produce_scattertext_explorer(
        	corpus,
        	category='1',  # Categoria positiva (se '1' è "Recommended")
        	category_name='Recensioni Raccomandate',  # Nome per la categoria positiva
        	not_category_name='Recensioni Non Raccomandate',  # Nome per la categoria negativa
        	minimum_term_frequency=5,  # Frequenza minima per i termini
        	width_in_pixels=700,  # Larghezza del grafico in pixel
        	metadata=df_scat['Review Text']  # Metadati per il grafico
    	)


    	return html

	html = scatter_text(df_filtered)
	# Mostra il grafico HTML generato da scattertext
	st.components.v1.html(html, height=800)