0Pricing
R Academy · Lezione

TF-IDF e analisi della frequenza dei termini

Valuti l'importanza dei termini nei documenti con bind_tf_idf()

TF-IDF e analisi della frequenza dei termini è una lezione R Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento R Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso R Academy include 4 lezioni in totale.

Che cos'è il TF-IDF?

TF-IDF (Term Frequency–Inverse Document Frequency, frequenza dei termini–frequenza inversa dei documenti) misura quanto una parola sia distintiva per un documento specifico all'interno di un corpus. Un punteggio TF-IDF elevato indica che la parola è frequente in quel documento ma rara nell'insieme dei documenti: è quindi un buon indicatore degli argomenti principali del documento.

# TF-IDF formula
# TF(w, d)  = count of w in document d / total words in d
# IDF(w)    = log(N / number of docs containing w)
# TF-IDF(w, d) = TF(w, d) * IDF(w)

# Manual example
N <- 4  # total documents
docs_with_word <- 1  # 'neural' appears in only 1 doc
tf <- 5 / 100  # word appears 5 times in 100-word doc
idf <- log(N / docs_with_word)
tfidf <- tf * idf

cat('TF:     ', round(tf, 4), '\n')
cat('IDF:    ', round(idf, 4), '\n')
cat('TF-IDF: ', round(tfidf, 4), '\n')

Preparare il conteggio dei token

Prima di calcolare il TF-IDF, è necessario disporre di un data frame con le colonne: document (identificatore del documento), word (token) e n (conteggio). Utilizzare unnest_tokens() seguito da count(document, word).

library(tidytext)
library(dplyr)

# Simulate a 4-document corpus on tech topics
docs <- tibble::tibble(
  document = c(rep('ML', 3), rep('Stats', 3), rep('DB', 3), rep('Web', 3)),
  text = c(
    'machine learning neural networks training',
    'deep learning models gradient descent',
    'reinforcement learning reward policy agent',
    'probability distributions hypothesis testing',
    'bayesian inference regression analysis variance',
    'statistics sampling confidence intervals normal',
    'database sql joins indexes queries transactions',
    'relational tables primary keys foreign constraints',
    'nosql document store mongodb redis cassandra',
    'html css javascript frontend react components',
    'dom events browser api fetch requests',
    'responsive design flexbox grid layout'
  )
)

word_counts <- docs |>
  unnest_tokens(word, text) |>
  count(document, word, sort = TRUE)

cat('Document-word pairs:', nrow(word_counts), '\n')
print(head(word_counts, 8))

bind_tf_idf: calcolare il TF-IDF

bind_tf_idf(word, document, n) prende un data frame tidy con i conteggi e aggiunge tre colonne: tf (frequenza dei termini), idf (frequenza inversa dei documenti) e tf_idf (il loro prodotto). Calcola l'IDF a partire dai documenti presenti nel data frame.

library(tidytext)
library(dplyr)

docs <- tibble::tibble(
  document = c(rep('ML', 2), rep('Stats', 2), rep('DB', 2)),
  text = c(
    'machine learning neural gradient',
    'deep networks training epochs',
    'probability distributions variance covariance',
    'bayesian inference prior posterior',
    'sql database tables joins indexes',
    'queries transactions foreign primary'
  )
)

tfidf <- docs |>
  unnest_tokens(word, text) |>
  count(document, word) |>
  bind_tf_idf(word, document, n)

cat('Columns added:', names(tfidf), '\n')
print(head(arrange(tfidf, desc(tf_idf)), 8))

arrange(desc(tf_idf)): termini principali

Ordinare tf_idf in ordine decrescente per vedere quali parole caratterizzano meglio ciascun documento. Le parole con IDF pari a zero (presenti in ogni documento) avranno TF-IDF pari a zero indipendentemente dalla loro frequenza: non possono distinguere i documenti.

library(tidytext)
library(dplyr)

docs <- tibble::tibble(
  document = c(rep('Python', 3), rep('R', 3), rep('Julia', 3)),
  text = c(
    'python pandas numpy scipy programming',
    'machine learning scikit tensorflow keras',
    'jupyter notebooks scripts debugging modules',
    'ggplot2 dplyr tidyverse statistics vectors',
    'shiny rmarkdown knitr cran bioconductor',
    'linear models factors dataframes packages',
    'julia multiple dispatch type system macros',
    'package ecosystem flux diffeq parallel',
    'scientific computing performance benchmarks'
  )
)

top_terms <- docs |>
  unnest_tokens(word, text) |>
  count(document, word) |>
  bind_tf_idf(word, document, n) |>
  arrange(desc(tf_idf))

cat('Top distinctive terms per language:\n')
print(head(top_terms[, c('document', 'word', 'tf_idf')], 9))

Termini con TF-IDF più elevato per documento

Utilizzare group_by(document) |> slice_max(tf_idf, n = 5) per estrarre i primi N termini più distintivi per documento. È un riepilogo efficace di un corpus: il vocabolario distintivo di ciascun documento emerge chiaramente.

library(tidytext)
library(dplyr)

docs <- tibble::tibble(
  document = c(rep('Cooking', 3), rep('Finance', 3), rep('Sports', 3)),
  text = c(
    'recipe ingredients oven bake flour butter',
    'cooking temperature boil simmer saute',
    'kitchen knife chopping herbs spices garnish',
    'investment portfolio returns dividends stocks bonds',
    'market equity risk hedge fund derivatives',
    'inflation interest rate treasury balance sheet',
    'goal tackle pass dribble goalkeeper penalty',
    'tournament league championship trophy season',
    'athlete training stamina sprint endurance'
  )
)

top5 <- docs |>
  unnest_tokens(word, text) |>
  count(document, word) |>
  bind_tf_idf(word, document, n) |>
  group_by(document) |>
  slice_max(tf_idf, n = 3) |>
  ungroup()

print(top5[, c('document', 'word', 'tf_idf')])

Visualizzare il TF-IDF per documento

I grafici a barre dei punteggi TF-IDF, suddivisi per documento, mostrano a colpo d'occhio il vocabolario distintivo di ciascun documento. Utilizzare facet_wrap(~document, scales = 'free_y') affinché ogni riquadro mostri autonomamente i propri termini principali.

library(tidytext)
library(dplyr)
library(ggplot2)

docs <- tibble::tibble(
  document = c(rep('AI', 3), rep('DB', 3), rep('Web', 3)),
  text = c(
    'neural networks gradient backpropagation',
    'deep learning transformer attention bert',
    'reinforcement policy reward exploration',
    'sql database indexes joins transactions',
    'relational schema normalization queries',
    'nosql mongodb redis cassandra document',
    'html css javascript react dom',
    'frontend api fetch async components',
    'responsive flexbox grid webpack bundle'
  )
)

plot_data <- docs |>
  unnest_tokens(word, text) |>
  count(document, word) |>
  bind_tf_idf(word, document, n) |>
  group_by(document) |>
  slice_max(tf_idf, n = 4) |>
  ungroup()

ggplot(plot_data, aes(reorder(word, tf_idf), tf_idf, fill = document)) +
  geom_col(show.legend = FALSE) +
  facet_wrap(~document, scales = 'free_y') +
  coord_flip() +
  labs(x = NULL, y = 'TF-IDF', title = 'Top TF-IDF Terms per Topic') +
  theme_minimal()

IDF: parole presenti in tutti i documenti

Le parole presenti in ogni documento hanno IDF = log(N/N) = 0 e, di conseguenza, TF-IDF = 0. In questo modo le parole comuni all'intero corpus vengono automaticamente ponderate meno, senza bisogno di un elenco di stop word; tuttavia, la rimozione delle stop word resta utile per i corpus molto piccoli.

library(tidytext)
library(dplyr)

docs <- tibble::tibble(
  document = c('A', 'B', 'C'),
  text = c(
    'data analysis statistics regression probability',
    'data engineering pipelines etl transformation',
    'data visualisation ggplot2 charts dashboards'
  )
)

tfidf <- docs |>
  unnest_tokens(word, text) |>
  count(document, word) |>
  bind_tf_idf(word, document, n)

# 'data' appears in all 3 docs: tf_idf should be 0
data_rows <- filter(tfidf, word == 'data')
cat('TF-IDF for "data" across documents:\n')
print(data_rows[, c('document', 'word', 'idf', 'tf_idf')])

Confrontare due documenti

Il TF-IDF semplifica il confronto tra documenti: individuare i termini con TF-IDF elevato in un documento ma basso o nullo nell'altro consente di capire che cosa rende unico ciascun documento. Eseguire un inner join delle tabelle TF-IDF sulla word e confrontare i punteggi.

library(tidytext)
library(dplyr)

docs <- tibble::tibble(
  document = c(rep('Doc1', 3), rep('Doc2', 3)),
  text = c(
    'bayesian statistics prior posterior mcmc',
    'markov chain monte carlo sampling',
    'probability distributions conjugate inference',
    'convolutional neural network image classification',
    'pooling activation relu softmax batch',
    'convolution filter feature map stride padding'
  )
)

tfidf <- docs |>
  unnest_tokens(word, text) |>
  count(document, word) |>
  bind_tf_idf(word, document, n)

# Top 3 unique terms per document
tfidf |>
  group_by(document) |>
  slice_max(tf_idf, n = 3) |>
  select(document, word, tf_idf) |>
  print()

TF-IDF con i romanzi di Jane Austen

Il pacchetto janeaustenr fornisce il testo completo di sei romanzi di Austen. È un benchmark classico per il TF-IDF: gli appassionati di Austen possono identificare il vocabolario distintivo di ciascun romanzo; la parola "wentworth" è quasi esclusiva di Persuasion.

library(tidytext)
library(dplyr)

# Requires janeaustenr package
# library(janeaustenr)
# austen_books() returns: book, text

# Simulated mini-Austen corpus
mini_austen <- tibble::tibble(
  book = c(rep('Sense', 3), rep('Pride', 3), rep('Emma', 3)),
  text = c(
    'elinor marianne dashwood willoughby colonel',
    'edward ferrars barton cottage sister sense',
    'brandon feelings attachment sensibility heart',
    'darcy bennet bingley netherfield wickham',
    'jane lizzy lydia longbourn pemberley',
    'pride prejudice proposal marriage happiness',
    'emma woodhouse knightley harriet weston',
    'highbury match social governess niece',
    'frank jane fairfax box hill picnic'
  )
)

top <- mini_austen |>
  unnest_tokens(word, text) |>
  count(book, word) |>
  bind_tf_idf(word, book, n) |>
  group_by(book) |>
  slice_max(tf_idf, n = 3) |>
  select(book, word, tf_idf)

print(top)

TF-IDF per l'ingegneria delle feature

I punteggi TF-IDF possono essere utilizzati come feature nei classificatori di machine learning. Convertire l'output tidy del TF-IDF in una matrice documento-termine utilizzando cast_dtm() o cast_sparse() e passarla a glmnet, xgboost o qualsiasi altro classificatore.

library(tidytext)
library(dplyr)

docs <- tibble::tibble(
  document = c(rep('Positive', 4), rep('Negative', 4)),
  text = c(
    'excellent product love recommend quality',
    'amazing fast delivery five star perfect',
    'great value money satisfied happy return',
    'wonderful experience purchase outstanding best',
    'terrible waste money broken arrived damaged',
    'horrible quality slow delivery disappointed awful',
    'poor value cheap plastic flimsy broken',
    'worst experience refund needed useless junk'
  )
)

# TF-IDF as features
tfidf_wide <- docs |>
  unnest_tokens(word, text) |>
  count(document, word) |>
  bind_tf_idf(word, document, n) |>
  cast_dtm(document, word, tf_idf)

cat('DTM dimensions:', dim(tfidf_wide), '\n')
cat('(rows=documents, cols=unique words)\n')

Limitazioni e alternative

Il TF-IDF presenta alcune limitazioni: tratta le parole come indipendenti, ignora l'ordine e il contesto delle parole e può essere influenzato eccessivamente dagli errori di ortografia rari. Le alternative moderne includono gli embedding delle parole (word2vec, GloVe) e gli embedding contestuali (BERT), ma il TF-IDF resta eccellente per il recupero dei documenti e come baseline per la classificazione.

# TF-IDF strengths and weaknesses summary
criteria <- data.frame(
  Criterion = c('Speed', 'Interpretability', 'Context', 'Word order',
                'Rare words', 'Scalability'),
  TF_IDF    = c('Fast', 'High', 'None', 'Ignored',
                'High IDF (inflated)', 'Excellent'),
  BERT      = c('Slow', 'Low', 'Rich', 'Captured',
                'Handled', 'Moderate')
)

print(criteria, row.names = FALSE)

Verifica rapida

Una parola compare in tutti i documenti del corpus. Quale sarà il suo punteggio TF-IDF?

Riepilogo: analisi TF-IDF

Concetti chiave:

  • TF-IDF = frequenza dei termini × frequenza inversa dei documenti; un punteggio elevato indica una parola distintiva
  • Flusso di lavoro: unnest_tokens() → count(document, word) → bind_tf_idf(word, document, n)
  • bind_tf_idf() aggiunge le colonne tf, idf e tf_idf
  • arrange(desc(tf_idf)) / slice_max(tf_idf, n = 5) mostrano i termini principali per documento
  • Le parole presenti in tutti i documenti ottengono automaticamente IDF = 0 e TF-IDF = 0
  • cast_dtm(document, word, tf_idf) converte i dati in una matrice documento-termine per il machine learning
  • I grafici a barre suddivisi per documento sono la visualizzazione standard dei risultati TF-IDF
library(tidytext)
library(dplyr)

# Minimal TF-IDF pipeline
tibble::tibble(
  doc = c('A', 'A', 'B', 'B'),
  text = c('neural networks deep', 'learning training', 'sql database query', 'joins indexes')
) |>
  unnest_tokens(word, text) |>
  count(doc, word) |>
  bind_tf_idf(word, doc, n) |>
  arrange(desc(tf_idf)) |>
  print()

Domande Frequenti

La lezione «TF-IDF e analisi della frequenza dei termini» è gratuita?

Sì — il testo completo di «TF-IDF e analisi della frequenza dei termini» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso R Academy, passa a CoddyKit PRO. Il corso R Academy include 4 lezioni in totale.

Cosa imparerò in «TF-IDF e analisi della frequenza dei termini»?

Valuti l'importanza dei termini nei documenti con bind_tf_idf() Eserciti R Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare R Academy?

Non è richiesta alcuna esperienza precedente. R Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «TF-IDF e analisi della frequenza dei termini»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione R Academy?

Sì. Ogni lezione R Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Tokenizzazione e rimozione delle stop word
  2. TF-IDF e analisi della frequenza dei termini
  3. Analisi del sentiment in R
  4. Topic modeling con LDA
← Torna a R Academy