CS30 - Spring 2016 - Class 16

Example code in this lecture

   word-stats.py
   write_user_input.py
   unique.py

Lecture notes

  • admin
       - assignment 7
          - Part A due tonight
          - Part B due Friday
       - Academic honesty

  • what does the print_stats function in word-stats.py code do? What can we call it with?
       - Anything that is iterable, e.g.
          - a list
          - a string
          - a tuple
          (also need to be able to call len() on the items in it, e.g. a list of strings)

       - It iterates over each item (say in the list) and keeps track of:
          - longest string found
          - shortest string found
          - total length of the strings iterated over
          - the total number of strings/items

       - how does it keep track of the longest?
          - starts with ""
          - compares every word to the longest so far
          - if longer, updates longest

       - what does 'shortest == "" or' do? Why don't we have it for the longest condition?
          - for longest, we started with the shortest possible string, so any string will be longer
          - hard to start with the longest possible string
          - instead we add a special case for the first time through the loop
             - could have initialized shortest to be a really long string, but this is a more robust solution

  • running print_stats
       - we can run it directly by passing it a list of strings

          >>> print_stats(["this", "is", "a", "list", "of", "words"])
          Number of words: 6
          Longest word: words
          Shortest word: a
          Avg. word length: 3.0

       - look at the sentence_stats function in word-stats.py
          - the "split" method is called on a string and splits up the string into a list of strings based on spaces
          
             >>> "this is a sentence".split()
             ['this', 'is', 'a', 'sentence']
       
          - the sentence_stats function just creates a list of strings and then calls the print_stats function

             >>> sentence_stats("this is a sentence")
             Number of words: 4
             Longest word: sentence
             Shortest word: a
             Avg. word length: 3.75

  • files
       - what is a file?
          - a chunk of data stored on the hard disk
       - why do we need files?
          - hard-drives persist state regardless of whether the power is on or not
          - when a program is running, all the data it is generating/processing is in main memory (e.g. RAM)
             - main memory is faster, but doesn't persist when the power goes off

  • reading files
       - to read a file in Python we first need to open it
       
          - If we just want to hard-code the name and the name of the file is "some_file_name" then:

             file = open("some_file_name", "r")

          or if the name of the file is in a variable, then

             name_of_file = "some_file_name"
             file = open(name_of_file, "r")

          - open is another function that has two parameters
          - the first parameter is a *string* identifying the filename
             - be careful about the path/directory. Python looks for the file in the same directory as the program (.py file) unless you tell it to look elsewhere
          - the second parameter is another string telling Python what you want to do with the file
             - "r" stands for "read", that is, we're going to read some data from the file
          - open returns a 'file' object that we can use later on for reading purposes
             - above, I've saved that in a variable called "file", but I could have called it anything else

       - once we have a file open, we can read a line at a time from the file using a for loop:

          for <variable> in <file_variable>:
             # do something

          - for each line in the file, the loop will get run
          - each time the variable will get assigned to the next line in the file
             - the line will be of type string
             - the line will also have an endline at the end of it which you'll often want to get rid of (the strings strip() method is often good for this)

  • a simple example
       - put some text in a file called "example.txt", e.g.

          this is my file
          it has three lines
          and this is the third

       - if we have following program in a .py file *saved in the same directory*

          reader = open("example.txt", "r")

          for line in reader:
           print line

          reader.close()

       - then we will see the following:

          this is my file

          it has three lines

          and this is the third
          >>>

       - Anything funny about this?

       - add "print len(line)" in the for and run again:

          this is my file

          16
          it has three lines

          19
          and this is the third
          21
       
       - what's the problem?
          - when you read a line of from the file, you also get the end of line character
          - what's really in this file is:

          this is my file\nit has three lines\nand this is the third

       - to fix this, we want to "strip" (i.e. remove) the end of line character:

          reader = open("example.txt", "r")

          for line in reader:
           line = line.strip()
           print line

          reader.close()


  • look at file_stats in word-stats.py
       - because we can iterate over lines in a file, once we open the file, we can use the same print_stats function to analyze words in a file
          - this is the line word = word.strip() is in print_stats

       - I have a file called "english.txt" which contains a list of ~47K English words. I can use this to understand some basic stats about English:
          
          
          - again, the file called "english.txt" needs to be in the same directory as the .py file

             >>> file_stats("english.txt")
             Number of words: 47158
             Longest word: antidisestablishmentarianism
             Shortest word: Hz
             Avg. word length: 8.37891768099

  • what does this tell us about English? Average word length is 8.3? Does that sound right?
       - seems long!
       - the problem is that it doesn't take into account word frequency. This is just a dictionary of words
       - How might we measure actual word average length in language use?
          - try and find a corpus/sample of dialogue

  • wikipedia data
       - although not exactly spoken data, looking at Wikipedia data should give a reasonable approximation for English usage
       - We'll analyze some data I put together that includes the sentences from 60K English Wikipedia articles
          - if you want to do your own experiments, you can find the data at: http://www.cs.pomona.edu/~dkauchak/simplification/ (it's version 2.0 with the document aligned data)
       
       - if we look at this data, can we just use our file_stats function?
          - No. It assumes one word per line!

       - look at the general_print_stats function in word-stats.py code
          - does the same thing as print_stats
          - BUT, splits the line up first into words, so we end up with two for loops
             - the outer for loop iterates over lines in a file
             - the inner for loop iterates of the words in a given line

       - there is a general_file_stats function as well that then uses this function to print out the stats for the file

       - if we run it we get:
          >>> general_file_stats("wikipedia.txt")
          Number of words: 97912818
          Longest word: http://search.dma.mil/search?q=cache:0r3uwrsm8b8j:www.navy.mil/oceans/5090_1c_manual.pdf+officially+regard+the+whole+region+as+international+waters&client=navy_search&proxystylesheet=navy_search&output=xml_no_dtd&ie=utf-8&oe=utf-8&site=navy_all&access=p
          Shortest word: ,
          Avg. word length: 4.49793781852

          - any problems?
             - both the longest word and shortest word are a little unsatisfying
             - we shouldn't be considering these things as "words"
             - we could just add some more code to filter these, but better to write some code to generate *new* data that's been cleaned up

  • writing files
       - we can also write data to files
       - look at write_user_input.py code
       - we can open a file for "writing" by using a "w" instead of an "r"
          - "w" stands for write
          - if the file doesn't exist it will create it
          - if the file does exists, it will erase the current contents and overwrite it (be careful!)
          - we can also write to a file without overwriting the contents, but instead append to the end
             - "a" stands for append
       
       - just like with reading from a file, we get a file object when we call open
          - the "write" method writes an object to the file as a string
          - if you want to write a line to a file, you need to include the end of line character ("\n"), it does not do this by default

       - the write_me_to_file function opens a file for writing and then prompts the user for strings. It then writes this to the file as long as the user keeps entering non-empty data
          - For example, if I run it:

             >>> write_me_to_file("test.txt")
             Next line: this is line 1
             Next line: and I can keep
             Next line: entering text
             Next line: as long as I want
             Next line: and it will get written to the
             Next line: file
             Next line:

          and then look in the file "test.txt", I'll find those lines in the file

  • look at cleanup_data in word-stats.py
       - looks similar to the print_general_stats function
       - opens the file for reading and the output file
       - iterates over the lines in the input file
          - splits up the line into words
          - for each words uses the "isalpha" method to determine if the string is all alphabetic characters and appends those that are onto cleaned

       - what do you think "join" does?
          >>> help(str.join)
          Help on method_descriptor:
          
          join(...)
           S.join(iterable) -> string

           Return a string which is the concatenation of the strings in the
           iterable. The separator between elements is S.

          >>> list = ["some", "words", "in", "a", "list"]
          >>> " ".join(list)
          'some words in a list'
          >>> ", ".join(list)
          'some, words, in, a, list'
          >>> "--".join(list)
          'some--words--in--a--list'

       - make sure to call "close()" when you're writing a file
          - in most cases, if you don't do it when *reading* a file, it's fine (but still should get in the habit of doing it)
          - can (and will) cause problems if you don't do it when you're writing a file
             - it can lead to the last bit of data you wrote NOT appearing in the file!

       - I used this function to generate "wikipedia.cleaned.txt"
          >>> general_file_stats("wikipedia.cleaned.txt")
          Number of words: 80581346
          Longest word: outsideofadogabookismansbeguituitglsajsakhdlaysioeyashdklsalkdn
          Shortest word: a
          Avg. word length: 4.94404439459      

  • other questions we might want to ask about wikipedia?

  • how many unique words (well, strings) are in wikipedia?

  • dictionaries (aka maps)
       - store keys and an associated value
          - each key is associated with a value
          - lookup can be done based on the key
          - this is a very common phenomena in the real world. What are some examples?
             - social security number
                - key = social security number
                - value = name, address, etc
             - phone numbers in your phone (and phone directories in general)
                - key = name
                - value = phone number
             - websites
                - key = url
                - value = location of the computer that hosts this website
             - car license plates
                - key = license plate number
                - value = owner, type of car, ...
             - flight information
                - key = flight number
                - value = departure city, destination city, time, ...

       - dictionaries allow us to efficiently lookup (and update) keys in the dictionary

       - creating new dictionaries
          - dictionaries can be created using curly braces
             >>> d = {}
             >>> d
             {}
       
       - dictionaries function similarly to lists, except we can put things in ANY index and can use non-numerical indices
          >>> d["grapes"] = "purple"

          - this says associate the value "purple" with the key "grapes"

          >>> d
          {'grapes': 'purple'}

          - when they're printed out they're printed as key/value pairs, e.g.

          >>> d["apples"] = "red"
          >>> d
          {'apples': 'red', 'grapes': 'purple'}

       - accessing values
          - you can get back the value associated with a key
             >>> d["apples"]
             'red'

       - keys are unique!
          - if you assign to a key again, it will update the key

             >>> d["apples"] = "green"
             >>> d["apples"]
             'green'
             >>> d
             {'apples': 'green', 'grapes': 'purple'}

  • how can we use this to count the number of unique words?
       - look at unique.py code
          - iterate through each of the words
          - add each to a dictionary with value 1 (in fact, any value would work)
          - return the len of the dictionary (i.e. how many entries are in the dictionary)
       
       - we can leverage the fact that keys *must* be unique
          - if we see a word multiple times it will still only have one entry in the dictionary

       >>> unique_words("wikipedia.cleaned.txt")
       553736