messenger_logo
Liên hệ qua Messenger
SciEco

Phân tích văn bản trong r với quanteda (phần 1)

I
IEFPA
Ngày viết: 10/07/2026

Trong kỷ nguyên dữ liệu lớn, khả năng trích xuất thông tin có giá trị từ dữ liệu văn bản phi cấu trúc là một kỹ năng vô cùng quan trọng đối với các nhà khoa học dữ liệu. Dù là phân tích phản hồi của khách hàng, nghiên cứu tin tức hay khám phá các chủ đề trong tài liệu khoa học, phân tích văn bản cung cấp cái nhìn sâu sắc giúp định hình các quyết định kinh doanh và nghiên cứu. Bài viết này sẽ giới thiệu bạn đến với `quanteda`, một gói phần mềm mạnh mẽ và hiệu quả trong R, được thiết kế đặc biệt cho việc phân tích văn bản. Đây là phần đầu tiên trong chuỗi bài viết, tập trung vào các khái niệm cơ bản và các bước tiền xử lý chính.

Các Gói Phần Mềm Cần Thiết

1library(quanteda)
2library(quanteda.textstats)
3library(quanteda.textplots)
4library(readr)
5library(dplyr)
6library(ggplot2)
7library(stringr)
8library(DT)
9library(tidytext)

Nắm Vững Kiến Thức Cơ Bản Về Phân Tích Văn Bản

Phân tích văn bản là quá trình biến đổi dữ liệu văn bản thành dữ liệu có cấu trúc phù hợp để phân tích. Một quy trình làm việc điển hình bao gồm các bước sau:

* **Thu thập và tải văn bản**: Nhập dữ liệu văn bản từ nhiều nguồn khác nhau.

* **Tiền xử lý**: Làm sạch và chuẩn hóa văn bản.

* **Token hóa**: Chia văn bản thành các đơn vị có ý nghĩa (từ, câu, N-grams).

* **Tạo ma trận tài liệu-đặc trưng (DFM)**: Biểu diễn văn bản dưới dạng số.

* **Phân tích**: Trích xuất thông tin chi tiết thông qua các phương pháp thống kê và tính toán.

Tạo Corpus: Chuẩn Bị Dữ Liệu Để Phân Tích

Corpus là một tập hợp văn bản có cấu trúc. Gói `quanteda` cung cấp hàm `corpus()` để tạo đối tượng corpus từ nhiều nguồn dữ liệu khác nhau.

Ví Dụ 1: Corpus Đơn Giản Từ Vector Ký Tự

1# Tạo một corpus đơn giản từ vector ký tự
2texts <- c(
3  "The quick brown fox jumps over the lazy dog.",
4  "Natural language processing is fascinating and powerful.",
5  "Text analytics enables data-driven decision making.",
6  "Machine learning algorithms can analyze text at scale.",
7  "Data science combines statistics, programming, and domain knowledge."
8)
9# Tạo corpus
10corp <- corpus(texts)
11# Kiểm tra corpus
12summary(corp)

Corpus bao gồm 5 tài liệu, hiển thị 5 tài liệu:

Text Types Tokens Sentences

text1 10 10 1

text2 8 8 1

text3 7 7 1

text4 9 9 1

text5 10 11 1

Ví Dụ 2: Corpus Từ Khung Dữ Liệu

Trong thực tế, dữ liệu văn bản thường đi kèm với siêu dữ liệu liên quan (ví dụ: tác giả, ngày, danh mục). `quanteda` xử lý vấn đề này rất tốt:

1# Tạo một khung dữ liệu với văn bản và siêu dữ liệu
2text_df <- data.frame(
3  text = c(
4    "Customer service was excellent and responsive.",
5    "Product quality is poor. Very disappointed.",
6    "Shipping was fast. Happy with my purchase.",
7    "Price is too high for the quality received.",
8    "Great value for money. Would recommend!"
9  ),
10  rating = c(5, 2, 4, 2, 5),
11  product_category = c("Electronics", "Clothing", "Electronics", "Clothing", "Electronics"),
12  review_date = as.Date(c("2025-01-15", "2025-02-20", "2025-03-10", "2025-04-05", "2025-05-12")),
13  stringsAsFactors = FALSE
14)
15datatable(text_df)
1# Tạo corpus từ khung dữ liệu
2reviews_corp <- corpus(text_df, text_field = "text")
3# Kiểm tra corpus với siêu dữ liệu
4summary(reviews_corp)

Corpus bao gồm 5 tài liệu, hiển thị 5 tài liệu:

Text Types Tokens Sentences rating product_category review_date

text1 7 7 1 5 Electronics 2025-01-15

text2 7 8 2 2 Clothing 2025-02-20

text3 8 9 2 4 Electronics 2025-03-10

text4 9 9 1 2 Clothing 2025-04-05

text5 8 8 2 5 Electronics 2025-05-12

