Proposal : Analysis of GET Wallet Mobile App Review Using Unsupervised Machine Learning

Background

Dalam era kontemporer, penyampaian opini atau pandangan melalui teks menjadi kebutuhan di berbagai bisnis. Sebagai contoh, ulasan tentang suatu jasa atau produk memiliki potensi untuk menjadi sumber yang berharga dalam dunia bisnis. Ulasan ini memiliki fungsi ganda: pertama, mereka menjadi termometer yang menunjukkan sejauh mana pelanggan puas dengan produk atau jasa yang mereka gunakan. Kedua, ulasan tersebut menjadi sumber informasi berharga bagi perusahaan untuk mendengarkan kritik dan saran, serta menindaklanjuti isu-isu yang mungkin muncul terkait produk atau layanan yang ditawarkan.

Namun, nilai dari informasi teks di media sosial tak terbatas hanya pada ulasan produk atau jasa. Teks-teks ini juga bisa menjadi sumber insight mengenai persepsi pengguna terhadap citra perusahaan, pemahaman mereka tentang dinamika pasar saat ini, tren yang sedang naik daun, dan bahkan mengungkap kebutuhan serta ekspektasi mereka yang mungkin belum terpenuhi.

Memanfaatkan semua informasi ini bukanlah hal yang sederhana. Namun, dengan alat dan teknologi yang tepat, bisnis dapat dengan efisien mengumpulkan, menganalisis, dan memanfaatkan feedback ini untuk inovasi dan perbaikan. Di era digital saat ini, beragam platform telah menyediakan fitur-fitur khusus untuk mendukung interaksi pengguna, seperti kolom komentar dan fitur ulasan pada aplikasi atau website. Melalui platform ini, perusahaan memiliki akses langsung ke ocean of insights yang berasal dari pelanggan mereka, memberikan wawasan yang mendalam dan luas serta respons instan yang bisa membantu dalam pengambilan keputusan bisnis.

Problem Statement

Mengetahui informasi yang relevan dan insight yang bermakna dari teks yang diunggah oleh individu merupakan tugas yang rumit, dan membuat ringkasan yang merepresentasikan seluruh kumpulan teks tersebut menjadi tantangan yang tak bisa diremehkan. Membangun sebuah rangkuman seperti itu hanya dengan mengandalkan kapabilitas manusia akan memakan waktu dan proses yang rumit dan substansial. Sebagai contoh, pemilik bisnis harus membaca dan merangkum 1.000 hingga bahkan 100.000 ulasan setiap bulannya, sebuah tugas yang sangat berat. Terutama di era teknologi maju ini, di mana bisnis-bisnis harus terus berlomba dengan menjaga kualitas layanan dan bergerak mengambil keputusan secepat mungkin. Oleh karena itu, metode pengolahan yang lebih efisien, akurat, dan sederhana menjadi sangat dibutuhkan. Terutama ketika berbicara tentang informasi yang berasal dari ulasan pelanggan, hal tersebut menjadi kunci dalam merumuskan arah pengembangan yang tepat.

NLP (Natural Language Processing) masuk sebagai alat yang berguna dalam mengolah volume teks yang besar. NLP membuka pintu ke pemahaman dan wawasan yang belum bisa diperoleh dari data numerik seperti peringkat atau rating. Proses NLP dalam bidang pembelajaran mesin melibatkan komputer dalam memahami, mengekstrak, dan memanipulasi data berbahasa manusia. Dengan menggabungkan kemampuan analisis kritis manusia dengan kehebatan teknologi seperti pembelajaran mesin, pencarian informasi dari data teks menjadi jauh lebih terjangkau.

Project Idea & Problem Scope

Mengidentifikasi kata kunci yang memiliki makna dan relevansi terhadap isu-isu yang ada adalah tugas yang dapat diselesaikan dengan menggunakan metode Natural Language Processing (NLP). Dalam proses ini, model NLP akan melakukan pencarian dan pengelompokan ulasan-ulasan yang berkaitan dengan aplikasi Get Wallet dalam rentang waktu tertentu menjadi beberapa topik utama. Hal ini bertujuan untuk mengklasifikasikan kata-kata kunci yang mencerminkan esensi dari setiap ulasan, sehingga dapat ditempatkan sesuai dengan topik utama yang mungkin tidak dapat diungkap hanya melalui penilaian atau peringkat yang diberikan oleh pengguna.

