Group 2 Members

Sentiment & Text Analysis on Products Reviews

Part 1: Introduction

1.1 Introduction

In today’s digital age, product reviews have become crucial for businesses to gather consumer feedback, greatly influencing business strategy and customer relationship management. For global retailers like Sephora, understanding consumer sentiment through these reviews is vital. This study utilizes Sephora’s product review data to conduct sentiment and text analysis, extracting significant patterns and emotions expressed by consumers. By analyzing this data, the study aims to assist Sephora in enhancing its product offerings, boosting customer satisfaction, and aligning strategies with consumer preferences and expectations.

1.2 Objective

  1. Sentiment Analysis: This involves categorizing customer reviews into positive, negative, or neutral sentiments. The aim is to gauge overall customer satisfaction and pinpoint areas for improvement. By tracking sentiment trends, Sephora can effectively manage its brand reputation and address consumer needs.

  2. Text Analysis: This focuses on topic modeling and extracting keywords from the review text. The goal is to uncover prevalent themes and concerns voiced by customers. Identifying these topics helps Sephora understand which product features or service attributes are favored by customers, guiding product development and marketing strategies.

Part 2: Data Understanding

2.1 Overview of Data Attributes

Product data content

Product data content has 27 attributes. The attributes are as the following:

  1. product_id - Unique identifier for the product from the site
  2. product_name - Full name of the product
  3. brand_id - Unique identifier for the product brand from the site
  4. brand_name - Full name of the product brand
  5. loves_count - The number of people who have marked this product as a favorite
  6. rating - The average rating of the product based on user reviews
  7. reviews - The number of user reviews for the product
  8. size - The size of the product, which may be in oz, ml, g, packs, or other units depending on the product type
  9. variation_type - The type of variation parameter for the product (e.g. Size, Color)
  10. variation_value - The specific value of the variation parameter for the product (e.g. 100 mL, Golden Sand)
  11. variation_desc - A description of the variation parameter for the product (e.g. tone for fairest skin)
  12. ingredients - A list of ingredients included in the product, for example: [‘Product variation 1:’, ‘Water, Glycerin’, ‘Product variation 2:’, ‘Talc, Mica’] or if no variations [‘Water, Glycerin’]
  13. price_usd - The price of the product in US dollars
  14. value_price_usd - The potential cost savings of the product, presented on the site next to the regular price
  15. sale_price_usd - The sale price of the product in US dollars
  16. limited_edition - Indicates whether the product is a limited edition or not (1-true, 0-false)
  17. new - Indicates whether the product is new or not (1-true, 0-false)
  18. online_only - Indicates whether the product is only sold online or not (1-true, 0-false)
  19. out_of_stock - Indicates whether the product is currently out of stock or not (1 if true, 0 if false)
  20. sephora_exclusive - Indicates whether the product is exclusive to Sephora or not (1 if true, 0 if false)
  21. highlights - A list of tags or features that highlight the product’s attributes (e.g. [‘Vegan’, ‘Matte Finish’])
  22. primary_category - First category in the breadcrumb section
  23. secondary_category - Second category in the breadcrumb section
  24. tertiary_category - Third category in the breadcrumb section
  25. child_count - The number of variations of the product available
  26. child_max_price - The highest price among the variations of the product
  27. child_min_price - The lowest price among the variations of the product

Review data content

Review data content has 15 attributes. The attributes are as the following:

  1. author_id - Unique identifier for the author of the review on the website
  2. rating - Rating given by the author for the product on a scale of 1 to 5
  3. is_recommended - Indicates if the author recommends the product or not (1-true, 0-false)
  4. helpfulness - The ratio of all ratings to positive ratings for the review: helpfulness = total_pos_feedback_count / total_feedback_count
  5. total_feedback_count - Total number of feedback (positive and negative ratings) left by users for the review
  6. total_neg_feedback_count - The number of users who gave a negative rating for the review
  7. total_pos_feedback_count - The number of users who gave a positive rating for the review
  8. submission_time - Date the review was posted on the website in the ‘yyyy-mm-dd’ format
  9. review_text - The main text of the review written by the author
  10. review_title - The title of the review written by the author
  11. skin_tone - Author’s skin tone (e.g. fair, tan, etc.)
  12. eye_color - Author’s eye color (e.g. brown, green, etc.)
  13. skin_type - Author’s skin type (e.g. combination, oily, etc.)
  14. hair_color - Author’s hair color (e.g. brown, auburn, etc.)
  15. product_id - Unique identifier for the product on the website

2.2 Import the necessary libraries

library(caret)
library(dplyr)
library(ggplot2)
library(LiblineaR)
library(lubridate)
library(NLP)
library(purrr)
library(quanteda)
library(quanteda.textmodels)
library(RCurl)
library(readxl)
library(slam)
library(SnowballC)
library(SparseM)
library(stringr)
library(text2vec)
library(tm)
library(tokenizers)
library(topicmodels)
library(wordcloud)
library(XML)

2.3 Import the original datasets

product <- read.csv("product_info.csv")
reviews_0_250 <- read.csv("reviews_0-250.csv")
reviews_250_500 <- read.csv("reviews_250-500.csv")
reviews_500_750 <- read.csv("reviews_500-750.csv")
reviews_750_1250 <- read.csv("reviews_750-1250.csv")
reviews_1250_end <- read.csv("reviews_1250-end.csv")

2.4 Basic understanding of the dataset

# Show same columns for 2 dataset
common_columns <- intersect(colnames(product),colnames(reviews_0_250))
print(common_columns)
## [1] "product_id"   "product_name" "brand_name"   "rating"       "price_usd"

Part 3: Data Preprocessing

Part 3.1: Merging all reviews

# Merge all reviews
all_reviews_raw <- rbind(reviews_0_250, reviews_250_500, reviews_500_750, reviews_750_1250, reviews_1250_end)

# Show the dimension
dim(all_reviews_raw)
## [1] 1094411      19

Part 3.2: Joining the data

# Identifying columns in 'product' not present in 'all_reviews_raw'
cols_to_use <- setdiff(names(product), names(all_reviews_raw))

# Adding 'product_id' to the list of columns to use
cols_to_use <- c(cols_to_use, "product_id")

# Merging the data frames
merged_outer_join <- merge(all_reviews_raw, product[cols_to_use], by = "product_id", all = TRUE)

# Removing the 'X' column by setting it to NULL
merged_outer_join$X <- NULL

# Show the dimensions of the raw/merged data frame
dim(all_reviews_raw)
## [1] 1094411      19
dim(product)
## [1] 8494   27
dim(merged_outer_join)
## [1] 1100554      40