1# Truy cập các biến tài liệu (siêu dữ liệu) (các cột không được khai báo là "text_field")
2docvars(reviews_corp)

rating product_category review_date

1 5 Electronics 2025-01-15

2 2 Clothing 2025-02-20

3 4 Electronics 2025-03-10

4 2 Clothing 2025-04-05

5 5 Electronics 2025-05-12

1# Tạo tập con của corpus theo siêu dữ liệu
2high_rated <- corpus_subset(reviews_corp, rating >= 4)
3summary(high_rated)

Corpus bao gồm 3 tài liệu, hiển thị 3 tài liệu:

Text Types Tokens Sentences rating product_category review_date

text1 7 7 1 5 Electronics 2025-01-15

text3 8 9 2 4 Electronics 2025-03-10

text5 8 8 2 5 Electronics 2025-05-12

Token Hóa: Chia Văn Bản Thành Các Đơn Vị

Token hóa là quá trình chia văn bản thành các đơn vị riêng lẻ (tokens), thường là các từ. Hàm `tokens()` cung cấp nhiều khả năng token hóa.

Token Hóa Cơ Bản

1# Token hóa corpus đánh giá
2toks <- tokens(reviews_corp)
3# Xem các tokens từ tất cả tài liệu
4print(toks)

Tokens bao gồm 5 tài liệu và 3 biến tài liệu.

text1 :

[1] "Customer" "service" "was" "excellent" "and"

[6] "responsive" "."

text2 :

[1] "Product" "quality" "is" "poor" "."

[6] "Very" "disappointed" "."

text3 :

[1] "Shipping" "was" "fast" "." "Happy" "with" "my"

[8] "purchase" "."

text4 :

[1] "Price" "is" "too" "high" "for" "the" "quality"

[8] "received" "."

text5 :

[1] "Great" "value" "for" "money" "." "Would"

[7] "recommend" "!"

Các Tùy Chọn Token Hóa Nâng Cao

`quanteda` cung cấp nhiều quyền kiểm soát đối với quá trình token hóa:

1# Tạo văn bản mẫu với các yếu tố khác nhau
2sample_text <- "Dr. Smith's email is
3[email protected]
4. 
5                He earned $100,000 in 2024! Visit https://example.com 
6                for more info. #DataScience #AI"
7sample_corp <- corpus(sample_text)
8# Các phương pháp token hóa khác nhau
9tokens_default <- tokens(sample_corp)
10tokens_no_punct <- tokens(sample_corp, remove_punct = TRUE)
11tokens_no_numbers <- tokens(sample_corp, remove_numbers = TRUE)
12tokens_no_symbols <- tokens(sample_corp, remove_symbols = TRUE)
13tokens_lowercase <- tokens(sample_corp, remove_punct = TRUE) %>% tokens_tolower()
14# So sánh kết quả
15print(tokens_default)

Tokens bao gồm 1 tài liệu.

text1 :

[1] "Dr" "." "Smith's"

[4] "email" "is" "

[email protected]

"

[7] "." "He" "earned"

[10] "$" "100,000" "in"

[ ... và 10 đơn vị khác ]

1print(tokens_no_punct)

Tokens bao gồm 1 tài liệu.

text1 :

[1] "Dr" "Smith's" "email"

[4] "is" "

[email protected]

" "He"

[7] "earned" "$" "100,000"

[10] "in" "2024" "Visit"

[ ... và 6 đơn vị khác ]

1print(tokens_no_numbers)

Tokens bao gồm 1 tài liệu.

text1 :

[1] "Dr" "." "Smith's"

[4] "email" "is" "

[email protected]

"

[7] "." "He" "earned"

[10] "$" "in" "!"

[ ... và 8 đơn vị khác ]

1print(tokens_no_symbols)

Tokens bao gồm 1 tài liệu.

text1 :

[1] "Dr" "." "Smith's"

[4] "email" "is" "

[email protected]

"

[7] "." "He" "earned"

[10] "100,000" "in" "2024"

[ ... và 9 đơn vị khác ]

1print(tokens_lowercase)

Tokens bao gồm 1 tài liệu.

text1 :

[1] "dr" "smith's" "email"

[4] "is" "

[email protected]

" "he"

[7] "earned" "$" "100,000"

[10] "in" "2024" "visit"

[ ... và 6 đơn vị khác ]

Loại Bỏ Từ Dừng

Từ dừng là những từ thông dụng (ví dụ: "the", "is", "at") mà thường không mang ý nghĩa đáng kể. Việc loại bỏ chúng giúp giảm nhiễu và cải thiện hiệu quả tổng thể.

1# Xem 20 từ dừng tiếng Anh tích hợp sẵn đầu tiên
2head(stopwords("english"), 20)

[1] "i" "me" "my" "myself" "we"

[6] "our" "ours" "ourselves" "you" "your"

[11] "yours" "yourself" "yourselves" "he" "him"

[16] "his" "himself" "she" "her" "hers"

