knitr::opts_chunk$set(
message = FALSE,
warning = FALSE,
fig.align = "center",
comment = "#>"
)
Di zaman sekarang, terdapat miliaran konten teks yang dihasilkan dari berbagai sumber seperti WhatsApp, Telegram, situs media sosial seperti Facebook, Instagram, situs penerbit berita, pencarian Google, dan lainnya. Semua sumber ini secara terus menerus menghasilkan volume data teks yang sangat besar setiap detik. Dan karena volume data teks yang besar ini, NLP (Natural Language Processing) menjadi sumber daya yang sangat penting dalam memahami konten teks. Dalam analisis ini berfokus pada Analisis Sentimen dari suatu situs penjualanan dari postingan media sosial.
Analisis Sentimen merupakan pengolahan data yang memikiki konteks sebuah teks yang mengidentifikasi dan mengekstrak informasi subjektif dalam data teks. Analisis Sentimen terbukti menjadi aset yang luar biasa bagi pengguna untuk mengekstrak informasi penting. Dalam kasus ini, akan dilakukan beberapa metode sentimen analisis yaitu (loughran, Afinn, dan Bing).
Dataset yang digunakan yaitu berupa data product review sebuah Clothing Product dari situs Amazone. Dataset ini menawarkan keragaman perspektif dan opini. Data ini didapatkan dari Kaggle (https://www.kaggle.com/datasets/willianoliveiragibin/review-of-clothing-product).
library(dplyr)
library(tm)
library(ggplot2)
library(plotly)
library(SnowballC)
library(wordcloud)
library(gridExtra)
library(RColorBrewer)
library(syuzhet)
library(tidytext)
library(forcats)
library(tidyverse)
library(textdata)
library(tibble)
data <- read.csv("data_input/product.csv")
head(data)
glimpse(data)
#> Rows: 48,559
#> Columns: 3
#> $ Review <chr> "Absolutely wonderful - silky and sexy and comfortable", "…
#> $ Cons_rating <int> 4, 5, 3, 5, 5, 2, 5, 4, 5, 5, 3, 5, 5, 5, 3, 4, 3, 5, 5, 5…
#> $ Cloth_class <chr> "Intimates", "Dresses", "Dresses", "Pants", "Blouses", "Dr…
Dari output di atas, kita dapat melihat bahwa dataset ini memiliki 3 kolom dan 48.559 observasi.
colSums(is.na(data))
#> Review Cons_rating Cloth_class
#> 0 0 0
Dalam dataset di atas, tidak ditemukan missing value dari semua kolom.
Sebelum melakukan analisis, langkah pertama adalah melakukan data
cleaning dengan mengubah data sesuai dengan kebutuhan. Dalam data teks,
kita sering menemukan karakter khusus, spasi kosong, atau kata-kata umum
(stop words). Disarankan untuk dihapus karena hal tersebut tidak
memberikan nilai tambah pada proses analisis. Kita dapat melakukan
langkah ini satu per satu menggunakan fungsi unnest_tokens
untuk menghapus spasi kosong, tanda baca, dan mengubah teks menjadi
huruf kecil, dan lain-lain.
# using unnest_tokens()
data_review <- data %>%
unnest_tokens(word, Review) # What to create (word) from where (Review) column
head(data_review)
Fungsi unnest_tokens() telah melakukan beberapa
pembersihan data teks, seperti menghapus tanda baca dan spasi kosong,
serta mengubah teks menjadi huruf kecil, dan lain-lain. Seperti yang
terlihat pada output di atas, setiap baris hanya berisi satu kata, yaitu
satu kata per baris. Karena ini adalah dataset yang sangat besar, kita
bisa melihat jumlah total baris dengan menggunakan fungsi
dim().
dim(data_review)
#> [1] 2062753 3
Secara total, kita memiliki 2,062,753 baris. Mari kita hitung jumlah kata dan urutkan dalam urutan menurun untuk melihat kata-kata mana yang lebih sering muncul.
# counting words
data_review %>%
count(word) %>%
arrange(desc(n)) %>%
head()
Dari hasil diatas masih terdapat beberapa kata umum seperti “the,”
“and,” “to,” “a,” dan sebagainya yang sering muncul. Untuk menganalisis
penggunaan kata yang unik dari seseorang, perlu dilakukan penghapusan
kata-kata tersebut yaitu dengan menggunakan anti_join
terhadap daftar kata berhenti (stop words) dari tidy text.
# using unnest_tokens() with stopwords
data_review2 <- data %>%
unnest_tokens(word, Review) %>%
anti_join(stop_words)
Selanjutnya akan dilakukan perhitungan kata-kata kembali untuk memastikan apakah funsi diatas telah berhasil menyelesaikan masalah tersebut.
# counting words again
data_review2 %>%
count(word) %>%
arrange(desc(n)) %>%
head()
Dari output di atas, dapat dilihat bahwa sekarang kata-kata yang paling sering muncul adalah “fit,” “size,” “dress,” dan “love,” yang sebenarnya mencerminkan konten yang sesuai dengan dataset ini.
Dengan melakukan proses EDA kita dapat mengetahui informasi secara umum dari dataset yang digunakan dalam bentuk visualisasi yang lebih mudah dipahami.
ggplot(data = data_review2, aes(x = Cons_rating)) +
geom_histogram(fill = "#9acd32", color = "white", binwidth = 0.5) +
labs(title = "Distribusi Rating Produk",
x = "Rating",
y = "Frekuensi") +
theme(plot.title = element_text(hjust = 0.5, size = 14, face = "bold"),
axis.title.x = element_text(size = 14),
axis.title.y = element_text(size = 14),
axis.text = element_text(size = 12),
axis.text.x = element_text(angle = 0, hjust = 1))
data$Cons_rating <- as.numeric(data$Cons_rating)
nude_green <- "#9acd32"
# Create box plot
plot1 <- ggplot(data_review2, aes(x = factor(1), y = Cons_rating, fill = "Rating")) +
geom_boxplot() +
labs(title = "Distribusi Rating Produk",
x = NULL,
y = "Rating") +
theme(axis.text.x = element_blank(),
legend.position = "none") +
scale_fill_manual(values = nude_green)
# Arrange the plots side by side
grid.arrange(plot1, ncol = 2)
Insight :
Sebagian besar produk memiliki Rating (3 hingga 5). Ini menunjukkan bahwa sebagian besar produk yang di review cenderung memiliki kualitas dan performa yang baik, sehingga mendapatkan rating yang tinggi dari pengguna.
category_freq <- data_review2 %>%
group_by(Cloth_class) %>%
summarise(frequency = n()) %>%
arrange(desc(frequency)) %>%
head(10)
# Visualisasi frekuensi kategori produk
ggplot(data = category_freq, aes(x = reorder(Cloth_class, -frequency), y = frequency, fill = Cloth_class)) +
geom_bar(stat = "identity") +
labs(title = "Frekuensi Kategori Produk",
x = "Cloth_class",
y = "Frequency")
Insight :
Kategori Dress, Blouses, dan Knits adalah kategori pakaian paling populer di platform Amazon. Informasi ini dapat membantu dalam mengidentifikasi preferensi pelanggan dan mengoptimalkan strategi pemasaran untuk setiap kategori produk.
# Count words and filter
word_counts <- data_review2 %>%
count(word) %>%
filter(n > 300) %>%
arrange(desc(n))
# Use head() to get the top 10 rows before plotting
top_words <- head(word_counts, 10)
# Create the plot
ggplot(data = top_words, aes(x = reorder(word, n), y = n)) +
geom_col() +
coord_flip() +
ggtitle("Review Word Counts") +
xlab("Word") +
ylab("Frequency")
Insights :
Kata “fit” muncul hampir 15.000 kali, menunjukkan banyak review yang membahas kesesuaian produk saat dipakai.
Kata “size” muncul sekitar 13.000 kali, menunjukkan ukuran pakaian yang dibeli.
Kata “dress”, muncul lebih dari 12.000 kali, menunjukkan kualitas dress dari toko pakaian, di mana dress adalah produk yang paling sering dibeli.
Kata “love” muncul lebih dari 12.000 kali, menggambarkan banyak review yang memberikan komentar positif tentang kualitas produk.
Data ini dapat memberikan wawasan tentang sentimen dan preferensi pelanggan terhadap produk tertentu serta membantu memahami dan meningkatkan kualitas produk dan layanan yang ditawarkan.
rat_5 <- data[data$Cons_rating == 5, ]
wordcloud(rat_5$Review, max.words = 10, scale = c(2.5, 1.25), colors = brewer.pal(8, "Dark2"),rot.per=0.5, random.order = FALSE)
Insight :
Dari visualisasi di atas, untuk review dengan rating “5”, terdapat kata-kata yang sering muncul seperti love, great, perfect, like, dan comfortable. Ini menunjukkan bahwa ada ulasan positif mengenai kualitas bahan pakaian, kecocokan ukuran pakaian saat dipakai, dan kualitas kain dari pakaian yang diproduksi.
rat_1 <- data[data$Cons_rating == 1, ]
wordcloud(rat_1$Review, max.words = 10, scale = c(2.5, 1.25), colors = brewer.pal(8, "Dark2"),rot.per=0.5, random.order = FALSE)
Insight :
Dari visualisasi di atas, untuk ulasan dengan peringkat rendah “1”, terdapat kata-kata yang sering muncul seperti like, material, fabric, sizefit, dan lain-lain. Ini menunjukkan bahwa ada ulasan negatif mengenai kualitas bahan pakaian, kecocokan ukuran pakaian saat dipakai, dan kualitas kain dari pakaian yang diproduksi.
Sekarang setelah melakukan proses data cleaning, transformasi, dan visualisasi secara umum, selanjutnya beralih ke analisis sentimen. Analisis sentimen adalah cara efektif untuk memahami opini tentang suatu topik tertentu. Ini sangat berguna untuk analisis pasar, umpan balik pelanggan, dan product review. Sentiment Analysis dapat dilakukan pada berbagai tingkat cakupan, seperti tingkat dokumen teks, tingkat kalimat, dan tingkat sub-kalimat.
Sentiment Analysis dapat dimodelkan sebagai masalah klasifikasi di mana dua sub-masalah ditangani: Klasifikasi subjektivitas (mengklasifikasikan kalimat sebagai subjektif atau objektif) dan klasifikasi polaritas (mengklasifikasikan kalimat sebagai positif, netral, atau negatif).
Kita akan memulai dengan menggunakan leksikon sentimen Loughran. Metode ini membantu dalam memahami bagaimana kata-kata tertentu mempengaruhi sentimen keseluruhan dari teks. Ini berguna dalam analisis pasar, product review, dan dokumen bisnis untuk mengidentifikasi perasaan dan opini yang tersirat dalam teks. Leksikon ini akan memberikan label kata-kata dengan enam sentimen, yaitu “negative”, “positive”, “litigious”, “uncertainty”, “constraining”, dan “superfluous”.
Dengan menggunakan leksikon Loughran, analisis sentimen menjadi lebih terfokus pada kata-kata yang memiliki arti khusus dalam konteks analisis, sehingga memberikan wawasan yang lebih mendalam tentang sentimen yang terkait dengan aspek tertentu dari teks.
# inner_join()
data_review %>%
inner_join(get_sentiments("loughran")) %>% head()
# counting sentiment
sentiment_review <- data_review %>%
inner_join(get_sentiments("loughran"))
sentiment_review %>%
count(sentiment)
Dapat dilihat pada output di atas bahwa jumlah kata telah berkurang
secara drastis karena inner_join hanya menyisakan kata-kata
yang ada dalam kamus Loughran. Sekarang, mari kita hitung kata-kata yang
paling sering muncul untuk setiap sentimen yang diberikan.
sentiment_review %>%
count(word, sentiment) %>%
arrange(desc(n)) %>% head()
Kita dapat memplot sentimen-sentimen tersebut dan melihat berapa kali setiap sentimen muncul.
sentiment_counts <- get_sentiments("loughran") %>%
count(sentiment) %>%
mutate(sentiment2 = fct_reorder(sentiment, n))
ggplot(sentiment_counts, aes(x=sentiment2, y=n)) +
geom_col() +
coord_flip() +
labs(
title = "Sentiment Counts in Loughran",
x = "Counts",
y = "Sentiment"
)
Hasil barplot di atas menunjukkan bahwa sentimen negatif paling sering muncul. Namun, untuk mempertahankan semua sentimen, lebih baik menyederhanakan analisis kita dengan hanya mempertimbangkan sentimen positif dan negatif. Dengan cara ini, kita dapat melihat kata-kata mana yang dianggap sebagai sentimen positif dan kata-kata mana yang dianggap sebagai sentimen negatif.
sentiment_review2 <- sentiment_review %>%
filter(sentiment %in% c("positive", "negative"))
word_counts <- sentiment_review2 %>%
count(word, sentiment) %>%
group_by(sentiment) %>%
top_n(10, n) %>%
ungroup() %>%
mutate(
word2 = fct_reorder(word, n)
)
# visualization
ggplot(word_counts, aes(x=word2, y=n, fill=sentiment)) +
geom_col(show.legend=FALSE) +
facet_wrap(~sentiment, scales="free") +
coord_flip() +
labs(
title = "Sentiment Word Counts loughran",
x = "Words"
)
Dari hasil sentiment analysis dengan “loughran” kita sudah bisa mendapatkan kata-kata mana yang mengandung sentimen positif maupun sentimen negatif.
Selanjutnya, akan dilakukan sentimenet analysis dengan mencoba metode AFINN & Bing. Leksikon AFINN adalah alat yang digunakan dalam analisis sentimen untuk memberi skor pada kata-kata dalam teks. Leksikon AFINN memberikan skor pada kata-kata yang berkisar antara -5 hingga 5, di mana skor negatif menunjukkan sentimen negatif dan skor positif menunjukkan sentimen positif.
# Sentiment Analysis using afinn ----
# counting sentiment
sentiment_review_afinn <- data_review %>%
inner_join(get_sentiments("afinn"))
sentiment_review_afinn %>%
count(value)
Dari hasil diatas untuk skor pada kata-kata dalam teks memiliki rentang skor antara -4 hingga 5.
# count what words are most often
# for a given sentiment
sentiment_review_afinn %>%
count(word, value) %>%
arrange(desc(n)) %>% head()
# filter sentiment review
# and keep only sentiment words
# that are strongly positive or negative
sentiment_review_afinn2 <- sentiment_review_afinn %>%
filter(value %in% c("5", "-4"))
word_counts_afinn2 <- sentiment_review_afinn2 %>%
count(word, value) %>%
group_by(value) %>%
top_n(10, n) %>%
ungroup() %>%
mutate(
word2 = fct_reorder(word, n)
)
# visualize the sentiment
ggplot(word_counts_afinn2, aes(x=word2, y=n, fill=value)) +
geom_col(show.legend=FALSE) +
facet_wrap(~value, scales="free") +
coord_flip() +
labs(
title = "Sentiment Word Counts Afinn",
x = "Words"
)
Kita bahkan dapat memfilter dan melihat kata-kata yang telah diberi skor 4, -4, 5, dan -5.
# Let's try with 4 -4, 5,
sentiment_review_afinn4 <- sentiment_review_afinn %>%
filter(value %in% c("4", "-4", "5"))
word_counts_afinn4 <- sentiment_review_afinn4 %>%
count(word, value) %>%
group_by(value) %>%
top_n(10, n) %>%
ungroup() %>%
mutate(
word2 = fct_reorder(word, n)
)
# visualize the sentiment
ggplot(word_counts_afinn4, aes(x=word2, y=n, fill=value)) +
geom_col(show.legend=FALSE) +
facet_wrap(~value, scales="free") +
coord_flip() +
labs(
title = "Sentiment Word Counts Afinn",
x = "Words"
)
Dari hasil barplot di atas Kita dapat melihat kata-kata yang telah diberi label sebagai sentimen positif atau negatif berdasarkan skornya.
Selain mempertimbangkan kata-kata untuk melakukan analisis sentimen, kita juga bisa mendapatkan sentimen berdasarkan peringkat. Pada dataset ini juga customers telah memberikan rating dari 1 hingga 5. Jadi, kita akan menghitung sentimen berdasarkan peringkat dengan menggunakan metode Bing.
# count sentiment by rating
data_review %>%
inner_join(get_sentiments("bing")) %>%
count(Cons_rating, sentiment)
Dapat dilihat dari output di atas bahwa untuk setiap peringkat, terdapat sentimen positif dan negatif. Akan dipisahkan menjadi dua kategori yang berbeda dan kemudian akan dihitung skor sentimen secara keseluruhan untuk setiap peringkat dengan mengambil selisih antara sentimen positif dan negatif.
# summary
# using spread()
data_review %>%
inner_join(get_sentiments("bing")) %>%
count(Cons_rating, sentiment) %>%
spread(sentiment, n)
# compute overall sentiment
data_review %>%
inner_join(get_sentiments("bing")) %>%
count(Cons_rating, sentiment) %>%
spread(sentiment, n) %>%
mutate(overall_sentiment = positive - negative)
Berikut dibawah ini hasil visualisasi skor sentimen keseluruhan terhadap peringkat.
# Visualize sentiment by rating
sentiment_stars <- data_review %>%
inner_join(get_sentiments("bing")) %>%
count(Cons_rating, sentiment) %>%
spread(sentiment, n) %>%
mutate(
overall_sentiment = positive - negative,
rating = fct_reorder(as.factor(Cons_rating), overall_sentiment)
)
# visualize sentiment by rating
ggplot(
sentiment_stars, aes(x=Cons_rating, y=overall_sentiment, fill=as.factor(Cons_rating))
) +
geom_col(show.legend=FALSE) +
coord_flip() +
labs(
title = "Overall Sentiment by Rating",
subtitle = "Reviews for kindle books",
x = "Rating",
y = "Overall Sentiment"
)
Dari visualisasi di atas, dapat dilihat bahwa peringkat dari 1 hingga 5 dianggap positif, meskipun peringkat 1 cenderung mengarah ke negatif. Peringkat 4 dan 5 dianggap sangat positif, sedangkan peringkat 2 dan 1 memiliki sentimen yang sangat rendah tetapi tetap dianggap positif.
Tujuan dari analisis ini adalah untuk melakukan Sentiment Analysis. Setelah dilakukan proses data cleaning, analisis ini menggunakan metode Loughran, Afinn, dan Bing untuk mengidentifikasi sentimen positif dan negatif. Hasil untuk setiap metode berbeda karena setiap metode memiliki kata-kata sentimen yang berbeda. Namun, dapat disimpulkan bahwa semua metode berhasil mengklasifikasikan kata-kata dengan benar sesuai dengan sentimen masing-masing.