Pada project ini, data diambil dari database milik Get Global Holding Pte. Ltd. berjumlah lebih dari 18.000 catatan yang disimpan sejak tahun 2020 hingga sekarang. Data merupakan umpan balik yang dikumpulkan oleh aplikasi dari pelanggan. Data terdiri dari kolom :

  • id: id data
  • userId: id dari user/customer yang memberikan rating dan review.
  • score: nilai rating yang diberikan oleh user/customer, dalam skala 1-10.
  • message: review yang diberikan oleh user/customer.
  • createdAt: tanggal rating dan review disimpan.
  • updatedAt: tanggal rating dan review diperbaharui.
  • childId: id dari subaccount user/customer.

Seperti yang telah disebutkan sebelumnya, proyek ini akan mengadopsi pendekatan unsupervised machine learning dengan menggunakan teknik Latent Dirichlet Allocation (LDA). Dalam konteks khusus ini, fokus utama bukanlah untuk menghasilkan prediksi seperti yang biasa dilakukan dalam supervised machine learning. Sebaliknya, kami akan menciptakan model yang mampu mengelompokkan teks-teks ulasan menjadi berbagai kategori topik, di mana pola-pola ini akan dipelajari oleh mesin dari data ulasan yang ada. Dengan kata lain, output yang akan dihasilkan oleh model ini adalah identifikasi beragam kategori topik yang muncul dalam teks-teks ulasan.

Keputusan untuk menggunakan metode unsupervised machine learning ini diambil setelah mempertimbangkan bahwa supervised machine learning mungkin kurang sesuai untuk mengatasi kasus ulasan yang sudah memiliki nilai rating terkait (contohnya, mencoba memprediksi sebuah teks untuk mendapatkan peringkat tertentu). Hal ini dikarenakan nilai rating tersebut langsung diinput oleh pengguna dan erat terkait dengan teks ulasan yang bersangkutan. Lebih lanjut, nilai-nilai rating yang telah ada dalam dataset dianggap sudah mencerminkan tingkat kepuasan pelanggan terhadap performa aplikasi. Oleh karena itu, melakukan analisis sentimen terpisah tidak dianggap perlu, mengingat nilai rating tersebut dianggap sebagai metrik yang cukup untuk merepresentasikan persepsi pelanggan terhadap aplikasi.

Output

Pada project ini, output yang akan dihasilkan berupa analisa review dan rating yang dimiliki Get Global Holding Pte. Ltd.. Selanjutnya, saya akan membuat sebuah model machine learning menggunakan teknik Latent Dirichlet Allocation (LDA) untuk membagi review kedalam topik-topik tertentu. Selain itu, output akhir akan berupa dashboard yang dapat menampilkan informasi:

  • Grafik atau plot yang menampilkan distribusi rating dengan fitur pemilihan periode tahun.
  • Grafik atau plot yang menampilkan banyak traffic review masuk dengan fitur pemilihan periode tahun dan bulan.
  • Grafik untuk menampilkan frekuensi kata yang sering muncul.
  • Hasil dari machine learning untuk menampilkan teks review dengan fitur filter topic yang diinput serta informasi rating yang diberikan dari review tersebut.

Business Impact

Manfaat bisnis yang dihasilkan melalui project ini akan membantu pelaku bisnis, khususnya Get Global Holding Pte. Ltd., dalam mengelola pengambilan keputusan bisnis dan pengembangan produk yang didukung oleh informasi berharga:

  • Memahami Tingkat Kepuasan Pelanggan: Dalam kasus ini, penekanannya adalah pada pengalaman pelanggan dalam menggunakan aplikasi, dan perubahan dalam tingkat kepuasan mereka. Ini dievaluasi berdasarkan analisis data peringkat yang diberikan oleh pelanggan.
  • Mengidentifikasi Isu-isu yang Relevan: Melalui analisis teks, kami dapat menentukan isu-isu atau topik-topik yang tengah diperbincangkan terkait dengan aplikasi Get Wallet dalam periode waktu tertentu. Ini membantu GET dalam mengenali permasalahan yang perlu segera ditangani.
  • Memahami Kebutuhan Pelanggan: Dengan memahami kata-kata dan ungkapan yang digunakan oleh pelanggan dalam ulasan mereka, kami dapat menentukan kebutuhan dan harapan mereka terhadap aplikasi.

