Introduction

Sir Robert Bryson Hall II, better known as Logic, is an American rapper, singer, songwriter and record producer. He is best known for his creative conceptual albums and broad range of music. This analysis will generate the different sentiments from each of his 8 albums. Logic is known to discuss topics raning from mental health and race to drugs and partying so because of this, it is predicted that his albums will have an overall negative sentiment.

Under Pressure

Step One: To run the genius package and select the first Logic album, Under Pressure

library(genius)
genius_album(artist = "logic", album = "under pressure") ->logic_pressure
## Joining, by = c("track_title", "track_n", "track_url")

Step Two: Filter out stop words and sort the remaining by number of appearances

library(tidyverse)
## ── Attaching packages ────────────────────────────────────────────────── tidyverse 1.3.0 ──
## ✓ ggplot2 3.2.1     ✓ purrr   0.3.3
## ✓ tibble  2.1.3     ✓ dplyr   0.8.4
## ✓ tidyr   1.0.2     ✓ stringr 1.4.0
## ✓ readr   1.3.1     ✓ forcats 0.4.0
## ── Conflicts ───────────────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::filter() masks stats::filter()
## x dplyr::lag()    masks stats::lag()
library(tidytext)
logic_pressure %>% 
  unnest_tokens(word,lyric) %>% 
  anti_join(stop_words) %>% 
  count(word, sort = TRUE) -> tidy_pressure
## Joining, by = "word"
tidy_pressure
## # A tibble: 1,160 x 2
##    word      n
##    <chr> <int>
##  1 yeah     69
##  2 shit     50
##  3 feel     48
##  4 fuck     44
##  5 na       36
##  6 uh       32
##  7 love     29
##  8 mind     26
##  9 fame     25
## 10 gotta    25
## # … with 1,150 more rows

Step Three: Create a custom stop words list

stopWords <- c("yeah", "na", "uh", "gotta", "i'ma", "wanna", "em")
stopWordsDF <- tibble(stopWords)

Step Four: Remove the remaining unwanted words

tidy_pressure1 <- tidy_pressure %>% 
  anti_join(stopWordsDF, by = c("word" = "stopWords"))

tidy_pressure1
## # A tibble: 1,153 x 2
##    word      n
##    <chr> <int>
##  1 shit     50
##  2 feel     48
##  3 fuck     44
##  4 love     29
##  5 mind     26
##  6 fame     25
##  7 life     24
##  8 bitch    22
##  9 god      21
## 10 hit      18
## # … with 1,143 more rows

Step Five: Generate a numbered sentiment from -5 to 5 for each word

tidy_pressure1afinn <- tidy_pressure1 %>% 
  inner_join(get_sentiments("afinn")) %>% 
  head(10)
## Joining, by = "word"
tidy_pressure1afinn
## # A tibble: 10 x 3
##    word        n value
##    <chr>   <int> <dbl>
##  1 shit       50    -4
##  2 fuck       44    -4
##  3 love       29     3
##  4 fame       25     1
##  5 bitch      22    -5
##  6 god        21     1
##  7 alive      14     1
##  8 hard       13    -1
##  9 crazy      11    -2
## 10 bitches    10    -5

Step Six: Create a wordcloud of all words

library(wordcloud2)
##install.packages("devtools")
library(devtools)
## Loading required package: usethis
##install_github("gaospecial/wordcloud2")
wordcloud2(tidy_pressure1)

This process was then repeated for each album.

The Incredible True Story

genius_album(artist = "logic", album = "the incredible true story") -> logic_story
## Joining, by = c("track_title", "track_n", "track_url")
logic_story %>% 
  unnest_tokens(word,lyric) %>% 
  anti_join(stop_words) %>% 
  count(word, sort = TRUE) -> tidy_story
