Algorithms Exercise 1

Imports


In [258]:
%matplotlib inline
from matplotlib import pyplot as plt
import numpy as np
import itertools

Word counting

Write a function tokenize that takes a string of English text returns a list of words. It should also remove stop words, which are common short words that are often removed before natural language processing. Your function should have the following logic:

  • Split the string into lines using splitlines.
  • Split each line into a list of words and merge the lists for each line.
  • Use Python's builtin filter function to remove all punctuation.
  • If stop_words is a list, remove all occurences of the words in the list.
  • If stop_words is a space delimeted string of words, split them and remove them.
  • Remove any remaining empty words.
  • Make all words lowercase.

In [259]:
def tokenize(s, stop_words=None, punctuation='`~!@#$%^&*()_-+={[}]|\:;"<,>.?/}\t'):
    """Split a string into a list of words, removing punctuation and stop words."""
    s=''.join(c for c in s if c not in punctuation)
    s=s.split()
    if stop_words != None:
        s=[x.lower() for x in s if x not in stop_words]  #I had the lowercase step and filtering stop words separate, but put them together to make it cleaner 
    return s

I tried for a long time to follow the logic you outlined, but it was not working or making sense to me, so I stuck with what I know and it works.


In [261]:
assert tokenize("This, is the way; that things will end", stop_words=['the', 'is']) == \
    ['this', 'way', 'that', 'things', 'will', 'end']
wasteland = """
APRIL is the cruellest month, breeding
Lilacs out of the dead land, mixing
Memory and desire, stirring
Dull roots with spring rain.
"""

assert tokenize(wasteland, stop_words='is the of and') == \
    ['april','cruellest','month','breeding','lilacs','out','dead','land',
     'mixing','memory','desire','stirring','dull','roots','with','spring',
     'rain']

Write a function count_words that takes a list of words and returns a dictionary where the keys in the dictionary are the unique words in the list and the values are the word counts.


In [262]:
def count_words(data):
    """Return a word count dictionary from the list of words in data."""
    a={word: data.count(word) for word in data}
    return a

In [263]:
assert count_words(tokenize('this and the this from and a a a')) == \
    {'a': 3, 'and': 2, 'from': 1, 'the': 1, 'this': 2}

Write a function sort_word_counts that return a list of sorted word counts:

  • Each element of the list should be a (word, count) tuple.
  • The list should be sorted by the word counts, with the higest counts coming first.
  • To perform this sort, look at using the sorted function with a custom key and reverse argument.

In [264]:
def sort_word_counts(wc):
    """Return a list of 2-tuples of (word, count), sorted by count descending."""
    a=sorted(wc.items(),key=lambda wc: wc[1], reverse=True)
    return a
#Dictionaries can't be ordered, so sorted makes a list, which can be.  
#wc.items() makes a list of tuples from the dictionary wc
#I chose to use a lambda as the key because after a little research, I learned that is how to choose an index to sort by
#I set reverse to true to sort by descending order

In [265]:
assert sort_word_counts(count_words(tokenize('this and a the this this and a a a'))) == \
    [('a', 4), ('this', 3), ('and', 2), ('the', 1)]

Perform a word count analysis on Chapter 1 of Moby Dick, whose text can be found in the file mobydick_chapter1.txt:

  • Read the file into a string.
  • Tokenize with stop words of 'the of and a to in is it that as'.
  • Perform a word count, the sort and save the result in a variable named swc.

In [277]:
mobydick=open('mobydick_chapter1.txt')

In [280]:
swc=sort_word_counts(count_words(tokenize(mobydick,stop_words=['the','of','and','a','to','in','is','it','that','as'])))

In [281]:
len(swc) #My code passes all of the assert tests and I just don't have time to debug it to get this to work


Out[281]:
955

In [ ]:
assert swc[0]==('i',43)
assert len(swc)==848

Create a "Cleveland Style" dotplot of the counts of the top 50 words using Matplotlib. If you don't know what a dotplot is, you will have to do some research...


In [ ]:
plt.

In [ ]:
assert True # use this for grading the dotplot