1# Số lượng từ dừng tiếng Anh
2length(stopwords("english"))

[1] 175

1# Loại bỏ từ dừng khỏi tokens
2toks_no_stop <- tokens(reviews_corp, 
3                       remove_punct = TRUE,
4                       remove_numbers = TRUE) %>%
5  tokens_tolower() %>%
6  tokens_remove(stopwords("english"))
7# So sánh có và không có từ dừng
8print(tokens(reviews_corp, remove_punct = TRUE)[1])

Tokens bao gồm 1 tài liệu và 3 biến tài liệu.

text1 :

[1] "Customer" "service" "was" "excellent" "and"

[6] "responsive"

1print(toks_no_stop[1])

Tokens bao gồm 1 tài liệu và 3 biến tài liệu.

text1 :

[1] "customer" "service" "excellent" "responsive"

1# Đếm số lượng tokens trước và sau
2print(ntoken(tokens(reviews_corp, remove_punct = TRUE)))

text1 text2 text3 text4 text5

6 6 7 8 6

1print(ntoken(toks_no_stop))

text1 text2 text3 text4 text5

4 4 4 4 4

Gọt Từ

Gọt từ (stemming) là kỹ thuật giảm các từ về dạng gốc bằng cách loại bỏ các hậu tố (ví dụ: "running" → "run").

1# Văn bản ví dụ minh họa các biến thể của từ
2stem_text <- c(
3  "The running runners ran faster than expected.",
4  "Computing computers computed complex calculations.",
5  "The analyst analyzed analytical data using analysis techniques."
6)
7stem_corp <- corpus(stem_text)
8# Token hóa
9stem_toks <- tokens(stem_corp, remove_punct = TRUE) %>% tokens_tolower()
10# Áp dụng gọt từ
11stem_toks_stemmed <- tokens_wordstem(stem_toks)
12# So sánh bản gốc và bản đã gọt từ
13print(stem_toks[1])

Tokens bao gồm 1 tài liệu.

text1 :

[1] "the" "running" "runners" "ran" "faster" "than" "expected"

1print(stem_toks_stemmed[1])

Tokens bao gồm 1 tài liệu.

[1] "the" "run" "runner" "ran" "faster" "than" "expect"

Ma Trận Tài Liệu-Đặc Trưng (DFM): Biểu Diễn Số

Ma trận tài liệu-đặc trưng (DFM) là một biểu diễn số của văn bản, trong đó các hàng đại diện cho tài liệu, các cột đại diện cho đặc trưng (thường là từ), và các giá trị trong ô cho biết tần suất đặc trưng trong mỗi tài liệu. Cấu trúc này cho phép phân tích thống kê và các ứng dụng máy học.

1# Tạo DFM từ corpus đánh giá của chúng ta
2reviews_dfm <- reviews_corp %>%
3  tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
4  tokens_tolower() %>%
5  tokens_remove(stopwords("english")) %>%
6  dfm()
7# Kiểm tra DFM
8print(reviews_dfm)

Ma trận tài liệu-đặc trưng của: 5 tài liệu, 19 đặc trưng (78.95% thưa) và 3 biến tài liệu.

features

docs customer service excellent responsive product quality poor disappointed

text1 1 1 1 1 0 0 0 0

text2 0 0 0 0 1 1 1 1

text3 0 0 0 0 0 0 0 0

text4 0 0 0 0 0 1 0 0

text5 0 0 0 0 0 0 0 0

features

docs shipping fast

text1 0 0

text2 0 0

text3 1 1

text4 0 0

text5 0 0

[ đạt max_nfeat ... 9 đặc trưng khác ]

1# Xem kích thước DFM
2print(dim(reviews_dfm))

[1] 5 19

Thống Kê Đặc Trưng: Hiểu Tần Suất Từ

Phân tích tần suất đặc trưng tiết lộ các thuật ngữ quan trọng nhất trong corpus.

1# Tính toán tần suất đặc trưng
2feat_freq <- textstat_frequency(reviews_dfm)
3# Xem các đặc trưng hàng đầu
4head(feat_freq, 15)

feature frequency rank docfreq group

1 quality 2 1 2 all

2 customer 1 2 1 all

3 service 1 2 1 all

4 excellent 1 2 1 all

5 responsive 1 2 1 all

6 product 1 2 1 all

7 poor 1 2 1 all

8 disappointed 1 2 1 all

9 shipping 1 2 1 all

10 fast 1 2 1 all

11 happy 1 2 1 all

12 purchase 1 2 1 all

13 price 1 2 1 all

14 high 1 2 1 all

15 received 1 2 1 all

1# Trực quan hóa các đặc trưng hàng đầu
2feat_freq %>%
3  head(15) %>%
4  ggplot(aes(x = reorder(feature, frequency), y = frequency)) +
5  geom_col(fill = "steelblue") +
6  coord_flip() +
7  labs(title = "15 Thuật Ngữ Phổ Biến Nhất",
8       x = "Thuật Ngữ",
9       y = "Tần Suất") +
10  theme_minimal()