Data Wrangling

Required Library

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
library(ggwordcloud)
library(glue)
library(hunspell)
library(lubridate)
## 
## Attaching package: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
library(scales)
library(SnowballC)
library(stringi)
library(textclean)
library(textmineR)
## Loading required package: Matrix
## 
## Attaching package: 'textmineR'
## The following object is masked from 'package:Matrix':
## 
##     update
## The following object is masked from 'package:stats':
## 
##     update
library(tidytext)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ forcats 1.0.0     ✔ stringr 1.5.0
## ✔ purrr   1.0.2     ✔ tibble  3.2.1
## ✔ readr   2.1.4     ✔ tidyr   1.3.0
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ readr::col_factor() masks scales::col_factor()
## ✖ purrr::discard()    masks scales::discard()
## ✖ tidyr::expand()     masks Matrix::expand()
## ✖ plotly::filter()    masks dplyr::filter(), stats::filter()
## ✖ dplyr::lag()        masks stats::lag()
## ✖ tidyr::pack()       masks Matrix::pack()
## ✖ tidyr::unpack()     masks Matrix::unpack()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(tm)
## Loading required package: NLP
## 
## Attaching package: 'NLP'
## 
## The following object is masked from 'package:ggplot2':
## 
##     annotate
library(tokenizers)
library(wordcloud)
## Loading required package: RColorBrewer

Load Data

review <- read.csv("assets/clubqnect.csv")
head(review)
##   id userId score
## 1  1 108161     8
## 2  2 324262     8
## 3  3 414503    10
## 4  4 351627     9
## 5  5 414659    10
## 6  6 414468    10
##                                                                               message
## 1                                                                          It is good
## 2                                                                               Hshah
## 3                                                                                  7s
## 4                                                                     I love this app
## 5 Great app but just need more feature, I hope you guys do better, you can do it :)) 
## 6                                                                           Very easy
##             createdAt           updatedAt childId
## 1 2021-01-11 07:52:15 2021-01-11 07:52:15      NA
## 2 2021-01-11 07:56:39 2021-01-11 07:56:39      NA
## 3 2021-01-12 02:44:24 2021-01-12 02:44:24      NA
## 4 2021-01-12 02:47:55 2021-01-12 02:47:55      NA
## 5 2021-01-12 03:16:32 2021-01-12 03:16:32      NA
## 6 2021-01-12 03:22:45 2021-01-12 03:22:45      NA

Berikut detail informasi yang diperoleh dari data frame:

  • id: id data
  • userId: id dari user/customer yang memberikan rating dan review.
  • score: nilai rating yang diberikan oleh user/customer, dalam skala 1-10.
  • message: review yang diberikan oleh user/customer.
  • createdAt: tanggal rating dan review disimpan.
  • updatedAt: tanggal rating dan review diperbaharui.
  • childId: id dari subaccount user/customer.

Data evaluation

Pada tahap ini saya melakukan pemeriksaan apakan terdapat data untuk mengetahui data apa saja yang perlu dibersihkan pada proses selanjutnya.

str(review)
## 'data.frame':    18488 obs. of  7 variables:
##  $ id       : int  1 2 3 4 5 6 7 9 10 11 ...
##  $ userId   : int  108161 324262 414503 351627 414659 414468 414493 414523 414536 414583 ...
##  $ score    : int  8 8 10 9 10 10 7 10 10 10 ...
##  $ message  : chr  "It is good" "Hshah" "7s" "I love this app" ...
##  $ createdAt: chr  "2021-01-11 07:52:15" "2021-01-11 07:56:39" "2021-01-12 02:44:24" "2021-01-12 02:47:55" ...
##  $ updatedAt: chr  "2021-01-11 07:52:15" "2021-01-11 07:56:39" "2021-01-12 02:44:24" "2021-01-12 02:47:55" ...
##  $ childId  : int  NA NA NA NA NA NA NA NA NA NA ...
colSums(is.na(review))
##        id    userId     score   message createdAt updatedAt   childId 
##         0         0         0         9         0         0     17597