Part 3.3: Check for unique and missing values

# Data types of each column
data_types <- sapply(merged_outer_join, class)

# Counts unique values in each column
unique_value_counts <- sapply(merged_outer_join, function(x) length(unique(na.omit(x))))

# Convert common incorrect NA representations to actual NA values
merged_outer_join[merged_outer_join == ""] <- NA  # Assuming empty strings should be treated as NA

# Calculate the number of missing values per column
missing_counts <- colSums(is.na(merged_outer_join))

# Calculate the percentage of missing values
total_rows <- nrow(merged_outer_join)
missing_percentage <- (missing_counts / total_rows) * 100

# Creating the initial summary table
summary_table <- data.frame(
  Column = names(data_types),
  DataType = data_types,
  TotalObservations = rep(total_rows, length(missing_counts)),  # Adding a column for total observations
  UniqueValueCount = unique_value_counts,
  MissingCount = missing_counts,
  MissingPercentage = sprintf("%.2f%%", missing_percentage)  # Adding percentage as a formatted string
)

# Sorting the summary table by MissingCount in descending order
summary_table <- summary_table[order(-summary_table$MissingCount),]

# Print the sorted summary table
print(summary_table)
##                                            Column  DataType TotalObservations
## variation_desc                     variation_desc character           1100554
## sale_price_usd                     sale_price_usd   numeric           1100554
## value_price_usd                   value_price_usd   numeric           1100554
## child_max_price                   child_max_price   numeric           1100554
## child_min_price                   child_min_price   numeric           1100554
## helpfulness                           helpfulness   numeric           1100554
## review_title                         review_title character           1100554
## hair_color                             hair_color character           1100554
## eye_color                               eye_color character           1100554
## skin_tone                               skin_tone character           1100554
## is_recommended                     is_recommended   numeric           1100554
## tertiary_category               tertiary_category character           1100554
## skin_type                               skin_type character           1100554
## highlights                             highlights character           1100554
## variation_value                   variation_value character           1100554
## variation_type                     variation_type character           1100554
## size                                         size character           1100554
## ingredients                           ingredients character           1100554
## review_text                           review_text character           1100554
## author_id                               author_id character           1100554
## rating                                     rating   integer           1100554
## total_feedback_count         total_feedback_count   integer           1100554
## total_neg_feedback_count total_neg_feedback_count   integer           1100554
## total_pos_feedback_count total_pos_feedback_count   integer           1100554
## submission_time                   submission_time character           1100554
## product_name                         product_name character           1100554
## brand_name                             brand_name character           1100554
## price_usd                               price_usd   numeric           1100554
## reviews                                   reviews   integer           1100554
## secondary_category             secondary_category character           1100554
## product_id                             product_id character           1100554
## brand_id                                 brand_id   integer           1100554
## loves_count                           loves_count   integer           1100554
## limited_edition                   limited_edition   integer           1100554
## new                                           new   integer           1100554
## online_only                           online_only   integer           1100554
## out_of_stock                         out_of_stock   integer           1100554
## sephora_exclusive               sephora_exclusive   integer           1100554
## primary_category                 primary_category character           1100554
## child_count                           child_count   integer           1100554
##                          UniqueValueCount MissingCount MissingPercentage
## variation_desc                        936      1091034            99.13%
## sale_price_usd                         88      1090576            99.09%
## value_price_usd                       174      1069365            97.17%
## child_max_price                       222       644796            58.59%
## child_min_price                       208       644796            58.59%
## helpfulness                          3767       567735            51.59%
## review_title                       364106       316797            28.79%
## hair_color                              8       232911            21.16%
## eye_color                               7       215771            19.61%
## skin_tone                              15       176682            16.05%
## is_recommended                          2       174131            15.82%
## tertiary_category                     119       161894            14.71%
## skin_type                               5       117700            10.69%
## highlights                           4418       115729            10.52%
## variation_value                      2730        64644             5.87%
## variation_type                          8        52560             4.78%
## size                                 2056        44661             4.06%
## ingredients                          6539        22843             2.08%
## review_text                        969420         7587             0.69%
## author_id                          503216         6143             0.56%
## rating                                  5         6143             0.56%
## total_feedback_count                  676         6143             0.56%
## total_neg_feedback_count              259         6143             0.56%
## total_pos_feedback_count              590         6143             0.56%
## submission_time                      5317         6143             0.56%
## product_name                         2334         6143             0.56%
## brand_name                            142         6143             0.56%
## price_usd                             221         6143             0.56%
## reviews                              1556          278             0.03%
## secondary_category                     42            8             0.00%
## product_id                           8494            0             0.00%
## brand_id                              304            0             0.00%
## loves_count                          7436            0             0.00%
## limited_edition                         2            0             0.00%
## new                                     2            0             0.00%
## online_only                             2            0             0.00%
## out_of_stock                            2            0             0.00%
## sephora_exclusive                       2            0             0.00%
## primary_category                        9            0             0.00%
## child_count                            55            0             0.00%

Part 3.4: Drop high % missing columns and missing rows

# Identify columns with more than 50% missing values, excluding the 'helpfulness' column
columns_to_drop <- names(missing_percentage[missing_percentage > 50 & names(missing_percentage) != "helpfulness"])

# Drop these columns from the dataframe
merged_clean <- merged_outer_join[, !(names(merged_outer_join) %in% columns_to_drop)]

# Remove rows with any missing values
merged_clean <- na.omit(merged_clean)

# Display the cleaned dataframe dimensions
dim(merged_clean)
## [1] 216776     35

Part 3.5: Summary statistics & dimensions