Phân Tích Đặc Trưng Dựa Trên Nhóm

Phân tích các đặc trưng theo nhóm (ví dụ: đánh giá cao so với đánh giá thấp) tiết lộ từ vựng đặc trưng:

1# Nhóm DFM theo danh mục xếp hạng
2reviews_dfm_grouped <- reviews_corp %>%
3  tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
4  tokens_tolower() %>%
5  tokens_remove(stopwords("english")) %>%
6  dfm() %>%
7  dfm_group(groups = rating)
8# Tính toán tần suất theo nhóm
9freq_by_rating <- textstat_frequency(reviews_dfm_grouped, groups = rating)
10# Xem các đặc trưng hàng đầu cho mỗi xếp hạng
11print(freq_by_rating %>% filter(group == 5) %>% head(10))

feature frequency rank docfreq group

12 customer 1 1 1 5

13 service 1 1 1 5

14 excellent 1 1 1 5

15 responsive 1 1 1 5

16 great 1 1 1 5

17 value 1 1 1 5

18 money 1 1 1 5

19 recommend 1 1 1 5

1print(freq_by_rating %>% filter(group == 2) %>% head(10))

feature frequency rank docfreq group

1 quality 2 1 1 2

2 product 1 2 1 2

3 poor 1 2 1 2

4 disappointed 1 2 1 2

5 price 1 2 1 2

6 high 1 2 1 2

7 received 1 2 1 2

1# Trực quan hóa so sánh
2freq_by_rating %>%
3  filter(group %in% c(2, 5)) %>%
4  group_by(group) %>%
5  slice_max(frequency, n = 8) %>%
6  ungroup() %>%
7  mutate(feature = reorder_within(feature, frequency, group)) %>% 
8  ggplot(aes(x = feature, y = frequency, fill = factor(group))) +
9  geom_col(show.legend = FALSE) +
10  facet_wrap(~ group, scales = "free_y", labeller = labeller(group = c("2" = "Đánh Giá 2 Sao", "5" = "Đánh Giá 5 Sao"))) +
11  scale_x_reordered() +
12  coord_flip() +
13  labs(title = "Các Thuật Ngữ Hàng Đầu Theo Xếp Hạng Đánh Giá",
14       x = "Thuật Ngữ",
15       y = "Tần Suất") +
16  theme_minimal()

Đám Mây Từ: Khám Phá Trực Quan

Đám mây từ cung cấp hình ảnh trực quan trực quan về tần suất thuật ngữ:

1# Tạo đám mây từ
2set.seed(123)
3textplot_wordcloud(reviews_dfm, 
4                   min_count = 1,
5                   max_words = 50,
6                   rotation = 0.25,
7                   color = RColorBrewer::brewer.pal(8, "Dark2"))

N-grams: Các Biểu Thức Nhiều Từ

N-grams là các chuỗi N tokens liên tiếp. Bigrams (2-grams) và trigrams (3-grams) nắm bắt các biểu thức và cụm từ nhiều từ mà các từ đơn lẻ bỏ qua.

1# Tạo văn bản mẫu để phân tích N-gram
2ngram_text <- c(
3  "Machine learning and artificial intelligence are transforming data science.",
4  "Natural language processing enables text analytics at scale.",
5  "Deep learning models achieve state of the art results.",
6  "Data science requires domain knowledge and technical skills.",
7  "Text mining extracts insights from unstructured data."
8)
9ngram_corp <- corpus(ngram_text)
10# Tạo bigrams
11bigrams <- ngram_corp %>%
12  tokens(remove_punct = TRUE) %>%
13  tokens_tolower() %>%
14  tokens_ngrams(n = 2) %>%
15  dfm()
16# Tính toán tần suất bigram
17bigram_freq <- textstat_frequency(bigrams)
18head(bigram_freq, 15)

feature frequency rank docfreq group

1 data_science 2 1 2 all

2 machine_learning 1 2 1 all

3 learning_and 1 2 1 all

4 and_artificial 1 2 1 all

5 artificial_intelligence 1 2 1 all

6 intelligence_are 1 2 1 all

7 are_transforming 1 2 1 all

8 transforming_data 1 2 1 all

9 natural_language 1 2 1 all

10 language_processing 1 2 1 all

11 processing_enables 1 2 1 all

12 enables_text 1 2 1 all

13 text_analytics 1 2 1 all

14 analytics_at 1 2 1 all

15 at_scale 1 2 1 all