## Joining, by = "word"
tidy_story
## # A tibble: 1,356 x 2
##    word       n
##    <chr>  <int>
##  1 yeah      82
##  2 fuck      52
##  3 life      45
##  4 shit      43
##  5 uh        39
##  6 em        38
##  7 fade      35
##  8 hold      31
##  9 love      26
## 10 people    26
## # … with 1,346 more rows
stopWords1 <- c("uh", "em", "yeah")
stopWordsDF1 <- tibble(stopWords1)

tidy_story1 <- tidy_story %>% 
  anti_join(stopWordsDF1, by = c("word" = "stopWords1"))

tidy_story1
## # A tibble: 1,353 x 2
##    word       n
##    <chr>  <int>
##  1 fuck      52
##  2 life      45
##  3 shit      43
##  4 fade      35
##  5 hold      31
##  6 love      26
##  7 people    26
##  8 bitch     21
##  9 day       21
## 10 feel      21
## # … with 1,343 more rows
tidy_story1afinn <- tidy_story1 %>% 
  inner_join(get_sentiments("afinn")) %>% 
  head(10)
## Joining, by = "word"
tidy_story1afinn
## # A tibble: 10 x 3
##    word         n value
##    <chr>    <int> <dbl>
##  1 fuck        52    -4
##  2 shit        43    -4
##  3 love        26     3
##  4 bitch       21    -5
##  5 paradise    13     3
##  6 damn        12    -4
##  7 god         11     1
##  8 goddamn     10    -3
##  9 wrong       10    -2
## 10 doubt        9    -1
library(wordcloud2)
wordcloud2(tidy_story1)

Bobby Tarantino

genius_album(artist = "logic", album = "bobby tarantino") -> logic_bt
## Joining, by = c("track_title", "track_n", "track_url")
logic_bt %>% 
  unnest_tokens(word,lyric) %>% 
  anti_join(stop_words) %>% 
  count(word, sort = TRUE) -> tidy_bt
## Joining, by = "word"
tidy_bt
## # A tibble: 771 x 2
##    word         n
##    <chr>    <int>
##  1 shit        98
##  2 yeah        65
##  3 god         49
##  4 money       48
##  5 fuck        37
##  6 goodness    34
##  7 deeper      32
##  8 hey         29
##  9 killin      21
## 10 flickin     18
## # … with 761 more rows
stopWords2 <- c("hey", "yeah")
stopWordsDF2 <- tibble(stopWords2)

tidy_bt1 <- tidy_bt %>% 
  anti_join(stopWordsDF2, by = c("word" = "stopWords2"))

tidy_bt1
## # A tibble: 769 x 2
##    word             n
##    <chr>        <int>
##  1 shit            98
##  2 god             49
##  3 money           48
##  4 fuck            37
##  5 goodness        34
##  6 deeper          32
##  7 killin          21
##  8 flickin         18
##  9 life            17
## 10 motherfucker    17
## # … with 759 more rows
tidy_bt1afinn <- tidy_bt1 %>% 
  inner_join(get_sentiments("afinn")) %>% 
  head(10)
## Joining, by = "word"
tidy_bt1afinn
## # A tibble: 10 x 3
##    word             n value
##    <chr>        <int> <dbl>
##  1 shit            98    -4
##  2 god             49     1
##  3 fuck            37    -4
##  4 goodness        34     3
##  5 motherfucker    17    -5
##  6 bitch           13    -5
##  7 hard            12    -1
##  8 fucking          8    -4
##  9 happy            8     3
## 10 damn             7    -4
wordcloud2(tidy_bt1)

Everybody

genius_album(artist = "logic", album = "everybody") -> logic_evb
## Joining, by = c("track_title", "track_n", "track_url")
logic_evb %>% 
  unnest_tokens(word,lyric) %>% 
  anti_join(stop_words) %>% 
  count(word, sort = TRUE) -> tidy_evb
## Joining, by = "word"
tidy_evb
## # A tibble: 1,147 x 2
##    word       n
##    <chr>  <int>
##  1 black     94
##  2 mind      77
##  3 god       68
##  4 wanna     68
##  5 people    66
##  6 shit      64
##  7 i'ma      55
##  8 feel      51
##  9 life      50
## 10 atom      48
## # … with 1,137 more rows
stopWords3 <- c("i'ma")
stopWordsDF3 <- tibble(stopWords3)

