Assignment: Read in the file called manifestos.xslx. It contains the writings of several mass killers, incuding the Unabomber, Anders Breivik who killed 70+ people in Norway, Pekka-Eric Auvinen a school shooter from Finland, Elliot Rodger who killed people in California, Seung-Hui Cho who killed people at Virginia Tech, and Chris Harper-Mercer who killed people at a college in Oregon. (I collected these writings and put them into an excel file. Breivik wrote the most by far; I took only a small portion of his writings.)

  1. Read in the text and unnest the words.
  2. Generate a table that includes both lexical diversity and density, and the total number of words, of each document.
  3. Generate a table with the mean word length of each document.
  4. Genernate a graph with mini histograms of each document’s word lengths.
  5. Remove stop words and then create a graph with the most common words in each document.
  6. Calculate tf-idfs and create a graph of the words with the highest tf-idfs in each document.
library(tidyverse)
── Attaching packages ─────────────────────── tidyverse 1.2.1 ──
✔ ggplot2 3.1.0     ✔ purrr   0.2.5
✔ tibble  2.0.0     ✔ dplyr   0.7.8
✔ tidyr   0.8.2     ✔ stringr 1.3.1
✔ readr   1.3.1     ✔ forcats 0.3.0
── Conflicts ────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(DT)
library(tidytext)        # package for text analysis
library(readxl)          # reads excel files, the format I used for the data
killer_notes <- read_excel("manifestos.xlsx")

killer_notes
killer_words <- killer_notes %>%
  unnest_tokens(word, text)

killer_words
killer_words %>% 
  group_by(author) %>% 
  summarize(num_words = n(), lex_diversity = n_distinct(word))
killer_words %>% 
  group_by(author) %>% 
  summarise(num_words = n(),
            lex_diversity = n_distinct(word), 
            lex_density = n_distinct(word)/n())
killer_words %>%
  mutate(word_length = nchar(word)) %>% 
  distinct(word, word_length, author) %>% 
  arrange(-word_length)
killer_words %>%
  group_by(author) %>% 
  mutate(word_length = nchar(word)) %>% 
  summarize(mean_word_length = mean(word_length)) %>% 
  arrange(-mean_word_length)
killer_words %>%
  mutate(word_length = nchar(word)) %>% 
  ggplot(aes(word_length)) +
  geom_histogram(binwidth = 1) 

killer_words %>%
  mutate(word_length = nchar(word)) %>% 
  ggplot(aes(word_length)) +
  geom_histogram(binwidth = 1) +
  facet_wrap(vars(author), scales = "free_y") +
labs(title = "Word Length Distrobutions of killer manifestos by Author")

killer_words %>% 
  count(word, sort = T) 
killer_words %>% 
  group_by(author) %>%
  count(word, sort = T)
killer_words %>% 
  group_by(author) %>%
  count(word, sort = T) %>% 
  top_n(5) %>%
  ungroup() %>% 
  mutate(word = reorder(word, n)) %>%
  ggplot(aes(word, n, fill = author)) +
  geom_col(show.legend = FALSE) +
  coord_flip() +
  facet_wrap(~author, scales = "free") +           # creates separate graphs for each author
  scale_fill_viridis_d() +                         # uses a nicer color scheme
  theme_minimal() +                                # removes the gray background
  labs(x = NULL, y = "Most common words")
Selecting by n

stop_words <- get_stopwords()
stop_words$word
  [1] "i"          "me"         "my"         "myself"    
  [5] "we"         "our"        "ours"       "ourselves" 
  [9] "you"        "your"       "yours"      "yourself"  
 [13] "yourselves" "he"         "him"        "his"       
 [17] "himself"    "she"        "her"        "hers"      
 [21] "herself"    "it"         "its"        "itself"    
 [25] "they"       "them"       "their"      "theirs"    
 [29] "themselves" "what"       "which"      "who"       
 [33] "whom"       "this"       "that"       "these"     
 [37] "those"      "am"         "is"         "are"       
 [41] "was"        "were"       "be"         "been"      
 [45] "being"      "have"       "has"        "had"       
 [49] "having"     "do"         "does"       "did"       
 [53] "doing"      "would"      "should"     "could"     
 [57] "ought"      "i'm"        "you're"     "he's"      
 [61] "she's"      "it's"       "we're"      "they're"   
 [65] "i've"       "you've"     "we've"      "they've"   
 [69] "i'd"        "you'd"      "he'd"       "she'd"     
 [73] "we'd"       "they'd"     "i'll"       "you'll"    
 [77] "he'll"      "she'll"     "we'll"      "they'll"   
 [81] "isn't"      "aren't"     "wasn't"     "weren't"   
 [85] "hasn't"     "haven't"    "hadn't"     "doesn't"   
 [89] "don't"      "didn't"     "won't"      "wouldn't"  
 [93] "shan't"     "shouldn't"  "can't"      "cannot"    
 [97] "couldn't"   "mustn't"    "let's"      "that's"    