1# Trực quan hóa các bigrams hàng đầu
2bigram_freq %>%
3  head(10) %>%
4  ggplot(aes(x = reorder(feature, frequency), y = frequency)) +
5  geom_col(fill = "indianred") +
6  coord_flip() +
7  labs(title = "10 Bigrams Hàng Đầu",
8       x = "Bigram",
9       y = "Tần Suất") +
10  theme_minimal()
1# Tạo trigrams
2trigrams <- ngram_corp %>%
3  tokens(remove_punct = TRUE) %>%
4  tokens_tolower() %>%
5  tokens_ngrams(n = 3) %>%
6  dfm()
7# Tính toán tần suất trigram
8trigram_freq <- textstat_frequency(trigrams)
9# Trực quan hóa các bigrams hàng đầu
10trigram_freq %>%
11  head(10) %>%
12  ggplot(aes(x = reorder(feature, frequency), y = frequency)) +
13  geom_col(fill = "steelblue") +
14  coord_flip() +
15  labs(title = "10 Trigrams Hàng Đầu",
16       x = "Trigram",
17       y = "Tần Suất") +
18  theme_minimal()

Ví Dụ Thực Tế: Phân Tích Phản Hồi Khách Hàng

Hãy thử áp dụng các kỹ thuật này vào một kịch bản thực tế hơn.

1# Tạo một tập dữ liệu phản hồi khách hàng thực tế
2set.seed(456)
3feedback_df <- data.frame(
4  text = c(
5    "Absolutely love this product! Best purchase I've made all year. Quality is outstanding.",
6    "Terrible experience. Product broke after one week. Customer service was unhelpful.",
7    "Good value for the price. Works as expected. Would buy again.",
8    "Shipping took forever. Product is okay but not worth the wait.",
9    "Amazing quality and fast delivery. Highly recommend to everyone!",
10    "Product description was misleading. Not what I expected at all.",
11    "Decent product but customer support needs improvement. Long wait times.",
12    "Exceeded my expectations! Great features and easy to use.",
13    "Poor quality control. Received damaged item. Return process was difficult.",
14    "Perfect! Exactly what I needed. Five stars all around.",
15    "Overpriced for what you get. Better alternatives available elsewhere.",
16    "Good product but instructions were confusing. Setup took hours.",
17    "Love it! Works perfectly and looks great too.",
18    "Not satisfied. Product feels cheap and flimsy.",
19    "Best customer service ever! They resolved my issue immediately.",
20    "Average product. Nothing special but gets the job done.",
21    "Fantastic! Will definitely purchase from this company again.",
22    "Disappointed with the quality. Expected much better.",
23    "Great features but battery life is poor.",
24    "Excellent value. Highly recommend for budget shoppers."
25  ),
26  rating = c(5, 1, 4, 2, 5, 1, 3, 5, 1, 5, 2, 3, 5, 2, 5, 3, 5, 2, 3, 4),
27  category = sample(c("Electronics", "Home & Kitchen", "Clothing"), 20, replace = TRUE),
28  helpful_votes = sample(0:50, 20, replace = TRUE),
29  stringsAsFactors = FALSE
30)
31# Tạo corpus
32feedback_corp <- corpus(feedback_df, text_field = "text")
33# Hoàn thành quy trình tiền xử lý
34feedback_dfm <- feedback_corp %>%
35  tokens(remove_punct = TRUE, 
36         remove_numbers = TRUE,
37         remove_symbols = TRUE) %>%
38  tokens_tolower() %>%
39  tokens_remove(stopwords("english")) %>%
40  tokens_wordstem() %>%
41  dfm()
42# Phân tích các thuật ngữ liên quan đến cảm xúc tổng thể
43sentiment_terms <- c("love", "best", "great", "excel", "amaz", "perfect", 
44                     "terribl", "poor", "worst", "disappoint", "bad")
45sentiment_dfm <- dfm_select(feedback_dfm, pattern = sentiment_terms)
46# Tính toán tần suất thuật ngữ cảm xúc
47sentiment_freq <- textstat_frequency(sentiment_dfm)
48# Trực quan hóa các thuật ngữ cảm xúc
49ggplot(sentiment_freq, aes(x = reorder(feature, frequency), y = frequency)) +
50  geom_col(aes(fill = feature), show.legend = FALSE) +
51  coord_flip() +
52  labs(title = "Tần Suất Các Thuật Ngữ Liên Quan Đến Cảm Xúc",
53       subtitle = "Phân Tích Phản Hồi Khách Hàng",
54       x = "Thuật Ngữ (Đã Gọt Từ)",
55       y = "Tần Suất") +
56  theme_minimal() +
57  scale_fill_manual(values = c(
58    "love" = "darkgreen", "best" = "darkgreen", "great" = "darkgreen",
59    "excel" = "darkgreen", "amaz" = "darkgreen", "perfect" = "darkgreen",
60    "terribl" = "darkred", "poor" = "darkred", "worst" = "darkred",
61    "disappoint" = "darkred", "bad" = "darkred"
62  ))
1# So sánh các đánh giá cao và thấp
2# Tạo biến danh mục xếp hạng
3rating_category <- ifelse(docvars(feedback_corp, "rating") >= 4, "High Rating", "Low Rating")
4feedback_grouped <- feedback_corp %>%
5  tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
6  tokens_tolower() %>%
7  tokens_remove(stopwords("english")) %>%
8  dfm() %>%
9  dfm_group(groups = rating_category)
10# Tính toán độ đặc trưng của từ
11keyness_stats <- textstat_keyness(feedback_grouped, target = "High Rating")
12# Trực quan hóa độ đặc trưng của từ
13textplot_keyness(keyness_stats, n = 10, color = c("darkgreen", "darkred")) +
14  labs(title = "Các Thuật Ngữ Đặc Trưng: Đánh Giá Cao so với Đánh Giá Thấp") +
15  theme_minimal()

