File size: 23,012 Bytes
ba0cf89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3e02674
ba0cf89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
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

nltk.download('punkt') 

################
#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")

# Aggiungi un pulsante di reset
if st.button("Resetta Dashboard"):
    # Ripristina sessione e variabili
    st.session_state.clear()
    st.experimental_rerun()  # Ricarica la pagina per resettare tutto


# 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 (salva e poi ricarica il file)"):
    if app_id:
        df = download_steam_api(app_id)
        st.session_state.df = df # Salva il DataFrame in session_state
        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.session_state.df = df # Salva il DataFrame in session_state
    #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 (fallo alla fine)",
        data=csv,
        file_name="steam_reviews.csv",
        mime="text/csv"
    )

# Pulsante per scaricare il CSV
if 'df' in locals():
    df = st.session_state.df
    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 iniziale per lingua
    if 'language_filter' not in st.session_state:
        st.session_state.language_filter = 'Tutti'

    language_filter = st.selectbox("Seleziona la lingua o tutte le lingue", ['Tutti'] + df['Language'].unique().tolist(), index=0 if st.session_state.language_filter == 'Tutti' else df['Language'].unique().tolist().index(st.session_state.language_filter))

    if language_filter != 'Tutti':
        df_filtered = df[df['Language'] == language_filter]
        st.session_state.language_filter = language_filter
    else:
        df_filtered = df
        st.session_state.language_filter = 'Tutti'


#### 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)