# Display descriptive statistics of the data frame
print(summary(merged_clean))
##   product_id         author_id             rating      is_recommended  
##  Length:216776      Length:216776      Min.   :1.000   Min.   :0.0000  
##  Class :character   Class :character   1st Qu.:3.000   1st Qu.:1.0000  
##  Mode  :character   Mode  :character   Median :5.000   Median :1.0000  
##                                        Mean   :4.067   Mean   :0.7651  
##                                        3rd Qu.:5.000   3rd Qu.:1.0000  
##                                        Max.   :5.000   Max.   :1.0000  
##   helpfulness     total_feedback_count total_neg_feedback_count
##  Min.   :0.0000   Min.   :   1.000     Min.   :  0.000         
##  1st Qu.:0.6667   1st Qu.:   2.000     1st Qu.:  0.000         
##  Median :0.9242   Median :   4.000     Median :  1.000         
##  Mean   :0.7739   Mean   :   9.472     Mean   :  1.964         
##  3rd Qu.:1.0000   3rd Qu.:   9.000     3rd Qu.:  2.000         
##  Max.   :1.0000   Max.   :3851.000     Max.   :500.000         
##  total_pos_feedback_count submission_time    review_text       
##  Min.   :   0.000         Length:216776      Length:216776     
##  1st Qu.:   1.000         Class :character   Class :character  
##  Median :   3.000         Mode  :character   Mode  :character  
##  Mean   :   7.508                                              
##  3rd Qu.:   7.000                                              
##  Max.   :3481.000                                              
##  review_title        skin_tone          eye_color          skin_type        
##  Length:216776      Length:216776      Length:216776      Length:216776     
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##   hair_color        product_name        brand_name          price_usd     
##  Length:216776      Length:216776      Length:216776      Min.   :  3.00  
##  Class :character   Class :character   Class :character   1st Qu.: 28.00  
##  Mode  :character   Mode  :character   Mode  :character   Median : 42.00  
##                                                           Mean   : 49.83  
##                                                           3rd Qu.: 64.00  
##                                                           Max.   :425.00  
##     brand_id     loves_count        reviews         size          
##  Min.   :1063   Min.   :     0   Min.   :   1   Length:216776     
##  1st Qu.:5987   1st Qu.: 24567   1st Qu.: 477   Class :character  
##  Median :6189   Median : 63782   Median :1121   Mode  :character  
##  Mean   :5946   Mean   :122074   Mean   :1742                     
##  3rd Qu.:6285   3rd Qu.:167407   3rd Qu.:2449                     
##  Max.   :8017   Max.   :763168   Max.   :8733                     
##  variation_type     variation_value    ingredients        limited_edition  
##  Length:216776      Length:216776      Length:216776      Min.   :0.00000  
##  Class :character   Class :character   Class :character   1st Qu.:0.00000  
##  Mode  :character   Mode  :character   Mode  :character   Median :0.00000  
##                                                           Mean   :0.01874  
##                                                           3rd Qu.:0.00000  
##                                                           Max.   :1.00000  
##       new           online_only       out_of_stock     sephora_exclusive
##  Min.   :0.00000   Min.   :0.00000   Min.   :0.00000   Min.   :0.0000   
##  1st Qu.:0.00000   1st Qu.:0.00000   1st Qu.:0.00000   1st Qu.:0.0000   
##  Median :0.00000   Median :0.00000   Median :0.00000   Median :0.0000   
##  Mean   :0.01208   Mean   :0.06424   Mean   :0.01782   Mean   :0.4233   
##  3rd Qu.:0.00000   3rd Qu.:0.00000   3rd Qu.:0.00000   3rd Qu.:1.0000   
##  Max.   :1.00000   Max.   :1.00000   Max.   :1.00000   Max.   :1.0000   
##   highlights        primary_category   secondary_category tertiary_category 
##  Length:216776      Length:216776      Length:216776      Length:216776     
##  Class :character   Class :character   Class :character   Class :character  
##  Mode  :character   Mode  :character   Mode  :character   Mode  :character  
##                                                                             
##                                                                             
##                                                                             
##   child_count     
##  Min.   : 0.0000  
##  1st Qu.: 0.0000  
##  Median : 0.0000  
##  Mean   : 0.8277  
##  3rd Qu.: 1.0000  
##  Max.   :13.0000
# Print the dimensions of the data frame
print(dim(merged_clean))
## [1] 216776     35
# Export the data frame to a CSV file
write.csv(merged_clean, "merged_clean.csv", row.names = FALSE)

Part 4: Exploratory Data Analysis

Part 4.1: Univariate Analysis

##            Status Percentages
## 1     Recommended       76.51
## 2 Not_Recommended       23.49

The pie chart above illustrates the distribution of the “is_recommended” column. The pie chart shows that approximately 76.51%, which represents a significant majority recommended the products that they purchased in Sephora. On the other hand, 23.49% of the users did not recommend the products that they purchased in Sephora.

Part 4.2: Bivariate Analysis

The bar chart above displays the “Top 10 Recommended Products” based on users’ responses. The product “Niacinamide 10% + Zinc 1% Oil Control Serum” has the highest number of recommendations among the top 10 products. This suggests that it is the most popular or effective product among the ones considered. It leads significantly with over 2381 recommendations, surpassing the second-place product by more than 649 recommendations.

“Superfood Antioxidant Cleanser” and “Salicylic Acid Acne Healing Dots” also have a high number of recommendations, indicating that they are well-liked by users. two of the products have gained more than 1700 recommendations each.

The bar chart highlights the “Top 10 Most Expensive Products” at Sephora. The top 10 products clustered between 300 and 450 USD which show a small price difference among these items. The Concentrate Serum” appears as the most expensive product with the price 425 USD. It lead the second most expensive product, “The Regenerating Serum” by only 10 USD. Interestingly, serums dominate the list with four entries, suggesting that they generally come with a higher price tag compared to other types of products.

The bar chart above shows the “Top 10 Cheapest Products” among all the products in Sephora. The top 10 cheapest products are all below 10 USD making them highly affordable for the public. “Clean Charcoal Nose Strip” appears to be the most affordable among all the products with a price at 3 USD. Masks are noted as the most common among the cheapest products with 7 out of the 10 entries being various types of masks.

The scatter plot illustrates the correlation between the prices of products and their favourity among customers. The plot reveals a lack of a strong relationship between a product’s price and its favourity. A significant number of products are clustered towards the lower spectrum of both price and popularity, indicating that irrespective of their popularity, most products are priced reasonably. Interestingly, there are several products having a high favourity are still priced low. This could imply that these products are widely favored but remain cost-effective.

Part 4.3: Multivariate Analysis

## [1] "The submission data involves the following years:"
## [1] 2017 2018 2019 2020 2021 2022 2023
## # A tibble: 7 × 4
##    year total_feedback_count total_neg_feedback_count total_pos_feedback_count
##   <dbl>                <int>                    <int>                    <int>
## 1  2017                76890                    11925                    64965
## 2  2018               317599                    49581                   268018
## 3  2019               277088                    48241                   228847
## 4  2020               671909                   147861                   524048
## 5  2021               426967                    99320                   327647
## 6  2022               257723                    62188                   195535
## 7  2023                25189                     6710                    18479

The line graph shows the trend of feedback counts over the years. These three variables (“Total Feedback Count”, “Total Negative Feedback Count” and “Total Positive Feedback Count”) show a high degree of correlation as they all follow a similar directional trend. Apart from that, the volume of feedback reaches its peak in 2020 with an impressive record of over 650,000. Besides that, the volume of positive feedback consistently surpasses negative feedback each year, which is a favorable indicator for Sephora’s performance and customer satisfaction.