Phân Tích Độ Tương Đồng Tài Liệu

Hiểu độ tương đồng của tài liệu là rất quan trọng cho các tác vụ như phát hiện trùng lặp, phân cụm tài liệu và hệ thống đề xuất:

1# Sử dụng DFM đã tiền xử lý để đo lường độ tương đồng tốt hơn
2feedback_dfm_clean <- feedback_corp %>%
3  tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
4  tokens_tolower() %>%
5  tokens_remove(stopwords("english")) %>%
6  tokens_wordstem() %>%
7  dfm()
8# Tính toán độ tương đồng tài liệu bằng độ tương đồng cosin
9doc_similarity <- textstat_simil(feedback_dfm_clean, 
10                                 method = "cosine",
11                                 margin = "documents")
12# Tìm các tài liệu tương đồng nhất với đánh giá đầu tiên (một đánh giá tích cực)
13similarity_df <- as.data.frame(as.matrix(doc_similarity))
14similarity_to_doc1 <- sort(as.numeric(similarity_df[1, ]), decreasing = TRUE)[2:6]  # Bỏ qua tài liệu đầu tiên (chính nó)
15# Tài liệu đánh giá đầu tiên
16as.character(feedback_corp)[1]

text1

"Absolutely love this product! Best purchase I've made all year. Quality is outstanding."

1# 3 tài liệu tương đồng hàng đầu
2for(i in 2:4) {
3  doc_idx <- order(as.numeric(similarity_df[1, ]), decreasing = TRUE)[i]
4  cat("\nDocument", doc_idx, "(Similarity:", round(similarity_df[1, doc_idx], 3), "):\n")
5  cat(as.character(feedback_corp)[doc_idx], "\n")
6}

Document 6 (Similarity: 0.167 ):

Product description was misleading. Not what I expected at all.

Document 17 (Similarity: 0.167 ):

Fantastic! Will definitely purchase from this company again.

Document 13 (Similarity: 0.149 ):

Love it! Works perfectly and looks great too.

Cần lưu ý rằng độ tương đồng cosin đơn thuần có thể không đủ vì tài liệu tương đồng hàng đầu không khớp với cảm xúc của tài liệu gốc.

Độ Tương Đồng Có Nhận Thức Về Cảm Xúc

Để cải thiện việc đánh giá độ tương đồng, chúng ta có thể kết hợp điểm cảm xúc. Hãy thêm điểm cảm xúc như một đặc trưng.

1# Định nghĩa từ điển cảm xúc tích cực và tiêu cực
2positive_words <- c("love", "best", "great", "excellent", "amazing", "perfect", 
3                    "fantastic", "outstanding", "happy", "wonderful", "superb")
4negative_words <- c("terrible", "poor", "worst", "disappointing", "bad", "awful",
5                    "horrible", "useless", "disappointed", "misleading", "cheap")
6# Tạo tokens
7feedback_toks <- feedback_corp %>%
8  tokens(remove_punct = TRUE, remove_numbers = TRUE) %>%
9  tokens_tolower() %>%
10  tokens_remove(stopwords("english"))
11# Tính toán điểm cảm xúc cho mỗi tài liệu
12sentiment_scores <- sapply(feedback_toks, function(doc_tokens) {
13  pos_count <- sum(doc_tokens %in% positive_words)
14  neg_count <- sum(doc_tokens %in% negative_words)
15  # Điểm cảm xúc ròng
16  (pos_count - neg_count) / length(doc_tokens)
17})
18# Tạo DFM với các đặc trưng cảm xúc
19feedback_dfm_sentiment <- feedback_toks %>%
20  tokens_wordstem() %>%
21  dfm()
22# Thêm điểm cảm xúc như một đặc trưng có trọng số
23# Tạo một đặc trưng cảm xúc bằng cách nhân đôi điểm cảm xúc
24sentiment_feature_matrix <- matrix(sentiment_scores * 10,  # Tăng tỷ lệ để dễ thấy
25                                   nrow = ndoc(feedback_dfm_sentiment),
26                                   ncol = 1,
27                                   dimnames = list(docnames(feedback_dfm_sentiment), 
28                                                   "SENTIMENT_SCORE"))
29# Kết hợp với DFM gốc
30feedback_dfm_with_sentiment <- cbind(feedback_dfm_sentiment, sentiment_feature_matrix)
31# Tính toán độ tương đồng với cảm xúc
32doc_similarity_sentiment <- textstat_simil(feedback_dfm_with_sentiment,
33                                           method = "cosine",
34                                           margin = "documents")
35# So sánh kết quả
36similarity_df_sentiment <- as.data.frame(as.matrix(doc_similarity_sentiment))
37# Độ tương đồng tiêu chuẩn so với độ tương đồng có nhận thức về cảm xúc
38# Tài liệu đầu tiên
39cat(as.character(feedback_corp)[1], "\n")