tidy_evb1 <- tidy_evb %>% 
  anti_join(stopWordsDF3, by = c("word" = "stopWords3"))

tidy_evb1
## # A tibble: 1,146 x 2
##    word       n
##    <chr>  <int>
##  1 black     94
##  2 mind      77
##  3 god       68
##  4 wanna     68
##  5 people    66
##  6 shit      64
##  7 feel      51
##  8 life      50
##  9 atom      48
## 10 fuck      40
## # … with 1,136 more rows
tidy_evb1afinn <- tidy_evb1 %>% 
  inner_join(get_sentiments("afinn")) %>% 
  head(10)
## Joining, by = "word"
tidy_evb1afinn
## # A tibble: 10 x 3
##    word        n value
##    <chr>   <int> <dbl>
##  1 god        68     1
##  2 shit       64    -4
##  3 fuck       40    -4
##  4 yeah       36     1
##  5 feeling    32     1
##  6 love       25     3
##  7 fight      22    -1
##  8 ass        16    -4
##  9 bitch      16    -5
## 10 die        16    -3
wordcloud2(tidy_evb1)

Bobby Tarantino II

genius_album(artist = "logic", album = "bobby tarantino ii") -> logic_bt2
## Joining, by = c("track_title", "track_n", "track_url")
logic_bt2 %>% 
  unnest_tokens(word,lyric) %>% 
  anti_join(stop_words) %>% 
  count(word, sort = TRUE) -> tidy_bt2
## Joining, by = "word"
tidy_bt2
## # A tibble: 966 x 2
##    word      n
##    <chr> <int>
##  1 yeah    127
##  2 shit     96
##  3 fuck     47
##  4 em       44
##  5 bitch    43
##  6 bobby    30
##  7 logic    30
##  8 life     28
##  9 morty    22
## 10 ay       20
## # … with 956 more rows
stopWords5 <- c("em", "ay", "yeah", "la", "woo")
stopWordsDF5 <- tibble(stopWords5)

tidy_bt21 <- tidy_bt2 %>% 
  anti_join(stopWordsDF5, by = c("word" = "stopWords5"))

tidy_bt21
## # A tibble: 961 x 2
##    word       n
##    <chr>  <int>
##  1 shit      96
##  2 fuck      47
##  3 bitch     43
##  4 bobby     30
##  5 logic     30
##  6 life      28
##  7 morty     22
##  8 money     20
##  9 feel      18
## 10 reason    18
## # … with 951 more rows
tidy_bt21afinn <- tidy_bt21 %>% 
  inner_join(get_sentiments("afinn")) %>% 
  head(10)
## Joining, by = "word"
tidy_bt21afinn
## # A tibble: 10 x 3
##    word      n value
##    <chr> <int> <dbl>
##  1 shit     96    -4
##  2 fuck     47    -4
##  3 bitch    43    -5
##  4 die      16    -3
##  5 hard     15    -1
##  6 fire     13    -2
##  7 leave    11    -1
##  8 love     11     3
##  9 trap     11    -1
## 10 warm     10     1
wordcloud2(tidy_bt21)

YSIV

genius_album(artist = "logic", album = "ysiv") -> logic_ysiv
## Joining, by = c("track_title", "track_n", "track_url")
logic_ysiv %>% 
  unnest_tokens(word,lyric) %>% 
  anti_join(stop_words) %>% 
  count(word, sort = TRUE) -> tidy_ysiv
## Joining, by = "word"
tidy_ysiv
## # A tibble: 2,167 x 2
##    word      n
##    <chr> <int>
##  1 shit    108
##  2 yeah    107
##  3 love     57
##  4 day      53
##  5 uh       51
##  6 fuck     47
##  7 feel     44
##  8 em       39
##  9 gotta    39
## 10 life     39
## # … with 2,157 more rows
stopWords6 <- c("em", "uh", "yeah")
stopWordsDF6 <- tibble(stopWords6)