[101] "who's"      "what's"     "here's"     "there's"   
[105] "when's"     "where's"    "why's"      "how's"     
[109] "a"          "an"         "the"        "and"       
[113] "but"        "if"         "or"         "because"   
[117] "as"         "until"      "while"      "of"        
[121] "at"         "by"         "for"        "with"      
[125] "about"      "against"    "between"    "into"      
[129] "through"    "during"     "before"     "after"     
[133] "above"      "below"      "to"         "from"      
[137] "up"         "down"       "in"         "out"       
[141] "on"         "off"        "over"       "under"     
[145] "again"      "further"    "then"       "once"      
[149] "here"       "there"      "when"       "where"     
[153] "why"        "how"        "all"        "any"       
[157] "both"       "each"       "few"        "more"      
[161] "most"       "other"      "some"       "such"      
[165] "no"         "nor"        "not"        "only"      
[169] "own"        "same"       "so"         "than"      
[173] "too"        "very"       "will"      
killer_words %>%
  anti_join(stop_words)
Joining, by = "word"
killer_words %>%
  anti_join(stop_words) %>%
  count(word, sort = T)
Joining, by = "word"
killer_words %>%
  anti_join(stop_words) %>% 
  group_by(author) %>% 
  count(word, sort = T) 
Joining, by = "word"
killer_words %>%
  anti_join(stop_words) %>% 
  group_by(author) %>% 
  count(word, sort = T) %>%
  top_n(5) %>% 
  ungroup() %>% 
  mutate(word = reorder(word, n)) %>%
  ggplot(aes(word, n, fill = author)) +
  geom_col(show.legend = FALSE) +
  labs(x = NULL, y = "Most common words") +
  facet_wrap(vars(author), scales = "free") +
  scale_fill_viridis_d() +
  theme_minimal() +
  coord_flip()
Joining, by = "word"
Selecting by n

killer_word_counts <- killer_notes %>%             # This counts each word per author
  unnest_tokens(word, text) %>%
  count(author, word, sort = TRUE) 

total_words <- killer_word_counts %>%               # This counts total words per author
  group_by(author) %>% 
  summarize(total = sum(n))

killer_word_counts <- left_join(killer_word_counts, total_words)    # Joins the two
Joining, by = "author"
killer_tf_idf <- killer_word_counts %>%             # Calculates tf-idf
  bind_tf_idf(word, author, n)

killer_tf_idf %>%                                   # Displays it
  arrange(-tf_idf)                          
NA
killer_tf_idf %>%
  arrange(-tf_idf) %>%
  mutate(word = factor(word, levels = rev(unique(word)))) %>% 
  group_by(author) %>% 
  top_n(5) %>% 
  ggplot(aes(word, tf_idf, fill = author)) +
  geom_col(show.legend = FALSE) +
  labs(x = NULL, y = "tf-idf") +
  facet_wrap(~author, scales = "free") +
  coord_flip() +
  theme_minimal() +
  scale_fill_viridis_d() +
  labs(title = "Most distinctive words in each killer manifesto")
Selecting by tf_idf