Dapat diketahui bahwa :

  • Format data untuk createdAt masih dalam bentuk char dan harus dirubah dalam bentuk date.
  • message dan childId memiliki missing atau n/a value. Maka dari itu kita akan menghapus 9 data yang memiliki n/a value pada kolom message. Selain itu kolom childId juga akan dihapus karena hampir seluruh datanya kosong.
  • Kolim id, userId updatedAt dan childId akan dihapus karena tidak memiliki informasi yang bermakna

Data cleaning

review_clean <- review %>%
  mutate(
    score = as.factor(score),  # Converting 'score' to a factor
    createdAt = as_datetime(createdAt)) %>%
  select(-c(1, 2, 6, 7))

head(review_clean)
##   score
## 1     8
## 2     8
## 3    10
## 4     9
## 5    10
## 6    10
##                                                                               message
## 1                                                                          It is good
## 2                                                                               Hshah
## 3                                                                                  7s
## 4                                                                     I love this app
## 5 Great app but just need more feature, I hope you guys do better, you can do it :)) 
## 6                                                                           Very easy
##             createdAt
## 1 2021-01-11 07:52:15
## 2 2021-01-11 07:56:39
## 3 2021-01-12 02:44:24
## 4 2021-01-12 02:47:55
## 5 2021-01-12 03:16:32
## 6 2021-01-12 03:22:45
review_clean <- na.omit(review_clean) 
colSums(is.na(review_clean))
##     score   message createdAt 
##         0         0         0
review_clean[review_clean$message == "",]
## [1] score     message   createdAt
## <0 rows> (or 0-length row.names)
head(review_clean)
##   score
## 1     8
## 2     8
## 3    10
## 4     9
## 5    10
## 6    10
##                                                                               message
## 1                                                                          It is good
## 2                                                                               Hshah
## 3                                                                                  7s
## 4                                                                     I love this app
## 5 Great app but just need more feature, I hope you guys do better, you can do it :)) 
## 6                                                                           Very easy
##             createdAt
## 1 2021-01-11 07:52:15
## 2 2021-01-11 07:56:39
## 3 2021-01-12 02:44:24
## 4 2021-01-12 02:47:55
## 5 2021-01-12 03:16:32
## 6 2021-01-12 03:22:45
str(review_clean)
## 'data.frame':    18479 obs. of  3 variables:
##  $ score    : Factor w/ 10 levels "1","2","3","4",..: 8 8 10 9 10 10 7 10 10 10 ...
##  $ message  : chr  "It is good" "Hshah" "7s" "I love this app" ...
##  $ createdAt: POSIXct, format: "2021-01-11 07:52:15" "2021-01-11 07:56:39" ...
##  - attr(*, "na.action")= 'omit' Named int [1:9] 383 4607 8348 10007 16158 17300 17442 17872 18227
##   ..- attr(*, "names")= chr [1:9] "383" "4607" "8348" "10007" ...

Exploratory and Data Analysis

Exploratory Data Analysis (EDA) adalah proses analisis data yang bertujuan untuk memahami karakteristik dan pola dalam dataset tanpa melakukan inferensi statistik formal. Dalam EDA, data dieksplorasi melalui berbagai teknik visualisasi dan statistik deskriptif untuk mengidentifikasi tren, anomali, dan hubungan antar variabel. Tujuannya adalah untuk mendapatkan wawasan awal tentang data sehingga peneliti atau analis data dapat membuat hipotesis awal, merencanakan analisis lebih lanjut, dan membuat keputusan yang lebih baik dalam pengolahan dan interpretasi data. EDA membantu menyusun dasar yang kuat untuk penelitian lebih lanjut atau pengambilan keputusan berdasarkan pemahaman yang lebih dalam tentang data.

Frequency of Review and Rating

range(review_clean$createdAt)
## [1] "2021-01-11 07:52:15 UTC" "2023-09-03 08:19:55 UTC"

Tahap ini melibatkan pencarian informasi mengenai frekuensi ulasan berdasarkan peringkat yang diberikan setiap tahunnya. Sebagai catatan, total ulasan yang terekam dalam periode dari 13 Juli 2021 hingga 3 September 2023 sebanyak 18.479 ulasan (sesuai dengan jumlah total baris data).