Part 5: Sentiment Analysis

Part 5.1 Data Selection

# 5.1 Data Selection
# Import data
df <- read.csv("merged_clean.csv")

# Select the text, label and rating columns, rename & preview
df <- df[, c('review_text', 'is_recommended', 'rating')]
colnames(df) <- c('text', 'label', 'rating')
head(df)
##                                                                                                                                                                                                                                                                                                                                                                                                                              text
## 1                                                                                                                                                                                                       I wanted to try these to help with the texture of my skin, as well as visible pores. I am floored by the results. My pores shrank, and my skin is probably the smoothest it’s been in years! It even helped with dryness!
## 2                                                                                                                                                                                                     I’ve only been using this product for a few weeks and so far I’m seeing great results! The pats are super thick and the peach Bellini smell is yummy! You can see all the oil that is absorbed by the pads. Love it so far!
## 3                                                                                                                                                                                                                                                 Ever since I’ve started using this, I’ve had no blackheads whatsoever. I couldn’t be happier and it is now is staple in my skin care routine. I highly recommend this product.
## 4                                                                               I am in love with these must have acne pads. Anytime I feel a zit or pimple come on, I wipe it down with one of these, and the next day it’s either gone, or tiny. I use these after micro blading to keep my face from breaking out, and it works wonders! One container lasted me 4 months. I will never go without these, they’re a must have!
## 5 I’m so thankful that I discovered this product. I developed sebaceous hyperplasia on my forehead. I’ve had in-office treatment ( electrocauterization ) done and they just come back. My dermatologist prescribed me Tret 0.05% and it did nothing. I recently purchased these pads and my forehead is clearing up. I think that the combo of Tret 0.05% and these pads is what finally did the trick. Thank freaking goodness!
## 6                                                                                                                                                                                                                                           Very potent but wow my skin is so soft and i have no more texture. Acne is actually gone. Recommend using one pad a day just so your skin doesn’t strip and use a good moisturizer !!
##   label rating
## 1     1      5
## 2     1      5
## 3     1      5
## 4     1      5
## 5     1      5
## 6     1      5

Part 5.2 Handling imbalanced data

# 5.2 Handling imbalanced data
# Summary of positive (1) and negative (0) reviews in count and percentage
table(df$label)
## 
##      0      1 
##  50910 165866
positive_percentage <- round(table(df$label)[2] / nrow(df) * 100, 2)
negative_percentage <- round(table(df$label)[1] / nrow(df) * 100, 2)
cat("Positive labels percentage:", positive_percentage, "%\n")
## Positive labels percentage: 76.51 %
cat("Negative labels percentage:", negative_percentage, "%\n")
## Negative labels percentage: 23.49 %
# Balancing the dataset
df_neg <- df[df$label == 0, ]
df_pos <- df[df$label == 1, ]
df_pos_sampled <- df_pos[sample(nrow(df_pos), nrow(df_neg)), ]

# Checking label counts in negative and positive subsets
table(df_neg$label)
## 
##     0 
## 50910
table(df_pos_sampled$label)
## 
##     1 
## 50910
# Concatenating and shuffling to get final usable dataset
df_balanced <- rbind(df_pos_sampled, df_neg)
df_balanced <- df_balanced[sample(nrow(df_balanced)), ]
head(df_balanced)
##                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              text
## 208408 This is the Vitamin C serum we have all been searching for!! All the benefits of a Vitamin C serum, but it actually plays well under makeup! It absorbs fast without drying out or leaving a film on the skin. Not only that, it elevates my look and makes my makeup look and stay put even better. Doesn’t dry out my normal-dry skin, and no surprise breakouts. Just happy glowing skin! I love that I can turn a dull skin day into a fantastic one with just a half pump of this magical face elixir!  A little goes a long way, so the serum is as cost effective as it is functional, which we all know is a rarity when it comes to quality skincare. The packaging is almost as amazing as the serum itself! Never seen anything like it before. The “cap“ isn’t a cap. The top twists (2 clicks) to reveal the pump. No more lost caps or accidental product waste (from accidental pumps, from losing the cap lol). Can’t say enough amazing things about this Vitamin C Brightening serum! Highly recommend!!
## 62292                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Great dupe for Glossier’s super bounce! A little thicker but I love it.
## 141026                                                              This is a super serum all right.  Super terrible serum.  It is beyond me why these skincare companies, with all the research on ingredients and what works for skin, still insist upon adding cheap, toxic, irritating ingredients to their products.  Has anyone bothered to read the ingredient list?  Second ingredient -Dimethicone.  Alright. Not terrible.  It’s a filler, but being second means that’s most all this serum is.  Filler.  THIRD -and this is what dropped my jaw.  Witch hazel.  Witch hazel is a plant derivative that when derived from bark, the ingredient is left with skin irritating, sensitizing ALCOHOL.  I would NEVER put this anywhere near my face.  Orange peel oil?!  It is used as fragrance (bad for skin ) and it is very sensitizing on skin.  The toted hyaluronic acid... it’s halfway down in the ingredient list, after all the fillers and muck so there isn’t much of it in it.  I am appalled by this serum.
## 167536                                                                                                                                                                                                       This product has no identifiable smell so it’s easy to use on your skin. What I don’t like is how the consistency is just like water so it will drip quickly. When I pat it on my face it leave my hands super sticky. My face right now is sticky. I just put my chin to my shoulder and felt my skin do the stretchy thing when it’s stuck to something. The application is in the bottle pretty snugly so if you tip it over i doubt any will spill out. I imagine it’s that way because of its watery consistency. I definitely don’t see this lasting very long if you have to use twice a day and you have to use more because it’s so thin and spreads weird. I don’t think I’ll buy it again. But maybe it will make my skin the best it’s ever been. If it does, I’ll post another review of edit this one.
## 19749                                                                                                                                                                                                                                                                                                                    I received this product for free in exchange for my honest review. I have been fighting adult acne for years. I’m 25 years old, and with fair skin that scars easily, I am even more self conscious about any breakouts. I’ve been using this cleanser for about 3 or 4 weeks now. This is the first cleanser that has made a visible difference in my skin! My breakouts were smoothed and diminished immediately, and I’ve even seen a change in my scarring. It’s just strong enough to give the skin a good chemical exfoliation, but not so strong that it dries you out. It leaves my skin fresh and smooth! Love! Will definitely be a repeat purchase until I banish acne and scarring for good!
## 188213                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     It leaves my skin feeling more moisturized and clean at the same time.
##        label rating
## 208408     1      5
## 62292      1      5
## 141026     0      1
## 167536     0      2
## 19749      1      5
## 188213     1      5
# Print percentage of both labels present in the balanced dataset
positive_percentage_balanced <- round(table(df_balanced$label)[2] / nrow(df_balanced) * 100, 2)
negative_percentage_balanced <- round(table(df_balanced$label)[1] / nrow(df_balanced) * 100, 2)
cat("Positive labels percentage:", positive_percentage_balanced, "%\n")
## Positive labels percentage: 50 %
cat("Negative labels percentage:", negative_percentage_balanced, "%\n")
## Negative labels percentage: 50 %

