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(wordcloud2)
## Warning: package 'wordcloud2' was built under R version 4.3.3
library(textclean)
## Warning: package 'textclean' was built under R version 4.3.3
library(tokenizers)
## Warning: package 'tokenizers' was built under R version 4.3.3
library(tidytext)
## Warning: package 'tidytext' was built under R version 4.3.3
library(formattable)
## Warning: package 'formattable' was built under R version 4.3.3
library(kableExtra)
## Warning: package 'kableExtra' was built under R version 4.3.3
## 
## Attaching package: 'kableExtra'
## The following object is masked from 'package:dplyr':
## 
##     group_rows
# read data
Justin_ori <- read.csv("C:/Users/fadhe/OneDrive/Documents/Belajar Coding/Kelas/JustinBieber.csv")

# melihat nama kolom
colnames(Justin_ori)
## [1] "X"      "Artist" "Title"  "Album"  "Year"   "Date"   "Lyric"
Justin_ori$Lyric[1]
## [1] "produced by benny blanco   for all the times that you rained on my parade and all the clubs you get in using my name you think you broke my heart oh girl for goodness sake you think i'm cryin' on my own well i ain't  refrain and i didn't wanna write a song 'cause i didn't want anyone thinking i still care i don't but you still hit my phone up and baby i'll be movin' on and i think you should be somethin' i don't wanna hold back maybe you should know that  pre my mama don't like you and she likes everyone and i never like to admit that i was wrong and i've been so caught up in my job didn't see what's going on but now i know i'm better sleeping on my own   'cause if you like the way you look that much oh baby you should go and love yourself and if you think that i'm still holdin' on to somethin' you should go and love yourself   but when you told me that you hated my friends the only problem was with you and not them and every time you told me my opinion was wrong and tried to make me forget where i came from  refrain and i didn't wanna write a song 'cause i didn't want anyone thinking i still care i don't but you still hit my phone up and baby i'll be movin' on and i think you should be somethin' i don't wanna hold back maybe you should know that  pre my mama don't like you and she likes everyone and i never like to admit that i was wrong and i've been so caught up in my job didn't see what's going on but now i know i'm better sleeping on my own   'cause if you like the way you look that much oh baby you should go and love yourself and if you think that i'm still holdin' on to somethin' you should go and love yourself   for all the times that you made me feel small i fell in love now i feel nothin' at all i never felt so low and i was vulnerable was i a fool to let you break down my walls   'cause if you like the way you look that much oh baby you should go and love yourself and if you think that i'm still holdin' on to somethin' you should go and love yourself 'cause if you like the way you look that much oh baby you should go and love yourself and if you think that i'm still holdin' on to somethin' you should go and love yourself"
# mengganti kata yang tidak baku
Justin_ori$Lyric <- sapply(Justin_ori$Lyric, replace_contraction)

# mengganti singkata n' menjadi ng
indeks <- grep("n'", Justin_ori$Lyric)
Justin_ori$Lyric[indeks] <- gsub("n'", "ng", Justin_ori$Lyric[indeks])

# menghapus karakter spesial
removeSpecialChars <- function(x) gsub("[^a-zA-Z0-9 ]", " ", x)
Justin_ori$Lyric <- sapply(Justin_ori$Lyric, removeSpecialChars)

# menjadikan huruf kecil
Justin_ori$Lyric <- sapply(Justin_ori$Lyric, tolower)

# menambah kolom untuk memudahkan pembersihan tahun
Justin <- Justin_ori %>%
  mutate(decade = 
           ifelse(Justin_ori$Year %in% 2000:2009, "2000s", 
           ifelse(Justin_ori$Year %in% 2010:2019, "2010s", 
           ifelse(Justin_ori$Year %in% 2020:2029, "2020s", 
                  "NA"))))

# menambah kolom untuk memudahkan pembersihan album
Justin <- Justin %>%
  mutate(Ket_Album =
           ifelse(Justin$Album == "", "Tidak ber-album", "ber-album"))


# re-indexing
Justin$X <- 1:nrow(Justin)