tidy_ysiv1 <- tidy_ysiv %>% 
  anti_join(stopWordsDF6, by = c("word" = "stopWords6"))

tidy_ysiv1
## # A tibble: 2,164 x 2
##    word        n
##    <chr>   <int>
##  1 shit      108
##  2 love       57
##  3 day        53
##  4 fuck       47
##  5 feel       44
##  6 gotta      39
##  7 life       39
##  8 ayo        37
##  9 time       37
## 10 sinatra    29
## # … with 2,154 more rows
tidy_ysiv1afinn <- tidy_ysiv1 %>% 
  inner_join(get_sentiments("afinn")) %>% 
  head(10)
## Joining, by = "word"
tidy_ysiv1afinn
## # A tibble: 10 x 3
##    word        n value
##    <chr>   <int> <dbl>
##  1 shit      108    -4
##  2 love       57     3
##  3 fuck       47    -4
##  4 bitch      25    -5
##  5 alive      21     1
##  6 damn       16    -4
##  7 crazy      15    -2
##  8 die        14    -3
##  9 fucking    13    -4
## 10 hate       13    -3
wordcloud2(tidy_ysiv1)

Supermarket

genius_album(artist = "logic", album = "Supermarket") -> logic_super
## Joining, by = c("track_title", "track_n", "track_url")
logic_super %>% 
  unnest_tokens(word,lyric) %>% 
  anti_join(stop_words) %>% 
  count(word, sort = TRUE) -> tidy_super
## Joining, by = "word"
tidy_super
## # A tibble: 379 x 2
##    word       n
##    <chr>  <int>
##  1 girl      34
##  2 na        33
##  3 yeah      33
##  4 baby      32
##  5 friend    26
##  6 world     22
##  7 guess     18
##  8 break     15
##  9 time      15
## 10 love      14
## # … with 369 more rows
stopWords7 <- c("na")
stopWordsDF7 <- tibble(stopWords7)

tidy_super1 <- tidy_super %>% 
  anti_join(stopWordsDF7, by = c("word" = "stopWords7"))

tidy_super1
## # A tibble: 378 x 2
##    word       n
##    <chr>  <int>
##  1 girl      34
##  2 yeah      33
##  3 baby      32
##  4 friend    26
##  5 world     22
##  6 guess     18
##  7 break     15
##  8 time      15
##  9 love      14
## 10 fall      13
## # … with 368 more rows
tidy_super1afinn <- tidy_super1 %>% 
  inner_join(get_sentiments("afinn")) %>% 
  head(10)
## Joining, by = "word"
tidy_super1afinn
## # A tibble: 10 x 3
##    word          n value
##    <chr>     <int> <dbl>
##  1 yeah         33     1
##  2 love         14     3
##  3 pretty       13     1
##  4 promise      12     1
##  5 beautiful    11     3
##  6 shit          8    -4
##  7 risk          7    -2
##  8 drop          6    -1
##  9 free          6     1
## 10 fuck          6    -4
wordcloud2(tidy_super1)

Confessions of a Dangerous Mind

genius_album(artist = "logic", album = "confessions of a dangerous mind") -> logic_cdm
## Joining, by = c("track_title", "track_n", "track_url")
logic_cdm %>% 
  unnest_tokens(word,lyric) %>% 
  anti_join(stop_words) %>% 
  count(word, sort = TRUE) -> tidy_cdm
## Joining, by = "word"
tidy_cdm
## # A tibble: 1,454 x 2
##    word       n
##    <chr>  <int>
##  1 shit      96
##  2 ballin    88
##  3 yeah      73
##  4 ayy       57
##  5 fuck      51
##  6 bobby     49
##  7 uh        49
##  8 icy       46
##  9 break     39
## 10 wanna     39
## # … with 1,444 more rows
stopWords8 <- c("ayy", "uh", "yeah")
stopWordsDF8 <- tibble(stopWords8)