Part 5.3 Text Pre-processing

# 5.3 Text Pre-processing
preprocess_text <- function(text) {
  # Create a corpus
  corpus <- Corpus(VectorSource(text))
  # Convert text to lowercase
  corpus <- tm_map(corpus, content_transformer(tolower))
  # Remove punctuation
  corpus <- tm_map(corpus, removePunctuation)
  # Remove numbers
  corpus <- tm_map(corpus, removeNumbers)
  # Remove stop words
  corpus <- tm_map(corpus, removeWords, stopwords("english"))
  # Strip whitespace
  corpus <- tm_map(corpus, stripWhitespace)
  # Remove special characters (non-alphabetic)
  corpus <- tm_map(corpus, content_transformer(function(x) gsub("[^[:alpha:][:space:]]*", "", x)))
  # Convert corpus to a character vector
  cleaned_text <- sapply(corpus, as.character)
  return(cleaned_text)
}

# Preprocess text data & generate a new column
df_balanced$cleaned_text <- preprocess_text(df_balanced$text)

# View text before & after preprocessing
cat('Before preprocessing \n', df_balanced$text[2], '\n')
## Before preprocessing 
##  Great dupe for Glossier’s super bounce! A little thicker but I love it.
cat('After preprocessing \n', df_balanced$cleaned_text[2], '\n')
## After preprocessing 
##  great dupe glossiers super bounce little thicker love

Part 5.4 Split the data into training and testing sets (80-20)

# 5.4 Split the data into training and testing sets (80-20)
set.seed(123) # Set seed for reproducibility
train_indices <- sample(1:nrow(df_balanced), 0.8 * nrow(df_balanced))
train_data <- df_balanced[train_indices, ]
test_data <- df_balanced[-train_indices, ]

Part 5.5 Vectorize text data using TF-IDF

# 5.5 Vectorize text data using TF-IDF
# Create a corpus for the balanced dataset using the cleaned text
corpus <- corpus(df_balanced, text_field = "cleaned_text")

# Tokenize the corpus
tokens <- tokens(corpus, what = "word", remove_punct = TRUE, remove_symbols = TRUE, remove_numbers = TRUE, remove_url = TRUE)

# Create the Document-Feature Matrix (DFM) from tokens and apply TF-IDF weighting
dfm <- dfm(tokens) %>%
  dfm_tfidf()

# Split the DFM into training and testing sets based on indices
train_dfm <- dfm[train_indices, ]
test_dfm <- dfm[-train_indices, ]

# Ensure the labels are factors for classification
train_labels <- as.factor(df_balanced$label[train_indices])
test_labels <- as.factor(df_balanced$label[-train_indices])

Part 5.6 Train and test using the Naive Bayes Model

# 5.6 Train and test using the Naive Bayes Model
# Train Naive Bayes model using the quanteda.textmodels package
naive_bayes_model <- textmodel_nb(train_dfm, train_labels)

# Predict on the test set using the quanteda.textmodels package
predictions <- predict(naive_bayes_model, newdata = test_dfm)

Part 5.7 Evaluation of the Naive Bayes model

# 5.7 Evaluation of the Naive Bayes model
# Evaluate the model using confusion matrix
confusion_matrix <- table(Predicted = predictions, Actual = test_labels)

# Print confusion matrix
print(confusion_matrix)
##          Actual
## Predicted    0    1
##         0 8792 1409
##         1 1370 8793
# Calculate accuracy, precision, recall, and F1 score
accuracy <- sum(diag(confusion_matrix)) / sum(confusion_matrix)
precision <- confusion_matrix[2, 2] / sum(confusion_matrix[2, ])
recall <- confusion_matrix[2, 2] / sum(confusion_matrix[, 2])
f1_score <- 2 * precision * recall / (precision + recall)

cat("Accuracy:", round(accuracy, 2), "\n")
## Accuracy: 0.86
cat("Precision:", round(precision, 2), "\n")
## Precision: 0.87
cat("Recall:", round(recall, 2), "\n")
## Recall: 0.86
cat("F1 Score:", round(f1_score, 2), "\n")
## F1 Score: 0.86

Part 6: Topic Modelling

Part 6.1 Product selection

# Import Raw Data
product_try <- read.csv("merged_clean.csv")

# Filter the data based on specific conditions
top1_cleanser_notrecommended <- product_try %>%
  filter(
    product_name == 'Superfood Antioxidant Cleanser',
    is_recommended == 0
  )
top1_cleanser_recommended <- product_try %>%
  filter(
    product_name == 'Superfood Antioxidant Cleanser',
    is_recommended == 1
  )
bottom1_cleanser_recommended <- product_try %>%
  filter(
    product_name == 'Melting Cleansing Balm Cleanse + Balance',
    is_recommended == 1
  )
bottom1_cleanser_notrecommended <- product_try %>%
  filter(
    product_name == 'Melting Cleansing Balm Cleanse + Balance',
    is_recommended == 0
  )

Part 6.2 LDA Preprocessing & Modelling