Justin$Lyric[2]
## [1] "written by julia michaels justin tranter and justin bieber   you gotta go and get angry at all of my honesty you know i try but i do not do too well with apologies i hope i do not run out of time could someone call a referee because i just need one more shot at forgiveness i know you know that i made those mistakes maybe once or twice by once or twice i mean maybe a couple a hundred times so let me oh let me redeem oh redeem oh myself tonight because i just need one more shot at second chances  pre yeah is it too late now to say sorry because i am missing more than just your body oh is it too late now to say sorry yeah i know that i let you down is it too late to say i am sorry now   i am sorry yeah sorry yeah sorry yeah i know that i let you down is it too late to say i am sorry now   i will take every single piece of the blame if you want me to but you know that there is no innocent one in this game for two i will go i will go and then you go you go out and spill the truth can we both say the words and forget this  pre yeah is it too late now to say sorry because i am missing more than just your body oh is it too late now to say sorry yeah i know that i let you down is it too late to say i am sorry now   i am not just trying to get you back on me oh no no because i am missing more than just your body your body oh is it too late now to say sorry yeah i know that i let you down is it too late to say i am sorry now   i am sorry yeah sorry oh sorry yeah i know that i let you down is it too late to say i am sorry now i am sorry yeah sorry oh sorry yeah i know that i let you down is it too late to say i am sorry now"
write.csv(Justin, "Justin_Clear.csv")
Justin %>%
  filter(decade != "NA") %>%
  group_by(decade, Ket_Album) %>%
  summarise(number_of_songs = n()) %>%
  ggplot() +
  geom_bar(aes(x = decade, y = number_of_songs, 
               fill = Ket_Album), stat = "identity")  +
  theme(plot.title = element_text(hjust = 0.5),
        legend.title = element_blank(),
        panel.grid.minor = element_blank()) +
  labs(x = NULL, y = "Song Count") +
  ggtitle("All Songs in Data")
## `summarise()` has grouped output by 'decade'. You can override using the
## `.groups` argument.

full_word_count <- Justin %>%
  unnest_tokens(word, Lyric) %>%
  group_by(Title, Ket_Album) %>%
  summarise(num_words = n()) %>%
  arrange(desc(num_words))
## `summarise()` has grouped output by 'Title'. You can override using the
## `.groups` argument.

Word Frequency

full_word_count[1:8,] %>%
  ungroup(num_words, Title) %>%
  mutate(num_words = color_bar("lightblue")(num_words)) %>%
  mutate(Title = color_tile("lightpink","lightblue")(Title)) %>%
  kable("html", escape = FALSE, align = "c", caption = "Songs With Highest Word Count") %>%
  kable_styling(bootstrap_options = 
                  c("striped", "condensed", "bordered"), 
                  full_width = FALSE)
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `Title = color_tile("lightpink", "lightblue")(Title)`.
## Caused by warning in `gradient()`:
## ! NAs introduced by coercion
Songs With Highest Word Count
Title Ket_Album num_words
Bieber’s Paparazzi Deposition Tidak ber-album 1005
Runaway Love (Remix) ber-album 774
Boyfriend (Remix) Tidak ber-album 759
Confident - Single Version Tidak ber-album 752
Confident ber-album 750
Looking For You Tidak ber-album 744
One Less Lonely Girl ber-album 724
Can’t Wait ber-album 699
full_word_count %>%
  ggplot() +
    geom_histogram(aes(x = num_words, fill = Ket_Album )) +
    ylab("Song Count") + 
    xlab("Word Count per Song") +
    ggtitle("Word Count Distribution") +
    theme(plot.title = element_text(hjust = 0.5),
          legend.title = element_blank(),
          panel.grid.minor.y = element_blank())
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

undesirableWords <- c("prince", "chorus", "repeat", "lyrics", 
                       "theres", "bridge", "fe0f", "yeah", "baby", 
                       "alright", "wanna", "gonna", "chorus", "verse", 
                       "whoa", "gotta", "make", "miscellaneous", "2", 
                       "4", "ooh", "uurh", "pheromone", "poompoom", "3121", 
                       "matic", " ai ", " ca ", " la ", "hey", " na ", 
                       " da ", " uh ", " tin ", "  ll", "transcription",
                       "repeats")