revw.freq <- review_clean %>%
  mutate(years = year(createdAt)) %>% 
  group_by(years) %>% 
  summarise(freq = n()) %>% 
  mutate(years = as.factor(years))

persentase <- c(0.0,(diff(revw.freq$freq)/revw.freq$freq[1:3])*100) #menghitung persentase kenaikan/penurunan frekuensi review masuk dari tahun sebelumnya
## Warning in diff(revw.freq$freq)/revw.freq$freq[1:3]: longer object length is
## not a multiple of shorter object length
plot1 <- ggplot(revw.freq, aes(y = freq, x = years)) +
 geom_col(aes(fill = freq), show.legend = F) +
  labs(x = NULL,
       y = NULL,
       title = "Frekuensi Review Periode 2021 - 2023") +
  theme_minimal() +
  theme(plot.title = element_text(size = 16, face = "bold", hjust = 0),
        axis.title = element_text(hjust = .5),
        axis.text = element_text(size = 12, face = "bold"))

ggplotly(plot1)

💡 Insight :

  • Frekuensi review-rating yang diunggah mencapai nilai tertinggi pada tahun 2021(tahun pertama aplikasi release) yaitu sebanyak 13.332 reviews.
  • Frekuensi review-rating menurun pada tahun tahun selanjutnya. Pada 2022, jumlah rating yang terkumpul 4810 dan pada tahun 2023 berjumlah 347.
rvw.bulan <- review_clean %>% 
  mutate(bulan = month(createdAt, label = T),
         tahun = year(createdAt)) %>% 
  group_by(tahun, bulan) %>% 
  summarize(freq = n()) %>% 
  mutate(label = glue(
    "Frekuensi: {comma(freq)}"
  )) %>% 
  arrange(tahun, bulan) 
## `summarise()` has grouped output by 'tahun'. You can override using the
## `.groups` argument.
plot2 <- ggplot(rvw.bulan[rvw.bulan$tahun == 2021,], aes(y = freq, x = bulan)) +
  geom_col(aes(fill = freq, text = label), show.legend = F) +
  labs(x = NULL,
       y = NULL,
       title = "Frekuensi Review Masuk per Bulan Tahun 2021") +
  geom_hline(aes(yintercept = mean(freq)), col = "red") +
  theme_minimal() +
  theme(plot.title = element_text(size = 16, face = "bold", hjust = 0),
        axis.title = element_text(hjust = .5),
        axis.text = element_text(size = 12, face = "bold"))
## Warning in geom_col(aes(fill = freq, text = label), show.legend = F): Ignoring
## unknown aesthetics: text
ggplotly(plot2, tooltip = "text")

💡 Insight :

  • Pada tahun 2021 rating-review yang diunggah user berada pada pertengahan tahun yaitu pada bulan May - August, dengan frekuensi tertinggi pada bulan July berjumlah 2.510

Rating Distribution

round(prop.table(table(review_clean$score))*100, 2) %>% sort(decreasing = T)
## 
##    10     9     1     8     7     5     6     4     2     3 
## 56.62 10.79  7.32  7.02  5.82  5.64  3.66  1.24  1.05  0.84

💡 Insight :

  • Selama periode tahun 2021 - 2023 distribusi rating menunjukan nilai tertingi rating 10 dan diikuti oleh rating 1.
  • Hal ini menunjukan 43% pengguna aplikasi masih tidak puas dengan aplikasi, untuk analisis lebih lanjut mari kelompokan sesuai periode tahunnya.
rating.fq <- review_clean %>%
  mutate(years = as.factor(year(createdAt)),
         score = as.factor(score)) %>% 
  group_by(years, score) %>% 
  summarize(freq = n()) %>% 
  mutate(label = glue(
           "Tahun: {years}
            Frekuensi: {comma(freq)}
            Rating: {score}"
         ))
## `summarise()` has grouped output by 'years'. You can override using the
## `.groups` argument.
plot3 <- ggplot(rating.fq, aes(y = freq, x = years)) +
  geom_line(aes(group = score, col = score), show.legend = F) +
  geom_point(aes(col = score, text = label), show.legend = F) +
  labs(y = NULL,
       x = "Tahun",
       title = "Grafik Rating per Tahun") +
  theme_minimal() +
  theme(axis.text.x = element_text(face = "bold"))