perform_lda <- function(data, product_name, is_recommended, num_topics = 5) {
  # Ensure the review_text column is of character type
  data$review_text <- as.character(data$review_text)
  
  # Check the filtered data
  print(paste("Number of reviews for", product_name, "(Recommended:", is_recommended, "):", nrow(data)))
  if (nrow(data) > 0) {
    print(head(data$review_text))
  } else {
    stop("No reviews found for the specified product and conditions.")
  }
  
  # LDA START
  # Create a corpus
  corpus <- Corpus(VectorSource(data$review_text))
  
  # Check if corpus is empty
  if (length(corpus) == 0) {
    stop("Corpus is empty. Please check the input data and transformations.")
  }
  
  # Convert text to lowercase
  corpus <- tm_map(corpus, content_transformer(tolower))
  # Remove punctuation
  corpus <- tm_map(corpus, removePunctuation)
  # Remove numbers
  corpus <- tm_map(corpus, removeNumbers)
  # Remove stop words
  corpus <- tm_map(corpus, removeWords, stopwords("english"))
  # Strip whitespace
  corpus <- tm_map(corpus, stripWhitespace)
  # Remove special characters (non-alphabetic)
  corpus <- tm_map(corpus, content_transformer(function(x) gsub("[^[:alpha:][:space:]]*", "", x)))
  
  # Inspect the corpus after preprocessing
  inspect_corpus <- function(corpus, n = 5) {
    if (length(corpus) < n) {
      n <- length(corpus)
    }
    for (i in 1:n) {
      cat(paste("Document", i, ":", "\n"))
      cat(content(corpus[[i]]), "\n\n")
    }
  }
  inspect_corpus(corpus)
  
  # Create a Document-Term Matrix
  dtm <- DocumentTermMatrix(corpus)
  print(paste("Number of documents in DTM:", nrow(dtm)))
  print(paste("Number of terms in DTM:", ncol(dtm)))
  
  # Check if the DTM is empty
  if (nrow(dtm) == 0 || ncol(dtm) == 0) {
    stop("Document-Term Matrix is empty. Please check the input data and transformations.")
  }
  
  # Build LDA model
  lda_model <- LDA(dtm, k = num_topics, control = list(seed = 1234))
  
  # Extract terms from the model
  terms <- terms(lda_model, 10)
  cat("LDA Terms for", product_name, "(Recommended:", is_recommended, "):\n")
  print(terms)
}

Part 6.3 LDA Iteration