tidy_cdm1 <- tidy_cdm %>% 
  anti_join(stopWordsDF8, by = c("word" = "stopWords8"))

tidy_cdm1
## # A tibble: 1,451 x 2
##    word       n
##    <chr>  <int>
##  1 shit      96
##  2 ballin    88
##  3 fuck      51
##  4 bobby     49
##  5 icy       46
##  6 break     39
##  7 wanna     39
##  8 clean     38
##  9 y'all     37
## 10 boy       33
## # … with 1,441 more rows
tidy_cdm1afinn <- tidy_cdm1 %>% 
  inner_join(get_sentiments("afinn")) %>% 
  head(10)
## Joining, by = "word"
tidy_cdm1afinn
## # A tibble: 10 x 3
##    word             n value
##    <chr>        <int> <dbl>
##  1 shit            96    -4
##  2 fuck            51    -4
##  3 clean           38     2
##  4 afraid          32    -2
##  5 bitch           29    -5
##  6 love            27     3
##  7 leave           21    -1
##  8 damn            19    -4
##  9 motherfucker    15    -5
## 10 stop            13    -1
wordcloud2(tidy_cdm1)

Conclusion

Clearly Logic has an overall negative sentiment when analyzing his lyrics. By taking the afinn score of the top ten words in each album, an overall number score can be generated to easily compare each of them.

score <- c("-25", "-21", "-20", "-17", "-16", "-15", "-6", "-1")
album <- c("YSIV", "Confessions of a Dangerous Mind", "Bobby Tarantino", "Bobby Tarantino II", "The Incredible True Story", "Under Pressure", "Everybody", "Supermarket")

albumscore <- data.frame(score, album)

albumscore
##   score                           album
## 1   -25                            YSIV
## 2   -21 Confessions of a Dangerous Mind
## 3   -20                 Bobby Tarantino
## 4   -17              Bobby Tarantino II
## 5   -16       The Incredible True Story
## 6   -15                  Under Pressure
## 7    -6                       Everybody
## 8    -1                     Supermarket

Looking at Logic’s overall sentiment, it is clear that it is mainly negative. There is one exception being the album Supermarket. This is because Logic published a book of the same name and released this album to accompany it. The book is a love story, which strays from the usual topics that Logic raps about. Besides this album, Logic’s albums can be considered extremely negative.

The most frequent words that Logic uses are derogatory. Each slur created a -4 or -5 rating which heavily impacted the albums overall sentiment. There were also many words that could not be analyzed. For instance, in the album Everybody, Logic talks a lot about God and and his experience being biracial. Two of the top three words in that album were ‘god’ and ‘black’. These words taken out of context cannot have a sentiment analysis therefore they could not contribute to the overall sentiment. In fact, this is why most of his albums seems so negative. Taken out of context and analyzed individually, Logic’s lyrics are very crass and explicit. However, when listening to the songs as a whole it is clear that Logic is a pretty positive person. He takls about tough issues like mental health and racial issues which have negative sentiments. Logic also likes to poke fun at the explicit nature of rap music which is made most appearant in the track “Granpa’s Spaceship” off of the Bobby Tarantino II album. This track is a conversation exchange between two popular TV characters, Rick and Morty. Rick says:

“Don’t come at me like a little punk ass motherfucker, don’t try to come at me, Morty I’m saying that he’s got a plethora of music that varies from mood to mood, Morty, okay? And I’m saying that I’m in the mood to turn some shit up, Morty I’m not in the mood for a message about how I can be whatever I want or Ooh you know like equality and everybody and all that shit, alright? Just wanna hear some fuckin’, about titties, throwin’ stacks on some ass, you know Just some good old fuckin’ ATL style club rap, Morty”

Again, this is extremely explicit in nature but by doing so it is ironically playing at the culture of rap music. Even though the hypothesis was correct about Logic’s albums having an overall negative sentiment, this is solely due to his choice of words, the subject matter and the irony of the words instead of the actual context of the lyrics.