## Warning in geom_point(aes(col = score, text = label), show.legend = F):
## Ignoring unknown aesthetics: text
ggplotly(plot3, tooltip = "text")
rating.fq_clean <- rating.fq %>% 
  select(-c(4))

rating.fq_clean
## # A tibble: 30 × 3
## # Groups:   years [3]
##    years score  freq
##    <fct> <fct> <int>
##  1 2021  1       811
##  2 2021  2       115
##  3 2021  3        97
##  4 2021  4       152
##  5 2021  5       666
##  6 2021  6       448
##  7 2021  7       744
##  8 2021  8       936
##  9 2021  9      1442
## 10 2021  10     7911
## # ℹ 20 more rows

💡 Insight :

  • Terlihat bahwa frekuensi rating cenderung meningkat dari tahun ke tahun (2021 ke 2022), tetapi kemudian mengalami penurunan pada tahun 2023. Ini bisa menunjukkan adanya fluktuasi dalam aktivitas pengguna atau perubahan dalam produk atau layanan yang ditawarkan.
  • Rating 10 adalah rating paling umum yang diberikan oleh pengguna setiap tahun, diikuti oleh rating 9 dan 8. Ini menunjukkan bahwa sebagian besar pengguna memberikan penilaian positif terhadap produk atau layanan yang dinilai. Rating 1 adalah yang paling jarang diberikan oleh pengguna, yang menunjukkan bahwa rating rendah kurang umum.
  • Tahun 2021 memiliki frekuensi rating tertinggi dibandingkan tahun-tahun lainnya, sementara tahun 2023 memiliki frekuensi rating terendah. Ini bisa disebabkan oleh berbagai faktor, termasuk perubahan dalam popularitas produk atau layanan, perubahan dalam jumlah pengguna, atau perubahan dalam strategi perusahaan.
  • Tahun 2021 mencatat frekuensi rating tertinggi untuk rating 10. Hal ini bisa menunjukkan bahwa produk atau layanan pada tahun itu sangat disukai oleh pengguna dan mendapat banyak ulasan positif.
  • Tahun 2023 mencatat frekuensi rating terendah untuk rating 1. Ini bisa menjadi perhatian jika ada penurunan signifikan dalam kualitas produk atau layanan pada tahun itu.
  • Tidak ada pola musiman yang jelas yang dapat dilihat dari data ini, tetapi jika data ini mencakup beberapa tahun lagi, Anda dapat melihat apakah ada tren musiman dalam rating selama periode tertentu dalam setahun.
  • Data menunjukkan variasi besar dalam frekuensi rating di berbagai skala (1-10) dari tahun ke tahun. Ini menunjukkan keragaman dalam pengalaman dan pendapat pengguna terhadap produk atau layanan.

Untuk mempermudah melihat distribusi rating khususnya tahun 2023, kita dapat memlihat plot di bawah ini:

plot4 <- ggplot(rating.fq[rating.fq$years == 2023, ], aes(x = score, y = freq)) + 
  geom_col(fill = c("#4281f5"), show.legend = F, aes(text = label)) +
  labs(x = "Nilai Rating",
       y = "Frekuensi",
       title = "Distribusi Rating Tahun 2023") +
  scale_y_continuous(labels = comma) +
  theme_minimal() +
  theme(plot.title = element_text(size = 18, face = "bold", hjust = .5),
        axis.text.x = element_text(size = 12, face = "bold"))
## Warning in geom_col(fill = c("#4281f5"), show.legend = F, aes(text = label)):
## Ignoring unknown aesthetics: text
ggplotly(plot4, tooltip = "text")

Text Cleansing

Proses pembersihan teks diperlukan untuk memastikan bahwa teks hanya berisi informasi yang relevan dan penting, sehingga unsur-unsur yang tidak memiliki signifikansi atau tidak berkontribusi pada pemahaman suatu pernyataan dapat dihapus. Hal ini bertujuan untuk membuat proses pemodelan menjadi lebih efisien dan efektif. Proses pembersihan teks adalah:

  • Mengubah semua teks menjadi huruf kecil.
  • Menghapus tag HTML.
  • Memperpanjang kata-kata yang disingkat (misalnya, “don’t” menjadi “tidak” dan “I’ll” menjadi “saya akan”).
  • Mengganti semua tanda hubung (-) dengan spasi.
  • Menghilangkan semua tanda baca.
  • Mengganti semua karakter numerik menjadi kata-kata.