# Apply the function to each dataset
perform_lda(top1_cleanser_notrecommended, "Superfood Antioxidant Cleanser", 0)
## [1] "Number of reviews for Superfood Antioxidant Cleanser (Recommended: 0 ): 603"
## [1] "somehow, the price of this isn’t the worst part about it- it’s the fact that it straight up doesn’t work for me, even though you can’t find a list for combination skin without seeing this wash. i don’t get it. i’ve tried it twice now (not two times, two bottles worth) both alone in the morning, alone at night, with a double cleanse + any other way you could use a face wash and most of the time i found residue/makeup on my cotton pad and saw little to no results. the smell is amazing. if it were made into a candle or air freshener, i’d happily buy it."
## [2] "My skin hated this, it left my face red and tight. Gifted to my cousin, it worked much better for her. Really wanted to like this product but I am clearly sensitive to an ingredient or two."                                                                                                                                                                                                                                                                                                                                                                               
## [3] "I wanted to love this product due to the glowing reviews. I used it for two weeks and my whole forehead broke out terribly. Within 3 days of not using my skin started immediately getting better."                                                                                                                                                                                                                                                                                                                                                                          
## [4] "I really wanted to love it, but it dried my skin and I got a few pimple right after using it. Happy I only got the mini won’t be getting again."                                                                                                                                                                                                                                                                                                                                                                                                                             
## [5] "I don’t write many reviews but I had to for this. I hate this. I’ve tried to like it but it keeps making me break out so bad. :(("                                                                                                                                                                                                                                                                                                                                                                                                                                           
## [6] "So the cleanser definitely made my face feel cool and clean after each use, but I would break out like crazy every time so after a few uses I was forced to stop using. It seems great, smells clean, but definitely not for everyone."                                                                                                                                                                                                                                                                                                                                      
## Document 1 : 
## somehow price isnt worst part s fact straight doesnt work even though cant find list combination skin without seeing wash dont get ve tried twice now two times two bottles worth alone morning alone night double cleanse way use face wash time found residuemakeup cotton pad saw little results smell amazing made candle air freshener d happily buy  
## 
## Document 2 : 
##  skin hated left face red tight gifted cousin worked much better really wanted like product clearly sensitive ingredient two 
## 
## Document 3 : 
##  wanted love product due glowing reviews used two weeks whole forehead broke terribly within days using skin started immediately getting better 
## 
## Document 4 : 
##  really wanted love dried skin got pimple right using happy got mini wont getting  
## 
## Document 5 : 
##  dont write many reviews hate ve tried like keeps making break bad  
## 
## [1] "Number of documents in DTM: 603"
## [1] "Number of terms in DTM: 2461"
## LDA Terms for Superfood Antioxidant Cleanser (Recommended: 0 ):
##       Topic 1    Topic 2    Topic 3    Topic 4    Topic 5   
##  [1,] "skin"     "skin"     "cleanser" "face"     "skin"    
##  [2,] "cleanser" "product"  "like"     "using"    "dry"     
##  [3,] "using"    "like"     "feel"     "product"  "cleanser"
##  [4,] "use"      "cleanser" "didnt"    "skin"     "product" 
##  [5,] "product"  "face"     "just"     "just"     "really"  
##  [6,] "bottle"   "using"    "good"     "cleanser" "face"    
##  [7,] "also"     "use"      "love"     "like"     "oily"    
##  [8,] "didnt"    "didnt"    "dont"     "really"   "price"   
##  [9,] "face"     "just"     "dry"      "dont"     "like"    
## [10,] "acne"     "feel"     "skin"     "bottle"   "didnt"
perform_lda(top1_cleanser_recommended, "Superfood Antioxidant Cleanser", 1)
## [1] "Number of reviews for Superfood Antioxidant Cleanser (Recommended: 1 ): 1732"
## [1] "I have used this on and off for a few years now. It didn’t do too much for my oily-ness but I did notice my pores appear larger when I’m not using this. No wow factor tho"                                                                                                                                                                                
## [2] "Love this product, leaves my face feeling fresh and clean."                                                                                                                                                                                                                                                                                                
## [3] "I’ve used this for a few years now after searching for a product that works on my temperamental combination skin. I find this cleanses well without feeling like it’s stripping my skin, and when followed with moisturizing products I find it’s the perfect first step in my am/pm skincare. Also love that you can buy the refillable size!"            
## [4] "I LOVE THIS FACE WASH. It smells so nice, subtle of course. It washes my skin well and doesnt leave it feeling dry and I have super dry skin with psoriasis. But dang why does it have to be so expensive!? I literally have to treat myself to get this face wash. It works great but for the price there should be chunks of gold in there or something."
## [5] "For the price it was a no for me. It gave the same results as a 12$ Walmart face wash. I will finish it because I paid for it but will not waste the money again."                                                                                                                                                                                         
## [6] "After using this for myself, i feel as thought this is probably overpriced. it’s a good cleanser but i noticed better results from a cleanser that was significantly cheaper. i do like the smell though."                                                                                                                                                 
## Document 1 : 
##  used years now didnt much oilyness notice pores appear larger m using wow factor tho 
## 
## Document 2 : 
## love product leaves face feeling fresh clean 
## 
## Document 3 : 
## ve used years now searching product works temperamental combination skin find cleanses well without feeling like s stripping skin followed moisturizing products find s perfect first step ampm skincare also love can buy refillable size 
## 
## Document 4 : 
##  love face wash smells nice subtle course washes skin well doesnt leave feeling dry super dry skin psoriasis dang expensive literally treat get face wash works great price chunks gold something 
## 
## Document 5 : 
##  price gave results walmart face wash will finish paid will waste money  
## 
## [1] "Number of documents in DTM: 1732"
## [1] "Number of terms in DTM: 4293"
## LDA Terms for Superfood Antioxidant Cleanser (Recommended: 1 ):
##       Topic 1    Topic 2    Topic 3    Topic 4    Topic 5   
##  [1,] "skin"     "skin"     "product"  "cleanser" "skin"    
##  [2,] "face"     "use"      "skin"     "love"     "cleanser"
##  [3,] "dry"      "face"     "cleanser" "skin"     "face"    
##  [4,] "love"     "like"     "like"     "feel"     "clean"   
##  [5,] "use"      "using"    "using"    "clean"    "love"    
##  [6,] "acne"     "makeup"   "dry"      "acne"     "like"    
##  [7,] "cleanser" "just"     "use"      "size"     "smells"  
##  [8,] "clean"    "also"     "doesnt"   "using"    "great"   
##  [9,] "one"      "cleanser" "really"   "will"     "really"  
## [10,] "great"    "product"  "leaves"   "feeling"  "just"
perform_lda(bottom1_cleanser_recommended, "Melting Cleansing Balm Cleanse + Balance", 1)
## [1] "Number of reviews for Melting Cleansing Balm Cleanse + Balance (Recommended: 1 ): 145"
## [1] "i really like it! before using it, I was doing a single wash but the double wash has made a difference! i don’t have a ton of experience with cleansing balms and perhaps I like this one because it’s the first one I tried. it feels very nice on the skin and has a subtle scent that is nice as well. I won’t give it 5 stars cause I’m not raving over it but I still think it’s a great option and I’m happy with the price and quality overall!"                                                                                                                                                                                                              
## [2] "Generally a really good product. Helps to effectively remove makeup. Would not recommend for oily skin. But overall decent. Needed to apply more than indicated on the package."                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
## [3] "The best cleansing balm ever, doesn’t sting eyes and is super hydrating and not stripping. 100% recommend :)"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
## [4] "Ever since I got this, this is almost the only thing I use to take off my makeup. Formula is quite nice and convenient packaging. Really comparable to the more high end cleansing balms. It’s most likely discontinued now which is shocking and sad!"                                                                                                                                                                                                                                                                                                                                                                                                              
## [5] "Okay so here is the rundown on this product: If you’re looking for a luxurious cleansing balm that breaks down makeup really well and leaves your skin feeling refreshed and clean after one cleanse, this isn’t the product for you. HOWEVER, for the price along with the amount of product you get, it is a decent product. I use it to remove my makeup after a night out and always follow with a second cleanse. My skin feels very clean and makeup free after! Does it have a nice smell and feel luxurious on my face? No. But it’s honestly a great bang for your buck and I’ll probably buy it again because it hasn’t broken me out! Overall rating: 4/5"
## [6] "The first time I bought it I would have given it 5 stars.Dig in, apply to dry face,  rinse off. It was amazing at removing all my makeup without a mess.I ordered it again after having to wait for it to come back in stock. I believe the product has been watered down, as it is now quite sloppy to apply/use. The entire consistency is just... runnier than the last one was.  A lot runnier.I’m not buying it again."                                                                                                                                                                                                                                         
## Document 1 : 
##  really like using single wash double wash made difference dont ton experience cleansing balms perhaps like one s first one tried feels nice skin subtle scent nice well wont give stars cause m raving still think s great option m happy price quality overall 
## 
## Document 2 : 
## generally really good product helps effectively remove makeup recommend oily skin overall decent needed apply indicated package 
## 
## Document 3 : 
##  best cleansing balm ever doesnt sting eyes super hydrating stripping recommend  
## 
## Document 4 : 
## ever since got almost thing use take makeup formula quite nice convenient packaging really comparable high end cleansing balms s likely discontinued now shocking sad 
## 
## Document 5 : 
## okay rundown product re looking luxurious cleansing balm breaks makeup really well leaves skin feeling refreshed clean one cleanse isnt product however price along amount product get decent product use remove makeup night always follow second cleanse skin feels clean makeup free nice smell feel luxurious face s honestly great bang buck ll probably buy hasnt broken overall rating  
## 
## [1] "Number of documents in DTM: 145"
## [1] "Number of terms in DTM: 1058"
## LDA Terms for Melting Cleansing Balm Cleanse + Balance (Recommended: 1 ):
##       Topic 1     Topic 2     Topic 3     Topic 4     Topic 5     
##  [1,] "cleansing" "makeup"    "makeup"    "skin"      "balm"      
##  [2,] "balm"      "face"      "skin"      "makeup"    "makeup"    
##  [3,] "makeup"    "farmacy"   "use"       "price"     "cleansing" 
##  [4,] "skin"      "get"       "like"      "balm"      "skin"      
##  [5,] "like"      "balm"      "product"   "oil"       "clean"     
##  [6,] "one"       "one"       "face"      "cleansing" "doesnt"    
##  [7,] "product"   "product"   "love"      "doesnt"    "love"      
##  [8,] "love"      "just"      "really"    "well"      "little"    
##  [9,] "balms"     "love"      "cleansing" "like"      "way"       
## [10,] "sephora"   "cleansing" "cleanse"   "leaves"    "definitely"
perform_lda(bottom1_cleanser_notrecommended, "Melting Cleansing Balm Cleanse + Balance", 0)
## [1] "Number of reviews for Melting Cleansing Balm Cleanse + Balance (Recommended: 0 ): 80"
## [1] "This wasn’t my favorite cleansing balm. It does not melt and turn into a creamy balm/oil like others. It says thick and lotiony and didn’t do a good job at breaking my makeup down. Also left a film on my skin. Pass on this one!"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
## [2] "This doesn’t remove regular mascara as seamlessly as other cleansing balms and oils I’ve tried. Crumbly bits stay on your eyes and it takes a lot of rubbing which can cause lash fallout or skin irritation. It washes off okay, but you definitely need to double cleanse to feel “clean“. I think if you can spare a few extra dollars, the physicians formula cleansing balm is much much better. This is also personal preference but I really wish this wasn’t in a tub – a squeeze tube is so much more hygienic and easy to portion control"                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
## [3] "I tried this because I liked their previous cleansing oil and cleansing oil in balm, both which are no longer for sale.I didn’t really like the texture when applying, but I didn’t think much of it because it’s meant to be removed.After washing with warm water, it still felt filmy even though it says specifically it won’t, but I still didn’t think much of it because I was using it in a double cleanse, as I will wash again with a water-based cleanser.After finishing the double “cleanse“, it did not feel clean at all. I had to double cleanse again, after using the water-based cleanser again, before my face felt close to normal. So 5x cleansing, which is ridiculous. This is the only product I’ve tried from this store that I wanted to return, but of course now I can’t because of the shortened return window. I did try adding jojoba oil when applying this and it seems to wash away much easier now (only double cleansing once). So at least not a total waste of money, I guess."
## [4] "Vaseline is better than this. Really disappointed in this product which will now just sit in my bathroom to rot."                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
## [5] "Let me start this review by saying I don’t wear makeup so i can’t attest to its makeup removing ability. i use this as the first cleanse in my double cleanse to remove sunscreen but it’s just ok. it has a very strong scent that i don’t like (and i don’t even mind fragrance in products) and doesn’t really “melt” as the name would suggest. It does leave a weird film on your face after rinsing. Makes your eyes cloudy after rubbing it on your face. Even for the price, I think you’d be better off just buying a more expensive one that’s better. It manages to get my sunscreen off decently well but i’d imagine you it would be tough to get makeup off with it. Overall, i’d say find another cleansing balm/oil if you are looking for one."                                                                                                                                                                                                                                                      
## [6] "Bought this as a cheaper substitute for Farmacy Green Clean but wouldn’t repurchase. The cleansing power of it works well but the consistency is much different than green clean. Feels more like a thick gel than balm and takes a while warm up in your fingers before working into the skin, which makes it feel like I’m pulling my skin by using this. Not worth returning. As long as I have the budget for Farmacy I’ll stick with that."                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
## Document 1 : 
##  wasnt favorite cleansing balm melt turn creamy balmoil like others says thick lotiony didnt good job breaking makeup also left film skin pass one 
## 
## Document 2 : 
##  doesnt remove regular mascara seamlessly cleansing balms oils ve tried crumbly bits stay eyes takes lot rubbing can cause lash fallout skin irritation washes okay definitely need double cleanse feel clean think can spare extra dollars physicians formula cleansing balm much much better also personal preference really wish wasnt tub  squeeze tube much hygienic easy portion control 
## 
## Document 3 : 
##  tried liked previous cleansing oil cleansing oil balm longer salei didnt really like texture applying didnt think much s meant removedafter washing warm water still felt filmy even though says specifically wont still didnt think much using double cleanse will wash waterbased cleanserafter finishing double cleanse feel clean double cleanse using waterbased cleanser face felt close normal x cleansing ridiculous product ve tried store wanted return course now cant shortened return window try adding jojoba oil applying seems wash away much easier now double cleansing least total waste money guess 
## 
## Document 4 : 
## vaseline better really disappointed product will now just sit bathroom rot 
## 
## Document 5 : 
## let start review saying dont wear makeup cant attest makeup removing ability use first cleanse double cleanse remove sunscreen s just ok strong scent dont like dont even mind fragrance products doesnt really melt name suggest leave weird film face rinsing makes eyes cloudy rubbing face even price think d better just buying expensive one s better manages get sunscreen decently well d imagine tough get makeup overall d say find another cleansing balmoil looking one 
## 
## [1] "Number of documents in DTM: 80"
## [1] "Number of terms in DTM: 729"
## LDA Terms for Melting Cleansing Balm Cleanse + Balance (Recommended: 0 ):
##       Topic 1     Topic 2     Topic 3      Topic 4   Topic 5    
##  [1,] "like"      "skin"      "cleansing"  "skin"    "makeup"   
##  [2,] "cleansing" "balm"      "really"     "like"    "balm"     
##  [3,] "balm"      "using"     "like"       "face"    "like"     
##  [4,] "product"   "also"      "makeup"     "makeup"  "well"     
##  [5,] "balms"     "product"   "doesnt"     "doesnt"  "doesnt"   
##  [6,] "skin"      "mascara"   "face"       "feels"   "cleansing"
##  [7,] "eyes"      "left"      "definitely" "balm"    "get"      
##  [8,] "mascara"   "well"      "product"    "texture" "dont"     
##  [9,] "face"      "try"       "skin"       "clean"   "thick"    
## [10,] "work"      "cleansing" "cleanser"   "thick"   "eyes"

