This assignment was completed using the dataset from the previous word frequency analysis regarding the Mazda Miata. A word co-occurrence analysis was conducted to determine the direct relationships between paired words, providing deeper context regarding the underlying themes of the discussions.
library(tidyverse)
## ── 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(tidytext)
library(widyr)
library(igraph)
##
## 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)
library(knitr)
# I am specifically displaying only the text column in my scrapped data set.
comments_clean <- read_csv("Mazda_comments.csv", col_select = text, show_col_types = FALSE)
head(comments_clean)
## # A tibble: 6 × 1
## text
## <chr>
## 1 "Has anyone dropped a Kawasaki H2R engine into a car? Like a Caterham or a Mi…
## 2 "Isso e nunca terem importado oficialmente o MX-5 Miata"
## 3 "my Tacoma has the same size bed as anything else. only once have I need to …
## 4 "Well hey at least something's going right with the Miata\n\nTurns out my rou…
## 5 "Yeah, I got some work to do.. \"Fresh Canvas!\"\n**that's a 12 year old soft…
## 6 "I've been able to put pressure on my broken toe and took my brother-in-law o…
data(stop_words)
custom_stop_words <- tibble(
word = c("miata", "mazda", "car", "games"),
lexicon = "custom"
)
all_stop_words <- bind_rows(stop_words, custom_stop_words)
mazda_words <- comments_clean %>%
mutate(id = row_number()) %>%
select(id, text) %>%
filter(!is.na(text)) %>%
unnest_tokens(word, text) %>%
anti_join(all_stop_words, by = "word") %>%
filter(str_detect(word, "^[a-z]+$")) %>%
filter(str_length(word) > 2)
head(mazda_words)
## # A tibble: 6 × 2
## id word
## <int> <chr>
## 1 1 dropped
## 2 1 kawasaki
## 3 1 engine
## 4 1 caterham
## 5 2 isso
## 6 2 nunca
mazda_pairs <- mazda_words %>%
pairwise_count(word, id, sort = TRUE, upper = FALSE)
head(mazda_pairs, 20)
## # A tibble: 20 × 3
## item1 item2 n
## <chr> <chr> <dbl>
## 1 japan quieter 5
## 2 sale http 5
## 3 edition japan 3
## 4 edition quieter 3
## 5 edition stricter 3
## 6 japan stricter 3
## 7 quieter stricter 3
## 8 edition regulations 3
## 9 japan regulations 3
## 10 quieter regulations 3
## 11 stricter regulations 3
## 12 edition forced 3
## 13 japan forced 3
## 14 quieter forced 3
## 15 stricter forced 3
## 16 regulations forced 3
## 17 edition iconic 3
## 18 japan iconic 3
## 19 quieter iconic 3
## 20 stricter iconic 3
mazda_matrix <- mazda_pairs %>%
bind_rows(mazda_pairs %>% rename(item1 = item2, item2 = item1)) %>%
cast_sparse(item1, item2, n) %>%
as.matrix()
mazda_matrix[1:10, 1:10]
## quieter http japan stricter regulations forced iconic pure sport
## japan 5 0 0 3 3 3 3 3 3
## sale 0 5 0 0 0 0 0 0 0
## edition 3 0 3 3 3 3 3 3 3
## quieter 0 0 5 3 3 3 3 3 3
## stricter 3 0 3 0 3 3 3 3 3
## regulations 3 0 3 3 0 3 3 3 3
## forced 3 0 3 3 3 0 3 3 3
## iconic 3 0 3 3 3 3 0 3 3
## pure 3 0 3 3 3 3 3 0 3
## sport 3 0 3 3 3 3 3 3 0
## arrives
## japan 3
## sale 0
## edition 3
## quieter 3
## stricter 3
## regulations 3
## forced 3
## iconic 3
## pure 3
## sport 3
mazda_pairs %>%
filter(n > 1) %>%
graph_from_data_frame() %>%
ggraph(layout = "fr") +
geom_edge_link(alpha = 0.3) +
geom_node_point(color = "steelblue", size = 4) +
geom_node_text(aes(label = name), repel = TRUE) +
theme_void()
We are able to derive some insite into the dicustions and market response to the Mazdas Miata sports car. The Co-coccurrence network reveals the discussion around Miata to be clustered around the feeling, senation and iconic nature of the vehical. The words pure, iconic, beloved, and awesome provides great insight into the consumer sentiment of the car it self, which from what we can see is very favorable. Consumers are very satisfied with this vehical and the network provided a graph visualiztion to understand consumer sentiment for marketing purposes.
Q1: I removed ‘miata’, ‘mazda’, ‘car’, and ‘games’ from the dataset as custom stop words, selecting them for two main reasons. First, the words ‘miata’ and ‘mazda’ are prevalent throughout the comments; removing them ensures a more useful visualization free from the excessive clutter of dominant search terms. Second, ‘games’ was removed because the Mazda Miata is a highly popular vehicle to modify within various video games. While this finding is interesting in its own right, it clutters the network and makes it more difficult to isolate and understand consumers of the physical car.
Q2: When changing \(n\) from 1 to 3, the graph lost a significant number of its connections. This yielded a worse result for my analysis and provided much less useful insight.
Q3 I prefer the graph with fewer nodes. It is easier to follow and provides a clearer representation of which words are more frequently used.
Q4 The pairs that surprised me are “regulations” and “stricter.” This is interesting because it shows that some of the discussions surrounding the Miata involve complaints about the restrictions of the car.
Q5 Yes, both SPCX and SpaceX need to be added as separate tokens. Because they refer to the same company, linking them to the same token would ensure that the overall discussion of the company remains unified within the same network matrix.
Q6 A smaller dataset would be heavily biased due to the small number of respondents. This would not accurately represent true comment sentiment or reveal what the discussions and words are truly communicating. If forced to use a small dataset, I would need to disclose that the results are only representative of the analyzed sample and do not reflect the wider opinions of the community or demographic.
Q7 Yes, a topic can be analyzed through text scraping, especially if it stems from a significant event. Typically, significant events trend across the internet, allowing one to scrape data by targeting keywords surrounding the event. For example, a high-profile court trial—such as the legal proceedings involving Luigi Mangione—remains a highly relevant and trending topic. As the case develops, public views and opinions can shift wildly based on the emerging evidence.
By using co-occurrence analysis, we are able to reveal relationships that remain hidden during a simple word frequency analysis. The unique connections and pairings of words provide significantly greater value, allowing us to draw deeper insights and actionable business recommendations.