library(tidytext)
## Warning: package 'tidytext' was built under R version 4.6.1
library(tidyverse)
## Warning: package 'tidyverse' was built under R version 4.6.1
## Warning: package 'ggplot2' was built under R version 4.6.1
## Warning: package 'tibble' was built under R version 4.6.1
## Warning: package 'tidyr' was built under R version 4.6.1
## Warning: package 'purrr' was built under R version 4.6.1
## Warning: package 'dplyr' was built under R version 4.6.1
## Warning: package 'forcats' was built under R version 4.6.1
## Warning: package 'lubridate' was built under R version 4.6.1
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.2.1 ✔ readr 2.2.0
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ ggplot2 4.0.3 ✔ tibble 3.3.1
## ✔ lubridate 1.9.5 ✔ tidyr 1.3.2
## ✔ purrr 1.2.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(widyr)
## Warning: package 'widyr' was built under R version 4.6.1
library(igraph)
## Warning: package 'igraph' was built under R version 4.6.1
##
## Attaching package: 'igraph'
##
## The following objects are masked from 'package:lubridate':
##
## %--%, union
##
## The following objects are masked from 'package:dplyr':
##
## as_data_frame, groups, union
##
## The following objects are masked from 'package:purrr':
##
## compose, simplify
##
## The following object is masked from 'package:tidyr':
##
## crossing
##
## The following object is masked from 'package:tibble':
##
## as_data_frame
##
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
##
## The following object is masked from 'package:base':
##
## union
library(ggraph)
## Warning: package 'ggraph' was built under R version 4.6.1
library(checkdown)
## Warning: package 'checkdown' was built under R version 4.6.1
library(dplyr)
library(purrr)
library(tidyr)
library(lubridate)
library(tibble)
library(base)
library(tuber)
library(readr)
library(ggplot2)
library(wordcloud)
## Loading required package: RColorBrewer
library(RColorBrewer)
library(tm)
## Loading required package: NLP
##
## Attaching package: 'NLP'
##
## The following object is masked from 'package:ggplot2':
##
## annotate
library(httpuv)
library(stringr)
In this article, I learned the importance of automating text analyses. Because it is a tedious process to do by hand, or say, manually, using R to complete the task of analyzing text data made sense. In this article, he used OnePlus phones as a case study because the author is/was a customer of theirs. This was particularly interesting to me because I’d want to see what others are saying about a brand that I purchase from and doing it in this way could have meaningful results.
Because words like ‘the’, ‘and’, ‘a’, ‘to’, don’t necessarily provide sentiment, the author filtered them out for easier analysis and visualization. Overall, the article shows that learning text analysis with R can help business analysts extract meaningful insights from unstructured text data and improve decision-making through automation.
comments_clean <- read_csv("comments_clean.csv")
## Rows: 1377 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (3): authorDisplayName, textOriginal, id
## dbl (1): likeCount
## dttm (1): publishedAt
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
custom_stop_words <- tibble(
word = c("video", "like")
)
comments_words <- comments_clean %>%
select(id, textOriginal) %>%
unnest_tokens(word, textOriginal) %>%
anti_join(stop_words, by = "word") %>%
anti_join(custom_stop_words, by = "word") %>%
filter(!str_detect(word, "^[0-9]+$"))
comments_words %>%
count(word, sort = TRUE) %>%
head(20)
## # A tibble: 20 × 2
## word n
## <chr> <int>
## 1 band 125
## 2 music 118
## 3 scott 112
## 4 boy 110
## 5 fall 107
## 6 ian 90
## 7 song 89
## 8 love 86
## 9 time 85
## 10 rock 83
## 11 andy 79
## 12 awesome 79
## 13 anthrax 70
## 14 fob 70
## 15 lol 70
## 16 metal 67
## 17 fucking 62
## 18 joe 61
## 19 guys 56
## 20 album 52
comments_pairs <- comments_words %>%
pairwise_count(word, id, sort = TRUE, upper = FALSE)
comments_pairs %>%
head(20)
## # A tibble: 20 × 3
## item1 item2 n
## <chr> <chr> <dbl>
## 1 fall boy 90
## 2 scott ian 77
## 3 time die 39
## 4 joe andy 28
## 5 keith buckley 25
## 6 brian posehn 23
## 7 jon lajoie 22
## 8 boy anthrax 22
## 9 anthrax die 22
## 10 time anthrax 21
## 11 fall band 20
## 12 boy band 20
## 13 fall anthrax 19
## 14 anthrax scott 18
## 15 boy die 17
## 16 andy hair 17
## 17 music band 16
## 18 band fob 16
## 19 music boy 15
## 20 time boy 15
comments_pairs %>%
filter(n > 5) %>%
graph_from_data_frame() %>%
ggraph(layout = "fr") +
geom_edge_link(aes(edge_alpha = n, edge_width = n),
show.legend = FALSE) +
geom_node_point() +
geom_node_text(aes(label = name), repel = TRUE) +
labs(title = "Word Co-occurrence Network: YouTube Comments")
## Warning: The `trans` argument of `continuous_scale()` is deprecated as of ggplot2 3.5.0.
## ℹ Please use the `transform` argument instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
The additional words that I added manually were “video” and “like.” It made sense to remove these words because the audience is aware that it is a YouTube video in which the analysis takes place, and depending on region, “like” can be used as a filler word instead of something used to make a comparison or to declare whether or not they enjoyed the video.
I changed the filter value from n > 1 to n > 5. This means the graph only shows word pairs that appeared together more than five times. The result looked better because it removed weaker connections and made the network more evenly spaced and easier to interpret. My final value was 5 because it reduced clutter while still leaving enough word pairs to analyze.