Part 6.4: LDA Evaluation

In the LDA model of text analysis, this study selected the product “Superfood Antioxidant Cleanser” with the most reviews in the Sephora skincare category and the product “Melting Cleansing Balm Cleanse + Balance” with fewer reviews as the analysis objects. By comparing user reviews of these two products, this study aimed to explore the factors that influence the number of user reviews and analyze keywords that frequently appear in positive reviews.

First and foremost, for “Superfood Antioxidant Cleanser”, the top 50 keywords in its positive reviews include “skin”, “face”, “love”, “like”, “clean”, etc., with a total of 1,732 positive reviews. These positive reviews mainly express users’ satisfaction with the cleansing effect of the cleanser and its gentleness on the skin. As for negative reviews, there were 603 in total. These reviews mainly focused on skin discomfort that the product may cause, such as dryness, allergies, or failure to achieve the expected cleaning effect.

Next, for “Melting Cleansing Balm Cleanse + Balance”, the top 50 keywords in the positive reviews include “cleansing”, “makeup”, “balm”, “price”, “skin”, etc., with a total of 145 positive reviews. The positive reviews from users mainly emphasized the product’s effectiveness in removing makeup and cleaning, while there were 80 negative reviews, which mainly pointed out some shortcomings of the product, such as incomplete makeup removal, poor use feeling or residual feeling.

Part 7: Conclusion

The study analyzed product reviews and information from multiple datasets, revealing a high level of customer satisfaction. The top 1 recommended and most expensive products were identified, with “Niacinamide 10% + Zinc 1% Oil Control Serum” being the most recommended. The Naive Bayes model achieved an accuracy of 0.89, with precision and recall scores of 0.88 and 0.90, respectively. Topic modeling was used to uncover prevalent themes in both recommended and not recommended reviews. Future recommendations include exploring advanced machine learning algorithms, a comprehensive approach to feature engineering, and expanding the dataset with more diverse reviews. This analysis provided deeper insights into customer sentiments and product-specific issues.