review.clean <- review_clean %>% 
   mutate(text_clean = message %>% 
             replace_non_ascii() %>% 
             replace_html(symbol = F) %>% # remove html tag
             str_replace_all("[0-9]", " ") %>% 
             str_replace_all(pattern = "[:digit:]", replacement = " ") %>% 
             str_replace_all("[-|]", " ") %>% # replace "-" with space
             tolower() %>% #lowercase
             replace_symbol() %>%
             replace_contraction() %>% 
             replace_word_elongation() %>%  # lengthen shortened word
             str_replace_all("[[:punct:]]", " ") %>% # remove punctuation
             str_replace_all(" dr ", " doctor ") %>% 
             make_plural() %>%
             str_replace_all(" s ", " ") %>%  
             str_squish() %>% # remove double whitespace
             str_trim() # remove whitespace at the start and end of the text
          )

Selanjutnya, kita harus menghapus Stop Words. Pada tahap ini kita akan menghapus kata-kata yang tidak memiliki makna yang dapat mendeskripsikan sebuah pernyataan maupun yang tidak berkontribusi terhadap analisis kita.

stop_words <- stopwords("en")

remove_stopwords <- function(text) {
  stopwords <- stop_words
  words <- unlist(strsplit(text, "\\s+"))
  # Remove stopwords
  filtered_words <- words[!tolower(words) %in% stopwords]
  cleaned_text <- paste(filtered_words, collapse = " ")
  return(cleaned_text)
}

review.clean$message <- sapply(review.clean$message, remove_stopwords)

#Text Visualisation

Untuk mengetahui kata-kata yang sering muncul pada review yang masuk, kita dapat memprosesnya dengan mengubah teks ke dalam bentuk DTM (Document Terms Matrix, matrix yang menyimpan terms/kata pada dokumen kita) lalu menghitung frekuensi kemunculan tiap kata pada keseluruhan data teks.

# Membuat teks ke bentuk corpus lalu dibuat ke bentuk matrix DTM
text.corpus <- VCorpus(VectorSource(review.clean$message))
text.dtm <- DocumentTermMatrix(x = text.corpus)

# Sorting frekuensi kemunculan secara descending
text.words <- as.matrix(text.dtm)
words.list <- sort(colSums(text.words), decreasing = T)

# Membuat data ke bentuk dataframe untuk kebutuhan visualisasi
words.df <- data.frame(word = names(words.list), freq=words.list)
words.df <- words.df %>% 
  mutate(label = glue(
    "Frekuensi: {comma(freq)}"))
plot5 <- ggplot(head(words.df,7), aes(y = reorder(word,freq), x = freq)) +
  geom_col(aes(fill = freq, text = label), show.legend = F) +
  labs(x = "Frekuensi",
       y = "Terms/Kata",
       title = "Frekuensi Kata Tertinggi") +
  scale_x_continuous(labels = comma) +
  theme_minimal() +
  theme(axis.text.y = element_text(face = "bold", size = 11))
## Warning in geom_col(aes(fill = freq, text = label), show.legend = F): Ignoring
## unknown aesthetics: text
ggplotly(plot5, tooltip = "text")
review.clean %>% wordcloud( max.words = 200, 
                            scale = c(2, 1),
                            random.order = FALSE)

💡 Insight :

  • Dapat kita perhatikan, kata paling sering muncul adalah good, use, easy, convenient, app, it's dan card. Sesuai dengan nilai rating 10 yang tinggi pada tahun 2021.

Grafik di atas memberikan gambaran awal mengenai poin-poin yang sering dibahas dalam dokumen kita, ditunjukkan oleh seberapa seringnya istilah-istilah tersebut muncul dalam dokumen. Namun, hasil ini belum dapat diinterpretasikan sepenuhnya karena kita belum mengetahui apakah kata-kata tersebut memiliki hubungan satu sama lain atau mungkin tidak relevan dengan topik yang berbeda.

Dashboard Design

Rencana desain yang akan digunakan adalah:

1. Analisa Rating

2. Analisa Review

1. Hasil Machine Learning (LDA)