LS0tCnRpdGxlOiAiaW50cm9fdGV4dF9hbmFseXNpcyBhc3NpZ25tZW50IgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpBc3NpZ25tZW50OgpSZWFkIGluIHRoZSBmaWxlIGNhbGxlZCBtYW5pZmVzdG9zLnhzbHguIEl0IGNvbnRhaW5zIHRoZSB3cml0aW5ncyBvZiBzZXZlcmFsIG1hc3Mga2lsbGVycywgaW5jdWRpbmcgdGhlIFVuYWJvbWJlciwgQW5kZXJzIEJyZWl2aWsgd2hvIGtpbGxlZCA3MCsgcGVvcGxlIGluIE5vcndheSwgUGVra2EtRXJpYyBBdXZpbmVuIGEgc2Nob29sIHNob290ZXIgZnJvbSBGaW5sYW5kLCBFbGxpb3QgUm9kZ2VyIHdobyBraWxsZWQgcGVvcGxlIGluIENhbGlmb3JuaWEsIFNldW5nLUh1aSBDaG8gd2hvIGtpbGxlZCBwZW9wbGUgYXQgVmlyZ2luaWEgVGVjaCwgYW5kIENocmlzIEhhcnBlci1NZXJjZXIgd2hvIGtpbGxlZCBwZW9wbGUgYXQgYSBjb2xsZWdlIGluIE9yZWdvbi4gKEkgY29sbGVjdGVkIHRoZXNlIHdyaXRpbmdzIGFuZCBwdXQgdGhlbSBpbnRvIGFuIGV4Y2VsIGZpbGUuIEJyZWl2aWsgd3JvdGUgdGhlIG1vc3QgYnkgZmFyOyBJIHRvb2sgb25seSBhIHNtYWxsIHBvcnRpb24gb2YgaGlzIHdyaXRpbmdzLikKCjEuIFJlYWQgaW4gdGhlIHRleHQgYW5kIHVubmVzdCB0aGUgd29yZHMuICAKMi4gR2VuZXJhdGUgYSB0YWJsZSB0aGF0IGluY2x1ZGVzIGJvdGggbGV4aWNhbCBkaXZlcnNpdHkgYW5kIGRlbnNpdHksIGFuZCB0aGUgdG90YWwgbnVtYmVyIG9mIHdvcmRzLCBvZiBlYWNoIGRvY3VtZW50LiAgCjMuIEdlbmVyYXRlIGEgdGFibGUgd2l0aCB0aGUgbWVhbiB3b3JkIGxlbmd0aCBvZiBlYWNoIGRvY3VtZW50LiAgCjQuIEdlbmVybmF0ZSBhIGdyYXBoIHdpdGggbWluaSBoaXN0b2dyYW1zIG9mIGVhY2ggZG9jdW1lbnQncyB3b3JkIGxlbmd0aHMuICAKNS4gUmVtb3ZlIHN0b3Agd29yZHMgYW5kIHRoZW4gY3JlYXRlIGEgZ3JhcGggd2l0aCB0aGUgbW9zdCBjb21tb24gd29yZHMgaW4gZWFjaCBkb2N1bWVudC4gIAo2LiBDYWxjdWxhdGUgdGYtaWRmcyBhbmQgY3JlYXRlIGEgZ3JhcGggb2YgdGhlIHdvcmRzIHdpdGggdGhlIGhpZ2hlc3QgdGYtaWRmcyBpbiBlYWNoIGRvY3VtZW50LiAgCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoRFQpCmxpYnJhcnkodGlkeXRleHQpICAgICAgICAjIHBhY2thZ2UgZm9yIHRleHQgYW5hbHlzaXMKbGlicmFyeShyZWFkeGwpICAgICAgICAgICMgcmVhZHMgZXhjZWwgZmlsZXMsIHRoZSBmb3JtYXQgSSB1c2VkIGZvciB0aGUgZGF0YQpgYGAKCgoKYGBge3J9CmtpbGxlcl9ub3RlcyA8LSByZWFkX2V4Y2VsKCJtYW5pZmVzdG9zLnhsc3giKQoKa2lsbGVyX25vdGVzCmBgYAoKYGBge3J9CmtpbGxlcl93b3JkcyA8LSBraWxsZXJfbm90ZXMgJT4lCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0KQoKa2lsbGVyX3dvcmRzCmBgYAoKCmBgYHtyfQpraWxsZXJfd29yZHMgJT4lIAogIGdyb3VwX2J5KGF1dGhvcikgJT4lIAogIHN1bW1hcml6ZShudW1fd29yZHMgPSBuKCksIGxleF9kaXZlcnNpdHkgPSBuX2Rpc3RpbmN0KHdvcmQpKQpgYGAKCgoKYGBge3J9CmtpbGxlcl93b3JkcyAlPiUgCiAgZ3JvdXBfYnkoYXV0aG9yKSAlPiUgCiAgc3VtbWFyaXNlKG51bV93b3JkcyA9IG4oKSwKICAgICAgICAgICAgbGV4X2RpdmVyc2l0eSA9IG5fZGlzdGluY3Qod29yZCksIAogICAgICAgICAgICBsZXhfZGVuc2l0eSA9IG5fZGlzdGluY3Qod29yZCkvbigpKQpgYGAKCgpgYGB7cn0Ka2lsbGVyX3dvcmRzICU+JQogIG11dGF0ZSh3b3JkX2xlbmd0aCA9IG5jaGFyKHdvcmQpKSAlPiUgCiAgZGlzdGluY3Qod29yZCwgd29yZF9sZW5ndGgsIGF1dGhvcikgJT4lIAogIGFycmFuZ2UoLXdvcmRfbGVuZ3RoKQpgYGAKCgoKYGBge3J9CmtpbGxlcl93b3JkcyAlPiUKICBncm91cF9ieShhdXRob3IpICU+JSAKICBtdXRhdGUod29yZF9sZW5ndGggPSBuY2hhcih3b3JkKSkgJT4lIAogIHN1bW1hcml6ZShtZWFuX3dvcmRfbGVuZ3RoID0gbWVhbih3b3JkX2xlbmd0aCkpICU+JSAKICBhcnJhbmdlKC1tZWFuX3dvcmRfbGVuZ3RoKQpgYGAKCmBgYHtyfQpraWxsZXJfd29yZHMgJT4lCiAgbXV0YXRlKHdvcmRfbGVuZ3RoID0gbmNoYXIod29yZCkpICU+JSAKICBnZ3Bsb3QoYWVzKHdvcmRfbGVuZ3RoKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgCmBgYAoKCmBgYHtyfQpraWxsZXJfd29yZHMgJT4lCiAgbXV0YXRlKHdvcmRfbGVuZ3RoID0gbmNoYXIod29yZCkpICU+JSAKICBnZ3Bsb3QoYWVzKHdvcmRfbGVuZ3RoKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gMSkgKwogIGZhY2V0X3dyYXAodmFycyhhdXRob3IpLCBzY2FsZXMgPSAiZnJlZV95IikgKwpsYWJzKHRpdGxlID0gIldvcmQgTGVuZ3RoIERpc3Ryb2J1dGlvbnMgb2Yga2lsbGVyIG1hbmlmZXN0b3MgYnkgQXV0aG9yIikKYGBgCgoKYGBge3J9CmtpbGxlcl93b3JkcyAlPiUgCiAgY291bnQod29yZCwgc29ydCA9IFQpIApgYGAKCgoKYGBge3J9CmtpbGxlcl93b3JkcyAlPiUgCiAgZ3JvdXBfYnkoYXV0aG9yKSAlPiUKICBjb3VudCh3b3JkLCBzb3J0ID0gVCkKYGBgCgoKYGBge3J9CmtpbGxlcl93b3JkcyAlPiUgCiAgZ3JvdXBfYnkoYXV0aG9yKSAlPiUKICBjb3VudCh3b3JkLCBzb3J0ID0gVCkgJT4lIAogIHRvcF9uKDUpICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgbXV0YXRlKHdvcmQgPSByZW9yZGVyKHdvcmQsIG4pKSAlPiUKICBnZ3Bsb3QoYWVzKHdvcmQsIG4sIGZpbGwgPSBhdXRob3IpKSArCiAgZ2VvbV9jb2woc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgZmFjZXRfd3JhcCh+YXV0aG9yLCBzY2FsZXMgPSAiZnJlZSIpICsgICAgICAgICAgICMgY3JlYXRlcyBzZXBhcmF0ZSBncmFwaHMgZm9yIGVhY2ggYXV0aG9yCiAgc2NhbGVfZmlsbF92aXJpZGlzX2QoKSArICAgICAgICAgICAgICAgICAgICAgICAgICMgdXNlcyBhIG5pY2VyIGNvbG9yIHNjaGVtZQogIHRoZW1lX21pbmltYWwoKSArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIHJlbW92ZXMgdGhlIGdyYXkgYmFja2dyb3VuZAogIGxhYnMoeCA9IE5VTEwsIHkgPSAiTW9zdCBjb21tb24gd29yZHMiKQoKYGBgCgoKYGBge3J9CnN0b3Bfd29yZHMgPC0gZ2V0X3N0b3B3b3JkcygpCnN0b3Bfd29yZHMkd29yZApgYGAKYGBge3J9CmtpbGxlcl93b3JkcyAlPiUKICBhbnRpX2pvaW4oc3RvcF93b3JkcykKYGBgCgpgYGB7cn0Ka2lsbGVyX3dvcmRzICU+JQogIGFudGlfam9pbihzdG9wX3dvcmRzKSAlPiUKICBjb3VudCh3b3JkLCBzb3J0ID0gVCkKYGBgCgoKCmBgYHtyfQpraWxsZXJfd29yZHMgJT4lCiAgYW50aV9qb2luKHN0b3Bfd29yZHMpICU+JSAKICBncm91cF9ieShhdXRob3IpICU+JSAKICBjb3VudCh3b3JkLCBzb3J0ID0gVCkgCmBgYAoKCgpgYGB7cn0Ka2lsbGVyX3dvcmRzICU+JQogIGFudGlfam9pbihzdG9wX3dvcmRzKSAlPiUgCiAgZ3JvdXBfYnkoYXV0aG9yKSAlPiUgCiAgY291bnQod29yZCwgc29ydCA9IFQpICU+JQogIHRvcF9uKDUpICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIG11dGF0ZSh3b3JkID0gcmVvcmRlcih3b3JkLCBuKSkgJT4lCiAgZ2dwbG90KGFlcyh3b3JkLCBuLCBmaWxsID0gYXV0aG9yKSkgKwogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gIk1vc3QgY29tbW9uIHdvcmRzIikgKwogIGZhY2V0X3dyYXAodmFycyhhdXRob3IpLCBzY2FsZXMgPSAiZnJlZSIpICsKICBzY2FsZV9maWxsX3ZpcmlkaXNfZCgpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGNvb3JkX2ZsaXAoKQpgYGAKCgpgYGB7cn0Ka2lsbGVyX3dvcmRfY291bnRzIDwtIGtpbGxlcl9ub3RlcyAlPiUgICAgICAgICAgICAgIyBUaGlzIGNvdW50cyBlYWNoIHdvcmQgcGVyIGF1dGhvcgogIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCkgJT4lCiAgY291bnQoYXV0aG9yLCB3b3JkLCBzb3J0ID0gVFJVRSkgCgp0b3RhbF93b3JkcyA8LSBraWxsZXJfd29yZF9jb3VudHMgJT4lICAgICAgICAgICAgICAgIyBUaGlzIGNvdW50cyB0b3RhbCB3b3JkcyBwZXIgYXV0aG9yCiAgZ3JvdXBfYnkoYXV0aG9yKSAlPiUgCiAgc3VtbWFyaXplKHRvdGFsID0gc3VtKG4pKQoKa2lsbGVyX3dvcmRfY291bnRzIDwtIGxlZnRfam9pbihraWxsZXJfd29yZF9jb3VudHMsIHRvdGFsX3dvcmRzKSAgICAjIEpvaW5zIHRoZSB0d28KCmtpbGxlcl90Zl9pZGYgPC0ga2lsbGVyX3dvcmRfY291bnRzICU+JSAgICAgICAgICAgICAjIENhbGN1bGF0ZXMgdGYtaWRmCiAgYmluZF90Zl9pZGYod29yZCwgYXV0aG9yLCBuKQoKa2lsbGVyX3RmX2lkZiAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgRGlzcGxheXMgaXQKICBhcnJhbmdlKC10Zl9pZGYpICAgICAgICAgICAgICAgICAgICAgICAgICAKCmBgYAoKCmBgYHtyfQpraWxsZXJfdGZfaWRmICU+JQogIGFycmFuZ2UoLXRmX2lkZikgJT4lCiAgbXV0YXRlKHdvcmQgPSBmYWN0b3Iod29yZCwgbGV2ZWxzID0gcmV2KHVuaXF1ZSh3b3JkKSkpKSAlPiUgCiAgZ3JvdXBfYnkoYXV0aG9yKSAlPiUgCiAgdG9wX24oNSkgJT4lIAogIGdncGxvdChhZXMod29yZCwgdGZfaWRmLCBmaWxsID0gYXV0aG9yKSkgKwogIGdlb21fY29sKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gInRmLWlkZiIpICsKICBmYWNldF93cmFwKH5hdXRob3IsIHNjYWxlcyA9ICJmcmVlIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBzY2FsZV9maWxsX3ZpcmlkaXNfZCgpICsKICBsYWJzKHRpdGxlID0gIk1vc3QgZGlzdGluY3RpdmUgd29yZHMgaW4gZWFjaCBraWxsZXIgbWFuaWZlc3RvIikKYGBgCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg==