TF-IDF e análise de frequência de termos
Calcule a importância dos termos entre documentos com bind_tf_idf().
TF-IDF e análise de frequência de termos é uma aula grátis de R Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de R Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de R Academy inclui 4 aulas no total.
O que é TF-IDF?
TF-IDF (frequência do termo–frequência inversa do documento) mede o quanto uma palavra é característica de um documento específico dentro de um corpus. Uma pontuação TF-IDF alta significa que a palavra é frequente nesse documento, mas rara no conjunto de documentos — um bom indicador dos principais temas do 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')Preparando a contagem de tokens
Antes de calcular o TF-IDF, você precisa de um quadro de dados com as colunas: document (identificador do documento), word (token) e n (contagem). Use unnest_tokens() seguido de 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: Calculando o TF-IDF
bind_tf_idf(word, document, n) recebe um quadro de dados organizado com contagens e acrescenta três colunas: tf (frequência do termo), idf (frequência inversa do documento) e tf_idf (o produto das duas). O IDF é calculado a partir dos documentos presentes no quadro de dados.
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)): Principais termos
Ordene tf_idf em ordem decrescente para ver quais palavras melhor caracterizam cada documento. Palavras com IDF igual a zero (presentes em todos os documentos) terão TF-IDF igual a zero, independentemente da frequência — elas não conseguem distinguir os documentos.
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))Principais termos de TF-IDF por documento
Use group_by(document) |> slice_max(tf_idf, n = 5) para extrair os N termos mais característicos de cada documento. Esse é um resumo poderoso de um corpus — o vocabulário característico de cada documento aparece claramente.
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')])Visualizando o TF-IDF por documento
Gráficos de barras das pontuações TF-IDF, separados por documento, revelam de imediato o vocabulário característico de cada documento. Use facet_wrap(~document, scales = 'free_y') para que cada painel mostre seus próprios termos principais de forma independente.
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: Palavras presentes em todos os documentos
Palavras presentes em todos os documentos recebem IDF = log(N/N) = 0 e, portanto, TF-IDF = 0. Isso reduz automaticamente o peso das palavras comuns em todo o corpus sem exigir uma lista de palavras funcionais — embora removê-las ainda seja útil em corpora muito pequenos.
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')])Comparando dois documentos
O TF-IDF facilita a comparação de documentos: encontre termos com TF-IDF alto em um documento, mas baixo ou zero em outro, para entender o que torna cada documento único. Faça uma junção interna das tabelas de TF-IDF pela coluna word e compare as pontuações.
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 com os romances de Jane Austen
O pacote janeaustenr fornece o texto completo de seis romances de Austen. Esse é um exemplo clássico de TF-IDF: os fãs de Austen podem identificar o vocabulário característico de cada romance — a palavra "wentworth" é quase exclusiva de 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 para engenharia de atributos
As pontuações TF-IDF podem ser usadas como atributos em classificadores de aprendizado de máquina. Converta o resultado organizado do TF-IDF em uma matriz documento-termo usando cast_dtm() ou cast_sparse() e passe-a para glmnet, xgboost ou qualquer outro classificador.
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')Limitações e alternativas
O TF-IDF tem limitações: trata as palavras como independentes, ignora a ordem e o contexto e pode ser dominado por erros ortográficos raros. As alternativas modernas incluem representações vetoriais de palavras (word2vec, GloVe) e representações contextuais (BERT), mas o TF-IDF continua excelente para recuperação de documentos e como referência para classificação.
# 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ção rápida
Uma palavra aparece em todos os documentos do seu corpus. Qual será sua pontuação TF-IDF?
Recapitulação: Análise de TF-IDF
Principais conclusões:
- TF-IDF = frequência do termo × frequência inversa do documento; pontuação alta = palavra característica
- Fluxo de trabalho:
unnest_tokens()→count(document, word)→bind_tf_idf(word, document, n) bind_tf_idf()acrescenta as colunastf,idfetf_idfarrange(desc(tf_idf))/slice_max(tf_idf, n = 5)mostram os principais termos por documento- Palavras presentes em todos os documentos recebem automaticamente IDF = 0 e TF-IDF = 0
cast_dtm(document, word, tf_idf)converte os dados em uma matriz documento-termo para aprendizado de máquina- Gráficos de barras separados por facetas são a visualização padrão dos resultados de 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()Perguntas Frequentes
A aula “TF-IDF e análise de frequência de termos” é grátis?
Sim — o texto completo de “TF-IDF e análise de frequência de termos” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de R Academy, atualize para CoddyKit PRO. O curso de R Academy inclui 4 aulas no total.
O que vou aprender em “TF-IDF e análise de frequência de termos”?
Calcule a importância dos termos entre documentos com bind_tf_idf(). Você pratica R Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar R Academy?
Nenhuma experiência prévia é necessária. R Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “TF-IDF e análise de frequência de termos”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de R Academy?
Sim. Cada aula de R Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Tokenização e remoção de palavras irrelevantes
- TF-IDF e análise de frequência de termos
- Análise de sentimentos em R
- Modelagem de tópicos com LDA