Justin_words_filtered <- Justin %>%
  unnest_tokens(word, Lyric) %>%
  anti_join(stop_words) %>%
  distinct() %>%
  filter(!word %in% undesirableWords) %>%
  filter(nchar(word) > 3)
## Joining with `by = join_by(word)`
Justin_words_filtered %>%
  count(word, sort = TRUE) %>%
  top_n(10) %>%
  ungroup() %>%
  mutate(word = reorder(word, n)) %>%
  ggplot() +
    geom_col(aes(word, n)) +
    theme(legend.position = "none", 
          plot.title = element_text(hjust = 0.5),
          panel.grid.major = element_blank()) +
    xlab("") + 
    ylab("Song Count") +
    ggtitle("Most Frequently Used Words in Justin Lyrics") +
    coord_flip()
## Selecting by n

## Word Lenghts

Justin_word_lengths <- Justin %>%
  unnest_tokens(word, Lyric) %>%
  group_by(Title,decade) %>%
  distinct() %>%
  filter(!word %in% undesirableWords) %>%
  mutate(word_length = nchar(word)) 

Justin_word_lengths %>%
  count(word_length, sort = TRUE) %>%
  ggplot(aes(word_length), 
         binwidth = 10) + 
    geom_histogram(aes(fill = ..count..),
                   breaks = seq(1,25, by = 2), 
                   show.legend = FALSE) + 
    xlab("Word Length") + 
    ylab("Word Count") +
    ggtitle("Word Length Distribution") +
    theme(plot.title = element_text(hjust = 0.5),
          panel.grid.minor = element_blank())
## Warning: The dot-dot notation (`..count..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(count)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

wc <- Justin_word_lengths %>%
  ungroup() %>%
  select(word, word_length) %>%
  distinct() %>%
  arrange(desc(word_length))

wordcloud2(wc[1:200, ], 
           size = .15,
           minSize = .0005,
           ellipticity = .3, 
           rotateRatio = 1, 
           fontWeight = "bold")

Lexical Diversity

lex_diversity_per_year <- Justin %>%
  filter(decade != "NA") %>%
  unnest_tokens(word, Lyric) %>%
  group_by(Title,Year) %>%
  summarise(lex_diversity = n_distinct(word)) %>%
  arrange(desc(lex_diversity))
## `summarise()` has grouped output by 'Title'. You can override using the
## `.groups` argument.
diversity_plot <- lex_diversity_per_year %>%
  ggplot(aes(Year, lex_diversity)) +
    geom_point(alpha = .4,
               color = "brown",
               size = 4, 
               position = "jitter") + 
    stat_smooth(color = "black", se = FALSE, method = "lm") +
    geom_smooth(aes(x = Year, y = lex_diversity), se = FALSE,
                color = "blue", lwd = 2) +
    ggtitle("Lexical Diversity") +
    xlab("Years") + 
    ylab("") +
    theme_classic()

diversity_plot
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'

Lexical Density

lex_density_per_year <- Justin %>%
  filter(decade != "NA") %>%
  unnest_tokens(word, Lyric) %>%
  group_by(Title,Year) %>%
  summarise(lex_density = n_distinct(word)/n()) %>%
  arrange(desc(lex_density))
## `summarise()` has grouped output by 'Title'. You can override using the
## `.groups` argument.
density_plot <- lex_density_per_year %>%
  ggplot(aes(Year, lex_density)) + 
    geom_point(color = "red",
               alpha = .4, 
               size = 4, 
               position = "jitter") + 
    stat_smooth(color = "black", 
                se = FALSE, 
                method = "lm") +
    geom_smooth(aes(x = Year, y = lex_density), 
                se = FALSE,
                color = "blue", 
                lwd = 2) +
    ggtitle("Lexical Density") + 
    xlab("Years") + 
    ylab("") +
    theme_classic()

density_plot
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'