Absolutely love this product! Best purchase I've made all year. Quality is outstanding.

1# Độ tương đồng có nhận thức về cảm xúc
2for(i in 2:4) {
3  doc_idx <- order(as.numeric(similarity_df_sentiment[1, ]), decreasing = TRUE)[i]
4  cat("\nDocument", doc_idx, "(Similarity:", round(similarity_df_sentiment[1, doc_idx], 3), "):\n")
5  cat(as.character(feedback_corp)[doc_idx], "\n")
6  cat("Rating:", docvars(feedback_corp, "rating")[doc_idx], 
7      "| Sentiment:", round(sentiment_scores[doc_idx], 3), "\n")
8}

Document 13 (Similarity: 0.697 ):

Love it! Works perfectly and looks great too.

Rating: 5 | Sentiment: 0.4

Document 17 (Similarity: 0.65 ):

Fantastic! Will definitely purchase from this company again.

Rating: 5 | Sentiment: 0.25

Document 5 (Similarity: 0.427 ):

Amazing quality and fast delivery. Highly recommend to everyone!

Rating: 5 | Sentiment: 0.143

Phân Tích Đồng Xuất Hiện Đặc Trưng

Hiểu những từ nào thường xuất hiện cùng nhau có thể giúp tiết lộ các mối quan hệ ngữ nghĩa.

1# Tạo ma trận đồng xuất hiện đặc trưng (FCM)
2fcm <- feedback_corp %>%
3  tokens(remove_punct = TRUE) %>%
4  tokens_tolower() %>%
5  tokens_remove(stopwords("english")) %>%
6  fcm()
7# Xem các đồng xuất hiện hàng đầu
8feat_cooc <- fcm[1:20, 1:20]
9# Trực quan hóa mạng lưới ngữ nghĩa
10set.seed(123)
11textplot_network(fcm, 
12                 min_freq = 2,
13                 edge_alpha = 0.5,
14                 edge_size = 2,
15                 vertex_labelsize = 3) +
16  labs(title = "Mạng Lưới Ngữ Nghĩa Phản Hồi Khách Hàng")

Thao Tác Và Chuyển Đổi DFM

`quanteda` cung cấp các hàm mạnh mẽ để thao tác DFM:

1# Cắt tỉa DFM để loại bỏ các đặc trưng hiếm và rất phổ biến
2feedback_dfm_trimmed <- dfm_trim(feedback_dfm,
3                                 min_termfreq = 2,  # Loại bỏ các thuật ngữ xuất hiện < 2 lần
4                                 max_docfreq = 0.8,  # Loại bỏ các thuật ngữ xuất hiện trong > 80% tài liệu
5                                 docfreq_type = "prop")
6# Kích thước DFM gốc
7print(dim(feedback_dfm))

[1] 20 95

1# Kích thước DFM đã cắt tỉa
2print(dim(feedback_dfm_trimmed))

[1] 20 22

1# Trọng số DFM sử dụng TF-IDF
2feedback_tfidf <- dfm_tfidf(feedback_dfm_trimmed)
3# Các đặc trưng hàng đầu theo TF-IDF
4tfidf_freq <- textstat_frequency(feedback_tfidf, force = T)
5print(head(tfidf_freq, 15))

feature frequency rank docfreq group

1 product 3.183520 1 8 all

2 qualiti 2.795880 2 4 all

3 expect 2.795880 2 4 all

4 custom 2.471726 4 3 all

5 great 2.471726 4 3 all

6 love 2.000000 6 2 all

7 best 2.000000 6 2 all

8 purchas 2.000000 6 2 all

9 servic 2.000000 6 2 all

10 good 2.000000 6 2 all

11 valu 2.000000 6 2 all

12 work 2.000000 6 2 all

13 took 2.000000 6 2 all

14 wait 2.000000 6 2 all

15 high 2.000000 6 2 all

1# Chọn các đặc trưng cụ thể
2service_terms <- c("service", "support", "help", "response", "customer")
3service_dfm <- dfm_select(feedback_dfm, pattern = service_terms)
4# Tần suất các thuật ngữ liên quan đến dịch vụ
5print(colSums(service_dfm))

support

1

