TF-IDF i analiza częstości terminów
Oceniaj ważność terminów w dokumentach za pomocą bind_tf_idf().
TF-IDF i analiza częstości terminów to bezpłatna lekcja R Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej R Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs R Academy zawiera 4 lekcji w sumie.
Czym jest TF-IDF?
TF-IDF (Term Frequency–Inverse Document Frequency, częstość terminu–odwrotna częstość dokumentu) mierzy, jak charakterystyczne jest dane słowo dla konkretnego dokumentu w korpusie. Wysoka wartość TF-IDF oznacza, że słowo często występuje w tym dokumencie, ale rzadko we wszystkich dokumentach — jest więc dobrym wskaźnikiem głównych tematów dokumentu.
# 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')Przygotowanie zliczeń tokenów
Przed obliczeniem TF-IDF potrzebna jest ramka danych z kolumnami: document (identyfikator dokumentu), word (token) i n (liczba wystąpień). Należy użyć unnest_tokens(), a następnie 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: obliczanie TF-IDF
bind_tf_idf(word, document, n) przyjmuje uporządkowaną ramkę danych ze zliczeniami i dołącza trzy kolumny: tf (częstość terminu), idf (odwrotna częstość dokumentu) oraz tf_idf (ich iloczyn). IDF jest obliczane na podstawie dokumentów obecnych w ramce danych.
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)): najważniejsze terminy
Sortowanie malejąco według tf_idf pozwala sprawdzić, które słowa najlepiej charakteryzują każdy dokument. Słowa o wartości IDF równej zero (obecne w każdym dokumencie) będą miały TF-IDF równe zero niezależnie od swojej częstości — nie pozwalają rozróżniać dokumentów.
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))Najważniejsze terminy TF-IDF dla każdego dokumentu
Należy użyć group_by(document) |> slice_max(tf_idf, n = 5), aby wyodrębnić N najbardziej charakterystycznych terminów dla każdego dokumentu. Jest to przydatne podsumowanie korpusu — charakterystyczne słownictwo każdego dokumentu staje się wyraźnie widoczne.
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')])Wizualizacja TF-IDF dla każdego dokumentu
Wykresy słupkowe wartości TF-IDF z podziałem na dokumenty pokazują na pierwszy rzut oka charakterystyczne słownictwo każdego z nich. Należy użyć facet_wrap(~document, scales = 'free_y'), aby każdy panel niezależnie przedstawiał własne najważniejsze terminy.
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: słowa występujące we wszystkich dokumentach
Słowa występujące w każdym dokumencie mają IDF = log(N/N) = 0, a zatem TF-IDF = 0. Automatycznie zmniejsza to znaczenie słów często występujących w całym korpusie bez konieczności używania listy słów nieznaczących — choć ich usuwanie nadal jest przydatne w bardzo małych korpusach.
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')])Porównywanie dwóch dokumentów
TF-IDF ułatwia porównywanie dokumentów: należy znaleźć terminy o wysokiej wartości TF-IDF w jednym dokumencie, ale niskiej lub zerowej w innym, aby zrozumieć, co wyróżnia każdy dokument. Tabele TF-IDF należy połączyć wewnętrznie według word i porównać wartości.
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 z powieściami Jane Austen
Pakiet janeaustenr udostępnia pełny tekst sześciu powieści Austen. Jest to klasyczny przykład zastosowania TF-IDF: miłośnicy Austen mogą rozpoznać charakterystyczne słownictwo każdej powieści — słowo "wentworth" występuje niemal wyłącznie w 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 do tworzenia cech
Wartości TF-IDF można wykorzystać jako cechy w klasyfikatorach uczenia maszynowego. Uporządkowane dane wyjściowe TF-IDF należy przekształcić w macierz dokument–termin za pomocą cast_dtm() lub cast_sparse(), a następnie przekazać do glmnet, xgboost lub dowolnego innego klasyfikatora.
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')Ograniczenia i alternatywy
TF-IDF ma pewne ograniczenia: traktuje słowa niezależnie, ignoruje ich kolejność i kontekst oraz może być zdominowane przez rzadkie literówki. Nowoczesne alternatywy obejmują embeddingi słów (word2vec, GloVe) i embeddingi kontekstowe (BERT), ale TF-IDF nadal doskonale sprawdza się jako metoda bazowa w wyszukiwaniu dokumentów i klasyfikacji.
# 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)Szybkie sprawdzenie
Słowo występuje we wszystkich dokumentach korpusu. Jaka będzie jego wartość TF-IDF?
Podsumowanie: analiza TF-IDF
Najważniejsze informacje:
- TF-IDF = częstość terminu × odwrotna częstość dokumentu; wysoka wartość oznacza charakterystyczne słowo
- Schemat pracy:
unnest_tokens()→count(document, word)→bind_tf_idf(word, document, n) bind_tf_idf()dodaje kolumnytf,idfitf_idfarrange(desc(tf_idf))/slice_max(tf_idf, n = 5)pokazują najważniejsze terminy dla każdego dokumentu- Słowa obecne we wszystkich dokumentach automatycznie otrzymują IDF = 0 i TF-IDF = 0
cast_dtm(document, word, tf_idf)przekształca dane w macierz dokument–termin na potrzeby uczenia maszynowego- Wykresy słupkowe z podziałem na panele są standardową wizualizacją wyników 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()Ucz się R dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 43
- Lekcje
- 159
Często zadawane pytania
Czy lekcja „TF-IDF i analiza częstości terminów” jest bezpłatna?
Tak — pełny tekst „TF-IDF i analiza częstości terminów” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu R Academy, przejdź na CoddyKit PRO. Kurs R Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „TF-IDF i analiza częstości terminów”?
Oceniaj ważność terminów w dokumentach za pomocą bind_tf_idf(). Ćwiczysz R Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć R Academy?
Nie wymagamy żadnego doświadczenia. R Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.
Ile czasu zajmuje lekcja „TF-IDF i analiza częstości terminów”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji R Academy?
Tak. Każda lekcja R Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Tokenizacja i usuwanie słów pustych
- TF-IDF i analiza częstości terminów
- Analiza sentymentu w R
- Modelowanie tematów za pomocą LDA