1# Loại bỏ các đặc trưng cụ thể
2filtered_dfm <- dfm_remove(feedback_dfm, pattern = c("product", "item"))
3# Số lượng đặc trưng gốc
4nfeat(feedback_dfm)

[1] 95

1# Số lượng đặc trưng đã lọc
2nfeat(filtered_dfm)

[1] 93

✨ Giá trị đắt giá

Phần 1 của chuỗi bài viết này đã trang bị cho bạn những công cụ cần thiết để bắt đầu hành trình phân tích văn bản trong R với gói `quanteda`. Bạn đã học cách:

* Xây dựng `corpus` từ nhiều nguồn dữ liệu.

* Thực hiện các bước tiền xử lý văn bản thiết yếu như token hóa, loại bỏ từ dừng và gọt từ.

* Tạo và thao tác ma trận tài liệu-đặc trưng (DFM) để biến văn bản thành dữ liệu số.

* Khám phá tần suất từ, phân tích theo nhóm và trực quan hóa dữ liệu văn bản bằng đám mây từ.

* Áp dụng N-grams để nắm bắt các biểu thức nhiều từ.

* Thực hiện phân tích độ tương đồng tài liệu cơ bản và nâng cao có nhận thức về cảm xúc.

* Khám phá ma trận đồng xuất hiện đặc trưng (FCM) để hiểu mối quan hệ giữa các từ.

* Thực hiện các thao tác DFM nâng cao như cắt tỉa và trọng số TF-IDF.

Những kỹ năng này là nền tảng cho bất kỳ dự án khoa học dữ liệu văn bản nào, mở ra cánh cửa cho những phân tích phức tạp hơn.

Câu hỏi tư duy hoặc bài tập ứng dụng

1. Dựa trên kiến thức về tiền xử lý văn bản, hãy thảo luận khi nào việc loại bỏ các từ dừng hoặc áp dụng gọt từ có thể không phù hợp cho một tác vụ phân tích cụ thể (ví dụ: phân tích văn phong, phân tích cảm xúc dựa trên ngữ cảnh).

2. Hãy thử tìm một tập dữ liệu văn bản công khai (ví dụ: bình luận phim, tiêu đề tin tức) và áp dụng quy trình tiền xử lý đầy đủ mà bạn đã học. Sau đó, tạo biểu đồ 15 từ phổ biến nhất và 10 bigram phổ biến nhất.


Bài viết khác
Trong bài viết trước, chúng ta đã khám phá ba phương pháp cơ bản để thực thi mã Python trực tiếp trong Stata. Mặc dù các ví dụ ban đầu khá đơn giản, chúng đã tạo nền tảng vững chắc để bạn bắt đầu kết hợp hai công cụ này. Tuy nhiên, sức mạnh thực sự của Python lại đến từ hệ sinh thái hàng nghìn thư viện mã nguồn mở phong phú. Bài viết này sẽ hướng dẫn bạn chi tiết cách quản lý, tải xuống và cài đặt các thư viện Python để mở rộng tối đa khả năng xử lý dữ liệu trong Stata. Kiểm tra cấu hình Python trong Stata Trước khi tiến hành cài đặt các gói mở rộng, chúng ta cần xác nhận rằng Python đã được tích hợp chính xác vào hệ thống và Stata đã sẵn sàng làm việc với môi trường này. Từ cửa sổ lệnh của Stata, bạn hãy chạy lệnh kiểm tra cấu hình:
Khi trình bày kết quả nghiên cứu, việc tạo ra các bảng biểu trực quan và đúng chuẩn xuất bản là tiêu chí vô cùng quan trọng. Trong các phiên bản Stata trước đây, việc định dạng bảng thường đòi hỏi nhiều thao tác thủ công hoặc chỉnh sửa lại trên các phần mềm xử lý văn bản. Stata 17 đã giải quyết triệt để thách thức này bằng hệ thống lệnh collect, cho phép người dùng tùy biến toàn bộ cấu trúc, nhãn hiển thị, đường viền và xuất bảng trực tiếp sang các định dạng tài liệu phổ biến. Khởi đầu với bảng thống kê cơ bản Để hiểu rõ cơ chế hoạt động của collect, hãy bắt đầu bằng việc tạo một bảng thống kê mô tả cơ bản kết hợp giữa hai biến số giới tính và huyết áp cao. Lệnh table dưới đây thu thập các thông số bao gồm tần suất, tỷ lệ phần trăm, giá trị trung bình và độ lệch chuẩn của tuổi tác.
SciEco
Science for Economics
Định hướng đào tạo phân tích dữ liệu, xây dựng chính sách, tối ưu hoá danh mục tài chính cá nhân và dự báo thị trường.
Liên hệ
Địa chỉ: Số 60, ngõ 41, Phố Thái Hà, Trung Liệt, Đống Đa, Hà Nội (Google Map)
Email: science.for.economics@gmail.com
Hotline: 03.57.94.7680 (Mrs. Hà)
Mạng xã hội